public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
@ 2010-06-07 16:00 Pedro Alves
  2010-06-07 16:04 ` Michael Snyder
  2010-06-10 17:28 ` Tom Tromey
  0 siblings, 2 replies; 31+ messages in thread
From: Pedro Alves @ 2010-06-07 16:00 UTC (permalink / raw)
  To: gdb-patches

This adds a bytecode compiler to the linux x86 ports of
gdbserver, that turns agent expression bytecodes into
native code.  This greatly speeds up conditional tracepoints
(by around an order of magnitude) that usually don't reference much
more than a few variables (memory/registers), to around 100ns or
less on a typical modern x86 box.

-- 
Pedro Alves

2010-06-07  Stan Shebs  <stan@codesourcery.com>
	    Pedro Alves  <pedro@codesourcery.com>

	Bytecode compiler.

	* linux-x86-low.c: Include limits.h.
	(add_insns): New.
	(always_true): New.
	(EMIT_ASM): New.
	(EMIT_ASM32): New.
	(amd64_emit_prologue, amd64_emit_epilogue, amd64_emit_add)
	(amd64_emit_sub, amd64_emit_mul, amd64_emit_lsh)
	(amd64_emit_rsh_signed, amd64_emit_rsh_unsigned, amd64_emit_ext,
	(amd64_emit_log_not, amd64_emit_bit_and, amd64_emit_bit_or)
	(amd64_emit_bit_xor, amd64_emit_bit_not, amd64_emit_equal,
	(amd64_emit_less_signed, amd64_emit_less_unsigned, amd64_emit_ref,
	(amd64_emit_if_goto, amd64_emit_goto, amd64_write_goto_address)
	(amd64_emit_const, amd64_emit_call, amd64_emit_reg)
	(amd64_emit_pop, amd64_emit_stack_flush, amd64_emit_zero_ext)
	(amd64_emit_swap, amd64_emit_stack_adjust, amd64_emit_int_call_1)
	(amd64_emit_void_call_2): New.
	(amd64_emit_ops): New.
	(i386_emit_prologue, i386_emit_epilogue, i386_emit_add)
	(i386_emit_sub,i386_emit_mul, i386_emit_lsh, i386_emit_rsh_signed)
	(i386_emit_rsh_unsigned, i386_emit_ext, i386_emit_log_not)
	(i386_emit_bit_and, i386_emit_bit_or, i386_emit_bit_xor)
	(i386_emit_bit_not, i386_emit_equal, i386_emit_less_signed)
	(i386_emit_less_unsigned, i386_emit_ref, i386_emit_if_goto)
	(i386_emit_goto, i386_write_goto_address, i386_emit_const)
	(i386_emit_call, i386_emit_reg, i386_emit_pop)
	(i386_emit_stack_flush, i386_emit_zero_ext, i386_emit_swap)
	(i386_emit_stack_adjust, i386_emit_int_call_1)
	(i386_emit_void_call_2): New.
	(i386_emit_ops): New.
	(x86_emit_ops): New.
	(the_low_target): Install x86_emit_ops.
	* server.h (struct emit_ops): New.
	(get_raw_reg_func_addr): Declare.
	(current_insn_ptr, emit_error): Declare.
	* tracepoint.c (get_raw_reg, get_trace_state_variable_value)
	(set_trace_state_variable_value): New defines.
	(struct ipa_sym_addresses): New fields addr_get_raw_reg,
	addr_get_trace_state_variable_value and
	addr_set_trace_state_variable_value.
	(symbol_list): New fields for get_raw_reg,
	get_trace_state_variable_value and set_trace_state_variable_value.
	(condfn): New typedef.
	(struct tracepoint): New field `compiled_cond'.
	(do_action_at_tracepoint): Clear compiled_cond.
	(get_trace_state_variable_value, set_trace_state_variable_value):
	Export in the IPA.
	(condition_true_at_tracepoint): If there's a compiled condition,
	run that.
	(current_insn_ptr, emit_error): New globals.
	(struct bytecode_address): New.
	(get_raw_reg_func_addr): New.
	(emit_prologue, emit_epilogue, emit_add, emit_sub, emit_mul)
	(emit_lsh, emit_rsh_signed, emit_rsh_unsigned, emit_ext)
	(emit_log_not, emit_bit_and, emit_bit_or, emit_bit_xor)
	(emit_bit_not, emit_equal, emit_less_signed, emit_less_unsigned)
	(emit_ref, emit_if_goto, emit_goto, write_goto_address, emit_const)
	(emit_reg, emit_pop, emit_stack_flush, emit_zero_ext, emit_swap)
	(emit_stack_adjust, emit_int_call_1, emit_void_call_2): New.
	(compile_tracepoint_condition, compile_bytecodes): New.
	* target.h (emit_ops): Forward declare.
	(struct target_ops): New field emit_ops.
	(target_emit_ops): New.
	* linux-amd64-ipa.c (gdb_agent_get_raw_reg): New.
	* linux-i386-ipa.c (gdb_agent_get_raw_reg): New.
	* linux-low.c (linux_emit_ops): New.
	(linux_target_ops): Install it.
	* linux-low.h (struct linux_target_ops): New field emit_ops.

---
 gdb/gdbserver/linux-amd64-ipa.c |    9 
 gdb/gdbserver/linux-i386-ipa.c  |   15 
 gdb/gdbserver/linux-low.c       |   12 
 gdb/gdbserver/linux-low.h       |    4 
 gdb/gdbserver/linux-x86-low.c   | 1032 +++++++++++++++++++++++++++++++++++++++-
 gdb/gdbserver/server.h          |   50 +
 gdb/gdbserver/target.h          |    8 
 gdb/gdbserver/tracepoint.c      |  624 ++++++++++++++++++++++++
 8 files changed, 1749 insertions(+), 5 deletions(-)

Index: src/gdb/gdbserver/linux-x86-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-x86-low.c	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/linux-x86-low.c	2010-06-07 16:43:25.000000000 +0100
@@ -20,6 +20,7 @@
 
 #include <stddef.h>
 #include <signal.h>
+#include <limits.h>
 #include "server.h"
 #include "linux-low.h"
 #include "i387-fp.h"
@@ -1470,6 +1471,1034 @@ x86_install_fast_tracepoint_jump_pad (CO
 						adjusted_insn_addr_end);
 }
 
+static void
+add_insns (unsigned char *start, int len)
+{
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  if (debug_threads)
+    fprintf (stderr, "Adding %d bytes of insn at %s\n",
+	     len, paddress (buildaddr));
+
+  append_insns (&buildaddr, len, start);
+  current_insn_ptr = buildaddr;
+}
+
+/* A function used to trick optimizers.  */
+
+int
+always_true (void)
+{
+  return 1;
+}
+
+/* Our general strategy for emitting code is to avoid specifying raw
+   bytes whenever possible, and instead copy a block of inline asm
+   that is embedded in the function.  This is a little messy, because
+   we need to keep the compiler from discarding what looks like dead
+   code, plus suppress various warnings.  */
+
+#define EMIT_ASM(NAME,INSNS)						\
+  { extern unsigned char start_ ## NAME, end_ ## NAME;			\
+    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
+    if (always_true ())						\
+      goto skipover ## NAME;						\
+    __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");	\
+    skipover ## NAME:							\
+    ; }
+
+
+#ifdef __x86_64__
+
+#define EMIT_ASM32(NAME,INSNS)						\
+  { extern unsigned char start_ ## NAME, end_ ## NAME;			\
+    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
+    if (always_true ())						\
+      goto skipover ## NAME;						\
+    __asm__ (".code32\n\tstart_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n" \
+	     "\t.code64\n\t");						\
+    skipover ## NAME:							\
+    ; }
+
+#else
+
+#define EMIT_ASM32(NAME,INSNS) EMIT_ASM(NAME,INSNS)
+
+#endif
+
+#ifdef __x86_64__
+
+static void
+amd64_emit_prologue (void)
+{
+  EMIT_ASM (amd64_prologue,
+	    "pushq %rbp\n\t"
+	    "movq %rsp,%rbp\n\t"
+	    "sub $0x20,%rsp\n\t"
+	    "movq %rdi,-8(%rbp)\n\t"
+	    "movq %rsi,-16(%rbp)");
+}
+
+
+static void
+amd64_emit_epilogue (void)
+{
+  EMIT_ASM (amd64_epilogue,
+	    "movq -16(%rbp),%rdi\n\t"
+	    "movq %rax,(%rdi)\n\t"
+	    "xor %rax,%rax\n\t"
+	    "leave\n\t"
+	    "ret");
+}
+
+static void
+amd64_emit_add (void)
+{
+  EMIT_ASM (amd64_add,
+	    "add (%rsp),%rax\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_sub (void)
+{
+  EMIT_ASM (amd64_sub,
+	    "sub %rax,(%rsp)\n\t"
+	    "pop %rax");
+}
+
+static void
+amd64_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+static void
+amd64_emit_lsh (void)
+{
+  emit_error = 1;
+}
+
+static void
+amd64_emit_rsh_signed (void)
+{
+  emit_error = 1;
+}
+
+static void
+amd64_emit_rsh_unsigned (void)
+{
+  emit_error = 1;
+}
+
+static void
+amd64_emit_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM (amd64_ext_8,
+		"cbtw\n\t"
+		"cwtl\n\t"
+		"cltq");
+      break;
+    case 16:
+      EMIT_ASM (amd64_ext_16,
+		"cwtl\n\t"
+		"cltq");
+      break;
+    case 32:
+      EMIT_ASM (amd64_ext_32,
+		"cltq");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+static void
+amd64_emit_log_not (void)
+{
+  EMIT_ASM (amd64_log_not,
+	    "test %rax,%rax\n\t"
+	    "sete %cl\n\t"
+	    "movzbq %cl,%rax");
+}
+
+static void
+amd64_emit_bit_and (void)
+{
+  EMIT_ASM (amd64_and,
+	    "and (%rsp),%rax\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_bit_or (void)
+{
+  EMIT_ASM (amd64_or,
+	    "or (%rsp),%rax\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_bit_xor (void)
+{
+  EMIT_ASM (amd64_xor,
+	    "xor (%rsp),%rax\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_bit_not (void)
+{
+  EMIT_ASM (amd64_bit_not,
+	    "xorq $0xffffffffffffffff,%rax");
+}
+
+static void
+amd64_emit_equal (void)
+{
+  EMIT_ASM (amd64_equal,
+	    "cmp %rax,(%rsp)\n\t"
+	    "je .Lamd64_equal_true\n\t"
+	    "xor %rax,%rax\n\t"
+	    "jmp .Lamd64_equal_end\n\t"
+	    ".Lamd64_equal_true:\n\t"
+	    "mov $0x1,%rax\n\t"
+	    ".Lamd64_equal_end:\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_less_signed (void)
+{
+  EMIT_ASM (amd64_less_signed,
+	    "cmp %rax,(%rsp)\n\t"
+	    "jl .Lamd64_less_signed_true\n\t"
+	    "xor %rax,%rax\n\t"
+	    "jmp .Lamd64_less_signed_end\n\t"
+	    ".Lamd64_less_signed_true:\n\t"
+	    "mov $1,%rax\n\t"
+	    ".Lamd64_less_signed_end:\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_less_unsigned (void)
+{
+  EMIT_ASM (amd64_less_unsigned,
+	    "cmp %rax,(%rsp)\n\t"
+	    "jb .Lamd64_less_unsigned_true\n\t"
+	    "xor %rax,%rax\n\t"
+	    "jmp .Lamd64_less_unsigned_end\n\t"
+	    ".Lamd64_less_unsigned_true:\n\t"
+	    "mov $1,%rax\n\t"
+	    ".Lamd64_less_unsigned_end:\n\t"
+	    "lea 0x8(%rsp),%rsp");
+}
+
+static void
+amd64_emit_ref (int size)
+{
+  switch (size)
+    {
+    case 1:
+      EMIT_ASM (amd64_ref1,
+		"movb (%rax),%al");
+      break;
+    case 2:
+      EMIT_ASM (amd64_ref2,
+		"movw (%rax),%ax");
+      break;
+    case 4:
+      EMIT_ASM (amd64_ref4,
+		"movl (%rax),%eax");
+      break;
+    case 8:
+      EMIT_ASM (amd64_ref8,
+		"movq (%rax),%rax");
+      break;
+    }
+}
+
+static void
+amd64_emit_if_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM (amd64_if_goto,
+	    "mov %rax,%rcx\n\t"
+	    "pop %rax\n\t"
+	    "cmp $0,%rcx\n\t"
+	    ".byte 0x0f, 0x85, 0x0, 0x0, 0x0, 0x0");
+  if (offset_p)
+    *offset_p = 10;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+amd64_emit_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM (amd64_goto,
+	    ".byte 0xe9, 0x0, 0x0, 0x0, 0x0");
+  if (offset_p)
+    *offset_p = 1;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+amd64_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  int diff = (to - (from + size));
+  unsigned char buf[sizeof (int)];
+
+  if (size != 4)
+    {
+      emit_error = 1;
+      return;
+    }
+
+  memcpy (buf, &diff, sizeof (int));
+  write_inferior_memory (from, buf, sizeof (int));
+}
+
+static void
+amd64_emit_const (int64_t num)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  i = 0;
+  buf[i++] = 0x48;  buf[i++] = 0xb8; /* mov $<n>,%rax */
+  *((int64_t *) (&buf[i])) = num;
+  i += 8;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+}
+
+static void
+amd64_emit_call (CORE_ADDR fn)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+  int64_t offset64;
+
+  /* The destination function being in the shared library, may be
+     >31-bits away off the compiled code pad.  */
+
+  buildaddr = current_insn_ptr;
+
+  offset64 = fn - (buildaddr + 1 /* call op */ + 4 /* 32-bit offset */);
+
+  i = 0;
+
+  if (offset64 > INT_MAX || offset64 < INT_MIN)
+    {
+      /* Offset is too large for a call.  Use callq, but that requires
+	 a register, so avoid it if possible.  Use r10, since it is
+	 call-clobbered, we don't have to push/pop it.  */
+      buf[i++] = 0x48; /* mov $fn,%r10 */
+      buf[i++] = 0xba;
+      memcpy (buf + i, &fn, 8);
+      i += 8;
+      buf[i++] = 0xff; /* callq *%r10 */
+      buf[i++] = 0xd2;
+    }
+  else
+    {
+      int offset32 = offset64; /* we know we can't overflow here.  */
+      memcpy (buf + i, &offset32, 4);
+      i += 4;
+    }
+
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+}
+
+static void
+amd64_emit_reg (int reg)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+
+  /* Assume raw_regs is still in %rdi.  */
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xbe; /* mov $<n>,%esi */
+  *((int *) (&buf[i])) = reg;
+  i += 4;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+  amd64_emit_call (get_raw_reg_func_addr ());
+}
+
+static void
+amd64_emit_pop (void)
+{
+  EMIT_ASM (amd64_pop,
+	    "pop %rax");
+}
+
+static void
+amd64_emit_stack_flush (void)
+{
+  EMIT_ASM (amd64_stack_flush,
+	    "push %rax");
+}
+
+static void
+amd64_emit_zero_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM (amd64_zero_ext_8,
+		"and $0xff,%rax");
+      break;
+    case 16:
+      EMIT_ASM (amd64_zero_ext_16,
+		"and $0xffff,%rax");
+      break;
+    case 32:
+      EMIT_ASM (amd64_zero_ext_32,
+		"mov $0xffffffff,%rcx\n\t"
+		"and %rcx,%rax");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+static void
+amd64_emit_swap (void)
+{
+  EMIT_ASM (amd64_swap,
+	    "mov %rax,%rcx\n\t"
+	    "pop %rax\n\t"
+	    "push %rcx");
+}
+
+static void
+amd64_emit_stack_adjust (int n)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  i = 0;
+  buf[i++] = 0x48; /* lea $<n>(%rsp),%rsp */
+  buf[i++] = 0x8d;
+  buf[i++] = 0x64;
+  buf[i++] = 0x24;
+  /* This only handles adjustments up to 16, but we don't expect any more.  */
+  buf[i++] = n * 8;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.  */
+
+static void
+amd64_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xbf; /* movl $<n>,%edi */
+  *((int *) (&buf[i])) = arg1;
+  i += 4;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+  amd64_emit_call (fn);
+}
+
+/* FN's prototype is `void(*fn)(int,int64_t)'.  */
+
+static void
+amd64_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xbf; /* movl $<n>,%edi */
+  *((int *) (&buf[i])) = arg1;
+  i += 4;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+  EMIT_ASM (amd64_void_call_2_a,
+	    /* Save away a copy of the stack top.  */
+	    "push %rax\n\t"
+	    /* Also pass top as the second argument.  */
+	    "mov %rax,%rsi");
+  amd64_emit_call (fn);
+  EMIT_ASM (amd64_void_call_2_b,
+	    /* Restore the stack top, %rax may have been trashed.  */
+	    "pop %rax");
+}
+
+struct emit_ops amd64_emit_ops =
+  {
+    amd64_emit_prologue,
+    amd64_emit_epilogue,
+    amd64_emit_add,
+    amd64_emit_sub,
+    amd64_emit_mul,
+    amd64_emit_lsh,
+    amd64_emit_rsh_signed,
+    amd64_emit_rsh_unsigned,
+    amd64_emit_ext,
+    amd64_emit_log_not,
+    amd64_emit_bit_and,
+    amd64_emit_bit_or,
+    amd64_emit_bit_xor,
+    amd64_emit_bit_not,
+    amd64_emit_equal,
+    amd64_emit_less_signed,
+    amd64_emit_less_unsigned,
+    amd64_emit_ref,
+    amd64_emit_if_goto,
+    amd64_emit_goto,
+    amd64_write_goto_address,
+    amd64_emit_const,
+    amd64_emit_call,
+    amd64_emit_reg,
+    amd64_emit_pop,
+    amd64_emit_stack_flush,
+    amd64_emit_zero_ext,
+    amd64_emit_swap,
+    amd64_emit_stack_adjust,
+    amd64_emit_int_call_1,
+    amd64_emit_void_call_2
+  };
+
+#endif /* __x86_64__ */
+
+static void
+i386_emit_prologue (void)
+{
+  EMIT_ASM32 (i386_prologue,
+	    "push %ebp\n\t"
+	    "mov %esp,%ebp");
+  /* At this point, the raw regs base address is at 8(%ebp), and the
+     value pointer is at 12(%ebp).  */
+}
+
+static void
+i386_emit_epilogue (void)
+{
+  EMIT_ASM32 (i386_epilogue,
+	    "mov 12(%ebp),%ecx\n\t"
+	    "mov %eax,(%ecx)\n\t"
+	    "mov %ebx,0x4(%ecx)\n\t"
+	    "xor %eax,%eax\n\t"
+	    "pop %ebp\n\t"
+	    "ret");
+}
+
+static void
+i386_emit_add (void)
+{
+  EMIT_ASM32 (i386_add,
+	    "add (%esp),%eax\n\t"
+	    "adc 0x4(%esp),%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_sub (void)
+{
+  EMIT_ASM32 (i386_sub,
+	    "subl %eax,(%esp)\n\t"
+	    "sbbl %ebx,4(%esp)\n\t"
+	    "pop %eax\n\t"
+	    "pop %ebx\n\t");
+}
+
+static void
+i386_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+static void
+i386_emit_lsh (void)
+{
+  emit_error = 1;
+}
+
+static void
+i386_emit_rsh_signed (void)
+{
+  emit_error = 1;
+}
+
+static void
+i386_emit_rsh_unsigned (void)
+{
+  emit_error = 1;
+}
+
+static void
+i386_emit_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM32 (i386_ext_8,
+		"cbtw\n\t"
+		"cwtl\n\t"
+		"movl %eax,%ebx\n\t"
+		"sarl $31,%ebx");
+      break;
+    case 16:
+      EMIT_ASM32 (i386_ext_16,
+		"cwtl\n\t"
+		"movl %eax,%ebx\n\t"
+		"sarl $31,%ebx");
+      break;
+    case 32:
+      EMIT_ASM32 (i386_ext_32,
+		"movl %eax,%ebx\n\t"
+		"sarl $31,%ebx");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+static void
+i386_emit_log_not (void)
+{
+  EMIT_ASM32 (i386_log_not,
+	    "or %ebx,%eax\n\t"
+	    "test %eax,%eax\n\t"
+	    "sete %cl\n\t"
+	    "xor %ebx,%ebx\n\t"
+	    "movzbl %cl,%eax");
+}
+
+static void
+i386_emit_bit_and (void)
+{
+  EMIT_ASM32 (i386_and,
+	    "and (%esp),%eax\n\t"
+	    "and 0x4(%esp),%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_bit_or (void)
+{
+  EMIT_ASM32 (i386_or,
+	    "or (%esp),%eax\n\t"
+	    "or 0x4(%esp),%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_bit_xor (void)
+{
+  EMIT_ASM32 (i386_xor,
+	    "xor (%esp),%eax\n\t"
+	    "xor 0x4(%esp),%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_bit_not (void)
+{
+  EMIT_ASM32 (i386_bit_not,
+	    "xor $0xffffffff,%eax\n\t"
+	    "xor $0xffffffff,%ebx\n\t");
+}
+
+static void
+i386_emit_equal (void)
+{
+  EMIT_ASM32 (i386_equal,
+	    "cmpl %ebx,4(%esp)\n\t"
+	    "jne .Li386_equal_false\n\t"
+	    "cmpl %eax,(%esp)\n\t"
+	    "je .Li386_equal_true\n\t"
+	    ".Li386_equal_false:\n\t"
+	    "xor %eax,%eax\n\t"
+	    "jmp .Li386_equal_end\n\t"
+	    ".Li386_equal_true:\n\t"
+	    "mov $1,%eax\n\t"
+	    ".Li386_equal_end:\n\t"
+	    "xor %ebx,%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_less_signed (void)
+{
+  EMIT_ASM32 (i386_less_signed,
+	    "cmpl %ebx,4(%esp)\n\t"
+	    "jl .Li386_less_signed_true\n\t"
+	    "jne .Li386_less_signed_false\n\t"
+	    "cmpl %eax,(%esp)\n\t"
+	    "jl .Li386_less_signed_true\n\t"
+	    ".Li386_less_signed_false:\n\t"
+	    "xor %eax,%eax\n\t"
+	    "jmp .Li386_less_signed_end\n\t"
+	    ".Li386_less_signed_true:\n\t"
+	    "mov $1,%eax\n\t"
+	    ".Li386_less_signed_end:\n\t"
+	    "xor %ebx,%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_less_unsigned (void)
+{
+  EMIT_ASM32 (i386_less_unsigned,
+	    "cmpl %ebx,4(%esp)\n\t"
+	    "jb .Li386_less_unsigned_true\n\t"
+	    "jne .Li386_less_unsigned_false\n\t"
+	    "cmpl %eax,(%esp)\n\t"
+	    "jb .Li386_less_unsigned_true\n\t"
+	    ".Li386_less_unsigned_false:\n\t"
+	    "xor %eax,%eax\n\t"
+	    "jmp .Li386_less_unsigned_end\n\t"
+	    ".Li386_less_unsigned_true:\n\t"
+	    "mov $1,%eax\n\t"
+	    ".Li386_less_unsigned_end:\n\t"
+	    "xor %ebx,%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_ref (int size)
+{
+  switch (size)
+    {
+    case 1:
+      EMIT_ASM32 (i386_ref1,
+		"movb (%eax),%al");
+      break;
+    case 2:
+      EMIT_ASM32 (i386_ref2,
+		"movw (%eax),%ax");
+      break;
+    case 4:
+      EMIT_ASM32 (i386_ref4,
+		"movl (%eax),%eax");
+      break;
+    case 8:
+      EMIT_ASM32 (i386_ref8,
+		"movl 4(%eax),%ebx\n\t"
+		"movl (%eax),%eax");
+      break;
+    }
+}
+
+static void
+i386_emit_if_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM32 (i386_if_goto,
+	    "mov %eax,%ecx\n\t"
+	    "or %ebx,%ecx\n\t"
+	    "pop %eax\n\t"
+	    "pop %ebx\n\t"
+	    "cmpl $0,%ecx\n\t"
+	    /* Don't trust the assembler to choose the right jump */
+	    ".byte 0x0f, 0x85, 0x0, 0x0, 0x0, 0x0");
+
+  if (offset_p)
+    *offset_p = 11; /* be sure that this matches the sequence above */
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+i386_emit_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM32 (i386_goto,
+	    /* Don't trust the assembler to choose the right jump */
+	    ".byte 0xe9, 0x0, 0x0, 0x0, 0x0");
+  if (offset_p)
+    *offset_p = 1;
+  if (size_p)
+    *size_p = 4;
+}
+
+static void
+i386_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  int diff = (to - (from + size));
+  unsigned char buf[sizeof (int)];
+
+  /* We're only doing 4-byte sizes at the moment.  */
+  if (size != 4)
+    {
+      emit_error = 1;
+      return;
+    }
+
+  memcpy (buf, &diff, sizeof (int));
+  write_inferior_memory (from, buf, sizeof (int));
+}
+
+static void
+i386_emit_const (int64_t num)
+{
+  unsigned char buf[16];
+  int i, hi;
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  i = 0;
+  buf[i++] = 0xb8; /* mov $<n>,%eax */
+  *((int *) (&buf[i])) = (num & 0xffffffff);
+  i += 4;
+  hi = ((num >> 32) & 0xffffffff);
+  if (hi)
+    {
+      buf[i++] = 0xbb; /* mov $<n>,%ebx */
+      *((int *) (&buf[i])) = hi;
+      i += 4;
+    }
+  else
+    {
+      buf[i++] = 0x31; buf[i++] = 0xdb; /* xor %ebx,%ebx */
+    }
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+}
+
+static void
+i386_emit_call (CORE_ADDR fn)
+{
+  unsigned char buf[16];
+  int i, offset;
+  CORE_ADDR buildaddr;
+
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xe8; /* call <reladdr> */
+  offset = ((int) fn) - (buildaddr + 5);
+  memcpy (buf + 1, &offset, 4);
+  append_insns (&buildaddr, 5, buf);
+  current_insn_ptr = buildaddr;
+}
+
+static void
+i386_emit_reg (int reg)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+
+  EMIT_ASM32 (i386_reg_a,
+	    "sub $0x8,%esp");
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xb8; /* mov $<n>,%eax */
+  *((int *) (&buf[i])) = reg;
+  i += 4;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+  EMIT_ASM32 (i386_reg_b,
+	    "mov %eax,4(%esp)\n\t"
+	    "mov 8(%ebp),%eax\n\t"
+	    "mov %eax,(%esp)");
+  i386_emit_call (get_raw_reg_func_addr ());
+  EMIT_ASM32 (i386_reg_c,
+	    "xor %ebx,%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+static void
+i386_emit_pop (void)
+{
+  EMIT_ASM32 (i386_pop,
+	    "pop %eax\n\t"
+	    "pop %ebx");
+}
+
+static void
+i386_emit_stack_flush (void)
+{
+  EMIT_ASM32 (i386_stack_flush,
+	    "push %ebx\n\t"
+	    "push %eax");
+}
+
+static void
+i386_emit_zero_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM32 (i386_zero_ext_8,
+		"and $0xff,%eax\n\t"
+		"xor %ebx,%ebx");
+      break;
+    case 16:
+      EMIT_ASM32 (i386_zero_ext_16,
+		"and $0xffff,%eax\n\t"
+		"xor %ebx,%ebx");
+      break;
+    case 32:
+      EMIT_ASM32 (i386_zero_ext_32,
+		"xor %ebx,%ebx");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+static void
+i386_emit_swap (void)
+{
+  EMIT_ASM32 (i386_swap,
+	    "mov %eax,%ecx\n\t"
+	    "mov %ebx,%edx\n\t"
+	    "pop %eax\n\t"
+	    "pop %ebx\n\t"
+	    "push %edx\n\t"
+	    "push %ecx");
+}
+
+static void
+i386_emit_stack_adjust (int n)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  i = 0;
+  buf[i++] = 0x8d; /* lea $<n>(%esp),%esp */
+  buf[i++] = 0x64;
+  buf[i++] = 0x24;
+  buf[i++] = n * 8;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.  */
+
+static void
+i386_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+
+  EMIT_ASM32 (i386_int_call_1_a,
+	    /* Reserve a bit of stack space.  */
+	    "sub $0x8,%esp");
+  /* Put the one argument on the stack.  */
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xc7;  /* movl $<arg1>,(%esp) */
+  buf[i++] = 0x04;
+  buf[i++] = 0x24;
+  *((int *) (&buf[i])) = arg1;
+  i += 4;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+  i386_emit_call (fn);
+  EMIT_ASM32 (i386_int_call_1_c,
+	    "mov %edx,%ebx\n\t"
+	    "lea 0x8(%esp),%esp");
+}
+
+/* FN's prototype is `void(*fn)(int,int64_t)'.  */
+
+static void
+i386_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  unsigned char buf[16];
+  int i;
+  CORE_ADDR buildaddr;
+
+  EMIT_ASM32 (i386_void_call_2_a,
+	    /* Preserve %eax only; we don't have to worry about %ebx.  */
+	    "push %eax\n\t"
+	    /* Reserve a bit of stack space for arguments.  */
+	    "sub $0x10,%esp\n\t"
+	    /* Copy "top" to the second argument position.  (Note that
+	       we can't assume function won't scribble on its
+	       arguments, so don't try to restore from this.)  */
+	    "mov %eax,4(%esp)\n\t"
+	    "mov %ebx,8(%esp)");
+  /* Put the first argument on the stack.  */
+  buildaddr = current_insn_ptr;
+  i = 0;
+  buf[i++] = 0xc7;  /* movl $<arg1>,(%esp) */
+  buf[i++] = 0x04;
+  buf[i++] = 0x24;
+  *((int *) (&buf[i])) = arg1;
+  i += 4;
+  append_insns (&buildaddr, i, buf);
+  current_insn_ptr = buildaddr;
+  i386_emit_call (fn);
+  EMIT_ASM32 (i386_void_call_2_b,
+	    "lea 0x10(%esp),%esp\n\t"
+	    /* Restore original stack top.  */
+	    "pop %eax");
+}
+
+struct emit_ops i386_emit_ops =
+  {
+    i386_emit_prologue,
+    i386_emit_epilogue,
+    i386_emit_add,
+    i386_emit_sub,
+    i386_emit_mul,
+    i386_emit_lsh,
+    i386_emit_rsh_signed,
+    i386_emit_rsh_unsigned,
+    i386_emit_ext,
+    i386_emit_log_not,
+    i386_emit_bit_and,
+    i386_emit_bit_or,
+    i386_emit_bit_xor,
+    i386_emit_bit_not,
+    i386_emit_equal,
+    i386_emit_less_signed,
+    i386_emit_less_unsigned,
+    i386_emit_ref,
+    i386_emit_if_goto,
+    i386_emit_goto,
+    i386_write_goto_address,
+    i386_emit_const,
+    i386_emit_call,
+    i386_emit_reg,
+    i386_emit_pop,
+    i386_emit_stack_flush,
+    i386_emit_zero_ext,
+    i386_emit_swap,
+    i386_emit_stack_adjust,
+    i386_emit_int_call_1,
+    i386_emit_void_call_2
+  };
+
+
+static struct emit_ops *
+x86_emit_ops (void)
+{
+#ifdef __x86_64__
+  int use_64bit = register_size (0) == 8;
+
+  if (use_64bit)
+    return &amd64_emit_ops;
+  else
+#endif
+    return &i386_emit_ops;
+}
+
 /* This is initialized assuming an amd64 target.
    x86_arch_setup will correct it for i386 or amd64 targets.  */
 
@@ -1504,5 +2533,6 @@ struct linux_target_ops the_low_target =
   x86_linux_process_qsupported,
   x86_supports_tracepoints,
   x86_get_thread_area,
-  x86_install_fast_tracepoint_jump_pad
+  x86_install_fast_tracepoint_jump_pad,
+  x86_emit_ops
 };
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/server.h	2010-06-07 16:13:24.000000000 +0100
@@ -573,6 +573,56 @@ void supply_fast_tracepoint_registers (s
 void stop_tracing (void);
 #endif
 
+/* Bytecode compilation function vector.  */
+
+struct emit_ops
+{
+  void (*emit_prologue) (void);
+  void (*emit_epilogue) (void);
+  void (*emit_add) (void);
+  void (*emit_sub) (void);
+  void (*emit_mul) (void);
+  void (*emit_lsh) (void);
+  void (*emit_rsh_signed) (void);
+  void (*emit_rsh_unsigned) (void);
+  void (*emit_ext) (int arg);
+  void (*emit_log_not) (void);
+  void (*emit_bit_and) (void);
+  void (*emit_bit_or) (void);
+  void (*emit_bit_xor) (void);
+  void (*emit_bit_not) (void);
+  void (*emit_equal) (void);
+  void (*emit_less_signed) (void);
+  void (*emit_less_unsigned) (void);
+  void (*emit_ref) (int size);
+  void (*emit_if_goto) (int *offset_p, int *size_p);
+  void (*emit_goto) (int *offset_p, int *size_p);
+  void (*write_goto_address) (CORE_ADDR from, CORE_ADDR to, int size);
+  void (*emit_const) (int64_t num);
+  void (*emit_call) (CORE_ADDR fn);
+  void (*emit_reg) (int reg);
+  void (*emit_pop) (void);
+  void (*emit_stack_flush) (void);
+  void (*emit_zero_ext) (int arg);
+  void (*emit_swap) (void);
+  void (*emit_stack_adjust) (int n);
+
+  /* Emit code for a generic function that takes one fixed integer
+     argument and returns a 64-bit int (for instance, tsv getter).  */
+  void (*emit_int_call_1) (CORE_ADDR fn, int arg1);
+
+  /* Emit code for a generic function that takes one fixed integer
+     argument and a 64-bit int from the top of the stack, and returns
+     nothing (for instance, tsv setter).  */
+  void (*emit_void_call_2) (CORE_ADDR fn, int arg1);
+};
+
+/* Returns the address of the get_raw_reg function in the IPA.  */
+CORE_ADDR get_raw_reg_func_addr (void);
+
+CORE_ADDR current_insn_ptr;
+int emit_error;
+
 /* Version information, from version.c.  */
 extern const char version[];
 extern const char host_name[];
Index: src/gdb/gdbserver/tracepoint.c
===================================================================
--- src.orig/gdb/gdbserver/tracepoint.c	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/tracepoint.c	2010-06-07 16:42:28.000000000 +0100
@@ -132,6 +132,9 @@ trace_vdebug (const char *fmt, ...)
 # define traceframe_write_count gdb_agent_traceframe_write_count
 # define traceframes_created gdb_agent_traceframes_created
 # define trace_state_variables gdb_agent_trace_state_variables
+# define get_raw_reg gdb_agent_get_raw_reg
+# define get_trace_state_variable_value gdb_agent_get_trace_state_variable_value
+# define set_trace_state_variable_value gdb_agent_set_trace_state_variable_value
 #endif
 
 #ifndef IN_PROCESS_AGENT
@@ -162,6 +165,9 @@ struct ipa_sym_addresses
   CORE_ADDR addr_traceframe_write_count;
   CORE_ADDR addr_traceframes_created;
   CORE_ADDR addr_trace_state_variables;
+  CORE_ADDR addr_get_raw_reg;
+  CORE_ADDR addr_get_trace_state_variable_value;
+  CORE_ADDR addr_set_trace_state_variable_value;
 };
 
 #define STRINGIZE_1(STR) #STR
@@ -200,6 +206,9 @@ static struct
   IPA_SYM(traceframe_write_count),
   IPA_SYM(traceframes_created),
   IPA_SYM(trace_state_variables),
+  IPA_SYM(get_raw_reg),
+  IPA_SYM(get_trace_state_variable_value),
+  IPA_SYM(set_trace_state_variable_value),
 };
 
 struct ipa_sym_addresses ipa_sym_addrs;
@@ -564,6 +573,9 @@ enum tracepoint_type
 
 struct tracepoint_hit_ctx;
 
+typedef enum eval_result_type (*condfn) (struct tracepoint_hit_ctx *,
+					 ULONGEST *);
+
 /* The definition of a tracepoint.  */
 
 /* Tracepoints may have multiple locations, each at a different
@@ -612,6 +624,8 @@ struct tracepoint
      Note that while-stepping steps are not counted as "hits".  */
   long hit_count;
 
+  CORE_ADDR compiled_cond;
+
   /* Link to the next tracepoint in the list.  */
   struct tracepoint *next;
 
@@ -1189,6 +1203,8 @@ static void collect_data_at_tracepoint (
 static void collect_data_at_step (struct tracepoint_hit_ctx *ctx,
 				  CORE_ADDR stop_pc,
 				  struct tracepoint *tpoint, int current_step);
+static void compile_tracepoint_condition (struct tracepoint *tpoint,
+					  CORE_ADDR *jump_entry);
 #endif
 static void do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
 				     CORE_ADDR stop_pc,
@@ -1610,6 +1626,7 @@ add_tracepoint (int num, CORE_ADDR addr)
   tpoint->type = trap_tracepoint;
   tpoint->orig_size = -1;
   tpoint->source_strings = NULL;
+  tpoint->compiled_cond = 0;
   tpoint->handle = NULL;
   tpoint->next = NULL;
 
@@ -1854,7 +1871,7 @@ create_trace_state_variable (int num, in
   return tsv;
 }
 
-static LONGEST
+IP_AGENT_EXPORT LONGEST
 get_trace_state_variable_value (int num)
 {
   struct trace_state_variable *tsv;
@@ -1880,7 +1897,7 @@ get_trace_state_variable_value (int num)
   return tsv->value;
 }
 
-static void
+IP_AGENT_EXPORT void
 set_trace_state_variable_value (int num, LONGEST val)
 {
   struct trace_state_variable *tsv;
@@ -3906,7 +3923,10 @@ condition_true_at_tracepoint (struct tra
   ULONGEST value = 0;
   enum eval_result_type err;
 
-  err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
+  if (tpoint->compiled_cond)
+    err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
+  else
+    err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
 
   if (err != expr_eval_no_error)
     {
@@ -4944,6 +4964,582 @@ gdb_collect (struct tracepoint *tpoint, 
 
 #ifndef IN_PROCESS_AGENT
 
+/* Bytecode compilation.  */
+
+CORE_ADDR current_insn_ptr;
+
+int emit_error;
+
+struct bytecode_address
+{
+  int pc;
+  CORE_ADDR address;
+  int goto_pc;
+  /* Offset and size of field to be modified in the goto block.  */
+  int from_offset, from_size;
+  struct bytecode_address *next;
+} *bytecode_address_table;
+
+CORE_ADDR
+get_raw_reg_func_addr (void)
+{
+  return ipa_sym_addrs.addr_get_raw_reg;
+}
+
+static void
+emit_prologue (void)
+{
+  target_emit_ops ()->emit_prologue ();
+}
+
+static void
+emit_epilogue (void)
+{
+  target_emit_ops ()->emit_epilogue ();
+}
+
+static void
+emit_add (void)
+{
+  target_emit_ops ()->emit_add ();
+}
+
+static void
+emit_sub (void)
+{
+  target_emit_ops ()->emit_sub ();
+}
+
+static void
+emit_mul (void)
+{
+  target_emit_ops ()->emit_mul ();
+}
+
+static void
+emit_lsh (void)
+{
+  target_emit_ops ()->emit_lsh ();
+}
+
+static void
+emit_rsh_signed (void)
+{
+  target_emit_ops ()->emit_rsh_signed ();
+}
+
+static void
+emit_rsh_unsigned (void)
+{
+  target_emit_ops ()->emit_rsh_unsigned ();
+}
+
+static void
+emit_ext (int arg)
+{
+  target_emit_ops ()->emit_ext (arg);
+}
+
+static void
+emit_log_not (void)
+{
+  target_emit_ops ()->emit_log_not ();
+}
+
+static void
+emit_bit_and (void)
+{
+  target_emit_ops ()->emit_bit_and ();
+}
+
+static void
+emit_bit_or (void)
+{
+  target_emit_ops ()->emit_bit_or ();
+}
+
+static void
+emit_bit_xor (void)
+{
+  target_emit_ops ()->emit_bit_xor ();
+}
+
+static void
+emit_bit_not (void)
+{
+  target_emit_ops ()->emit_bit_not ();
+}
+
+static void
+emit_equal (void)
+{
+  target_emit_ops ()->emit_equal ();
+}
+
+static void
+emit_less_signed (void)
+{
+  target_emit_ops ()->emit_less_signed ();
+}
+
+static void
+emit_less_unsigned (void)
+{
+  target_emit_ops ()->emit_less_unsigned ();
+}
+
+static void
+emit_ref (int size)
+{
+  target_emit_ops ()->emit_ref (size);
+}
+
+static void
+emit_if_goto (int *offset_p, int *size_p)
+{
+  target_emit_ops ()->emit_if_goto (offset_p, size_p);
+}
+
+static void
+emit_goto (int *offset_p, int *size_p)
+{
+  target_emit_ops ()->emit_goto (offset_p, size_p);
+}
+
+static void
+write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  target_emit_ops ()->write_goto_address (from, to, size);
+}
+
+static void
+emit_const (int64_t num)
+{
+  target_emit_ops ()->emit_const (num);
+}
+
+static void
+emit_reg (int reg)
+{
+  target_emit_ops ()->emit_reg (reg);
+}
+
+static void
+emit_pop (void)
+{
+  target_emit_ops ()->emit_pop ();
+}
+
+static void
+emit_stack_flush (void)
+{
+  target_emit_ops ()->emit_stack_flush ();
+}
+
+static void
+emit_zero_ext (int arg)
+{
+  target_emit_ops ()->emit_zero_ext (arg);
+}
+
+static void
+emit_swap (void)
+{
+  target_emit_ops ()->emit_swap ();
+}
+
+static void
+emit_stack_adjust (int n)
+{
+  target_emit_ops ()->emit_stack_adjust (n);
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.  */
+
+static void
+emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  target_emit_ops ()->emit_int_call_1 (fn, arg1);
+}
+
+/* FN's prototype is `void(*fn)(int,int64_t)'.  */
+
+static void
+emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  target_emit_ops ()->emit_void_call_2 (fn, arg1);
+}
+
+static enum eval_result_type compile_bytecodes (struct agent_expr *aexpr);
+
+static void
+compile_tracepoint_condition (struct tracepoint *tpoint, CORE_ADDR *jump_entry)
+{
+  CORE_ADDR entry_point = *jump_entry;
+  enum eval_result_type err;
+
+  trace_debug ("Starting condition compilation for tracepoint %d\n",
+	       tpoint->number);
+
+  /* Initialize the global pointer to the code being built.  */
+  current_insn_ptr = *jump_entry;
+
+  emit_prologue ();
+
+  err = compile_bytecodes (tpoint->cond);
+
+  if (err == expr_eval_no_error)
+    {
+      emit_epilogue ();
+
+      /* Record the beginning of the compiled code.  */
+      tpoint->compiled_cond = entry_point;
+
+      trace_debug ("Condition compilation for tracepoint %d complete\n",
+		   tpoint->number);
+    }
+  else
+    {
+      /* Leave the unfinished code in situ, but don't point to it.  */
+
+      tpoint->compiled_cond = 0;
+
+      trace_debug ("Condition compilation for tracepoint %d failed, "
+		   "error code %d",
+		   tpoint->number, err);
+    }
+
+  /* Update the code pointer passed in.  Note that we do this even if
+     the compile fails, so that we can look at the partial results
+     instead of letting them be overwritten.  */
+  *jump_entry = current_insn_ptr;
+
+  /* Leave a gap, to aid dump decipherment.  */
+  *jump_entry += 16;
+}
+
+/* Given an agent expression, turn it into native code.  */
+
+static enum eval_result_type
+compile_bytecodes (struct agent_expr *aexpr)
+{
+  int pc = 0;
+  int done = 0;
+  unsigned char op;
+  int arg;
+  /* This is only used to build 64-bit value for constants.  */
+  ULONGEST top;
+  struct bytecode_address *aentry, *aentry2;
+
+#define UNHANDLED					\
+  do							\
+    {							\
+      trace_debug ("Cannot compile op 0x%x\n", op);	\
+      return expr_eval_unhandled_opcode;		\
+    } while (0)
+
+  if (aexpr->length == 0)
+    {
+      trace_debug ("empty agent expression\n");
+      return expr_eval_empty_expression;
+    }
+
+  bytecode_address_table = NULL;
+
+  while (!done)
+    {
+      op = aexpr->bytes[pc];
+
+      trace_debug ("About to compile op 0x%x, pc=%d\n", op, pc);
+
+      /* Record the compiled-code address of the bytecode, for use by
+	 jump instructions.  */
+      aentry = xmalloc (sizeof (struct bytecode_address));
+      aentry->pc = pc;
+      aentry->address = current_insn_ptr;
+      aentry->goto_pc = -1;
+      aentry->from_offset = aentry->from_size = 0;
+      aentry->next = bytecode_address_table;
+      bytecode_address_table = aentry;
+
+      ++pc;
+
+      emit_error = 0;
+
+      switch (op)
+	{
+	case gdb_agent_op_add:
+	  emit_add ();
+	  break;
+
+	case gdb_agent_op_sub:
+	  emit_sub ();
+	  break;
+
+	case gdb_agent_op_mul:
+	  emit_mul ();
+	  break;
+
+	case gdb_agent_op_div_signed:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_div_unsigned:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_rem_signed:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_rem_unsigned:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_lsh:
+	  emit_lsh ();
+	  break;
+
+	case gdb_agent_op_rsh_signed:
+	  emit_rsh_signed ();
+	  break;
+
+	case gdb_agent_op_rsh_unsigned:
+	  emit_rsh_unsigned ();
+	  break;
+
+	case gdb_agent_op_trace:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_trace_quick:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_log_not:
+	  emit_log_not ();
+	  break;
+
+	case gdb_agent_op_bit_and:
+	  emit_bit_and ();
+	  break;
+
+	case gdb_agent_op_bit_or:
+	  emit_bit_or ();
+	  break;
+
+	case gdb_agent_op_bit_xor:
+	  emit_bit_xor ();
+	  break;
+
+	case gdb_agent_op_bit_not:
+	  emit_bit_not ();
+	  break;
+
+	case gdb_agent_op_equal:
+	  emit_equal ();
+	  break;
+
+	case gdb_agent_op_less_signed:
+	  emit_less_signed ();
+	  break;
+
+	case gdb_agent_op_less_unsigned:
+	  emit_less_unsigned ();
+	  break;
+
+	case gdb_agent_op_ext:
+	  arg = aexpr->bytes[pc++];
+	  if (arg < (sizeof (LONGEST) * 8))
+	    emit_ext (arg);
+	  break;
+
+	case gdb_agent_op_ref8:
+	  emit_ref (1);
+	  break;
+
+	case gdb_agent_op_ref16:
+	  emit_ref (2);
+	  break;
+
+	case gdb_agent_op_ref32:
+	  emit_ref (4);
+	  break;
+
+	case gdb_agent_op_ref64:
+	  emit_ref (8);
+	  break;
+
+	case gdb_agent_op_if_goto:
+	  arg = aexpr->bytes[pc++];
+	  arg = (arg << 8) + aexpr->bytes[pc++];
+	  aentry->goto_pc = arg;
+	  emit_if_goto (&(aentry->from_offset), &(aentry->from_size));
+	  break;
+
+	case gdb_agent_op_goto:
+	  arg = aexpr->bytes[pc++];
+	  arg = (arg << 8) + aexpr->bytes[pc++];
+	  aentry->goto_pc = arg;
+	  emit_goto (&(aentry->from_offset), &(aentry->from_size));
+	  break;
+
+	case gdb_agent_op_const8:
+	  emit_stack_flush ();
+	  top = aexpr->bytes[pc++];
+	  emit_const (top);
+	  break;
+
+	case gdb_agent_op_const16:
+	  emit_stack_flush ();
+	  top = aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  emit_const (top);
+	  break;
+
+	case gdb_agent_op_const32:
+	  emit_stack_flush ();
+	  top = aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  emit_const (top);
+	  break;
+
+	case gdb_agent_op_const64:
+	  emit_stack_flush ();
+	  top = aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  top = (top << 8) + aexpr->bytes[pc++];
+	  emit_const (top);
+	  break;
+
+	case gdb_agent_op_reg:
+	  emit_stack_flush ();
+	  arg = aexpr->bytes[pc++];
+	  arg = (arg << 8) + aexpr->bytes[pc++];
+	  emit_reg (arg);
+	  break;
+
+	case gdb_agent_op_end:
+	  trace_debug ("At end of expression\n");
+
+	  /* Assume there is one stack element left, and that it is
+	     cached in "top" where emit_epilogue can get to it.  */
+	  emit_stack_adjust (1);
+
+	  done = 1;
+	  break;
+
+	case gdb_agent_op_dup:
+	  /* In our design, dup is equivalent to stack flushing.  */
+	  emit_stack_flush ();
+	  break;
+
+	case gdb_agent_op_pop:
+	  emit_pop ();
+	  break;
+
+	case gdb_agent_op_zero_ext:
+	  arg = aexpr->bytes[pc++];
+	  if (arg < (sizeof (LONGEST) * 8))
+	    emit_zero_ext (arg);
+	  break;
+
+	case gdb_agent_op_swap:
+	  emit_swap ();
+	  break;
+
+	case gdb_agent_op_getv:
+	  emit_stack_flush ();
+	  arg = aexpr->bytes[pc++];
+	  arg = (arg << 8) + aexpr->bytes[pc++];
+	  emit_int_call_1 (ipa_sym_addrs.addr_get_trace_state_variable_value,
+			   arg);
+	  break;
+
+	case gdb_agent_op_setv:
+	  arg = aexpr->bytes[pc++];
+	  arg = (arg << 8) + aexpr->bytes[pc++];
+	  emit_void_call_2 (ipa_sym_addrs.addr_set_trace_state_variable_value,
+			    arg);
+	  break;
+
+	case gdb_agent_op_tracev:
+	  UNHANDLED;
+	  break;
+
+	  /* GDB never (currently) generates any of these ops.  */
+	case gdb_agent_op_float:
+	case gdb_agent_op_ref_float:
+	case gdb_agent_op_ref_double:
+	case gdb_agent_op_ref_long_double:
+	case gdb_agent_op_l_to_d:
+	case gdb_agent_op_d_to_l:
+	case gdb_agent_op_trace16:
+	  UNHANDLED;
+	  break;
+
+	default:
+	  trace_debug ("Agent expression op 0x%x not recognized\n", op);
+	  /* Don't struggle on, things will just get worse.  */
+	  return expr_eval_unrecognized_opcode;
+	}
+
+      /* This catches errors that occur in target-specific code
+	 emission.  */
+      if (emit_error)
+	{
+	  trace_debug ("Error %d while emitting code for %s\n",
+		       emit_error, gdb_agent_op_names[op]);
+	  return expr_eval_unhandled_opcode;
+	}
+
+      trace_debug ("Op %s compiled\n", gdb_agent_op_names[op]);
+    }
+
+  /* Now fill in real addresses as goto destinations.  */
+  for (aentry = bytecode_address_table; aentry; aentry = aentry->next)
+    {
+      int written = 0;
+
+      if (aentry->goto_pc < 0)
+	continue;
+
+      /* Find the location that we are going to, and call back into
+	 target-specific code to write the actual address or
+	 displacement.  */
+      for (aentry2 = bytecode_address_table; aentry2; aentry2 = aentry2->next)
+	{
+	  if (aentry2->pc == aentry->goto_pc)
+	    {
+	      trace_debug ("Want to jump from %s to %s\n",
+			   paddress (aentry->address),
+			   paddress (aentry2->address));
+	      write_goto_address (aentry->address + aentry->from_offset,
+				  aentry2->address, aentry->from_size);
+	      written = 1;
+	      break;
+	    }
+	}
+
+      /* Error out if we didn't find a destination.  */
+      if (!written)
+	{
+	  trace_debug ("Destination of goto %d not found\n",
+		       aentry->goto_pc);
+	  return expr_eval_invalid_goto;
+	}
+    }
+
+  return expr_eval_no_error;
+}
+
 /* We'll need to adjust these when we consider bi-arch setups, and big
    endian machines.  */
 
@@ -5022,6 +5618,28 @@ download_tracepoints (void)
       if (tpoint->type != fast_tracepoint)
 	continue;
 
+      /* Maybe download a compiled condition.  */
+      if (tpoint->cond != NULL && target_emit_ops() != NULL)
+	{
+	  CORE_ADDR jentry, jump_entry;
+
+	  jentry = jump_entry = get_jump_space_head ();
+
+	  if (tpoint->cond != NULL)
+	    {
+	      /* Pad to 8-byte alignment. (needed?)  */
+	      /* Actually this should be left for the target to
+		 decide.  */
+	      jentry = UALIGN (jentry, 8);
+
+	      compile_tracepoint_condition (tpoint, &jentry);
+	    }
+
+	  /* Pad to 8-byte alignment.  */
+	  jentry = UALIGN (jentry, 8);
+	  claim_jump_space (jentry - jump_entry);
+	}
+
       target_tracepoint = *tpoint;
 
       prev_tpptr = tpptr;
Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/target.h	2010-06-07 16:13:24.000000000 +0100
@@ -22,6 +22,8 @@
 #ifndef TARGET_H
 #define TARGET_H
 
+struct emit_ops;
+
 /* Ways to "resume" a thread.  */
 
 enum resume_kind
@@ -349,6 +351,10 @@ struct target_ops
 					   ULONGEST *jjump_pad_insn_size,
 					   CORE_ADDR *adjusted_insn_addr,
 					   CORE_ADDR *adjusted_insn_addr_end);
+
+  /* Return the bytecode operations vector for the current inferior.
+     Returns NULL if bytecode compilation is not supported.  */
+  struct emit_ops *(*emit_ops) (void);
 };
 
 extern struct target_ops *the_target;
@@ -452,6 +458,8 @@ void set_target_ops (struct target_ops *
 						   adjusted_insn_addr,	\
 						   adjusted_insn_addr_end)
 
+#define target_emit_ops() (*the_target->emit_ops) ()
+
 /* Start non-stop mode, returns 0 on success, -1 on failure.   */
 
 int start_non_stop (int nonstop);
Index: src/gdb/gdbserver/linux-amd64-ipa.c
===================================================================
--- src.orig/gdb/gdbserver/linux-amd64-ipa.c	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/linux-amd64-ipa.c	2010-06-07 16:13:24.000000000 +0100
@@ -66,6 +66,15 @@ supply_fast_tracepoint_registers (struct
 		     ((char *) buf) + x86_64_ft_collect_regmap[i]);
 }
 
+ULONGEST __attribute__ ((visibility("default"), used))
+gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
+{
+  if (regnum > X86_64_NUM_FT_COLLECT_GREGS)
+    return 0;
+
+  return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
+}
+
 /* This is only needed because reg-i386-linux-lib.o references it.  We
    may use it proper at some point.  */
 const char *gdbserver_xmltarget;
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/linux-low.c	2010-06-07 16:13:24.000000000 +0100
@@ -5054,6 +5054,15 @@ linux_install_fast_tracepoint_jump_pad (
      adjusted_insn_addr, adjusted_insn_addr_end);
 }
 
+static struct emit_ops *
+linux_emit_ops (void)
+{
+  if (the_low_target.emit_ops != NULL)
+    return (*the_low_target.emit_ops) ();
+  else
+    return NULL;
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -5109,7 +5118,8 @@ static struct target_ops linux_target_op
   linux_unpause_all,
   linux_cancel_breakpoints,
   linux_stabilize_threads,
-  linux_install_fast_tracepoint_jump_pad
+  linux_install_fast_tracepoint_jump_pad,
+  linux_emit_ops
 };
 
 static void
Index: src/gdb/gdbserver/linux-low.h
===================================================================
--- src.orig/gdb/gdbserver/linux-low.h	2010-06-07 16:13:07.000000000 +0100
+++ src/gdb/gdbserver/linux-low.h	2010-06-07 16:13:24.000000000 +0100
@@ -136,6 +136,10 @@ struct linux_target_ops
 					   ULONGEST *jjump_pad_insn_size,
 					   CORE_ADDR *adjusted_insn_addr,
 					   CORE_ADDR *adjusted_insn_addr_end);
+
+  /* Return the bytecode operations vector for the current inferior.
+     Returns NULL if bytecode compilation is not supported.  */
+  struct emit_ops *(*emit_ops) (void);
 };
 
 extern struct linux_target_ops the_low_target;
Index: src/gdb/gdbserver/linux-i386-ipa.c
===================================================================
--- src.orig/gdb/gdbserver/linux-i386-ipa.c	2010-06-07 16:43:41.000000000 +0100
+++ src/gdb/gdbserver/linux-i386-ipa.c	2010-06-07 16:44:45.000000000 +0100
@@ -95,6 +95,21 @@ supply_fast_tracepoint_registers (struct
     }
 }
 
+ULONGEST __attribute__ ((visibility("default"), used))
+gdb_agent_get_raw_reg (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,
+     or something.  */
+
+  if (regnum > i386_num_regs)
+    return 0;
+  else if (regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM)
+    return *(short *) (raw_regs + i386_ft_collect_regmap[regnum]);
+  else
+    return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
+}
+
 /* This is only needed because reg-i386-linux-lib.o references it.  We
    may use it proper at some point.  */
 const char *gdbserver_xmltarget;

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-07 16:00 [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints) Pedro Alves
@ 2010-06-07 16:04 ` Michael Snyder
  2010-06-07 16:35   ` Joel Brobecker
  2010-06-10 17:28 ` Tom Tromey
  1 sibling, 1 reply; 31+ messages in thread
From: Michael Snyder @ 2010-06-07 16:04 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches


This is way cool, but at some point I've gotta remark --

gdbserver has sure come a long way from the simple remote debug agent
that it started out to be.  Is anybody at all worried about the ever
increasing complexification of gdbserver?

Pedro Alves wrote:
> This adds a bytecode compiler to the linux x86 ports of
> gdbserver, that turns agent expression bytecodes into
> native code.  This greatly speeds up conditional tracepoints
> (by around an order of magnitude) that usually don't reference much
> more than a few variables (memory/registers), to around 100ns or
> less on a typical modern x86 box.
> 
> --
> Pedro Alves
> 
> 2010-06-07  Stan Shebs  <stan@codesourcery.com>
>             Pedro Alves  <pedro@codesourcery.com>
> 
>         Bytecode compiler.
> 
>         * linux-x86-low.c: Include limits.h.
>         (add_insns): New.
>         (always_true): New.
>         (EMIT_ASM): New.
>         (EMIT_ASM32): New.
>         (amd64_emit_prologue, amd64_emit_epilogue, amd64_emit_add)
>         (amd64_emit_sub, amd64_emit_mul, amd64_emit_lsh)
>         (amd64_emit_rsh_signed, amd64_emit_rsh_unsigned, amd64_emit_ext,
>         (amd64_emit_log_not, amd64_emit_bit_and, amd64_emit_bit_or)
>         (amd64_emit_bit_xor, amd64_emit_bit_not, amd64_emit_equal,
>         (amd64_emit_less_signed, amd64_emit_less_unsigned, amd64_emit_ref,
>         (amd64_emit_if_goto, amd64_emit_goto, amd64_write_goto_address)
>         (amd64_emit_const, amd64_emit_call, amd64_emit_reg)
>         (amd64_emit_pop, amd64_emit_stack_flush, amd64_emit_zero_ext)
>         (amd64_emit_swap, amd64_emit_stack_adjust, amd64_emit_int_call_1)
>         (amd64_emit_void_call_2): New.
>         (amd64_emit_ops): New.
>         (i386_emit_prologue, i386_emit_epilogue, i386_emit_add)
>         (i386_emit_sub,i386_emit_mul, i386_emit_lsh, i386_emit_rsh_signed)
>         (i386_emit_rsh_unsigned, i386_emit_ext, i386_emit_log_not)
>         (i386_emit_bit_and, i386_emit_bit_or, i386_emit_bit_xor)
>         (i386_emit_bit_not, i386_emit_equal, i386_emit_less_signed)
>         (i386_emit_less_unsigned, i386_emit_ref, i386_emit_if_goto)
>         (i386_emit_goto, i386_write_goto_address, i386_emit_const)
>         (i386_emit_call, i386_emit_reg, i386_emit_pop)
>         (i386_emit_stack_flush, i386_emit_zero_ext, i386_emit_swap)
>         (i386_emit_stack_adjust, i386_emit_int_call_1)
>         (i386_emit_void_call_2): New.
>         (i386_emit_ops): New.
>         (x86_emit_ops): New.
>         (the_low_target): Install x86_emit_ops.
>         * server.h (struct emit_ops): New.
>         (get_raw_reg_func_addr): Declare.
>         (current_insn_ptr, emit_error): Declare.
>         * tracepoint.c (get_raw_reg, get_trace_state_variable_value)
>         (set_trace_state_variable_value): New defines.
>         (struct ipa_sym_addresses): New fields addr_get_raw_reg,
>         addr_get_trace_state_variable_value and
>         addr_set_trace_state_variable_value.
>         (symbol_list): New fields for get_raw_reg,
>         get_trace_state_variable_value and set_trace_state_variable_value.
>         (condfn): New typedef.
>         (struct tracepoint): New field `compiled_cond'.
>         (do_action_at_tracepoint): Clear compiled_cond.
>         (get_trace_state_variable_value, set_trace_state_variable_value):
>         Export in the IPA.
>         (condition_true_at_tracepoint): If there's a compiled condition,
>         run that.
>         (current_insn_ptr, emit_error): New globals.
>         (struct bytecode_address): New.
>         (get_raw_reg_func_addr): New.
>         (emit_prologue, emit_epilogue, emit_add, emit_sub, emit_mul)
>         (emit_lsh, emit_rsh_signed, emit_rsh_unsigned, emit_ext)
>         (emit_log_not, emit_bit_and, emit_bit_or, emit_bit_xor)
>         (emit_bit_not, emit_equal, emit_less_signed, emit_less_unsigned)
>         (emit_ref, emit_if_goto, emit_goto, write_goto_address, emit_const)
>         (emit_reg, emit_pop, emit_stack_flush, emit_zero_ext, emit_swap)
>         (emit_stack_adjust, emit_int_call_1, emit_void_call_2): New.
>         (compile_tracepoint_condition, compile_bytecodes): New.
>         * target.h (emit_ops): Forward declare.
>         (struct target_ops): New field emit_ops.
>         (target_emit_ops): New.
>         * linux-amd64-ipa.c (gdb_agent_get_raw_reg): New.
>         * linux-i386-ipa.c (gdb_agent_get_raw_reg): New.
>         * linux-low.c (linux_emit_ops): New.
>         (linux_target_ops): Install it.
>         * linux-low.h (struct linux_target_ops): New field emit_ops.
> 
> ---
>  gdb/gdbserver/linux-amd64-ipa.c |    9
>  gdb/gdbserver/linux-i386-ipa.c  |   15
>  gdb/gdbserver/linux-low.c       |   12
>  gdb/gdbserver/linux-low.h       |    4
>  gdb/gdbserver/linux-x86-low.c   | 1032 +++++++++++++++++++++++++++++++++++++++-
>  gdb/gdbserver/server.h          |   50 +
>  gdb/gdbserver/target.h          |    8
>  gdb/gdbserver/tracepoint.c      |  624 ++++++++++++++++++++++++
>  8 files changed, 1749 insertions(+), 5 deletions(-)
> 
> Index: src/gdb/gdbserver/linux-x86-low.c
> ===================================================================
> --- src.orig/gdb/gdbserver/linux-x86-low.c      2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/linux-x86-low.c   2010-06-07 16:43:25.000000000 +0100
> @@ -20,6 +20,7 @@
> 
>  #include <stddef.h>
>  #include <signal.h>
> +#include <limits.h>
>  #include "server.h"
>  #include "linux-low.h"
>  #include "i387-fp.h"
> @@ -1470,6 +1471,1034 @@ x86_install_fast_tracepoint_jump_pad (CO
>                                                 adjusted_insn_addr_end);
>  }
> 
> +static void
> +add_insns (unsigned char *start, int len)
> +{
> +  CORE_ADDR buildaddr = current_insn_ptr;
> +
> +  if (debug_threads)
> +    fprintf (stderr, "Adding %d bytes of insn at %s\n",
> +            len, paddress (buildaddr));
> +
> +  append_insns (&buildaddr, len, start);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +/* A function used to trick optimizers.  */
> +
> +int
> +always_true (void)
> +{
> +  return 1;
> +}
> +
> +/* Our general strategy for emitting code is to avoid specifying raw
> +   bytes whenever possible, and instead copy a block of inline asm
> +   that is embedded in the function.  This is a little messy, because
> +   we need to keep the compiler from discarding what looks like dead
> +   code, plus suppress various warnings.  */
> +
> +#define EMIT_ASM(NAME,INSNS)                                           \
> +  { extern unsigned char start_ ## NAME, end_ ## NAME;                 \
> +    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);      \
> +    if (always_true ())                                                \
> +      goto skipover ## NAME;                                           \
> +    __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");   \
> +    skipover ## NAME:                                                  \
> +    ; }
> +
> +
> +#ifdef __x86_64__
> +
> +#define EMIT_ASM32(NAME,INSNS)                                         \
> +  { extern unsigned char start_ ## NAME, end_ ## NAME;                 \
> +    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);      \
> +    if (always_true ())                                                \
> +      goto skipover ## NAME;                                           \
> +    __asm__ (".code32\n\tstart_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n" \
> +            "\t.code64\n\t");                                          \
> +    skipover ## NAME:                                                  \
> +    ; }
> +
> +#else
> +
> +#define EMIT_ASM32(NAME,INSNS) EMIT_ASM(NAME,INSNS)
> +
> +#endif
> +
> +#ifdef __x86_64__
> +
> +static void
> +amd64_emit_prologue (void)
> +{
> +  EMIT_ASM (amd64_prologue,
> +           "pushq %rbp\n\t"
> +           "movq %rsp,%rbp\n\t"
> +           "sub $0x20,%rsp\n\t"
> +           "movq %rdi,-8(%rbp)\n\t"
> +           "movq %rsi,-16(%rbp)");
> +}
> +
> +
> +static void
> +amd64_emit_epilogue (void)
> +{
> +  EMIT_ASM (amd64_epilogue,
> +           "movq -16(%rbp),%rdi\n\t"
> +           "movq %rax,(%rdi)\n\t"
> +           "xor %rax,%rax\n\t"
> +           "leave\n\t"
> +           "ret");
> +}
> +
> +static void
> +amd64_emit_add (void)
> +{
> +  EMIT_ASM (amd64_add,
> +           "add (%rsp),%rax\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_sub (void)
> +{
> +  EMIT_ASM (amd64_sub,
> +           "sub %rax,(%rsp)\n\t"
> +           "pop %rax");
> +}
> +
> +static void
> +amd64_emit_mul (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +amd64_emit_lsh (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +amd64_emit_rsh_signed (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +amd64_emit_rsh_unsigned (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +amd64_emit_ext (int arg)
> +{
> +  switch (arg)
> +    {
> +    case 8:
> +      EMIT_ASM (amd64_ext_8,
> +               "cbtw\n\t"
> +               "cwtl\n\t"
> +               "cltq");
> +      break;
> +    case 16:
> +      EMIT_ASM (amd64_ext_16,
> +               "cwtl\n\t"
> +               "cltq");
> +      break;
> +    case 32:
> +      EMIT_ASM (amd64_ext_32,
> +               "cltq");
> +      break;
> +    default:
> +      emit_error = 1;
> +    }
> +}
> +
> +static void
> +amd64_emit_log_not (void)
> +{
> +  EMIT_ASM (amd64_log_not,
> +           "test %rax,%rax\n\t"
> +           "sete %cl\n\t"
> +           "movzbq %cl,%rax");
> +}
> +
> +static void
> +amd64_emit_bit_and (void)
> +{
> +  EMIT_ASM (amd64_and,
> +           "and (%rsp),%rax\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_bit_or (void)
> +{
> +  EMIT_ASM (amd64_or,
> +           "or (%rsp),%rax\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_bit_xor (void)
> +{
> +  EMIT_ASM (amd64_xor,
> +           "xor (%rsp),%rax\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_bit_not (void)
> +{
> +  EMIT_ASM (amd64_bit_not,
> +           "xorq $0xffffffffffffffff,%rax");
> +}
> +
> +static void
> +amd64_emit_equal (void)
> +{
> +  EMIT_ASM (amd64_equal,
> +           "cmp %rax,(%rsp)\n\t"
> +           "je .Lamd64_equal_true\n\t"
> +           "xor %rax,%rax\n\t"
> +           "jmp .Lamd64_equal_end\n\t"
> +           ".Lamd64_equal_true:\n\t"
> +           "mov $0x1,%rax\n\t"
> +           ".Lamd64_equal_end:\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_less_signed (void)
> +{
> +  EMIT_ASM (amd64_less_signed,
> +           "cmp %rax,(%rsp)\n\t"
> +           "jl .Lamd64_less_signed_true\n\t"
> +           "xor %rax,%rax\n\t"
> +           "jmp .Lamd64_less_signed_end\n\t"
> +           ".Lamd64_less_signed_true:\n\t"
> +           "mov $1,%rax\n\t"
> +           ".Lamd64_less_signed_end:\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_less_unsigned (void)
> +{
> +  EMIT_ASM (amd64_less_unsigned,
> +           "cmp %rax,(%rsp)\n\t"
> +           "jb .Lamd64_less_unsigned_true\n\t"
> +           "xor %rax,%rax\n\t"
> +           "jmp .Lamd64_less_unsigned_end\n\t"
> +           ".Lamd64_less_unsigned_true:\n\t"
> +           "mov $1,%rax\n\t"
> +           ".Lamd64_less_unsigned_end:\n\t"
> +           "lea 0x8(%rsp),%rsp");
> +}
> +
> +static void
> +amd64_emit_ref (int size)
> +{
> +  switch (size)
> +    {
> +    case 1:
> +      EMIT_ASM (amd64_ref1,
> +               "movb (%rax),%al");
> +      break;
> +    case 2:
> +      EMIT_ASM (amd64_ref2,
> +               "movw (%rax),%ax");
> +      break;
> +    case 4:
> +      EMIT_ASM (amd64_ref4,
> +               "movl (%rax),%eax");
> +      break;
> +    case 8:
> +      EMIT_ASM (amd64_ref8,
> +               "movq (%rax),%rax");
> +      break;
> +    }
> +}
> +
> +static void
> +amd64_emit_if_goto (int *offset_p, int *size_p)
> +{
> +  EMIT_ASM (amd64_if_goto,
> +           "mov %rax,%rcx\n\t"
> +           "pop %rax\n\t"
> +           "cmp $0,%rcx\n\t"
> +           ".byte 0x0f, 0x85, 0x0, 0x0, 0x0, 0x0");
> +  if (offset_p)
> +    *offset_p = 10;
> +  if (size_p)
> +    *size_p = 4;
> +}
> +
> +static void
> +amd64_emit_goto (int *offset_p, int *size_p)
> +{
> +  EMIT_ASM (amd64_goto,
> +           ".byte 0xe9, 0x0, 0x0, 0x0, 0x0");
> +  if (offset_p)
> +    *offset_p = 1;
> +  if (size_p)
> +    *size_p = 4;
> +}
> +
> +static void
> +amd64_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
> +{
> +  int diff = (to - (from + size));
> +  unsigned char buf[sizeof (int)];
> +
> +  if (size != 4)
> +    {
> +      emit_error = 1;
> +      return;
> +    }
> +
> +  memcpy (buf, &diff, sizeof (int));
> +  write_inferior_memory (from, buf, sizeof (int));
> +}
> +
> +static void
> +amd64_emit_const (int64_t num)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr = current_insn_ptr;
> +
> +  i = 0;
> +  buf[i++] = 0x48;  buf[i++] = 0xb8; /* mov $<n>,%rax */
> +  *((int64_t *) (&buf[i])) = num;
> +  i += 8;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +static void
> +amd64_emit_call (CORE_ADDR fn)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +  int64_t offset64;
> +
> +  /* The destination function being in the shared library, may be
> +     >31-bits away off the compiled code pad.  */
> +
> +  buildaddr = current_insn_ptr;
> +
> +  offset64 = fn - (buildaddr + 1 /* call op */ + 4 /* 32-bit offset */);
> +
> +  i = 0;
> +
> +  if (offset64 > INT_MAX || offset64 < INT_MIN)
> +    {
> +      /* Offset is too large for a call.  Use callq, but that requires
> +        a register, so avoid it if possible.  Use r10, since it is
> +        call-clobbered, we don't have to push/pop it.  */
> +      buf[i++] = 0x48; /* mov $fn,%r10 */
> +      buf[i++] = 0xba;
> +      memcpy (buf + i, &fn, 8);
> +      i += 8;
> +      buf[i++] = 0xff; /* callq *%r10 */
> +      buf[i++] = 0xd2;
> +    }
> +  else
> +    {
> +      int offset32 = offset64; /* we know we can't overflow here.  */
> +      memcpy (buf + i, &offset32, 4);
> +      i += 4;
> +    }
> +
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +static void
> +amd64_emit_reg (int reg)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +
> +  /* Assume raw_regs is still in %rdi.  */
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xbe; /* mov $<n>,%esi */
> +  *((int *) (&buf[i])) = reg;
> +  i += 4;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +  amd64_emit_call (get_raw_reg_func_addr ());
> +}
> +
> +static void
> +amd64_emit_pop (void)
> +{
> +  EMIT_ASM (amd64_pop,
> +           "pop %rax");
> +}
> +
> +static void
> +amd64_emit_stack_flush (void)
> +{
> +  EMIT_ASM (amd64_stack_flush,
> +           "push %rax");
> +}
> +
> +static void
> +amd64_emit_zero_ext (int arg)
> +{
> +  switch (arg)
> +    {
> +    case 8:
> +      EMIT_ASM (amd64_zero_ext_8,
> +               "and $0xff,%rax");
> +      break;
> +    case 16:
> +      EMIT_ASM (amd64_zero_ext_16,
> +               "and $0xffff,%rax");
> +      break;
> +    case 32:
> +      EMIT_ASM (amd64_zero_ext_32,
> +               "mov $0xffffffff,%rcx\n\t"
> +               "and %rcx,%rax");
> +      break;
> +    default:
> +      emit_error = 1;
> +    }
> +}
> +
> +static void
> +amd64_emit_swap (void)
> +{
> +  EMIT_ASM (amd64_swap,
> +           "mov %rax,%rcx\n\t"
> +           "pop %rax\n\t"
> +           "push %rcx");
> +}
> +
> +static void
> +amd64_emit_stack_adjust (int n)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr = current_insn_ptr;
> +
> +  i = 0;
> +  buf[i++] = 0x48; /* lea $<n>(%rsp),%rsp */
> +  buf[i++] = 0x8d;
> +  buf[i++] = 0x64;
> +  buf[i++] = 0x24;
> +  /* This only handles adjustments up to 16, but we don't expect any more.  */
> +  buf[i++] = n * 8;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +/* FN's prototype is `LONGEST(*fn)(int)'.  */
> +
> +static void
> +amd64_emit_int_call_1 (CORE_ADDR fn, int arg1)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xbf; /* movl $<n>,%edi */
> +  *((int *) (&buf[i])) = arg1;
> +  i += 4;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +  amd64_emit_call (fn);
> +}
> +
> +/* FN's prototype is `void(*fn)(int,int64_t)'.  */
> +
> +static void
> +amd64_emit_void_call_2 (CORE_ADDR fn, int arg1)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xbf; /* movl $<n>,%edi */
> +  *((int *) (&buf[i])) = arg1;
> +  i += 4;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +  EMIT_ASM (amd64_void_call_2_a,
> +           /* Save away a copy of the stack top.  */
> +           "push %rax\n\t"
> +           /* Also pass top as the second argument.  */
> +           "mov %rax,%rsi");
> +  amd64_emit_call (fn);
> +  EMIT_ASM (amd64_void_call_2_b,
> +           /* Restore the stack top, %rax may have been trashed.  */
> +           "pop %rax");
> +}
> +
> +struct emit_ops amd64_emit_ops =
> +  {
> +    amd64_emit_prologue,
> +    amd64_emit_epilogue,
> +    amd64_emit_add,
> +    amd64_emit_sub,
> +    amd64_emit_mul,
> +    amd64_emit_lsh,
> +    amd64_emit_rsh_signed,
> +    amd64_emit_rsh_unsigned,
> +    amd64_emit_ext,
> +    amd64_emit_log_not,
> +    amd64_emit_bit_and,
> +    amd64_emit_bit_or,
> +    amd64_emit_bit_xor,
> +    amd64_emit_bit_not,
> +    amd64_emit_equal,
> +    amd64_emit_less_signed,
> +    amd64_emit_less_unsigned,
> +    amd64_emit_ref,
> +    amd64_emit_if_goto,
> +    amd64_emit_goto,
> +    amd64_write_goto_address,
> +    amd64_emit_const,
> +    amd64_emit_call,
> +    amd64_emit_reg,
> +    amd64_emit_pop,
> +    amd64_emit_stack_flush,
> +    amd64_emit_zero_ext,
> +    amd64_emit_swap,
> +    amd64_emit_stack_adjust,
> +    amd64_emit_int_call_1,
> +    amd64_emit_void_call_2
> +  };
> +
> +#endif /* __x86_64__ */
> +
> +static void
> +i386_emit_prologue (void)
> +{
> +  EMIT_ASM32 (i386_prologue,
> +           "push %ebp\n\t"
> +           "mov %esp,%ebp");
> +  /* At this point, the raw regs base address is at 8(%ebp), and the
> +     value pointer is at 12(%ebp).  */
> +}
> +
> +static void
> +i386_emit_epilogue (void)
> +{
> +  EMIT_ASM32 (i386_epilogue,
> +           "mov 12(%ebp),%ecx\n\t"
> +           "mov %eax,(%ecx)\n\t"
> +           "mov %ebx,0x4(%ecx)\n\t"
> +           "xor %eax,%eax\n\t"
> +           "pop %ebp\n\t"
> +           "ret");
> +}
> +
> +static void
> +i386_emit_add (void)
> +{
> +  EMIT_ASM32 (i386_add,
> +           "add (%esp),%eax\n\t"
> +           "adc 0x4(%esp),%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_sub (void)
> +{
> +  EMIT_ASM32 (i386_sub,
> +           "subl %eax,(%esp)\n\t"
> +           "sbbl %ebx,4(%esp)\n\t"
> +           "pop %eax\n\t"
> +           "pop %ebx\n\t");
> +}
> +
> +static void
> +i386_emit_mul (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +i386_emit_lsh (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +i386_emit_rsh_signed (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +i386_emit_rsh_unsigned (void)
> +{
> +  emit_error = 1;
> +}
> +
> +static void
> +i386_emit_ext (int arg)
> +{
> +  switch (arg)
> +    {
> +    case 8:
> +      EMIT_ASM32 (i386_ext_8,
> +               "cbtw\n\t"
> +               "cwtl\n\t"
> +               "movl %eax,%ebx\n\t"
> +               "sarl $31,%ebx");
> +      break;
> +    case 16:
> +      EMIT_ASM32 (i386_ext_16,
> +               "cwtl\n\t"
> +               "movl %eax,%ebx\n\t"
> +               "sarl $31,%ebx");
> +      break;
> +    case 32:
> +      EMIT_ASM32 (i386_ext_32,
> +               "movl %eax,%ebx\n\t"
> +               "sarl $31,%ebx");
> +      break;
> +    default:
> +      emit_error = 1;
> +    }
> +}
> +
> +static void
> +i386_emit_log_not (void)
> +{
> +  EMIT_ASM32 (i386_log_not,
> +           "or %ebx,%eax\n\t"
> +           "test %eax,%eax\n\t"
> +           "sete %cl\n\t"
> +           "xor %ebx,%ebx\n\t"
> +           "movzbl %cl,%eax");
> +}
> +
> +static void
> +i386_emit_bit_and (void)
> +{
> +  EMIT_ASM32 (i386_and,
> +           "and (%esp),%eax\n\t"
> +           "and 0x4(%esp),%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_bit_or (void)
> +{
> +  EMIT_ASM32 (i386_or,
> +           "or (%esp),%eax\n\t"
> +           "or 0x4(%esp),%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_bit_xor (void)
> +{
> +  EMIT_ASM32 (i386_xor,
> +           "xor (%esp),%eax\n\t"
> +           "xor 0x4(%esp),%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_bit_not (void)
> +{
> +  EMIT_ASM32 (i386_bit_not,
> +           "xor $0xffffffff,%eax\n\t"
> +           "xor $0xffffffff,%ebx\n\t");
> +}
> +
> +static void
> +i386_emit_equal (void)
> +{
> +  EMIT_ASM32 (i386_equal,
> +           "cmpl %ebx,4(%esp)\n\t"
> +           "jne .Li386_equal_false\n\t"
> +           "cmpl %eax,(%esp)\n\t"
> +           "je .Li386_equal_true\n\t"
> +           ".Li386_equal_false:\n\t"
> +           "xor %eax,%eax\n\t"
> +           "jmp .Li386_equal_end\n\t"
> +           ".Li386_equal_true:\n\t"
> +           "mov $1,%eax\n\t"
> +           ".Li386_equal_end:\n\t"
> +           "xor %ebx,%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_less_signed (void)
> +{
> +  EMIT_ASM32 (i386_less_signed,
> +           "cmpl %ebx,4(%esp)\n\t"
> +           "jl .Li386_less_signed_true\n\t"
> +           "jne .Li386_less_signed_false\n\t"
> +           "cmpl %eax,(%esp)\n\t"
> +           "jl .Li386_less_signed_true\n\t"
> +           ".Li386_less_signed_false:\n\t"
> +           "xor %eax,%eax\n\t"
> +           "jmp .Li386_less_signed_end\n\t"
> +           ".Li386_less_signed_true:\n\t"
> +           "mov $1,%eax\n\t"
> +           ".Li386_less_signed_end:\n\t"
> +           "xor %ebx,%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_less_unsigned (void)
> +{
> +  EMIT_ASM32 (i386_less_unsigned,
> +           "cmpl %ebx,4(%esp)\n\t"
> +           "jb .Li386_less_unsigned_true\n\t"
> +           "jne .Li386_less_unsigned_false\n\t"
> +           "cmpl %eax,(%esp)\n\t"
> +           "jb .Li386_less_unsigned_true\n\t"
> +           ".Li386_less_unsigned_false:\n\t"
> +           "xor %eax,%eax\n\t"
> +           "jmp .Li386_less_unsigned_end\n\t"
> +           ".Li386_less_unsigned_true:\n\t"
> +           "mov $1,%eax\n\t"
> +           ".Li386_less_unsigned_end:\n\t"
> +           "xor %ebx,%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_ref (int size)
> +{
> +  switch (size)
> +    {
> +    case 1:
> +      EMIT_ASM32 (i386_ref1,
> +               "movb (%eax),%al");
> +      break;
> +    case 2:
> +      EMIT_ASM32 (i386_ref2,
> +               "movw (%eax),%ax");
> +      break;
> +    case 4:
> +      EMIT_ASM32 (i386_ref4,
> +               "movl (%eax),%eax");
> +      break;
> +    case 8:
> +      EMIT_ASM32 (i386_ref8,
> +               "movl 4(%eax),%ebx\n\t"
> +               "movl (%eax),%eax");
> +      break;
> +    }
> +}
> +
> +static void
> +i386_emit_if_goto (int *offset_p, int *size_p)
> +{
> +  EMIT_ASM32 (i386_if_goto,
> +           "mov %eax,%ecx\n\t"
> +           "or %ebx,%ecx\n\t"
> +           "pop %eax\n\t"
> +           "pop %ebx\n\t"
> +           "cmpl $0,%ecx\n\t"
> +           /* Don't trust the assembler to choose the right jump */
> +           ".byte 0x0f, 0x85, 0x0, 0x0, 0x0, 0x0");
> +
> +  if (offset_p)
> +    *offset_p = 11; /* be sure that this matches the sequence above */
> +  if (size_p)
> +    *size_p = 4;
> +}
> +
> +static void
> +i386_emit_goto (int *offset_p, int *size_p)
> +{
> +  EMIT_ASM32 (i386_goto,
> +           /* Don't trust the assembler to choose the right jump */
> +           ".byte 0xe9, 0x0, 0x0, 0x0, 0x0");
> +  if (offset_p)
> +    *offset_p = 1;
> +  if (size_p)
> +    *size_p = 4;
> +}
> +
> +static void
> +i386_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
> +{
> +  int diff = (to - (from + size));
> +  unsigned char buf[sizeof (int)];
> +
> +  /* We're only doing 4-byte sizes at the moment.  */
> +  if (size != 4)
> +    {
> +      emit_error = 1;
> +      return;
> +    }
> +
> +  memcpy (buf, &diff, sizeof (int));
> +  write_inferior_memory (from, buf, sizeof (int));
> +}
> +
> +static void
> +i386_emit_const (int64_t num)
> +{
> +  unsigned char buf[16];
> +  int i, hi;
> +  CORE_ADDR buildaddr = current_insn_ptr;
> +
> +  i = 0;
> +  buf[i++] = 0xb8; /* mov $<n>,%eax */
> +  *((int *) (&buf[i])) = (num & 0xffffffff);
> +  i += 4;
> +  hi = ((num >> 32) & 0xffffffff);
> +  if (hi)
> +    {
> +      buf[i++] = 0xbb; /* mov $<n>,%ebx */
> +      *((int *) (&buf[i])) = hi;
> +      i += 4;
> +    }
> +  else
> +    {
> +      buf[i++] = 0x31; buf[i++] = 0xdb; /* xor %ebx,%ebx */
> +    }
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +static void
> +i386_emit_call (CORE_ADDR fn)
> +{
> +  unsigned char buf[16];
> +  int i, offset;
> +  CORE_ADDR buildaddr;
> +
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xe8; /* call <reladdr> */
> +  offset = ((int) fn) - (buildaddr + 5);
> +  memcpy (buf + 1, &offset, 4);
> +  append_insns (&buildaddr, 5, buf);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +static void
> +i386_emit_reg (int reg)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +
> +  EMIT_ASM32 (i386_reg_a,
> +           "sub $0x8,%esp");
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xb8; /* mov $<n>,%eax */
> +  *((int *) (&buf[i])) = reg;
> +  i += 4;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +  EMIT_ASM32 (i386_reg_b,
> +           "mov %eax,4(%esp)\n\t"
> +           "mov 8(%ebp),%eax\n\t"
> +           "mov %eax,(%esp)");
> +  i386_emit_call (get_raw_reg_func_addr ());
> +  EMIT_ASM32 (i386_reg_c,
> +           "xor %ebx,%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +static void
> +i386_emit_pop (void)
> +{
> +  EMIT_ASM32 (i386_pop,
> +           "pop %eax\n\t"
> +           "pop %ebx");
> +}
> +
> +static void
> +i386_emit_stack_flush (void)
> +{
> +  EMIT_ASM32 (i386_stack_flush,
> +           "push %ebx\n\t"
> +           "push %eax");
> +}
> +
> +static void
> +i386_emit_zero_ext (int arg)
> +{
> +  switch (arg)
> +    {
> +    case 8:
> +      EMIT_ASM32 (i386_zero_ext_8,
> +               "and $0xff,%eax\n\t"
> +               "xor %ebx,%ebx");
> +      break;
> +    case 16:
> +      EMIT_ASM32 (i386_zero_ext_16,
> +               "and $0xffff,%eax\n\t"
> +               "xor %ebx,%ebx");
> +      break;
> +    case 32:
> +      EMIT_ASM32 (i386_zero_ext_32,
> +               "xor %ebx,%ebx");
> +      break;
> +    default:
> +      emit_error = 1;
> +    }
> +}
> +
> +static void
> +i386_emit_swap (void)
> +{
> +  EMIT_ASM32 (i386_swap,
> +           "mov %eax,%ecx\n\t"
> +           "mov %ebx,%edx\n\t"
> +           "pop %eax\n\t"
> +           "pop %ebx\n\t"
> +           "push %edx\n\t"
> +           "push %ecx");
> +}
> +
> +static void
> +i386_emit_stack_adjust (int n)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr = current_insn_ptr;
> +
> +  i = 0;
> +  buf[i++] = 0x8d; /* lea $<n>(%esp),%esp */
> +  buf[i++] = 0x64;
> +  buf[i++] = 0x24;
> +  buf[i++] = n * 8;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +}
> +
> +/* FN's prototype is `LONGEST(*fn)(int)'.  */
> +
> +static void
> +i386_emit_int_call_1 (CORE_ADDR fn, int arg1)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +
> +  EMIT_ASM32 (i386_int_call_1_a,
> +           /* Reserve a bit of stack space.  */
> +           "sub $0x8,%esp");
> +  /* Put the one argument on the stack.  */
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xc7;  /* movl $<arg1>,(%esp) */
> +  buf[i++] = 0x04;
> +  buf[i++] = 0x24;
> +  *((int *) (&buf[i])) = arg1;
> +  i += 4;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +  i386_emit_call (fn);
> +  EMIT_ASM32 (i386_int_call_1_c,
> +           "mov %edx,%ebx\n\t"
> +           "lea 0x8(%esp),%esp");
> +}
> +
> +/* FN's prototype is `void(*fn)(int,int64_t)'.  */
> +
> +static void
> +i386_emit_void_call_2 (CORE_ADDR fn, int arg1)
> +{
> +  unsigned char buf[16];
> +  int i;
> +  CORE_ADDR buildaddr;
> +
> +  EMIT_ASM32 (i386_void_call_2_a,
> +           /* Preserve %eax only; we don't have to worry about %ebx.  */
> +           "push %eax\n\t"
> +           /* Reserve a bit of stack space for arguments.  */
> +           "sub $0x10,%esp\n\t"
> +           /* Copy "top" to the second argument position.  (Note that
> +              we can't assume function won't scribble on its
> +              arguments, so don't try to restore from this.)  */
> +           "mov %eax,4(%esp)\n\t"
> +           "mov %ebx,8(%esp)");
> +  /* Put the first argument on the stack.  */
> +  buildaddr = current_insn_ptr;
> +  i = 0;
> +  buf[i++] = 0xc7;  /* movl $<arg1>,(%esp) */
> +  buf[i++] = 0x04;
> +  buf[i++] = 0x24;
> +  *((int *) (&buf[i])) = arg1;
> +  i += 4;
> +  append_insns (&buildaddr, i, buf);
> +  current_insn_ptr = buildaddr;
> +  i386_emit_call (fn);
> +  EMIT_ASM32 (i386_void_call_2_b,
> +           "lea 0x10(%esp),%esp\n\t"
> +           /* Restore original stack top.  */
> +           "pop %eax");
> +}
> +
> +struct emit_ops i386_emit_ops =
> +  {
> +    i386_emit_prologue,
> +    i386_emit_epilogue,
> +    i386_emit_add,
> +    i386_emit_sub,
> +    i386_emit_mul,
> +    i386_emit_lsh,
> +    i386_emit_rsh_signed,
> +    i386_emit_rsh_unsigned,
> +    i386_emit_ext,
> +    i386_emit_log_not,
> +    i386_emit_bit_and,
> +    i386_emit_bit_or,
> +    i386_emit_bit_xor,
> +    i386_emit_bit_not,
> +    i386_emit_equal,
> +    i386_emit_less_signed,
> +    i386_emit_less_unsigned,
> +    i386_emit_ref,
> +    i386_emit_if_goto,
> +    i386_emit_goto,
> +    i386_write_goto_address,
> +    i386_emit_const,
> +    i386_emit_call,
> +    i386_emit_reg,
> +    i386_emit_pop,
> +    i386_emit_stack_flush,
> +    i386_emit_zero_ext,
> +    i386_emit_swap,
> +    i386_emit_stack_adjust,
> +    i386_emit_int_call_1,
> +    i386_emit_void_call_2
> +  };
> +
> +
> +static struct emit_ops *
> +x86_emit_ops (void)
> +{
> +#ifdef __x86_64__
> +  int use_64bit = register_size (0) == 8;
> +
> +  if (use_64bit)
> +    return &amd64_emit_ops;
> +  else
> +#endif
> +    return &i386_emit_ops;
> +}
> +
>  /* This is initialized assuming an amd64 target.
>     x86_arch_setup will correct it for i386 or amd64 targets.  */
> 
> @@ -1504,5 +2533,6 @@ struct linux_target_ops the_low_target =
>    x86_linux_process_qsupported,
>    x86_supports_tracepoints,
>    x86_get_thread_area,
> -  x86_install_fast_tracepoint_jump_pad
> +  x86_install_fast_tracepoint_jump_pad,
> +  x86_emit_ops
>  };
> Index: src/gdb/gdbserver/server.h
> ===================================================================
> --- src.orig/gdb/gdbserver/server.h     2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/server.h  2010-06-07 16:13:24.000000000 +0100
> @@ -573,6 +573,56 @@ void supply_fast_tracepoint_registers (s
>  void stop_tracing (void);
>  #endif
> 
> +/* Bytecode compilation function vector.  */
> +
> +struct emit_ops
> +{
> +  void (*emit_prologue) (void);
> +  void (*emit_epilogue) (void);
> +  void (*emit_add) (void);
> +  void (*emit_sub) (void);
> +  void (*emit_mul) (void);
> +  void (*emit_lsh) (void);
> +  void (*emit_rsh_signed) (void);
> +  void (*emit_rsh_unsigned) (void);
> +  void (*emit_ext) (int arg);
> +  void (*emit_log_not) (void);
> +  void (*emit_bit_and) (void);
> +  void (*emit_bit_or) (void);
> +  void (*emit_bit_xor) (void);
> +  void (*emit_bit_not) (void);
> +  void (*emit_equal) (void);
> +  void (*emit_less_signed) (void);
> +  void (*emit_less_unsigned) (void);
> +  void (*emit_ref) (int size);
> +  void (*emit_if_goto) (int *offset_p, int *size_p);
> +  void (*emit_goto) (int *offset_p, int *size_p);
> +  void (*write_goto_address) (CORE_ADDR from, CORE_ADDR to, int size);
> +  void (*emit_const) (int64_t num);
> +  void (*emit_call) (CORE_ADDR fn);
> +  void (*emit_reg) (int reg);
> +  void (*emit_pop) (void);
> +  void (*emit_stack_flush) (void);
> +  void (*emit_zero_ext) (int arg);
> +  void (*emit_swap) (void);
> +  void (*emit_stack_adjust) (int n);
> +
> +  /* Emit code for a generic function that takes one fixed integer
> +     argument and returns a 64-bit int (for instance, tsv getter).  */
> +  void (*emit_int_call_1) (CORE_ADDR fn, int arg1);
> +
> +  /* Emit code for a generic function that takes one fixed integer
> +     argument and a 64-bit int from the top of the stack, and returns
> +     nothing (for instance, tsv setter).  */
> +  void (*emit_void_call_2) (CORE_ADDR fn, int arg1);
> +};
> +
> +/* Returns the address of the get_raw_reg function in the IPA.  */
> +CORE_ADDR get_raw_reg_func_addr (void);
> +
> +CORE_ADDR current_insn_ptr;
> +int emit_error;
> +
>  /* Version information, from version.c.  */
>  extern const char version[];
>  extern const char host_name[];
> Index: src/gdb/gdbserver/tracepoint.c
> ===================================================================
> --- src.orig/gdb/gdbserver/tracepoint.c 2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/tracepoint.c      2010-06-07 16:42:28.000000000 +0100
> @@ -132,6 +132,9 @@ trace_vdebug (const char *fmt, ...)
>  # define traceframe_write_count gdb_agent_traceframe_write_count
>  # define traceframes_created gdb_agent_traceframes_created
>  # define trace_state_variables gdb_agent_trace_state_variables
> +# define get_raw_reg gdb_agent_get_raw_reg
> +# define get_trace_state_variable_value gdb_agent_get_trace_state_variable_value
> +# define set_trace_state_variable_value gdb_agent_set_trace_state_variable_value
>  #endif
> 
>  #ifndef IN_PROCESS_AGENT
> @@ -162,6 +165,9 @@ struct ipa_sym_addresses
>    CORE_ADDR addr_traceframe_write_count;
>    CORE_ADDR addr_traceframes_created;
>    CORE_ADDR addr_trace_state_variables;
> +  CORE_ADDR addr_get_raw_reg;
> +  CORE_ADDR addr_get_trace_state_variable_value;
> +  CORE_ADDR addr_set_trace_state_variable_value;
>  };
> 
>  #define STRINGIZE_1(STR) #STR
> @@ -200,6 +206,9 @@ static struct
>    IPA_SYM(traceframe_write_count),
>    IPA_SYM(traceframes_created),
>    IPA_SYM(trace_state_variables),
> +  IPA_SYM(get_raw_reg),
> +  IPA_SYM(get_trace_state_variable_value),
> +  IPA_SYM(set_trace_state_variable_value),
>  };
> 
>  struct ipa_sym_addresses ipa_sym_addrs;
> @@ -564,6 +573,9 @@ enum tracepoint_type
> 
>  struct tracepoint_hit_ctx;
> 
> +typedef enum eval_result_type (*condfn) (struct tracepoint_hit_ctx *,
> +                                        ULONGEST *);
> +
>  /* The definition of a tracepoint.  */
> 
>  /* Tracepoints may have multiple locations, each at a different
> @@ -612,6 +624,8 @@ struct tracepoint
>       Note that while-stepping steps are not counted as "hits".  */
>    long hit_count;
> 
> +  CORE_ADDR compiled_cond;
> +
>    /* Link to the next tracepoint in the list.  */
>    struct tracepoint *next;
> 
> @@ -1189,6 +1203,8 @@ static void collect_data_at_tracepoint (
>  static void collect_data_at_step (struct tracepoint_hit_ctx *ctx,
>                                   CORE_ADDR stop_pc,
>                                   struct tracepoint *tpoint, int current_step);
> +static void compile_tracepoint_condition (struct tracepoint *tpoint,
> +                                         CORE_ADDR *jump_entry);
>  #endif
>  static void do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
>                                      CORE_ADDR stop_pc,
> @@ -1610,6 +1626,7 @@ add_tracepoint (int num, CORE_ADDR addr)
>    tpoint->type = trap_tracepoint;
>    tpoint->orig_size = -1;
>    tpoint->source_strings = NULL;
> +  tpoint->compiled_cond = 0;
>    tpoint->handle = NULL;
>    tpoint->next = NULL;
> 
> @@ -1854,7 +1871,7 @@ create_trace_state_variable (int num, in
>    return tsv;
>  }
> 
> -static LONGEST
> +IP_AGENT_EXPORT LONGEST
>  get_trace_state_variable_value (int num)
>  {
>    struct trace_state_variable *tsv;
> @@ -1880,7 +1897,7 @@ get_trace_state_variable_value (int num)
>    return tsv->value;
>  }
> 
> -static void
> +IP_AGENT_EXPORT void
>  set_trace_state_variable_value (int num, LONGEST val)
>  {
>    struct trace_state_variable *tsv;
> @@ -3906,7 +3923,10 @@ condition_true_at_tracepoint (struct tra
>    ULONGEST value = 0;
>    enum eval_result_type err;
> 
> -  err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
> +  if (tpoint->compiled_cond)
> +    err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
> +  else
> +    err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
> 
>    if (err != expr_eval_no_error)
>      {
> @@ -4944,6 +4964,582 @@ gdb_collect (struct tracepoint *tpoint,
> 
>  #ifndef IN_PROCESS_AGENT
> 
> +/* Bytecode compilation.  */
> +
> +CORE_ADDR current_insn_ptr;
> +
> +int emit_error;
> +
> +struct bytecode_address
> +{
> +  int pc;
> +  CORE_ADDR address;
> +  int goto_pc;
> +  /* Offset and size of field to be modified in the goto block.  */
> +  int from_offset, from_size;
> +  struct bytecode_address *next;
> +} *bytecode_address_table;
> +
> +CORE_ADDR
> +get_raw_reg_func_addr (void)
> +{
> +  return ipa_sym_addrs.addr_get_raw_reg;
> +}
> +
> +static void
> +emit_prologue (void)
> +{
> +  target_emit_ops ()->emit_prologue ();
> +}
> +
> +static void
> +emit_epilogue (void)
> +{
> +  target_emit_ops ()->emit_epilogue ();
> +}
> +
> +static void
> +emit_add (void)
> +{
> +  target_emit_ops ()->emit_add ();
> +}
> +
> +static void
> +emit_sub (void)
> +{
> +  target_emit_ops ()->emit_sub ();
> +}
> +
> +static void
> +emit_mul (void)
> +{
> +  target_emit_ops ()->emit_mul ();
> +}
> +
> +static void
> +emit_lsh (void)
> +{
> +  target_emit_ops ()->emit_lsh ();
> +}
> +
> +static void
> +emit_rsh_signed (void)
> +{
> +  target_emit_ops ()->emit_rsh_signed ();
> +}
> +
> +static void
> +emit_rsh_unsigned (void)
> +{
> +  target_emit_ops ()->emit_rsh_unsigned ();
> +}
> +
> +static void
> +emit_ext (int arg)
> +{
> +  target_emit_ops ()->emit_ext (arg);
> +}
> +
> +static void
> +emit_log_not (void)
> +{
> +  target_emit_ops ()->emit_log_not ();
> +}
> +
> +static void
> +emit_bit_and (void)
> +{
> +  target_emit_ops ()->emit_bit_and ();
> +}
> +
> +static void
> +emit_bit_or (void)
> +{
> +  target_emit_ops ()->emit_bit_or ();
> +}
> +
> +static void
> +emit_bit_xor (void)
> +{
> +  target_emit_ops ()->emit_bit_xor ();
> +}
> +
> +static void
> +emit_bit_not (void)
> +{
> +  target_emit_ops ()->emit_bit_not ();
> +}
> +
> +static void
> +emit_equal (void)
> +{
> +  target_emit_ops ()->emit_equal ();
> +}
> +
> +static void
> +emit_less_signed (void)
> +{
> +  target_emit_ops ()->emit_less_signed ();
> +}
> +
> +static void
> +emit_less_unsigned (void)
> +{
> +  target_emit_ops ()->emit_less_unsigned ();
> +}
> +
> +static void
> +emit_ref (int size)
> +{
> +  target_emit_ops ()->emit_ref (size);
> +}
> +
> +static void
> +emit_if_goto (int *offset_p, int *size_p)
> +{
> +  target_emit_ops ()->emit_if_goto (offset_p, size_p);
> +}
> +
> +static void
> +emit_goto (int *offset_p, int *size_p)
> +{
> +  target_emit_ops ()->emit_goto (offset_p, size_p);
> +}
> +
> +static void
> +write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
> +{
> +  target_emit_ops ()->write_goto_address (from, to, size);
> +}
> +
> +static void
> +emit_const (int64_t num)
> +{
> +  target_emit_ops ()->emit_const (num);
> +}
> +
> +static void
> +emit_reg (int reg)
> +{
> +  target_emit_ops ()->emit_reg (reg);
> +}
> +
> +static void
> +emit_pop (void)
> +{
> +  target_emit_ops ()->emit_pop ();
> +}
> +
> +static void
> +emit_stack_flush (void)
> +{
> +  target_emit_ops ()->emit_stack_flush ();
> +}
> +
> +static void
> +emit_zero_ext (int arg)
> +{
> +  target_emit_ops ()->emit_zero_ext (arg);
> +}
> +
> +static void
> +emit_swap (void)
> +{
> +  target_emit_ops ()->emit_swap ();
> +}
> +
> +static void
> +emit_stack_adjust (int n)
> +{
> +  target_emit_ops ()->emit_stack_adjust (n);
> +}
> +
> +/* FN's prototype is `LONGEST(*fn)(int)'.  */
> +
> +static void
> +emit_int_call_1 (CORE_ADDR fn, int arg1)
> +{
> +  target_emit_ops ()->emit_int_call_1 (fn, arg1);
> +}
> +
> +/* FN's prototype is `void(*fn)(int,int64_t)'.  */
> +
> +static void
> +emit_void_call_2 (CORE_ADDR fn, int arg1)
> +{
> +  target_emit_ops ()->emit_void_call_2 (fn, arg1);
> +}
> +
> +static enum eval_result_type compile_bytecodes (struct agent_expr *aexpr);
> +
> +static void
> +compile_tracepoint_condition (struct tracepoint *tpoint, CORE_ADDR *jump_entry)
> +{
> +  CORE_ADDR entry_point = *jump_entry;
> +  enum eval_result_type err;
> +
> +  trace_debug ("Starting condition compilation for tracepoint %d\n",
> +              tpoint->number);
> +
> +  /* Initialize the global pointer to the code being built.  */
> +  current_insn_ptr = *jump_entry;
> +
> +  emit_prologue ();
> +
> +  err = compile_bytecodes (tpoint->cond);
> +
> +  if (err == expr_eval_no_error)
> +    {
> +      emit_epilogue ();
> +
> +      /* Record the beginning of the compiled code.  */
> +      tpoint->compiled_cond = entry_point;
> +
> +      trace_debug ("Condition compilation for tracepoint %d complete\n",
> +                  tpoint->number);
> +    }
> +  else
> +    {
> +      /* Leave the unfinished code in situ, but don't point to it.  */
> +
> +      tpoint->compiled_cond = 0;
> +
> +      trace_debug ("Condition compilation for tracepoint %d failed, "
> +                  "error code %d",
> +                  tpoint->number, err);
> +    }
> +
> +  /* Update the code pointer passed in.  Note that we do this even if
> +     the compile fails, so that we can look at the partial results
> +     instead of letting them be overwritten.  */
> +  *jump_entry = current_insn_ptr;
> +
> +  /* Leave a gap, to aid dump decipherment.  */
> +  *jump_entry += 16;
> +}
> +
> +/* Given an agent expression, turn it into native code.  */
> +
> +static enum eval_result_type
> +compile_bytecodes (struct agent_expr *aexpr)
> +{
> +  int pc = 0;
> +  int done = 0;
> +  unsigned char op;
> +  int arg;
> +  /* This is only used to build 64-bit value for constants.  */
> +  ULONGEST top;
> +  struct bytecode_address *aentry, *aentry2;
> +
> +#define UNHANDLED                                      \
> +  do                                                   \
> +    {                                                  \
> +      trace_debug ("Cannot compile op 0x%x\n", op);    \
> +      return expr_eval_unhandled_opcode;               \
> +    } while (0)
> +
> +  if (aexpr->length == 0)
> +    {
> +      trace_debug ("empty agent expression\n");
> +      return expr_eval_empty_expression;
> +    }
> +
> +  bytecode_address_table = NULL;
> +
> +  while (!done)
> +    {
> +      op = aexpr->bytes[pc];
> +
> +      trace_debug ("About to compile op 0x%x, pc=%d\n", op, pc);
> +
> +      /* Record the compiled-code address of the bytecode, for use by
> +        jump instructions.  */
> +      aentry = xmalloc (sizeof (struct bytecode_address));
> +      aentry->pc = pc;
> +      aentry->address = current_insn_ptr;
> +      aentry->goto_pc = -1;
> +      aentry->from_offset = aentry->from_size = 0;
> +      aentry->next = bytecode_address_table;
> +      bytecode_address_table = aentry;
> +
> +      ++pc;
> +
> +      emit_error = 0;
> +
> +      switch (op)
> +       {
> +       case gdb_agent_op_add:
> +         emit_add ();
> +         break;
> +
> +       case gdb_agent_op_sub:
> +         emit_sub ();
> +         break;
> +
> +       case gdb_agent_op_mul:
> +         emit_mul ();
> +         break;
> +
> +       case gdb_agent_op_div_signed:
> +         UNHANDLED;
> +         break;
> +
> +       case gdb_agent_op_div_unsigned:
> +         UNHANDLED;
> +         break;
> +
> +       case gdb_agent_op_rem_signed:
> +         UNHANDLED;
> +         break;
> +
> +       case gdb_agent_op_rem_unsigned:
> +         UNHANDLED;
> +         break;
> +
> +       case gdb_agent_op_lsh:
> +         emit_lsh ();
> +         break;
> +
> +       case gdb_agent_op_rsh_signed:
> +         emit_rsh_signed ();
> +         break;
> +
> +       case gdb_agent_op_rsh_unsigned:
> +         emit_rsh_unsigned ();
> +         break;
> +
> +       case gdb_agent_op_trace:
> +         UNHANDLED;
> +         break;
> +
> +       case gdb_agent_op_trace_quick:
> +         UNHANDLED;
> +         break;
> +
> +       case gdb_agent_op_log_not:
> +         emit_log_not ();
> +         break;
> +
> +       case gdb_agent_op_bit_and:
> +         emit_bit_and ();
> +         break;
> +
> +       case gdb_agent_op_bit_or:
> +         emit_bit_or ();
> +         break;
> +
> +       case gdb_agent_op_bit_xor:
> +         emit_bit_xor ();
> +         break;
> +
> +       case gdb_agent_op_bit_not:
> +         emit_bit_not ();
> +         break;
> +
> +       case gdb_agent_op_equal:
> +         emit_equal ();
> +         break;
> +
> +       case gdb_agent_op_less_signed:
> +         emit_less_signed ();
> +         break;
> +
> +       case gdb_agent_op_less_unsigned:
> +         emit_less_unsigned ();
> +         break;
> +
> +       case gdb_agent_op_ext:
> +         arg = aexpr->bytes[pc++];
> +         if (arg < (sizeof (LONGEST) * 8))
> +           emit_ext (arg);
> +         break;
> +
> +       case gdb_agent_op_ref8:
> +         emit_ref (1);
> +         break;
> +
> +       case gdb_agent_op_ref16:
> +         emit_ref (2);
> +         break;
> +
> +       case gdb_agent_op_ref32:
> +         emit_ref (4);
> +         break;
> +
> +       case gdb_agent_op_ref64:
> +         emit_ref (8);
> +         break;
> +
> +       case gdb_agent_op_if_goto:
> +         arg = aexpr->bytes[pc++];
> +         arg = (arg << 8) + aexpr->bytes[pc++];
> +         aentry->goto_pc = arg;
> +         emit_if_goto (&(aentry->from_offset), &(aentry->from_size));
> +         break;
> +
> +       case gdb_agent_op_goto:
> +         arg = aexpr->bytes[pc++];
> +         arg = (arg << 8) + aexpr->bytes[pc++];
> +         aentry->goto_pc = arg;
> +         emit_goto (&(aentry->from_offset), &(aentry->from_size));
> +         break;
> +
> +       case gdb_agent_op_const8:
> +         emit_stack_flush ();
> +         top = aexpr->bytes[pc++];
> +         emit_const (top);
> +         break;
> +
> +       case gdb_agent_op_const16:
> +         emit_stack_flush ();
> +         top = aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         emit_const (top);
> +         break;
> +
> +       case gdb_agent_op_const32:
> +         emit_stack_flush ();
> +         top = aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         emit_const (top);
> +         break;
> +
> +       case gdb_agent_op_const64:
> +         emit_stack_flush ();
> +         top = aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         top = (top << 8) + aexpr->bytes[pc++];
> +         emit_const (top);
> +         break;
> +
> +       case gdb_agent_op_reg:
> +         emit_stack_flush ();
> +         arg = aexpr->bytes[pc++];
> +         arg = (arg << 8) + aexpr->bytes[pc++];
> +         emit_reg (arg);
> +         break;
> +
> +       case gdb_agent_op_end:
> +         trace_debug ("At end of expression\n");
> +
> +         /* Assume there is one stack element left, and that it is
> +            cached in "top" where emit_epilogue can get to it.  */
> +         emit_stack_adjust (1);
> +
> +         done = 1;
> +         break;
> +
> +       case gdb_agent_op_dup:
> +         /* In our design, dup is equivalent to stack flushing.  */
> +         emit_stack_flush ();
> +         break;
> +
> +       case gdb_agent_op_pop:
> +         emit_pop ();
> +         break;
> +
> +       case gdb_agent_op_zero_ext:
> +         arg = aexpr->bytes[pc++];
> +         if (arg < (sizeof (LONGEST) * 8))
> +           emit_zero_ext (arg);
> +         break;
> +
> +       case gdb_agent_op_swap:
> +         emit_swap ();
> +         break;
> +
> +       case gdb_agent_op_getv:
> +         emit_stack_flush ();
> +         arg = aexpr->bytes[pc++];
> +         arg = (arg << 8) + aexpr->bytes[pc++];
> +         emit_int_call_1 (ipa_sym_addrs.addr_get_trace_state_variable_value,
> +                          arg);
> +         break;
> +
> +       case gdb_agent_op_setv:
> +         arg = aexpr->bytes[pc++];
> +         arg = (arg << 8) + aexpr->bytes[pc++];
> +         emit_void_call_2 (ipa_sym_addrs.addr_set_trace_state_variable_value,
> +                           arg);
> +         break;
> +
> +       case gdb_agent_op_tracev:
> +         UNHANDLED;
> +         break;
> +
> +         /* GDB never (currently) generates any of these ops.  */
> +       case gdb_agent_op_float:
> +       case gdb_agent_op_ref_float:
> +       case gdb_agent_op_ref_double:
> +       case gdb_agent_op_ref_long_double:
> +       case gdb_agent_op_l_to_d:
> +       case gdb_agent_op_d_to_l:
> +       case gdb_agent_op_trace16:
> +         UNHANDLED;
> +         break;
> +
> +       default:
> +         trace_debug ("Agent expression op 0x%x not recognized\n", op);
> +         /* Don't struggle on, things will just get worse.  */
> +         return expr_eval_unrecognized_opcode;
> +       }
> +
> +      /* This catches errors that occur in target-specific code
> +        emission.  */
> +      if (emit_error)
> +       {
> +         trace_debug ("Error %d while emitting code for %s\n",
> +                      emit_error, gdb_agent_op_names[op]);
> +         return expr_eval_unhandled_opcode;
> +       }
> +
> +      trace_debug ("Op %s compiled\n", gdb_agent_op_names[op]);
> +    }
> +
> +  /* Now fill in real addresses as goto destinations.  */
> +  for (aentry = bytecode_address_table; aentry; aentry = aentry->next)
> +    {
> +      int written = 0;
> +
> +      if (aentry->goto_pc < 0)
> +       continue;
> +
> +      /* Find the location that we are going to, and call back into
> +        target-specific code to write the actual address or
> +        displacement.  */
> +      for (aentry2 = bytecode_address_table; aentry2; aentry2 = aentry2->next)
> +       {
> +         if (aentry2->pc == aentry->goto_pc)
> +           {
> +             trace_debug ("Want to jump from %s to %s\n",
> +                          paddress (aentry->address),
> +                          paddress (aentry2->address));
> +             write_goto_address (aentry->address + aentry->from_offset,
> +                                 aentry2->address, aentry->from_size);
> +             written = 1;
> +             break;
> +           }
> +       }
> +
> +      /* Error out if we didn't find a destination.  */
> +      if (!written)
> +       {
> +         trace_debug ("Destination of goto %d not found\n",
> +                      aentry->goto_pc);
> +         return expr_eval_invalid_goto;
> +       }
> +    }
> +
> +  return expr_eval_no_error;
> +}
> +
>  /* We'll need to adjust these when we consider bi-arch setups, and big
>     endian machines.  */
> 
> @@ -5022,6 +5618,28 @@ download_tracepoints (void)
>        if (tpoint->type != fast_tracepoint)
>         continue;
> 
> +      /* Maybe download a compiled condition.  */
> +      if (tpoint->cond != NULL && target_emit_ops() != NULL)
> +       {
> +         CORE_ADDR jentry, jump_entry;
> +
> +         jentry = jump_entry = get_jump_space_head ();
> +
> +         if (tpoint->cond != NULL)
> +           {
> +             /* Pad to 8-byte alignment. (needed?)  */
> +             /* Actually this should be left for the target to
> +                decide.  */
> +             jentry = UALIGN (jentry, 8);
> +
> +             compile_tracepoint_condition (tpoint, &jentry);
> +           }
> +
> +         /* Pad to 8-byte alignment.  */
> +         jentry = UALIGN (jentry, 8);
> +         claim_jump_space (jentry - jump_entry);
> +       }
> +
>        target_tracepoint = *tpoint;
> 
>        prev_tpptr = tpptr;
> Index: src/gdb/gdbserver/target.h
> ===================================================================
> --- src.orig/gdb/gdbserver/target.h     2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/target.h  2010-06-07 16:13:24.000000000 +0100
> @@ -22,6 +22,8 @@
>  #ifndef TARGET_H
>  #define TARGET_H
> 
> +struct emit_ops;
> +
>  /* Ways to "resume" a thread.  */
> 
>  enum resume_kind
> @@ -349,6 +351,10 @@ struct target_ops
>                                            ULONGEST *jjump_pad_insn_size,
>                                            CORE_ADDR *adjusted_insn_addr,
>                                            CORE_ADDR *adjusted_insn_addr_end);
> +
> +  /* Return the bytecode operations vector for the current inferior.
> +     Returns NULL if bytecode compilation is not supported.  */
> +  struct emit_ops *(*emit_ops) (void);
>  };
> 
>  extern struct target_ops *the_target;
> @@ -452,6 +458,8 @@ void set_target_ops (struct target_ops *
>                                                    adjusted_insn_addr,  \
>                                                    adjusted_insn_addr_end)
> 
> +#define target_emit_ops() (*the_target->emit_ops) ()
> +
>  /* Start non-stop mode, returns 0 on success, -1 on failure.   */
> 
>  int start_non_stop (int nonstop);
> Index: src/gdb/gdbserver/linux-amd64-ipa.c
> ===================================================================
> --- src.orig/gdb/gdbserver/linux-amd64-ipa.c    2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/linux-amd64-ipa.c 2010-06-07 16:13:24.000000000 +0100
> @@ -66,6 +66,15 @@ supply_fast_tracepoint_registers (struct
>                      ((char *) buf) + x86_64_ft_collect_regmap[i]);
>  }
> 
> +ULONGEST __attribute__ ((visibility("default"), used))
> +gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
> +{
> +  if (regnum > X86_64_NUM_FT_COLLECT_GREGS)
> +    return 0;
> +
> +  return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
> +}
> +
>  /* This is only needed because reg-i386-linux-lib.o references it.  We
>     may use it proper at some point.  */
>  const char *gdbserver_xmltarget;
> Index: src/gdb/gdbserver/linux-low.c
> ===================================================================
> --- src.orig/gdb/gdbserver/linux-low.c  2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/linux-low.c       2010-06-07 16:13:24.000000000 +0100
> @@ -5054,6 +5054,15 @@ linux_install_fast_tracepoint_jump_pad (
>       adjusted_insn_addr, adjusted_insn_addr_end);
>  }
> 
> +static struct emit_ops *
> +linux_emit_ops (void)
> +{
> +  if (the_low_target.emit_ops != NULL)
> +    return (*the_low_target.emit_ops) ();
> +  else
> +    return NULL;
> +}
> +
>  static struct target_ops linux_target_ops = {
>    linux_create_inferior,
>    linux_attach,
> @@ -5109,7 +5118,8 @@ static struct target_ops linux_target_op
>    linux_unpause_all,
>    linux_cancel_breakpoints,
>    linux_stabilize_threads,
> -  linux_install_fast_tracepoint_jump_pad
> +  linux_install_fast_tracepoint_jump_pad,
> +  linux_emit_ops
>  };
> 
>  static void
> Index: src/gdb/gdbserver/linux-low.h
> ===================================================================
> --- src.orig/gdb/gdbserver/linux-low.h  2010-06-07 16:13:07.000000000 +0100
> +++ src/gdb/gdbserver/linux-low.h       2010-06-07 16:13:24.000000000 +0100
> @@ -136,6 +136,10 @@ struct linux_target_ops
>                                            ULONGEST *jjump_pad_insn_size,
>                                            CORE_ADDR *adjusted_insn_addr,
>                                            CORE_ADDR *adjusted_insn_addr_end);
> +
> +  /* Return the bytecode operations vector for the current inferior.
> +     Returns NULL if bytecode compilation is not supported.  */
> +  struct emit_ops *(*emit_ops) (void);
>  };
> 
>  extern struct linux_target_ops the_low_target;
> Index: src/gdb/gdbserver/linux-i386-ipa.c
> ===================================================================
> --- src.orig/gdb/gdbserver/linux-i386-ipa.c     2010-06-07 16:43:41.000000000 +0100
> +++ src/gdb/gdbserver/linux-i386-ipa.c  2010-06-07 16:44:45.000000000 +0100
> @@ -95,6 +95,21 @@ supply_fast_tracepoint_registers (struct
>      }
>  }
> 
> +ULONGEST __attribute__ ((visibility("default"), used))
> +gdb_agent_get_raw_reg (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,
> +     or something.  */
> +
> +  if (regnum > i386_num_regs)
> +    return 0;
> +  else if (regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM)
> +    return *(short *) (raw_regs + i386_ft_collect_regmap[regnum]);
> +  else
> +    return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
> +}
> +
>  /* This is only needed because reg-i386-linux-lib.o references it.  We
>     may use it proper at some point.  */
>  const char *gdbserver_xmltarget;

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-07 16:04 ` Michael Snyder
@ 2010-06-07 16:35   ` Joel Brobecker
  0 siblings, 0 replies; 31+ messages in thread
From: Joel Brobecker @ 2010-06-07 16:35 UTC (permalink / raw)
  To: Michael Snyder; +Cc: Pedro Alves, gdb-patches

> gdbserver has sure come a long way from the simple remote debug agent
> that it started out to be.  Is anybody at all worried about the ever
> increasing complexification of gdbserver?

I personally am not.  I am a little preoccupied with the fact that
we seem to be duplicating more and more code between the gdbserver
and GDB, and one of these days we'll probably want to bite the bullet
and make the GDB code use the gdbserver target-side of the code
(read/write memory, step/run/continue, etc).  But in the meantime,
Pedro and others seem to be well on top of things :).

-- 
Joel

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-07 16:00 [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints) Pedro Alves
  2010-06-07 16:04 ` Michael Snyder
@ 2010-06-10 17:28 ` Tom Tromey
  2010-06-10 17:36   ` Pedro Alves
  1 sibling, 1 reply; 31+ messages in thread
From: Tom Tromey @ 2010-06-10 17:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

Pedro> This adds a bytecode compiler to the linux x86 ports of
Pedro> gdbserver, that turns agent expression bytecodes into
Pedro> native code.  This greatly speeds up conditional tracepoints
Pedro> (by around an order of magnitude) that usually don't reference much
Pedro> more than a few variables (memory/registers), to around 100ns or
Pedro> less on a typical modern x86 box.

This is awesome!  I think it deserves a NEWS entry.

Tom

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-10 17:28 ` Tom Tromey
@ 2010-06-10 17:36   ` Pedro Alves
  2010-06-10 18:43     ` Tom Tromey
  0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2010-06-10 17:36 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches

On Thursday 10 June 2010 18:27:48, Tom Tromey wrote:
> >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:
> 
> Pedro> This adds a bytecode compiler to the linux x86 ports of
> Pedro> gdbserver, that turns agent expression bytecodes into
> Pedro> native code.  This greatly speeds up conditional tracepoints
> Pedro> (by around an order of magnitude) that usually don't reference much
> Pedro> more than a few variables (memory/registers), to around 100ns or
> Pedro> less on a typical modern x86 box.
> 
> This is awesome!  I think it deserves a NEWS entry.

Hmmmm.  This is an implementation detail of gdbserver's fast
tracepoints, and gdbserver fast tracepoints are new in 7.2.  What
would we announce?

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-10 17:36   ` Pedro Alves
@ 2010-06-10 18:43     ` Tom Tromey
  2010-06-14 11:15       ` [NEWS/RFA] " Pedro Alves
  0 siblings, 1 reply; 31+ messages in thread
From: Tom Tromey @ 2010-06-10 18:43 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro> Hmmmm.  This is an implementation detail of gdbserver's fast
Pedro> tracepoints, and gdbserver fast tracepoints are new in 7.2.  What
Pedro> would we announce?

Just mention the JIT in the current paragraph.
JITting is cool, we should at least publicize it a little.

Tom

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-10 18:43     ` Tom Tromey
@ 2010-06-14 11:15       ` Pedro Alves
  2010-06-14 17:29         ` Eli Zaretskii
  0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2010-06-14 11:15 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Thursday 10 June 2010 19:43:37, Tom Tromey wrote:
> Pedro> Hmmmm.  This is an implementation detail of gdbserver's fast
> Pedro> tracepoints, and gdbserver fast tracepoints are new in 7.2.  What
> Pedro> would we announce?
> 
> Just mention the JIT in the current paragraph.
> JITting is cool, we should at least publicize it a little.

How about this, then?  Okay?

-- 
Pedro Alves

2010-06-14  Pedro Alves  <pedro@codesourcery.com>

	* NEWS: Mention GDBserver's JIT compilation of tracepoint
	bytecode.

---
 gdb/NEWS |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2010-06-14 11:59:21.000000000 +0100
+++ src/gdb/NEWS	2010-06-14 12:12:54.000000000 +0100
@@ -36,7 +36,14 @@ qRelocInsn
   - GDBserver now support tracepoints (including fast tracepoints).
     The feature is currently supported by the i386-linux and
     amd64-linux builds.  See the "Tracepoints support in gdbserver"
-    section in the manual for more information.
+    section in the manual for more information.  GDBserver JIT
+    compiles the tracepoint's conditional agent expression bytecode
+    into native code whenever possible for low overhead dynamic
+    tracepoints conditionals.  For such tracepoints, an expression
+    that examines program state is evaluated when the tracepoint is
+    reached, in order to determine whether to capture trace data.  If
+    the condition is simple and false, processing the tracepoint
+    finishes very quickly and no data is gathered.
 
   - GDBserver now supports x86_64 Windows 64-bit debugging.
 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-14 11:15       ` [NEWS/RFA] " Pedro Alves
@ 2010-06-14 17:29         ` Eli Zaretskii
  2010-06-14 22:19           ` Pedro Alves
  0 siblings, 1 reply; 31+ messages in thread
From: Eli Zaretskii @ 2010-06-14 17:29 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tromey, gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 14 Jun 2010 12:15:41 +0100
> Cc: gdb-patches@sourceware.org
> 
> On Thursday 10 June 2010 19:43:37, Tom Tromey wrote:
> > Pedro> Hmmmm.  This is an implementation detail of gdbserver's fast
> > Pedro> tracepoints, and gdbserver fast tracepoints are new in 7.2.  What
> > Pedro> would we announce?
> > 
> > Just mention the JIT in the current paragraph.
> > JITting is cool, we should at least publicize it a little.
> 
> How about this, then?  Okay?

Fine with me, thanks.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-14 17:29         ` Eli Zaretskii
@ 2010-06-14 22:19           ` Pedro Alves
  2010-06-16 18:57             ` Doug Evans
  0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2010-06-14 22:19 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii; +Cc: tromey

On Monday 14 June 2010 18:28:46, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > Date: Mon, 14 Jun 2010 12:15:41 +0100
> > Cc: gdb-patches@sourceware.org
> > 
> > On Thursday 10 June 2010 19:43:37, Tom Tromey wrote:
> > > Pedro> Hmmmm.  This is an implementation detail of gdbserver's fast
> > > Pedro> tracepoints, and gdbserver fast tracepoints are new in 7.2.  What
> > > Pedro> would we announce?
> > > 
> > > Just mention the JIT in the current paragraph.
> > > JITting is cool, we should at least publicize it a little.
> > 
> > How about this, then?  Okay?
> 
> Fine with me, thanks.

Thanks.  I've checked the whole thing in.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-14 22:19           ` Pedro Alves
@ 2010-06-16 18:57             ` Doug Evans
  2010-06-16 19:13               ` Stan Shebs
  0 siblings, 1 reply; 31+ messages in thread
From: Doug Evans @ 2010-06-16 18:57 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Eli Zaretskii, tromey

On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com> wrote:
>>
> Thanks.  I've checked the whole thing in.

I'm getting build failures that go away when compiling linux-x86-low.c with -g.

gcc is optimizing out the skipped over stuff I believe.


/* Our general strategy for emitting code is to avoid specifying raw
   bytes whenever possible, and instead copy a block of inline asm
   that is embedded in the function.  This is a little messy, because
   we need to keep the compiler from discarding what looks like dead
   code, plus suppress various warnings.  */

#define EMIT_ASM(NAME,INSNS)                                            \
  { extern unsigned char start_ ## NAME, end_ ## NAME;                  \
    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);       \
    if (always_true ())                                         \
      goto skipover ## NAME;                                            \
    __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");    \
    skipover ## NAME:                                                   \
    ; }

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-16 18:57             ` Doug Evans
@ 2010-06-16 19:13               ` Stan Shebs
  2010-06-16 19:16                 ` Pedro Alves
  0 siblings, 1 reply; 31+ messages in thread
From: Stan Shebs @ 2010-06-16 19:13 UTC (permalink / raw)
  To: Doug Evans; +Cc: Pedro Alves, gdb-patches, Eli Zaretskii, tromey

Doug Evans wrote:
> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com> wrote:
>   
>> Thanks.  I've checked the whole thing in.
>>     
>
> I'm getting build failures that go away when compiling linux-x86-low.c with -g.
>
> gcc is optimizing out the skipped over stuff I believe.
>   

Hmm, this particular trickery was my idea, but it always seemed 
vulnerable to ever-smarter optimization.  Does anybody have any better 
strategy?  Declaring the asm volatile didn't work, because the compiler 
was whacking everything around it.

The other approach is to build up instructions from bitfields, which is 
reliable but needs a lot of setup and helper routines.

Stan
>
> /* Our general strategy for emitting code is to avoid specifying raw
>    bytes whenever possible, and instead copy a block of inline asm
>    that is embedded in the function.  This is a little messy, because
>    we need to keep the compiler from discarding what looks like dead
>    code, plus suppress various warnings.  */
>
> #define EMIT_ASM(NAME,INSNS)                                            \
>   { extern unsigned char start_ ## NAME, end_ ## NAME;                  \
>     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);       \
>     if (always_true ())                                         \
>       goto skipover ## NAME;                                            \
>     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");    \
>     skipover ## NAME:                                                   \
>     ; }
>
>   

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-16 19:13               ` Stan Shebs
@ 2010-06-16 19:16                 ` Pedro Alves
  2010-06-16 19:21                   ` Doug Evans
  2010-06-16 19:31                   ` Stan Shebs
  0 siblings, 2 replies; 31+ messages in thread
From: Pedro Alves @ 2010-06-16 19:16 UTC (permalink / raw)
  To: Stan Shebs; +Cc: Doug Evans, gdb-patches, Eli Zaretskii, tromey

On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
> Doug Evans wrote:
> > On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> >   
> >> Thanks.  I've checked the whole thing in.
> >>     
> >
> > I'm getting build failures that go away when compiling linux-x86-low.c with -g.
> >
> > gcc is optimizing out the skipped over stuff I believe.
> >   
> 
> Hmm, this particular trickery was my idea, but it always seemed 
> vulnerable to ever-smarter optimization.  Does anybody have any better 
> strategy?  Declaring the asm volatile didn't work, because the compiler 
> was whacking everything around it.
> 
> The other approach is to build up instructions from bitfields, which is 
> reliable but needs a lot of setup and helper routines.

Quick thought: can we stick a couple of __attribute__((used))'s in the
macro, so the compiler doesn optimized things away, thinking they're
unused (given the uses are behind asm)?

> 
> Stan
> >
> > /* Our general strategy for emitting code is to avoid specifying raw
> >    bytes whenever possible, and instead copy a block of inline asm
> >    that is embedded in the function.  This is a little messy, because
> >    we need to keep the compiler from discarding what looks like dead
> >    code, plus suppress various warnings.  */
> >
> > #define EMIT_ASM(NAME,INSNS)                                            \
> >   { extern unsigned char start_ ## NAME, end_ ## NAME;                  \
> >     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);       \
> >     if (always_true ())                                         \
> >       goto skipover ## NAME;                                            \
> >     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");    \
> >     skipover ## NAME:                                                   \
> >     ; }
> >
> >   
> 
> 


-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-16 19:16                 ` Pedro Alves
@ 2010-06-16 19:21                   ` Doug Evans
  2010-06-16 23:58                     ` Ian Lance Taylor
  2010-06-16 19:31                   ` Stan Shebs
  1 sibling, 1 reply; 31+ messages in thread
From: Doug Evans @ 2010-06-16 19:21 UTC (permalink / raw)
  To: Pedro Alves, Ian Lance Taylor
  Cc: Stan Shebs, gdb-patches, Eli Zaretskii, tromey

On Wed, Jun 16, 2010 at 12:16 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>> Doug Evans wrote:
>> > On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com> wrote:
>> >
>> >> Thanks.  I've checked the whole thing in.
>> >>
>> >
>> > I'm getting build failures that go away when compiling linux-x86-low.c with -g.
>> >
>> > gcc is optimizing out the skipped over stuff I believe.
>> >
>>
>> Hmm, this particular trickery was my idea, but it always seemed
>> vulnerable to ever-smarter optimization.  Does anybody have any better
>> strategy?  Declaring the asm volatile didn't work, because the compiler
>> was whacking everything around it.
>>
>> The other approach is to build up instructions from bitfields, which is
>> reliable but needs a lot of setup and helper routines.
>
> Quick thought: can we stick a couple of __attribute__((used))'s in the
> macro, so the compiler doesn optimized things away, thinking they're
> unused (given the uses are behind asm)?
>
>>
>> Stan
>> >
>> > /* Our general strategy for emitting code is to avoid specifying raw
>> >    bytes whenever possible, and instead copy a block of inline asm
>> >    that is embedded in the function.  This is a little messy, because
>> >    we need to keep the compiler from discarding what looks like dead
>> >    code, plus suppress various warnings.  */
>> >
>> > #define EMIT_ASM(NAME,INSNS)                                            \
>> >   { extern unsigned char start_ ## NAME, end_ ## NAME;                  \
>> >     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);       \
>> >     if (always_true ())                                         \
>> >       goto skipover ## NAME;                                            \
>> >     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");    \
>> >     skipover ## NAME:                                                   \
>> >     ; }

This worked with the gcc4.4.0 variant I was using.

Ian: Is there a Right way to do this?

2010-06-16  Doug Evans  <dje@google.com>

        * linux-x86-low.c (always_true): Change to global.
        (EMIT_ASM, EMIT_ASM32): Update.

Index: linux-x86-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-x86-low.c,v
retrieving revision 1.19
diff -u -p -r1.19 linux-x86-low.c
--- linux-x86-low.c     15 Jun 2010 10:44:48 -0000      1.19
+++ linux-x86-low.c     16 Jun 2010 19:15:21 -0000
@@ -1484,13 +1484,8 @@ add_insns (unsigned char *start, int len
   current_insn_ptr = buildaddr;
 }

-/* A function used to trick optimizers.  */
-
-int
-always_true (void)
-{
-  return 1;
-}
+/* Used to trick optimizers.  */
+static volatile int always_true = 1;

 /* Our general strategy for emitting code is to avoid specifying raw
    bytes whenever possible, and instead copy a block of inline asm
@@ -1501,7 +1496,7 @@ always_true (void)
 #define EMIT_ASM(NAME,INSNS)                                           \
   { extern unsigned char start_ ## NAME, end_ ## NAME;                 \
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);      \
-    if (always_true ())                                                \
+    if (always_true)                                           \
       goto skipover ## NAME;                                           \
     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");   \
     skipover ## NAME:                                                  \
@@ -1513,7 +1508,7 @@ always_true (void)
 #define EMIT_ASM32(NAME,INSNS)                                         \
   { extern unsigned char start_ ## NAME, end_ ## NAME;                 \
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);      \
-    if (always_true ())                                                \
+    if (always_true)                                           \
       goto skipover ## NAME;                                           \
     __asm__ (".code32\n\tstart_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n" \
             "\t.code64\n\t");                                          \

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-16 19:16                 ` Pedro Alves
  2010-06-16 19:21                   ` Doug Evans
@ 2010-06-16 19:31                   ` Stan Shebs
  2010-06-17 18:03                     ` Michael Snyder
  1 sibling, 1 reply; 31+ messages in thread
From: Stan Shebs @ 2010-06-16 19:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Stan Shebs, Doug Evans, gdb-patches, Eli Zaretskii, tromey

Pedro Alves wrote:
> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>   
>> Doug Evans wrote:
>>     
>>> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com> wrote:
>>>   
>>>       
>>>> Thanks.  I've checked the whole thing in.
>>>>     
>>>>         
>>> I'm getting build failures that go away when compiling linux-x86-low.c with -g.
>>>
>>> gcc is optimizing out the skipped over stuff I believe.
>>>   
>>>       
>> Hmm, this particular trickery was my idea, but it always seemed 
>> vulnerable to ever-smarter optimization.  Does anybody have any better 
>> strategy?  Declaring the asm volatile didn't work, because the compiler 
>> was whacking everything around it.
>>
>> The other approach is to build up instructions from bitfields, which is 
>> reliable but needs a lot of setup and helper routines.
>>     
>
> Quick thought: can we stick a couple of __attribute__((used))'s in the
> macro, so the compiler doesn optimized things away, thinking they're
> unused (given the uses are behind asm)?
>   

The compiler is discarding the code with the definitions of the labels, 
because it's thinking they are maybe somewhere else in the program (the 
error is at link time).  Moving the labels into C code would fix that I 
think, but then it's hard to guarantee that the compiler won't sneak in 
a bit of code between label and asm sequence.

Stan

>> Stan
>>     
>>> /* Our general strategy for emitting code is to avoid specifying raw
>>>    bytes whenever possible, and instead copy a block of inline asm
>>>    that is embedded in the function.  This is a little messy, because
>>>    we need to keep the compiler from discarding what looks like dead
>>>    code, plus suppress various warnings.  */
>>>
>>> #define EMIT_ASM(NAME,INSNS)                                            \
>>>   { extern unsigned char start_ ## NAME, end_ ## NAME;                  \
>>>     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);       \
>>>     if (always_true ())                                         \
>>>       goto skipover ## NAME;                                            \
>>>     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");    \
>>>     skipover ## NAME:                                                   \
>>>     ; }
>>>
>>>   
>>>       
>>     
>
>
>   

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-16 19:21                   ` Doug Evans
@ 2010-06-16 23:58                     ` Ian Lance Taylor
  2010-06-20 22:27                       ` Pedro Alves
  0 siblings, 1 reply; 31+ messages in thread
From: Ian Lance Taylor @ 2010-06-16 23:58 UTC (permalink / raw)
  To: Doug Evans; +Cc: Pedro Alves, Stan Shebs, gdb-patches, Eli Zaretskii, tromey

Doug Evans <dje@google.com> writes:

> This worked with the gcc4.4.0 variant I was using.
>
> Ian: Is there a Right way to do this?

I don't know about a right way, but since this code is both gcc and
x86 specific, I think I would just write something along the lines of

#define EMIT_ASM(NAME, INSNS) \
  do \
   { \
     extern unsigned char start_ ## NAME, end_ ## NAME; \
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME); \
     asm ("jmp end_" NAME "\; start_" NAME ":\;" INSNS "\; end_" NAME ":"); \
   } while (0)

Ian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints)
  2010-06-16 19:31                   ` Stan Shebs
@ 2010-06-17 18:03                     ` Michael Snyder
  2010-06-19 16:13                       ` Hui Zhu
  0 siblings, 1 reply; 31+ messages in thread
From: Michael Snyder @ 2010-06-17 18:03 UTC (permalink / raw)
  To: Stan Shebs; +Cc: Pedro Alves, Doug Evans, gdb-patches, Eli Zaretskii, tromey

Stan Shebs wrote:
> Pedro Alves wrote:
>> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>>   
>>> Doug Evans wrote:
>>>     
>>>> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com> wrote:
>>>>   
>>>>       
>>>>> Thanks.  I've checked the whole thing in.
>>>>>     
>>>>>         
>>>> I'm getting build failures that go away when compiling linux-x86-low.c with -g.
>>>>
>>>> gcc is optimizing out the skipped over stuff I believe.
>>>>   
>>>>       
>>> Hmm, this particular trickery was my idea, but it always seemed 
>>> vulnerable to ever-smarter optimization.  Does anybody have any better 
>>> strategy?  Declaring the asm volatile didn't work, because the compiler 
>>> was whacking everything around it.
>>>
>>> The other approach is to build up instructions from bitfields, which is 
>>> reliable but needs a lot of setup and helper routines.
>>>     
>> Quick thought: can we stick a couple of __attribute__((used))'s in the
>> macro, so the compiler doesn optimized things away, thinking they're
>> unused (given the uses are behind asm)?
>>   
> 
> The compiler is discarding the code with the definitions of the labels, 
> because it's thinking they are maybe somewhere else in the program (the 
> error is at link time).  Moving the labels into C code would fix that I 
> think, but then it's hard to guarantee that the compiler won't sneak in 
> a bit of code between label and asm sequence.

Hurrr.  Code that depends on such deep knowledge of the compiler's
behavior is wrong code, IMO.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-17 18:03                     ` Michael Snyder
@ 2010-06-19 16:13                       ` Hui Zhu
  2010-06-19 16:16                         ` Doug Evans
  2010-06-20 18:31                         ` [NEWS/RFA] Re: [gdbserver] " Tom Tromey
  0 siblings, 2 replies; 31+ messages in thread
From: Hui Zhu @ 2010-06-19 16:13 UTC (permalink / raw)
  To: Pedro Alves
  Cc: Stan Shebs, Doug Evans, gdb-patches, Eli Zaretskii, tromey,
	Michael Snyder

lubuntu 10.04:

make[4]: ?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
rm -f gdbserver
gcc -Wall -g -O2    -I. -I../../../src/gdb/gdbserver
-I../../../src/gdb/gdbserver/../common
-I../../../src/gdb/gdbserver/../regformats
-I../../../src/gdb/gdbserver/../../include
-Wl,--dynamic-list=../../../src/gdb/gdbserver/proc-service.list -o
gdbserver inferiors.o regcache.o remote-utils.o server.o signals.o
target.o utils.o version.o mem-break.o hostio.o event-loop.o
tracepoint.o xml-builtin.o i386-linux.o i386-avx-linux.o
i386-mmx-linux.o linux-low.o linux-x86-low.o i386-low.o i387-fp.o
hostio-errno.o thread-db.o proc-service.o  \
	  -ldl
linux-x86-low.o: In function `i386_emit_void_call_2':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
undefined reference to `end_i386_void_call_2_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
undefined reference to `start_i386_void_call_2_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
undefined reference to `start_i386_void_call_2_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
undefined reference to `end_i386_void_call_2_b'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
undefined reference to `start_i386_void_call_2_b'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
undefined reference to `start_i386_void_call_2_b'
linux-x86-low.o: In function `i386_emit_int_call_1':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
undefined reference to `end_i386_int_call_1_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
undefined reference to `start_i386_int_call_1_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
undefined reference to `start_i386_int_call_1_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
undefined reference to `end_i386_int_call_1_c'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
undefined reference to `start_i386_int_call_1_c'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
undefined reference to `start_i386_int_call_1_c'
linux-x86-low.o: In function `i386_emit_swap':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
undefined reference to `end_i386_swap'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
undefined reference to `start_i386_swap'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
undefined reference to `start_i386_swap'
linux-x86-low.o: In function `i386_emit_zero_ext':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
undefined reference to `end_i386_zero_ext_8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
undefined reference to `start_i386_zero_ext_8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
undefined reference to `start_i386_zero_ext_8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
undefined reference to `end_i386_zero_ext_32'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
undefined reference to `start_i386_zero_ext_32'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
undefined reference to `start_i386_zero_ext_32'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
undefined reference to `end_i386_zero_ext_16'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
undefined reference to `start_i386_zero_ext_16'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
undefined reference to `start_i386_zero_ext_16'
linux-x86-low.o: In function `i386_emit_stack_flush':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
undefined reference to `end_i386_stack_flush'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
undefined reference to `start_i386_stack_flush'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
undefined reference to `start_i386_stack_flush'
linux-x86-low.o: In function `i386_emit_pop':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
undefined reference to `end_i386_pop'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
undefined reference to `start_i386_pop'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
undefined reference to `start_i386_pop'
linux-x86-low.o: In function `i386_emit_goto':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
undefined reference to `end_i386_goto'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
undefined reference to `start_i386_goto'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
undefined reference to `start_i386_goto'
linux-x86-low.o: In function `i386_emit_if_goto':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
undefined reference to `end_i386_if_goto'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
undefined reference to `start_i386_if_goto'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
undefined reference to `start_i386_if_goto'
linux-x86-low.o: In function `i386_emit_ref':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
undefined reference to `end_i386_ref1'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
undefined reference to `start_i386_ref1'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
undefined reference to `start_i386_ref1'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
undefined reference to `end_i386_ref8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
undefined reference to `start_i386_ref8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
undefined reference to `start_i386_ref8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
undefined reference to `end_i386_ref2'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
undefined reference to `start_i386_ref2'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
undefined reference to `start_i386_ref2'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
undefined reference to `end_i386_ref4'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
undefined reference to `start_i386_ref4'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
undefined reference to `start_i386_ref4'
linux-x86-low.o: In function `i386_emit_less_unsigned':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
undefined reference to `end_i386_less_unsigned'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
undefined reference to `start_i386_less_unsigned'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
undefined reference to `start_i386_less_unsigned'
linux-x86-low.o: In function `i386_emit_less_signed':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
undefined reference to `end_i386_less_signed'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
undefined reference to `start_i386_less_signed'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
undefined reference to `start_i386_less_signed'
linux-x86-low.o: In function `i386_emit_equal':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
undefined reference to `end_i386_equal'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
undefined reference to `start_i386_equal'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
undefined reference to `start_i386_equal'
linux-x86-low.o: In function `i386_emit_bit_not':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
undefined reference to `end_i386_bit_not'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
undefined reference to `start_i386_bit_not'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
undefined reference to `start_i386_bit_not'
linux-x86-low.o: In function `i386_emit_bit_xor':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
undefined reference to `end_i386_xor'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
undefined reference to `start_i386_xor'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
undefined reference to `start_i386_xor'
linux-x86-low.o: In function `i386_emit_bit_or':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
undefined reference to `end_i386_or'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
undefined reference to `start_i386_or'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
undefined reference to `start_i386_or'
linux-x86-low.o: In function `i386_emit_bit_and':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
undefined reference to `end_i386_and'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
undefined reference to `start_i386_and'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
undefined reference to `start_i386_and'
linux-x86-low.o: In function `i386_emit_log_not':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
undefined reference to `end_i386_log_not'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
undefined reference to `start_i386_log_not'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
undefined reference to `start_i386_log_not'
linux-x86-low.o: In function `i386_emit_ext':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
undefined reference to `end_i386_ext_8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
undefined reference to `start_i386_ext_8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
undefined reference to `start_i386_ext_8'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
undefined reference to `end_i386_ext_32'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
undefined reference to `start_i386_ext_32'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
undefined reference to `start_i386_ext_32'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
undefined reference to `end_i386_ext_16'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
undefined reference to `start_i386_ext_16'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
undefined reference to `start_i386_ext_16'
linux-x86-low.o: In function `i386_emit_sub':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
undefined reference to `end_i386_sub'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
undefined reference to `start_i386_sub'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
undefined reference to `start_i386_sub'
linux-x86-low.o: In function `i386_emit_add':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
undefined reference to `end_i386_add'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
undefined reference to `start_i386_add'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
undefined reference to `start_i386_add'
linux-x86-low.o: In function `i386_emit_epilogue':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
undefined reference to `end_i386_epilogue'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
undefined reference to `start_i386_epilogue'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
undefined reference to `start_i386_epilogue'
linux-x86-low.o: In function `i386_emit_prologue':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
undefined reference to `end_i386_prologue'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
undefined reference to `start_i386_prologue'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
undefined reference to `start_i386_prologue'
linux-x86-low.o: In function `i386_emit_reg':
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
undefined reference to `end_i386_reg_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
undefined reference to `start_i386_reg_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
undefined reference to `start_i386_reg_a'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
undefined reference to `end_i386_reg_b'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
undefined reference to `start_i386_reg_b'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
undefined reference to `start_i386_reg_b'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
undefined reference to `end_i386_reg_c'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
undefined reference to `start_i386_reg_c'
/home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
undefined reference to `start_i386_reg_c'
collect2: ld returned 1 exit status
make[4]: *** [gdbserver] ?? 1
make[4]:?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
make[3]: *** [subdir_do] ?? 1
make[3]:?????? `/home/teawater/gdb/bgdball/gdb'
make[2]: *** [all] ?? 2
make[2]:?????? `/home/teawater/gdb/bgdball/gdb'
make[1]: *** [all-gdb] ?? 2
make[1]:?????? `/home/teawater/gdb/bgdball'


On Fri, Jun 18, 2010 at 02:03, Michael Snyder <msnyder@vmware.com> wrote:
> Stan Shebs wrote:
>>
>> Pedro Alves wrote:
>>>
>>> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>>>
>>>>
>>>> Doug Evans wrote:
>>>>
>>>>>
>>>>> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com>
>>>>> wrote:
>>>>>
>>>>>>
>>>>>> Thanks.  I've checked the whole thing in.
>>>>>>
>>>>>
>>>>> I'm getting build failures that go away when compiling linux-x86-low.c
>>>>> with -g.
>>>>>
>>>>> gcc is optimizing out the skipped over stuff I believe.
>>>>>
>>>>
>>>> Hmm, this particular trickery was my idea, but it always seemed
>>>> vulnerable to ever-smarter optimization.  Does anybody have any better
>>>> strategy?  Declaring the asm volatile didn't work, because the compiler was
>>>> whacking everything around it.
>>>>
>>>> The other approach is to build up instructions from bitfields, which is
>>>> reliable but needs a lot of setup and helper routines.
>>>>
>>>
>>> Quick thought: can we stick a couple of __attribute__((used))'s in the
>>> macro, so the compiler doesn optimized things away, thinking they're
>>> unused (given the uses are behind asm)?
>>>
>>
>> The compiler is discarding the code with the definitions of the labels,
>> because it's thinking they are maybe somewhere else in the program (the
>> error is at link time).  Moving the labels into C code would fix that I
>> think, but then it's hard to guarantee that the compiler won't sneak in a
>> bit of code between label and asm sequence.
>
> Hurrr.  Code that depends on such deep knowledge of the compiler's
> behavior is wrong code, IMO.
>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-19 16:13                       ` Hui Zhu
@ 2010-06-19 16:16                         ` Doug Evans
  2010-06-19 17:13                           ` Hui Zhu
  2010-06-20 18:31                         ` [NEWS/RFA] Re: [gdbserver] " Tom Tromey
  1 sibling, 1 reply; 31+ messages in thread
From: Doug Evans @ 2010-06-19 16:16 UTC (permalink / raw)
  To: Hui Zhu
  Cc: Pedro Alves, Stan Shebs, gdb-patches, Eli Zaretskii, tromey,
	Michael Snyder

Yeah.
Until it gets fixed a workaround is to compile linux-x86-low.c with -O0.


On Sat, Jun 19, 2010 at 9:12 AM, Hui Zhu <teawater@gmail.com> wrote:
> lubuntu 10.04:
>
> make[4]: ?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
> rm -f gdbserver
> gcc -Wall -g -O2    -I. -I../../../src/gdb/gdbserver
> -I../../../src/gdb/gdbserver/../common
> -I../../../src/gdb/gdbserver/../regformats
> -I../../../src/gdb/gdbserver/../../include
> -Wl,--dynamic-list=../../../src/gdb/gdbserver/proc-service.list -o
> gdbserver inferiors.o regcache.o remote-utils.o server.o signals.o
> target.o utils.o version.o mem-break.o hostio.o event-loop.o
> tracepoint.o xml-builtin.o i386-linux.o i386-avx-linux.o
> i386-mmx-linux.o linux-low.o linux-x86-low.o i386-low.o i387-fp.o
> hostio-errno.o thread-db.o proc-service.o  \
>          -ldl
> linux-x86-low.o: In function `i386_emit_void_call_2':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
> undefined reference to `end_i386_void_call_2_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
> undefined reference to `start_i386_void_call_2_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
> undefined reference to `start_i386_void_call_2_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
> undefined reference to `end_i386_void_call_2_b'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
> undefined reference to `start_i386_void_call_2_b'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
> undefined reference to `start_i386_void_call_2_b'
> linux-x86-low.o: In function `i386_emit_int_call_1':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
> undefined reference to `end_i386_int_call_1_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
> undefined reference to `start_i386_int_call_1_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
> undefined reference to `start_i386_int_call_1_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
> undefined reference to `end_i386_int_call_1_c'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
> undefined reference to `start_i386_int_call_1_c'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
> undefined reference to `start_i386_int_call_1_c'
> linux-x86-low.o: In function `i386_emit_swap':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
> undefined reference to `end_i386_swap'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
> undefined reference to `start_i386_swap'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
> undefined reference to `start_i386_swap'
> linux-x86-low.o: In function `i386_emit_zero_ext':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
> undefined reference to `end_i386_zero_ext_8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
> undefined reference to `start_i386_zero_ext_8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
> undefined reference to `start_i386_zero_ext_8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
> undefined reference to `end_i386_zero_ext_32'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
> undefined reference to `start_i386_zero_ext_32'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
> undefined reference to `start_i386_zero_ext_32'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
> undefined reference to `end_i386_zero_ext_16'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
> undefined reference to `start_i386_zero_ext_16'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
> undefined reference to `start_i386_zero_ext_16'
> linux-x86-low.o: In function `i386_emit_stack_flush':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
> undefined reference to `end_i386_stack_flush'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
> undefined reference to `start_i386_stack_flush'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
> undefined reference to `start_i386_stack_flush'
> linux-x86-low.o: In function `i386_emit_pop':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
> undefined reference to `end_i386_pop'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
> undefined reference to `start_i386_pop'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
> undefined reference to `start_i386_pop'
> linux-x86-low.o: In function `i386_emit_goto':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
> undefined reference to `end_i386_goto'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
> undefined reference to `start_i386_goto'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
> undefined reference to `start_i386_goto'
> linux-x86-low.o: In function `i386_emit_if_goto':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
> undefined reference to `end_i386_if_goto'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
> undefined reference to `start_i386_if_goto'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
> undefined reference to `start_i386_if_goto'
> linux-x86-low.o: In function `i386_emit_ref':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
> undefined reference to `end_i386_ref1'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
> undefined reference to `start_i386_ref1'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
> undefined reference to `start_i386_ref1'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
> undefined reference to `end_i386_ref8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
> undefined reference to `start_i386_ref8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
> undefined reference to `start_i386_ref8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
> undefined reference to `end_i386_ref2'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
> undefined reference to `start_i386_ref2'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
> undefined reference to `start_i386_ref2'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
> undefined reference to `end_i386_ref4'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
> undefined reference to `start_i386_ref4'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
> undefined reference to `start_i386_ref4'
> linux-x86-low.o: In function `i386_emit_less_unsigned':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
> undefined reference to `end_i386_less_unsigned'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
> undefined reference to `start_i386_less_unsigned'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
> undefined reference to `start_i386_less_unsigned'
> linux-x86-low.o: In function `i386_emit_less_signed':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
> undefined reference to `end_i386_less_signed'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
> undefined reference to `start_i386_less_signed'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
> undefined reference to `start_i386_less_signed'
> linux-x86-low.o: In function `i386_emit_equal':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
> undefined reference to `end_i386_equal'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
> undefined reference to `start_i386_equal'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
> undefined reference to `start_i386_equal'
> linux-x86-low.o: In function `i386_emit_bit_not':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
> undefined reference to `end_i386_bit_not'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
> undefined reference to `start_i386_bit_not'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
> undefined reference to `start_i386_bit_not'
> linux-x86-low.o: In function `i386_emit_bit_xor':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
> undefined reference to `end_i386_xor'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
> undefined reference to `start_i386_xor'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
> undefined reference to `start_i386_xor'
> linux-x86-low.o: In function `i386_emit_bit_or':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
> undefined reference to `end_i386_or'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
> undefined reference to `start_i386_or'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
> undefined reference to `start_i386_or'
> linux-x86-low.o: In function `i386_emit_bit_and':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
> undefined reference to `end_i386_and'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
> undefined reference to `start_i386_and'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
> undefined reference to `start_i386_and'
> linux-x86-low.o: In function `i386_emit_log_not':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
> undefined reference to `end_i386_log_not'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
> undefined reference to `start_i386_log_not'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
> undefined reference to `start_i386_log_not'
> linux-x86-low.o: In function `i386_emit_ext':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
> undefined reference to `end_i386_ext_8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
> undefined reference to `start_i386_ext_8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
> undefined reference to `start_i386_ext_8'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
> undefined reference to `end_i386_ext_32'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
> undefined reference to `start_i386_ext_32'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
> undefined reference to `start_i386_ext_32'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
> undefined reference to `end_i386_ext_16'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
> undefined reference to `start_i386_ext_16'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
> undefined reference to `start_i386_ext_16'
> linux-x86-low.o: In function `i386_emit_sub':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
> undefined reference to `end_i386_sub'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
> undefined reference to `start_i386_sub'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
> undefined reference to `start_i386_sub'
> linux-x86-low.o: In function `i386_emit_add':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
> undefined reference to `end_i386_add'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
> undefined reference to `start_i386_add'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
> undefined reference to `start_i386_add'
> linux-x86-low.o: In function `i386_emit_epilogue':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
> undefined reference to `end_i386_epilogue'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
> undefined reference to `start_i386_epilogue'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
> undefined reference to `start_i386_epilogue'
> linux-x86-low.o: In function `i386_emit_prologue':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
> undefined reference to `end_i386_prologue'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
> undefined reference to `start_i386_prologue'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
> undefined reference to `start_i386_prologue'
> linux-x86-low.o: In function `i386_emit_reg':
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
> undefined reference to `end_i386_reg_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
> undefined reference to `start_i386_reg_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
> undefined reference to `start_i386_reg_a'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
> undefined reference to `end_i386_reg_b'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
> undefined reference to `start_i386_reg_b'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
> undefined reference to `start_i386_reg_b'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
> undefined reference to `end_i386_reg_c'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
> undefined reference to `start_i386_reg_c'
> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
> undefined reference to `start_i386_reg_c'
> collect2: ld returned 1 exit status
> make[4]: *** [gdbserver] ?? 1
> make[4]:?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
> make[3]: *** [subdir_do] ?? 1
> make[3]:?????? `/home/teawater/gdb/bgdball/gdb'
> make[2]: *** [all] ?? 2
> make[2]:?????? `/home/teawater/gdb/bgdball/gdb'
> make[1]: *** [all-gdb] ?? 2
> make[1]:?????? `/home/teawater/gdb/bgdball'
>
>
> On Fri, Jun 18, 2010 at 02:03, Michael Snyder <msnyder@vmware.com> wrote:
>> Stan Shebs wrote:
>>>
>>> Pedro Alves wrote:
>>>>
>>>> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>>>>
>>>>>
>>>>> Doug Evans wrote:
>>>>>
>>>>>>
>>>>>> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com>
>>>>>> wrote:
>>>>>>
>>>>>>>
>>>>>>> Thanks.  I've checked the whole thing in.
>>>>>>>
>>>>>>
>>>>>> I'm getting build failures that go away when compiling linux-x86-low.c
>>>>>> with -g.
>>>>>>
>>>>>> gcc is optimizing out the skipped over stuff I believe.
>>>>>>
>>>>>
>>>>> Hmm, this particular trickery was my idea, but it always seemed
>>>>> vulnerable to ever-smarter optimization.  Does anybody have any better
>>>>> strategy?  Declaring the asm volatile didn't work, because the compiler was
>>>>> whacking everything around it.
>>>>>
>>>>> The other approach is to build up instructions from bitfields, which is
>>>>> reliable but needs a lot of setup and helper routines.
>>>>>
>>>>
>>>> Quick thought: can we stick a couple of __attribute__((used))'s in the
>>>> macro, so the compiler doesn optimized things away, thinking they're
>>>> unused (given the uses are behind asm)?
>>>>
>>>
>>> The compiler is discarding the code with the definitions of the labels,
>>> because it's thinking they are maybe somewhere else in the program (the
>>> error is at link time).  Moving the labels into C code would fix that I
>>> think, but then it's hard to guarantee that the compiler won't sneak in a
>>> bit of code between label and asm sequence.
>>
>> Hurrr.  Code that depends on such deep knowledge of the compiler's
>> behavior is wrong code, IMO.
>>
>>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-19 16:16                         ` Doug Evans
@ 2010-06-19 17:13                           ` Hui Zhu
  2010-06-19 17:26                             ` Doug Evans
  0 siblings, 1 reply; 31+ messages in thread
From: Hui Zhu @ 2010-06-19 17:13 UTC (permalink / raw)
  To: gdb-patches, Pedro Alves, Stan Shebs, Eli Zaretskii, tromey,
	Michael Snyder, Doug Evans

Hi guys,

I say something about bytecode compiler .

I did some code work like it in skyeye dbct (dynamic binary code
translation)  in before (some introduce
http://www.skyeye.org/wiki/SkyeyeDBCTen).

In dbct, I get the binary code like what you do in this patch.
define a functon, get binary code from this function, and use it for
other thing.

But I want say, to maintain is not very easy.  At least, we need give up -O2.

Because Gcc's optimization will compile the function that support the
code to some asm code that we don't want it to be.

Any other trouble is , different user will use different version gcc,
different version gcc's optimization is different.
Actually, after gcc4, this issue is very different to handle.

And old version QEMU use this idea too.  And it has this issue too.
So a long time, compile qemu need gcc3.
Now, qemu handle this issue because it give up the old way and use TCC
to get the code.

Hope it can help a little better.

Thanks,
Hui

On Sun, Jun 20, 2010 at 00:16, Doug Evans <dje@google.com> wrote:
> Yeah.
> Until it gets fixed a workaround is to compile linux-x86-low.c with -O0.
>
>
> On Sat, Jun 19, 2010 at 9:12 AM, Hui Zhu <teawater@gmail.com> wrote:
>> lubuntu 10.04:
>>
>> make[4]: ?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
>> rm -f gdbserver
>> gcc -Wall -g -O2    -I. -I../../../src/gdb/gdbserver
>> -I../../../src/gdb/gdbserver/../common
>> -I../../../src/gdb/gdbserver/../regformats
>> -I../../../src/gdb/gdbserver/../../include
>> -Wl,--dynamic-list=../../../src/gdb/gdbserver/proc-service.list -o
>> gdbserver inferiors.o regcache.o remote-utils.o server.o signals.o
>> target.o utils.o version.o mem-break.o hostio.o event-loop.o
>> tracepoint.o xml-builtin.o i386-linux.o i386-avx-linux.o
>> i386-mmx-linux.o linux-low.o linux-x86-low.o i386-low.o i387-fp.o
>> hostio-errno.o thread-db.o proc-service.o  \
>>          -ldl
>> linux-x86-low.o: In function `i386_emit_void_call_2':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
>> undefined reference to `end_i386_void_call_2_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
>> undefined reference to `start_i386_void_call_2_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
>> undefined reference to `start_i386_void_call_2_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
>> undefined reference to `end_i386_void_call_2_b'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
>> undefined reference to `start_i386_void_call_2_b'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
>> undefined reference to `start_i386_void_call_2_b'
>> linux-x86-low.o: In function `i386_emit_int_call_1':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
>> undefined reference to `end_i386_int_call_1_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
>> undefined reference to `start_i386_int_call_1_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
>> undefined reference to `start_i386_int_call_1_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
>> undefined reference to `end_i386_int_call_1_c'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
>> undefined reference to `start_i386_int_call_1_c'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
>> undefined reference to `start_i386_int_call_1_c'
>> linux-x86-low.o: In function `i386_emit_swap':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
>> undefined reference to `end_i386_swap'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
>> undefined reference to `start_i386_swap'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
>> undefined reference to `start_i386_swap'
>> linux-x86-low.o: In function `i386_emit_zero_ext':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
>> undefined reference to `end_i386_zero_ext_8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
>> undefined reference to `start_i386_zero_ext_8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
>> undefined reference to `start_i386_zero_ext_8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
>> undefined reference to `end_i386_zero_ext_32'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
>> undefined reference to `start_i386_zero_ext_32'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
>> undefined reference to `start_i386_zero_ext_32'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
>> undefined reference to `end_i386_zero_ext_16'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
>> undefined reference to `start_i386_zero_ext_16'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
>> undefined reference to `start_i386_zero_ext_16'
>> linux-x86-low.o: In function `i386_emit_stack_flush':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
>> undefined reference to `end_i386_stack_flush'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
>> undefined reference to `start_i386_stack_flush'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
>> undefined reference to `start_i386_stack_flush'
>> linux-x86-low.o: In function `i386_emit_pop':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
>> undefined reference to `end_i386_pop'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
>> undefined reference to `start_i386_pop'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
>> undefined reference to `start_i386_pop'
>> linux-x86-low.o: In function `i386_emit_goto':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
>> undefined reference to `end_i386_goto'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
>> undefined reference to `start_i386_goto'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
>> undefined reference to `start_i386_goto'
>> linux-x86-low.o: In function `i386_emit_if_goto':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
>> undefined reference to `end_i386_if_goto'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
>> undefined reference to `start_i386_if_goto'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
>> undefined reference to `start_i386_if_goto'
>> linux-x86-low.o: In function `i386_emit_ref':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
>> undefined reference to `end_i386_ref1'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
>> undefined reference to `start_i386_ref1'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
>> undefined reference to `start_i386_ref1'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
>> undefined reference to `end_i386_ref8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
>> undefined reference to `start_i386_ref8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
>> undefined reference to `start_i386_ref8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
>> undefined reference to `end_i386_ref2'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
>> undefined reference to `start_i386_ref2'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
>> undefined reference to `start_i386_ref2'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
>> undefined reference to `end_i386_ref4'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
>> undefined reference to `start_i386_ref4'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
>> undefined reference to `start_i386_ref4'
>> linux-x86-low.o: In function `i386_emit_less_unsigned':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
>> undefined reference to `end_i386_less_unsigned'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
>> undefined reference to `start_i386_less_unsigned'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
>> undefined reference to `start_i386_less_unsigned'
>> linux-x86-low.o: In function `i386_emit_less_signed':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
>> undefined reference to `end_i386_less_signed'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
>> undefined reference to `start_i386_less_signed'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
>> undefined reference to `start_i386_less_signed'
>> linux-x86-low.o: In function `i386_emit_equal':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
>> undefined reference to `end_i386_equal'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
>> undefined reference to `start_i386_equal'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
>> undefined reference to `start_i386_equal'
>> linux-x86-low.o: In function `i386_emit_bit_not':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
>> undefined reference to `end_i386_bit_not'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
>> undefined reference to `start_i386_bit_not'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
>> undefined reference to `start_i386_bit_not'
>> linux-x86-low.o: In function `i386_emit_bit_xor':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
>> undefined reference to `end_i386_xor'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
>> undefined reference to `start_i386_xor'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
>> undefined reference to `start_i386_xor'
>> linux-x86-low.o: In function `i386_emit_bit_or':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
>> undefined reference to `end_i386_or'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
>> undefined reference to `start_i386_or'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
>> undefined reference to `start_i386_or'
>> linux-x86-low.o: In function `i386_emit_bit_and':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
>> undefined reference to `end_i386_and'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
>> undefined reference to `start_i386_and'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
>> undefined reference to `start_i386_and'
>> linux-x86-low.o: In function `i386_emit_log_not':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
>> undefined reference to `end_i386_log_not'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
>> undefined reference to `start_i386_log_not'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
>> undefined reference to `start_i386_log_not'
>> linux-x86-low.o: In function `i386_emit_ext':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
>> undefined reference to `end_i386_ext_8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
>> undefined reference to `start_i386_ext_8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
>> undefined reference to `start_i386_ext_8'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
>> undefined reference to `end_i386_ext_32'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
>> undefined reference to `start_i386_ext_32'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
>> undefined reference to `start_i386_ext_32'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
>> undefined reference to `end_i386_ext_16'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
>> undefined reference to `start_i386_ext_16'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
>> undefined reference to `start_i386_ext_16'
>> linux-x86-low.o: In function `i386_emit_sub':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
>> undefined reference to `end_i386_sub'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
>> undefined reference to `start_i386_sub'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
>> undefined reference to `start_i386_sub'
>> linux-x86-low.o: In function `i386_emit_add':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
>> undefined reference to `end_i386_add'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
>> undefined reference to `start_i386_add'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
>> undefined reference to `start_i386_add'
>> linux-x86-low.o: In function `i386_emit_epilogue':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
>> undefined reference to `end_i386_epilogue'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
>> undefined reference to `start_i386_epilogue'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
>> undefined reference to `start_i386_epilogue'
>> linux-x86-low.o: In function `i386_emit_prologue':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
>> undefined reference to `end_i386_prologue'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
>> undefined reference to `start_i386_prologue'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
>> undefined reference to `start_i386_prologue'
>> linux-x86-low.o: In function `i386_emit_reg':
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
>> undefined reference to `end_i386_reg_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
>> undefined reference to `start_i386_reg_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
>> undefined reference to `start_i386_reg_a'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
>> undefined reference to `end_i386_reg_b'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
>> undefined reference to `start_i386_reg_b'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
>> undefined reference to `start_i386_reg_b'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
>> undefined reference to `end_i386_reg_c'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
>> undefined reference to `start_i386_reg_c'
>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
>> undefined reference to `start_i386_reg_c'
>> collect2: ld returned 1 exit status
>> make[4]: *** [gdbserver] ?? 1
>> make[4]:?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
>> make[3]: *** [subdir_do] ?? 1
>> make[3]:?????? `/home/teawater/gdb/bgdball/gdb'
>> make[2]: *** [all] ?? 2
>> make[2]:?????? `/home/teawater/gdb/bgdball/gdb'
>> make[1]: *** [all-gdb] ?? 2
>> make[1]:?????? `/home/teawater/gdb/bgdball'
>>
>>
>> On Fri, Jun 18, 2010 at 02:03, Michael Snyder <msnyder@vmware.com> wrote:
>>> Stan Shebs wrote:
>>>>
>>>> Pedro Alves wrote:
>>>>>
>>>>> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>>>>>
>>>>>>
>>>>>> Doug Evans wrote:
>>>>>>
>>>>>>>
>>>>>>> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>>
>>>>>>>> Thanks.  I've checked the whole thing in.
>>>>>>>>
>>>>>>>
>>>>>>> I'm getting build failures that go away when compiling linux-x86-low.c
>>>>>>> with -g.
>>>>>>>
>>>>>>> gcc is optimizing out the skipped over stuff I believe.
>>>>>>>
>>>>>>
>>>>>> Hmm, this particular trickery was my idea, but it always seemed
>>>>>> vulnerable to ever-smarter optimization.  Does anybody have any better
>>>>>> strategy?  Declaring the asm volatile didn't work, because the compiler was
>>>>>> whacking everything around it.
>>>>>>
>>>>>> The other approach is to build up instructions from bitfields, which is
>>>>>> reliable but needs a lot of setup and helper routines.
>>>>>>
>>>>>
>>>>> Quick thought: can we stick a couple of __attribute__((used))'s in the
>>>>> macro, so the compiler doesn optimized things away, thinking they're
>>>>> unused (given the uses are behind asm)?
>>>>>
>>>>
>>>> The compiler is discarding the code with the definitions of the labels,
>>>> because it's thinking they are maybe somewhere else in the program (the
>>>> error is at link time).  Moving the labels into C code would fix that I
>>>> think, but then it's hard to guarantee that the compiler won't sneak in a
>>>> bit of code between label and asm sequence.
>>>
>>> Hurrr.  Code that depends on such deep knowledge of the compiler's
>>> behavior is wrong code, IMO.
>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-19 17:13                           ` Hui Zhu
@ 2010-06-19 17:26                             ` Doug Evans
  2010-06-20  9:30                               ` [RFA-new version][gdbserver] " Pierre Muller
       [not found]                               ` <-3945058798826177264@unknownmsgid>
  0 siblings, 2 replies; 31+ messages in thread
From: Doug Evans @ 2010-06-19 17:26 UTC (permalink / raw)
  To: Hui Zhu
  Cc: gdb-patches, Pedro Alves, Stan Shebs, Eli Zaretskii, tromey,
	Michael Snyder

The fix to the compilation problem (for now) should be as trivial as
applying Ian's suggested change.
gcc doesn't optimize *inside* the asm statement.

Now we just have to avoid things like mao. :-)
[mao is a post-gcc assembly level optimizer, transmeta had another
called caligula ...]


On Sat, Jun 19, 2010 at 10:13 AM, Hui Zhu <teawater@gmail.com> wrote:
> Hi guys,
>
> I say something about bytecode compiler .
>
> I did some code work like it in skyeye dbct (dynamic binary code
> translation)  in before (some introduce
> http://www.skyeye.org/wiki/SkyeyeDBCTen).
>
> In dbct, I get the binary code like what you do in this patch.
> define a functon, get binary code from this function, and use it for
> other thing.
>
> But I want say, to maintain is not very easy.  At least, we need give up -O2.
>
> Because Gcc's optimization will compile the function that support the
> code to some asm code that we don't want it to be.
>
> Any other trouble is , different user will use different version gcc,
> different version gcc's optimization is different.
> Actually, after gcc4, this issue is very different to handle.
>
> And old version QEMU use this idea too.  And it has this issue too.
> So a long time, compile qemu need gcc3.
> Now, qemu handle this issue because it give up the old way and use TCC
> to get the code.
>
> Hope it can help a little better.
>
> Thanks,
> Hui
>
> On Sun, Jun 20, 2010 at 00:16, Doug Evans <dje@google.com> wrote:
>> Yeah.
>> Until it gets fixed a workaround is to compile linux-x86-low.c with -O0.
>>
>>
>> On Sat, Jun 19, 2010 at 9:12 AM, Hui Zhu <teawater@gmail.com> wrote:
>>> lubuntu 10.04:
>>>
>>> make[4]: ?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
>>> rm -f gdbserver
>>> gcc -Wall -g -O2    -I. -I../../../src/gdb/gdbserver
>>> -I../../../src/gdb/gdbserver/../common
>>> -I../../../src/gdb/gdbserver/../regformats
>>> -I../../../src/gdb/gdbserver/../../include
>>> -Wl,--dynamic-list=../../../src/gdb/gdbserver/proc-service.list -o
>>> gdbserver inferiors.o regcache.o remote-utils.o server.o signals.o
>>> target.o utils.o version.o mem-break.o hostio.o event-loop.o
>>> tracepoint.o xml-builtin.o i386-linux.o i386-avx-linux.o
>>> i386-mmx-linux.o linux-low.o linux-x86-low.o i386-low.o i387-fp.o
>>> hostio-errno.o thread-db.o proc-service.o  \
>>>          -ldl
>>> linux-x86-low.o: In function `i386_emit_void_call_2':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
>>> undefined reference to `end_i386_void_call_2_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
>>> undefined reference to `start_i386_void_call_2_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2426:
>>> undefined reference to `start_i386_void_call_2_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
>>> undefined reference to `end_i386_void_call_2_b'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
>>> undefined reference to `start_i386_void_call_2_b'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2447:
>>> undefined reference to `start_i386_void_call_2_b'
>>> linux-x86-low.o: In function `i386_emit_int_call_1':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
>>> undefined reference to `end_i386_int_call_1_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
>>> undefined reference to `start_i386_int_call_1_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2398:
>>> undefined reference to `start_i386_int_call_1_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
>>> undefined reference to `end_i386_int_call_1_c'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
>>> undefined reference to `start_i386_int_call_1_c'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2412:
>>> undefined reference to `start_i386_int_call_1_c'
>>> linux-x86-low.o: In function `i386_emit_swap':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
>>> undefined reference to `end_i386_swap'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
>>> undefined reference to `start_i386_swap'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2364:
>>> undefined reference to `start_i386_swap'
>>> linux-x86-low.o: In function `i386_emit_zero_ext':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
>>> undefined reference to `end_i386_zero_ext_8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
>>> undefined reference to `start_i386_zero_ext_8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2343:
>>> undefined reference to `start_i386_zero_ext_8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
>>> undefined reference to `end_i386_zero_ext_32'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
>>> undefined reference to `start_i386_zero_ext_32'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2353:
>>> undefined reference to `start_i386_zero_ext_32'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
>>> undefined reference to `end_i386_zero_ext_16'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
>>> undefined reference to `start_i386_zero_ext_16'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2348:
>>> undefined reference to `start_i386_zero_ext_16'
>>> linux-x86-low.o: In function `i386_emit_stack_flush':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
>>> undefined reference to `end_i386_stack_flush'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
>>> undefined reference to `start_i386_stack_flush'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2332:
>>> undefined reference to `start_i386_stack_flush'
>>> linux-x86-low.o: In function `i386_emit_pop':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
>>> undefined reference to `end_i386_pop'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
>>> undefined reference to `start_i386_pop'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2324:
>>> undefined reference to `start_i386_pop'
>>> linux-x86-low.o: In function `i386_emit_goto':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
>>> undefined reference to `end_i386_goto'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
>>> undefined reference to `start_i386_goto'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2227:
>>> undefined reference to `start_i386_goto'
>>> linux-x86-low.o: In function `i386_emit_if_goto':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
>>> undefined reference to `end_i386_if_goto'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
>>> undefined reference to `start_i386_if_goto'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2209:
>>> undefined reference to `start_i386_if_goto'
>>> linux-x86-low.o: In function `i386_emit_ref':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
>>> undefined reference to `end_i386_ref1'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
>>> undefined reference to `start_i386_ref1'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2187:
>>> undefined reference to `start_i386_ref1'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
>>> undefined reference to `end_i386_ref8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
>>> undefined reference to `start_i386_ref8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2199:
>>> undefined reference to `start_i386_ref8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
>>> undefined reference to `end_i386_ref2'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
>>> undefined reference to `start_i386_ref2'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2191:
>>> undefined reference to `start_i386_ref2'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
>>> undefined reference to `end_i386_ref4'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
>>> undefined reference to `start_i386_ref4'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2195:
>>> undefined reference to `start_i386_ref4'
>>> linux-x86-low.o: In function `i386_emit_less_unsigned':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
>>> undefined reference to `end_i386_less_unsigned'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
>>> undefined reference to `start_i386_less_unsigned'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2165:
>>> undefined reference to `start_i386_less_unsigned'
>>> linux-x86-low.o: In function `i386_emit_less_signed':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
>>> undefined reference to `end_i386_less_signed'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
>>> undefined reference to `start_i386_less_signed'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2146:
>>> undefined reference to `start_i386_less_signed'
>>> linux-x86-low.o: In function `i386_emit_equal':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
>>> undefined reference to `end_i386_equal'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
>>> undefined reference to `start_i386_equal'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2128:
>>> undefined reference to `start_i386_equal'
>>> linux-x86-low.o: In function `i386_emit_bit_not':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
>>> undefined reference to `end_i386_bit_not'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
>>> undefined reference to `start_i386_bit_not'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2120:
>>> undefined reference to `start_i386_bit_not'
>>> linux-x86-low.o: In function `i386_emit_bit_xor':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
>>> undefined reference to `end_i386_xor'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
>>> undefined reference to `start_i386_xor'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2111:
>>> undefined reference to `start_i386_xor'
>>> linux-x86-low.o: In function `i386_emit_bit_or':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
>>> undefined reference to `end_i386_or'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
>>> undefined reference to `start_i386_or'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2102:
>>> undefined reference to `start_i386_or'
>>> linux-x86-low.o: In function `i386_emit_bit_and':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
>>> undefined reference to `end_i386_and'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
>>> undefined reference to `start_i386_and'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2093:
>>> undefined reference to `start_i386_and'
>>> linux-x86-low.o: In function `i386_emit_log_not':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
>>> undefined reference to `end_i386_log_not'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
>>> undefined reference to `start_i386_log_not'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2082:
>>> undefined reference to `start_i386_log_not'
>>> linux-x86-low.o: In function `i386_emit_ext':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
>>> undefined reference to `end_i386_ext_8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
>>> undefined reference to `start_i386_ext_8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2057:
>>> undefined reference to `start_i386_ext_8'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
>>> undefined reference to `end_i386_ext_32'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
>>> undefined reference to `start_i386_ext_32'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2070:
>>> undefined reference to `start_i386_ext_32'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
>>> undefined reference to `end_i386_ext_16'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
>>> undefined reference to `start_i386_ext_16'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2064:
>>> undefined reference to `start_i386_ext_16'
>>> linux-x86-low.o: In function `i386_emit_sub':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
>>> undefined reference to `end_i386_sub'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
>>> undefined reference to `start_i386_sub'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2020:
>>> undefined reference to `start_i386_sub'
>>> linux-x86-low.o: In function `i386_emit_add':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
>>> undefined reference to `end_i386_add'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
>>> undefined reference to `start_i386_add'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2011:
>>> undefined reference to `start_i386_add'
>>> linux-x86-low.o: In function `i386_emit_epilogue':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
>>> undefined reference to `end_i386_epilogue'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
>>> undefined reference to `start_i386_epilogue'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1999:
>>> undefined reference to `start_i386_epilogue'
>>> linux-x86-low.o: In function `i386_emit_prologue':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
>>> undefined reference to `end_i386_prologue'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
>>> undefined reference to `start_i386_prologue'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:1989:
>>> undefined reference to `start_i386_prologue'
>>> linux-x86-low.o: In function `i386_emit_reg':
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
>>> undefined reference to `end_i386_reg_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
>>> undefined reference to `start_i386_reg_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2302:
>>> undefined reference to `start_i386_reg_a'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
>>> undefined reference to `end_i386_reg_b'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
>>> undefined reference to `start_i386_reg_b'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2311:
>>> undefined reference to `start_i386_reg_b'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
>>> undefined reference to `end_i386_reg_c'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
>>> undefined reference to `start_i386_reg_c'
>>> /home/teawater/gdb/bgdball/gdb/gdbserver/../../../src/gdb/gdbserver/linux-x86-low.c:2316:
>>> undefined reference to `start_i386_reg_c'
>>> collect2: ld returned 1 exit status
>>> make[4]: *** [gdbserver] ?? 1
>>> make[4]:?????? `/home/teawater/gdb/bgdball/gdb/gdbserver'
>>> make[3]: *** [subdir_do] ?? 1
>>> make[3]:?????? `/home/teawater/gdb/bgdball/gdb'
>>> make[2]: *** [all] ?? 2
>>> make[2]:?????? `/home/teawater/gdb/bgdball/gdb'
>>> make[1]: *** [all-gdb] ?? 2
>>> make[1]:?????? `/home/teawater/gdb/bgdball'
>>>
>>>
>>> On Fri, Jun 18, 2010 at 02:03, Michael Snyder <msnyder@vmware.com> wrote:
>>>> Stan Shebs wrote:
>>>>>
>>>>> Pedro Alves wrote:
>>>>>>
>>>>>> On Wednesday 16 June 2010 20:12:44, Stan Shebs wrote:
>>>>>>
>>>>>>>
>>>>>>> Doug Evans wrote:
>>>>>>>
>>>>>>>>
>>>>>>>> On Mon, Jun 14, 2010 at 3:19 PM, Pedro Alves <pedro@codesourcery.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Thanks.  I've checked the whole thing in.
>>>>>>>>>
>>>>>>>>
>>>>>>>> I'm getting build failures that go away when compiling linux-x86-low.c
>>>>>>>> with -g.
>>>>>>>>
>>>>>>>> gcc is optimizing out the skipped over stuff I believe.
>>>>>>>>
>>>>>>>
>>>>>>> Hmm, this particular trickery was my idea, but it always seemed
>>>>>>> vulnerable to ever-smarter optimization.  Does anybody have any better
>>>>>>> strategy?  Declaring the asm volatile didn't work, because the compiler was
>>>>>>> whacking everything around it.
>>>>>>>
>>>>>>> The other approach is to build up instructions from bitfields, which is
>>>>>>> reliable but needs a lot of setup and helper routines.
>>>>>>>
>>>>>>
>>>>>> Quick thought: can we stick a couple of __attribute__((used))'s in the
>>>>>> macro, so the compiler doesn optimized things away, thinking they're
>>>>>> unused (given the uses are behind asm)?
>>>>>>
>>>>>
>>>>> The compiler is discarding the code with the definitions of the labels,
>>>>> because it's thinking they are maybe somewhere else in the program (the
>>>>> error is at link time).  Moving the labels into C code would fix that I
>>>>> think, but then it's hard to guarantee that the compiler won't sneak in a
>>>>> bit of code between label and asm sequence.
>>>>
>>>> Hurrr.  Code that depends on such deep knowledge of the compiler's
>>>> behavior is wrong code, IMO.
>>>>
>>>>
>>>
>>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [RFA-new version][gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-19 17:26                             ` Doug Evans
@ 2010-06-20  9:30                               ` Pierre Muller
       [not found]                               ` <-3945058798826177264@unknownmsgid>
  1 sibling, 0 replies; 31+ messages in thread
From: Pierre Muller @ 2010-06-20  9:30 UTC (permalink / raw)
  To: 'Doug Evans', 'Hui Zhu'
  Cc: gdb-patches, 'Pedro Alves', 'Stan Shebs',
	'Eli Zaretskii', tromey, 'Michael Snyder'

> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Doug Evans
> Envoyé : Saturday, June 19, 2010 7:26 PM
> À : Hui Zhu
> Cc : gdb-patches@sourceware.org; Pedro Alves; Stan Shebs; Eli
> Zaretskii; tromey@redhat.com; Michael Snyder
> Objet : Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode
> compiler (speed up conditional tracepoints)
> 
> The fix to the compilation problem (for now) should be as trivial as
> applying Ian's suggested change.
> gcc doesn't optimize *inside* the asm statement.

  As I said in a previous email, Ian's patch didn't work for me.
http://sourceware.org/ml/gdb-patches/2010-06/msg00424.html

  I propose here another small patch that fixes the linking failure.
Using a volatile variable, it explicitly forbids the compiler
to optimize out code by forbidding the assumption that this value will 
never change.

  This works on gcc16, an the approach seems reasonable.

Pierre Muller

 
gdbserver/ChangeLog entry:

2010-06-20  Pierre Muller  <muller@ics.u-strasbg.fr>

	* linux-x86-low.c (always_true): Delete function.
	(always_true): New  volatile variable.
	(EMIT_ASM, EMIT_ASM32): Adapt to always_true change.


Index: src/gdb/gdbserver/linux-x86-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-x86-low.c,v
retrieving revision 1.19
diff -u -p -r1.19 linux-x86-low.c
--- src/gdb/gdbserver/linux-x86-low.c     15 Jun 2010 10:44:48 -0000
1.19
+++ src/gdb/gdbserver/linux-x86-low.c     20 Jun 2010 06:25:07 -0000
@@ -1484,13 +1484,12 @@ add_insns (unsigned char *start, int len
   current_insn_ptr = buildaddr;
 }
 
-/* A function used to trick optimizers.  */
+/* A simple function returning the constant 1 is not enough
+   to trick modern optimizers anymore.  Use a volatile variable
+   seems to force inclusion of the code, as the compiler is forced
+   to assume that that value could be changed by some external code.  */
 
-int
-always_true (void)
-{
-  return 1;
-}
+static volatile int always_true = 1;
 
 /* Our general strategy for emitting code is to avoid specifying raw
    bytes whenever possible, and instead copy a block of inline asm
@@ -1501,7 +1500,7 @@ always_true (void)
 #define EMIT_ASM(NAME,INSNS)						\
   { extern unsigned char start_ ## NAME, end_ ## NAME;			\
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
-    if (always_true ())						\
+    if (always_true)						\
       goto skipover ## NAME;						\
     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");	\
     skipover ## NAME:							\
@@ -1513,7 +1512,7 @@ always_true (void)
 #define EMIT_ASM32(NAME,INSNS)						\
   { extern unsigned char start_ ## NAME, end_ ## NAME;			\
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
-    if (always_true ())						\
+    if (always_true)						\
       goto skipover ## NAME;						\
     __asm__ (".code32\n\tstart_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n"
\
 	     "\t.code64\n\t");						\

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
       [not found]                               ` <-3945058798826177264@unknownmsgid>
@ 2010-06-20 15:30                                 ` Doug Evans
  2010-06-20 17:02                                   ` Pierre Muller
                                                     ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Doug Evans @ 2010-06-20 15:30 UTC (permalink / raw)
  To: Pierre Muller
  Cc: Hui Zhu, gdb-patches, Pedro Alves, Stan Shebs, Eli Zaretskii,
	tromey, Michael Snyder

On Sun, Jun 20, 2010 at 2:29 AM, Pierre Muller
<pierre.muller@ics-cnrs.unistra.fr> wrote:
>  As I said in a previous email, Ian's patch didn't work for me.
> http://sourceware.org/ml/gdb-patches/2010-06/msg00424.html

That's weird.
Ian's approach involves removing the "if-always-true" test completely
leaving just an asm.
Can you send me the patch of Ian's that you tried?

>  I propose here another small patch that fixes the linking failure.
> Using a volatile variable, it explicitly forbids the compiler
> to optimize out code by forbidding the assumption that this value will
> never change.
>
>  This works on gcc16, an the approach seems reasonable.

That's my patch. :-)

http://sourceware.org/ml/gdb-patches/2010-06/msg00374.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
  2010-06-20 15:30                                 ` Doug Evans
@ 2010-06-20 17:02                                   ` Pierre Muller
       [not found]                                   ` <-1673004315710326113@unknownmsgid>
  2010-06-20 18:41                                   ` Tom Tromey
  2 siblings, 0 replies; 31+ messages in thread
From: Pierre Muller @ 2010-06-20 17:02 UTC (permalink / raw)
  To: 'Doug Evans'
  Cc: 'Hui Zhu', gdb-patches, 'Pedro Alves',
	'Stan Shebs', 'Eli Zaretskii',
	tromey, 'Michael Snyder'



> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Doug Evans
> Envoyé : Sunday, June 20, 2010 5:31 PM
> À : Pierre Muller
> Cc : Hui Zhu; gdb-patches@sourceware.org; Pedro Alves; Stan Shebs; Eli
> Zaretskii; tromey@redhat.com; Michael Snyder
> Objet : Re: [RFA-new version][gdbserver] x86 agent expression bytecode
> compiler (speed up conditional tracepoints)
> 
> On Sun, Jun 20, 2010 at 2:29 AM, Pierre Muller
> <pierre.muller@ics-cnrs.unistra.fr> wrote:
> >  As I said in a previous email, Ian's patch didn't work for me.
> > http://sourceware.org/ml/gdb-patches/2010-06/msg00424.html
> 
> That's weird.
> Ian's approach involves removing the "if-always-true" test completely
> leaving just an asm.
> Can you send me the patch of Ian's that you tried?

  I probably did a mistake indeed in my first try.
As it was not a patch to apply, I just modify the source directly,
and I suppose that I added the `do while (0)',
but forgot to remove the 'if (always_true ()) ' part, which would
explain why it works now and failed when I tried first...
  Sorry about that false alarm...

  Consider my RFA as withdrawn (see below),
but please it would be nice to get ASAP a patch in 
that allows again to use the standard gdb_tester.sh script.
  I cannot test any patch currently on gcc16 because gdbserver
compilation always fails.

> >  I propose here another small patch that fixes the linking failure.
> > Using a volatile variable, it explicitly forbids the compiler
> > to optimize out code by forbidding the assumption that this value
> will
> > never change.
> >
> >  This works on gcc16, an the approach seems reasonable.
> 
> That's my patch. :-)

  Sorry, I didn't read the whole thread, as I am not really interested in
this fast tracepoint feature.
 
> http://sourceware.org/ml/gdb-patches/2010-06/msg00374.html

  Sorry for resubmitting a patch same as your, but
at least it is as if I voted for your patch too!

Pierre

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
       [not found]                                   ` <-1673004315710326113@unknownmsgid>
@ 2010-06-20 17:11                                     ` Doug Evans
  0 siblings, 0 replies; 31+ messages in thread
From: Doug Evans @ 2010-06-20 17:11 UTC (permalink / raw)
  To: Pierre Muller
  Cc: Hui Zhu, gdb-patches, Pedro Alves, Stan Shebs, Eli Zaretskii,
	tromey, Michael Snyder

On Sun, Jun 20, 2010 at 10:02 AM, Pierre Muller
<pierre.muller@ics-cnrs.unistra.fr> wrote:
>  Sorry for resubmitting a patch same as your, but
> at least it is as if I voted for your patch too!

No worries.
I agree we need to get this fixed sooner rather than later.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-19 16:13                       ` Hui Zhu
  2010-06-19 16:16                         ` Doug Evans
@ 2010-06-20 18:31                         ` Tom Tromey
  1 sibling, 0 replies; 31+ messages in thread
From: Tom Tromey @ 2010-06-20 18:31 UTC (permalink / raw)
  To: Hui Zhu
  Cc: Pedro Alves, Stan Shebs, Doug Evans, gdb-patches, Eli Zaretskii,
	Michael Snyder

>>>>> ">" == Hui Zhu <teawater@gmail.com> writes:

>> In dbct, I get the binary code like what you do in this patch.
>> define a functon, get binary code from this function, and use it for
>> other thing.

>> Because Gcc's optimization will compile the function that support the
>> code to some asm code that we don't want it to be.

In this case I think the code is only using GCC as a sort of glorified
assembler.  From what I can see it is not taking the qemu approach of
having GCC compile C, then memcpying around the resulting object code.
Instead it is just using inline assembler, like:

  EMIT_ASM32 (i386_prologue,
	    "push %ebp\n\t"
	    "mov %esp,%ebp");

This seems more reliable than the write-it-in-C approach.

Tom

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
  2010-06-20 15:30                                 ` Doug Evans
  2010-06-20 17:02                                   ` Pierre Muller
       [not found]                                   ` <-1673004315710326113@unknownmsgid>
@ 2010-06-20 18:41                                   ` Tom Tromey
  2010-06-20 20:36                                     ` Pierre Muller
  2 siblings, 1 reply; 31+ messages in thread
From: Tom Tromey @ 2010-06-20 18:41 UTC (permalink / raw)
  To: Doug Evans
  Cc: Pierre Muller, Hui Zhu, gdb-patches, Pedro Alves, Stan Shebs,
	Eli Zaretskii, Michael Snyder

>>>>> "Doug" == Doug Evans <dje@google.com> writes:

Doug> That's weird.
Doug> Ian's approach involves removing the "if-always-true" test completely
Doug> leaving just an asm.
Doug> Can you send me the patch of Ian's that you tried?

I think that since Ian's patch works for Pierre, and since it seems
reasonable on its own merits, it is ok.  So, somebody please check it
in.

If this is not ok with somebody, it is fine to re-fix it a different way
later.  In the short run it is nice to fix the build.

Tom

^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
  2010-06-20 18:41                                   ` Tom Tromey
@ 2010-06-20 20:36                                     ` Pierre Muller
  2010-06-20 21:07                                       ` Pierre Muller
  0 siblings, 1 reply; 31+ messages in thread
From: Pierre Muller @ 2010-06-20 20:36 UTC (permalink / raw)
  To: tromey, 'Doug Evans'
  Cc: 'Hui Zhu', gdb-patches, 'Pedro Alves',
	'Stan Shebs', 'Eli Zaretskii',
	'Michael Snyder'

 This patch fixes compilation on gcc16.

May I commit this?


Pierre


gdbserver/ChangeLog entry:

2010-06-20  Ian Lance Taylor  <iant@google.com>
	    Pierre Muller  <muller@ics.u-strasbg.fr>

	* linux-x86-low.c (always_true): Delete function.
	(EMIT_ASM, EMIT_ASM32): Use `do ... while (0)' to avoid
	code been optimzed out.


Index: src/gdb/gdbserver/linux-x86-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-x86-low.c,v
retrieving revision 1.19
diff -u -p -r1.19 linux-x86-low.c
--- src/gdb/gdbserver/linux-x86-low.c     15 Jun 2010 10:44:48 -0000
1.19
+++ src/gdb/gdbserver/linux-x86-low.c     20 Jun 2010 06:25:07 -0000
@@ -1484,14 +1484,6 @@ add_insns (unsigned char *start, int len
   current_insn_ptr = buildaddr;
 }
 
-/* A function used to trick optimizers.  */
-
-int
-always_true (void)
-{
-  return 1;
-}
-
 /* Our general strategy for emitting code is to avoid specifying raw
    bytes whenever possible, and instead copy a block of inline asm
    that is embedded in the function.  This is a little messy, because
@@ -1499,26 +1491,20 @@ always_true (void)
    code, plus suppress various warnings.  */
 
 #define EMIT_ASM(NAME,INSNS)						\
-  { extern unsigned char start_ ## NAME, end_ ## NAME;			\
+  do  { extern unsigned char start_ ## NAME, end_ ## NAME;		\
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
-    if (always_true ())						\
-      goto skipover ## NAME;						\
     __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");	\
-    skipover ## NAME:							\
-    ; }
+    ; } while (0)
 
 
 #ifdef __x86_64__
 
 #define EMIT_ASM32(NAME,INSNS)						\
-  { extern unsigned char start_ ## NAME, end_ ## NAME;			\
+  do { extern unsigned char start_ ## NAME, end_ ## NAME;		\
     add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
-    if (always_true ())						\
-      goto skipover ## NAME;						\
     __asm__ (".code32\n\tstart_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n"
\
 	     "\t.code64\n\t");						\
-    skipover ## NAME:							\
-    ; }
+    ; } while (0)
 
 #else
 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
  2010-06-20 20:36                                     ` Pierre Muller
@ 2010-06-20 21:07                                       ` Pierre Muller
  2010-06-21  1:47                                         ` Tom Tromey
  0 siblings, 1 reply; 31+ messages in thread
From: Pierre Muller @ 2010-06-20 21:07 UTC (permalink / raw)
  To: tromey, 'Doug Evans'
  Cc: 'Hui Zhu', gdb-patches, 'Pedro Alves',
	'Stan Shebs', 'Eli Zaretskii',
	'Michael Snyder'

  Finally, I think that this version is wrong...
It fixes linking, but it also
removes the call to add_insns function,
and thus the assembler code is not registered anymore.
This probably kills the functionality of the whole
EMIT_CODE macros.

  Sorry for all those forward/backward steps,
but finally Doug's patch is far better
because it keeps the call to add_insns

  Tom, could you give your approval on
Doug's patch?

http://sourceware.org/ml/gdb-patches/2010-06/msg00374.html


Pierre Muller

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [NEWS/RFA] Re: [gdbserver] x86 agent expression bytecode compiler  (speed up conditional tracepoints)
  2010-06-16 23:58                     ` Ian Lance Taylor
@ 2010-06-20 22:27                       ` Pedro Alves
  0 siblings, 0 replies; 31+ messages in thread
From: Pedro Alves @ 2010-06-20 22:27 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Doug Evans, Stan Shebs, gdb-patches, Eli Zaretskii, tromey

On Thursday 17 June 2010 00:57:52, Ian Lance Taylor wrote:
> Doug Evans <dje@google.com> writes:
> 
> > This worked with the gcc4.4.0 variant I was using.
> >
> > Ian: Is there a Right way to do this?
> 
> I don't know about a right way, but since this code is both gcc and
> x86 specific, I think I would just write something along the lines of
> 
> #define EMIT_ASM(NAME, INSNS) \
>   do \
>    { \
>      extern unsigned char start_ ## NAME, end_ ## NAME; \
>      add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME); \
>      asm ("jmp end_" NAME "\; start_" NAME ":\;" INSNS "\; end_" NAME ":"); \
>    } while (0)

Thanks, works, nice and simple.  I've applied the patch below.

-- 
Pedro Alves

2010-06-20  Ian Lance Taylor  <iant@google.com>
	    Pedro Alves  <pedro@codesourcery.com>

	* linux-x86-low.c (always_true): Delete.
	(EMIT_ASM, EMIT_ASM32): Use an uncondition asm jmp instead of
	trying to fool the compiler with always_true.

---
 gdb/gdbserver/linux-x86-low.c |   46 +++++++++++++++++++-----------------------
 1 file changed, 21 insertions(+), 25 deletions(-)

Index: src/gdb/gdbserver/linux-x86-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-x86-low.c	2010-06-20 22:43:08.000000000 +0100
+++ src/gdb/gdbserver/linux-x86-low.c	2010-06-20 22:59:05.000000000 +0100
@@ -1484,41 +1484,37 @@ add_insns (unsigned char *start, int len
   current_insn_ptr = buildaddr;
 }
 
-/* A function used to trick optimizers.  */
-
-int
-always_true (void)
-{
-  return 1;
-}
-
 /* Our general strategy for emitting code is to avoid specifying raw
    bytes whenever possible, and instead copy a block of inline asm
    that is embedded in the function.  This is a little messy, because
    we need to keep the compiler from discarding what looks like dead
    code, plus suppress various warnings.  */
 
-#define EMIT_ASM(NAME,INSNS)						\
-  { extern unsigned char start_ ## NAME, end_ ## NAME;			\
-    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
-    if (always_true ())						\
-      goto skipover ## NAME;						\
-    __asm__ ("start_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n\t");	\
-    skipover ## NAME:							\
-    ; }
-
+#define EMIT_ASM(NAME, INSNS)						\
+  do									\
+    {									\
+      extern unsigned char start_ ## NAME, end_ ## NAME;		\
+      add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
+      __asm__ ("jmp end_" #NAME "\n"				\
+	       "\t" "start_" #NAME ":"					\
+	       "\t" INSNS "\n"						\
+	       "\t" "end_" #NAME ":");					\
+    } while (0)
 
 #ifdef __x86_64__
 
 #define EMIT_ASM32(NAME,INSNS)						\
-  { extern unsigned char start_ ## NAME, end_ ## NAME;			\
-    add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
-    if (always_true ())						\
-      goto skipover ## NAME;						\
-    __asm__ (".code32\n\tstart_" #NAME ":\n\t" INSNS "\n\tend_" #NAME ":\n" \
-	     "\t.code64\n\t");						\
-    skipover ## NAME:							\
-    ; }
+  do									\
+    {									\
+      extern unsigned char start_ ## NAME, end_ ## NAME;		\
+      add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME);	\
+      __asm__ (".code32\n"						\
+	       "\t" "jmp end_" #NAME "\n"				\
+	       "\t" "start_" #NAME ":\n"				\
+	       "\t" INSNS "\n"						\
+	       "\t" "end_" #NAME ":\n"					\
+	       ".code64\n");						\
+    } while (0)
 
 #else
 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
  2010-06-20 21:07                                       ` Pierre Muller
@ 2010-06-21  1:47                                         ` Tom Tromey
  2010-06-21  6:31                                           ` Pierre Muller
  0 siblings, 1 reply; 31+ messages in thread
From: Tom Tromey @ 2010-06-21  1:47 UTC (permalink / raw)
  To: Pierre Muller
  Cc: 'Doug Evans', 'Hui Zhu',
	gdb-patches, 'Pedro Alves', 'Stan Shebs',
	'Eli Zaretskii', 'Michael Snyder'

>>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr> writes:

Pierre>   Sorry for all those forward/backward steps,
Pierre> but finally Doug's patch is far better
Pierre> because it keeps the call to add_insns

Pierre>   Tom, could you give your approval on
Pierre> Doug's patch?

Pedro checked in the fix between when you sent this and when I saw it :-)

Tom

^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [RFA-new version][gdbserver] x86 agent expression bytecode  compiler (speed up conditional tracepoints)
  2010-06-21  1:47                                         ` Tom Tromey
@ 2010-06-21  6:31                                           ` Pierre Muller
  0 siblings, 0 replies; 31+ messages in thread
From: Pierre Muller @ 2010-06-21  6:31 UTC (permalink / raw)
  To: 'Tom Tromey'
  Cc: 'Doug Evans', 'Hui Zhu',
	gdb-patches, 'Pedro Alves', 'Stan Shebs',
	'Eli Zaretskii', 'Michael Snyder'



> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Tom Tromey
> Envoyé : Monday, June 21, 2010 3:47 AM
> À : Pierre Muller
> Cc : 'Doug Evans'; 'Hui Zhu'; gdb-patches@sourceware.org; 'Pedro
> Alves'; 'Stan Shebs'; 'Eli Zaretskii'; 'Michael Snyder'
> Objet : Re: [RFA-new version][gdbserver] x86 agent expression bytecode
> compiler (speed up conditional tracepoints)
> 
> >>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr>
> writes:
> 
> Pierre>   Sorry for all those forward/backward steps,
> Pierre> but finally Doug's patch is far better
> Pierre> because it keeps the call to add_insns
> 
> Pierre>   Tom, could you give your approval on
> Pierre> Doug's patch?
> 
> Pedro checked in the fix between when you sent this and when I saw it
> :-)

  The patch is OK, I missed the `jmp' instruction that was added 
by Ian.

 Sorry for all those useless emails :(
  
  On the good side, at least the patch tester scripts should work again!

Pierre Muller


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2010-06-21  6:31 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-07 16:00 [gdbserver] x86 agent expression bytecode compiler (speed up conditional tracepoints) Pedro Alves
2010-06-07 16:04 ` Michael Snyder
2010-06-07 16:35   ` Joel Brobecker
2010-06-10 17:28 ` Tom Tromey
2010-06-10 17:36   ` Pedro Alves
2010-06-10 18:43     ` Tom Tromey
2010-06-14 11:15       ` [NEWS/RFA] " Pedro Alves
2010-06-14 17:29         ` Eli Zaretskii
2010-06-14 22:19           ` Pedro Alves
2010-06-16 18:57             ` Doug Evans
2010-06-16 19:13               ` Stan Shebs
2010-06-16 19:16                 ` Pedro Alves
2010-06-16 19:21                   ` Doug Evans
2010-06-16 23:58                     ` Ian Lance Taylor
2010-06-20 22:27                       ` Pedro Alves
2010-06-16 19:31                   ` Stan Shebs
2010-06-17 18:03                     ` Michael Snyder
2010-06-19 16:13                       ` Hui Zhu
2010-06-19 16:16                         ` Doug Evans
2010-06-19 17:13                           ` Hui Zhu
2010-06-19 17:26                             ` Doug Evans
2010-06-20  9:30                               ` [RFA-new version][gdbserver] " Pierre Muller
     [not found]                               ` <-3945058798826177264@unknownmsgid>
2010-06-20 15:30                                 ` Doug Evans
2010-06-20 17:02                                   ` Pierre Muller
     [not found]                                   ` <-1673004315710326113@unknownmsgid>
2010-06-20 17:11                                     ` Doug Evans
2010-06-20 18:41                                   ` Tom Tromey
2010-06-20 20:36                                     ` Pierre Muller
2010-06-20 21:07                                       ` Pierre Muller
2010-06-21  1:47                                         ` Tom Tromey
2010-06-21  6:31                                           ` Pierre Muller
2010-06-20 18:31                         ` [NEWS/RFA] Re: [gdbserver] " Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).