diff -rupN /home/luke/Projects/gdb-7.0/gdb/b64.c /home/luke/Projects/gdb-trace/gdb/b64.c
--- /home/luke/Projects/gdb-7.0/gdb/b64.c	1970-01-01 12:00:00.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/b64.c	2009-12-02 22:29:46.737207424 +1300
@@ -0,0 +1,317 @@
+#include "b64.h"
+
+#include <unistd.h>
+#include <string.h>
+#include "gdbtypes.h"
+#include "value.h"
+
+static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+void
+b64_buf_init(struct b64_buf *b64_buf, char *mem_buf)
+{
+  b64_buf->in_size=0;
+  b64_buf->out=b64_buf->current=mem_buf;
+}
+
+char *
+b64_buf_one(const gdb_byte *addr,char *out)
+{
+  out[0]=cb64[addr[0]>>2];
+  out[1]=cb64[(addr[0]<<4|addr[1]>>4)&0x3f];
+  out[2]=cb64[(addr[1]<<2|addr[2]>>6)&0x3f];
+  out[3]=cb64[addr[2]&0x3f];
+  return out+4;
+}
+
+char *
+b64_buf_part(const gdb_byte *addr,unsigned char mod,char *out)
+{
+  out[0]=cb64[addr[0]>>2];
+  out[1]=cb64[(addr[0]<<4|(mod==1?0:(addr[1]>>4)))&0x3f];
+  out[2]=mod==1?'=':cb64[(addr[1]<<2|(mod==2?0:(addr[2]>>6)))&0x3f];
+  out[3]=mod!=0?'=':cb64[addr[2]&0x3f];
+  return out+4;
+}
+
+void
+b64_buf_byte(struct b64_buf *buf,char byte)
+{
+  b64_buf_print(buf,&byte,1);
+}
+
+void
+b64_buf_print(struct b64_buf *buf,const void *data,int len)
+{
+  int i;
+  int triplets;
+  unsigned char mod;
+  const gdb_byte *addr=(const gdb_byte*)data;
+
+  if(buf->in_size!=0)
+  {
+    i=0;
+
+    for(i=0;buf->in_size<3&&i<len;i++)
+      buf->in[buf->in_size++]=addr[i];
+
+    if(buf->in_size!=3)
+      return;
+    
+    buf->current=b64_buf_one(buf->in,buf->current);
+
+    buf->in_size=0;
+
+    len-=i;
+    addr+=i;
+  }
+
+  if(len==0)
+    return;
+  
+  triplets=(len+2)/3;
+  mod=len%3;
+  for(i=0;i<triplets-1;i++)
+    {
+      buf->current=b64_buf_one(addr,buf->current);
+      addr+=3;
+    }
+
+  if(mod==0)
+    buf->current=b64_buf_one(addr,buf->current);
+  else
+  {
+    for(i=0;i<mod;i++)
+      buf->in[i]=addr[i];
+    buf->in_size=mod;
+  }
+}
+
+void
+b64_buf_output(struct b64_buf *b64_buf,struct ui_file *stream)
+{
+  if(b64_buf->in_size)
+    b64_buf->current=b64_buf_part(b64_buf->in,b64_buf->in_size,b64_buf->current);
+  *(b64_buf->current++)=0;
+
+  fputs_unfiltered(b64_buf->out,stream);
+
+  b64_buf->in_size=0;
+  b64_buf->current=b64_buf->out;
+};
+
+void
+b64_buf_stdoutput(struct b64_buf *b64_buf)
+{
+  if(b64_buf->in_size)
+    b64_buf->current=b64_buf_part(b64_buf->in,b64_buf->in_size,b64_buf->current);
+
+  write(1,b64_buf->out,b64_buf->current-b64_buf->out);
+
+  b64_buf->in_size=0;
+  b64_buf->current=b64_buf->out;
+};
+
+void
+b64_one(const gdb_byte *addr,struct ui_file *stream)
+{
+  char output[5]={
+    cb64[addr[0]>>2],
+    cb64[(addr[0]<<4|addr[1]>>4)&0x3f],
+    cb64[(addr[1]<<2|addr[2]>>6)&0x3f],
+    cb64[addr[2]&0x3f],
+    0};
+  fputs_unfiltered(output,stream);
+}
+
+void
+b64_part(const gdb_byte *addr,unsigned char mod,struct ui_file *stream)
+{
+  char output[5]={
+    cb64[addr[0]>>2],
+    cb64[(addr[0]<<4|(mod==1?0:(addr[1]>>4)))&0x3f],
+    mod==1?'=':cb64[(addr[1]<<2|(mod==2?0:(addr[2]>>6)))&0x3f],
+    mod!=0?'=':cb64[addr[2]&0x3f],
+    0};
+  fputs_unfiltered(output,stream);
+}
+
+int b64_printf(const gdb_byte *addr, int len)
+{
+  int i;
+  int triplets=(len+2)/3;
+  unsigned char mod=len%3;
+  char *mem=malloc(triplets*4);
+  char *trip=mem;
+  
+  for(i=0;i<triplets-1;i++)
+    {
+      b64_buf_one(addr,trip);
+      addr+=3;
+	  trip+=4;
+    }
+  if(triplets!=0)
+    b64_buf_part(addr,mod,trip);
+
+  write(1,mem,triplets*4);
+  free(mem);
+
+  return triplets*4;
+};
+
+int
+b64_print(const gdb_byte *addr, int len,struct ui_file *stream)
+{
+  int i;
+  int triplets=(len+2)/3;
+  unsigned char mod=len%3;
+  for(i=0;i<triplets-1;i++)
+    {
+      b64_one(addr,stream);
+      addr+=3;
+    }
+  if(triplets!=0)
+    b64_part(addr,mod,stream);
+  return triplets*4;
+}
+
+void
+print_type_b64 (struct type *type, char *name, struct ui_file *stream)
+{
+  char *output=xmalloc(100000);
+  struct b64_buf buf;
+  b64_buf_init(&buf,output);
+  print_subtype_b64(type,name,&buf);
+  b64_buf_output(&buf,stream);
+  xfree(output);
+}
+
+void
+printf_type_b64 (struct type *type, char *name)
+{
+  char *output=xmalloc(100000);
+  struct b64_buf buf;
+  b64_buf_init(&buf,output);
+  print_subtype_b64(type,name,&buf);
+  buf.current=b64_buf_part(buf.in,buf.in_size,buf.current);
+  write(1,buf.out,buf.current-buf.out);
+  xfree(output);
+}
+
+void
+print_subtype_b64 (struct type *type, char *name, struct b64_buf *buf)
+{
+  enum type_code code;
+  struct field *field;
+  uint8_t n_u8;
+  uint16_t n_u16;
+  uint32_t n_u32;
+  char *memBuf;
+  long memLength;
+  struct ui_file *memFile = mem_fileopen();
+
+  // preserve the original type in case the de-typedef'd type has no name.
+  struct type *originalType=type;
+
+  CHECK_TYPEDEF (type);
+
+  // start by outputting the type code
+  code=TYPE_CODE (type);
+  n_u8=code;
+  b64_buf_print(buf,&n_u8,1);
+
+  // then the name of the type
+  if(type->main_type->name!=0)
+    type_print (type,"",memFile,0);
+  else
+    type_print (originalType,"",memFile,0);
+  memBuf=ui_file_xstrdup(memFile,&memLength);
+  b64_buf_print(buf,memBuf,memLength);
+  xfree(memBuf);
+
+  // then the name of the variable (if any)
+  b64_buf_byte(buf,0);
+  if(name&&name[0])
+    b64_buf_print(buf,name,strlen(name)+1);
+  else
+    b64_buf_byte(buf,0);
+
+  // then the size of the variable
+  n_u32=type->length;
+  b64_buf_print(buf,&n_u32,4);
+
+  switch(code)
+    {
+      case TYPE_CODE_REF:
+      case TYPE_CODE_PTR:
+      case TYPE_CODE_METHODPTR:
+      case TYPE_CODE_MEMBERPTR:
+      case TYPE_CODE_METHOD:
+      case TYPE_CODE_FUNC:
+      case TYPE_CODE_INTERNAL_FUNCTION:
+        //pointer requires no additional output
+        break;
+
+      case TYPE_CODE_ENUM:
+      case TYPE_CODE_FLAGS:
+      case TYPE_CODE_INT:
+      case TYPE_CODE_CHAR:
+      case TYPE_CODE_BOOL:
+        //output flags...
+        n_u8=TYPE_UNSIGNED(type);
+        b64_buf_print(buf,&n_u8,1);
+        break;
+
+      case TYPE_CODE_ARRAY:
+        //output element type information
+        print_subtype_b64 (type->main_type->target_type,"",buf);
+        /*
+        memBuf=ui_file_xstrdup(memFile,&memLength);
+        b64_buf_print(buf,memBuf,memLength);
+        xfree(memBuf);
+        */
+        break;
+
+      case TYPE_CODE_STRUCT:
+        //output number of fields
+        n_u16=type->main_type->nfields;
+        b64_buf_print(buf,&n_u16,2);
+        for(n_u16=0;n_u16<type->main_type->nfields;n_u16++)
+          {
+            field=&(type->main_type->fields[n_u16]);
+            n_u32=field->loc.bitpos;
+            b64_buf_print(buf,&n_u32,4);
+            n_u32=field->bitsize;
+            b64_buf_print(buf,&n_u32,4);
+            print_subtype_b64(field->type,field->name,buf);
+          }
+        break;
+        
+      case TYPE_CODE_FLT:
+        // no additional output required
+        break;
+
+      case TYPE_CODE_UNION:
+        // no output at present
+        break;
+
+      //none of these are supported at present.
+      case TYPE_CODE_DECFLOAT:
+      case TYPE_CODE_VOID:
+      case TYPE_CODE_TYPEDEF:
+      case TYPE_CODE_TEMPLATE:
+      case TYPE_CODE_TEMPLATE_ARG:
+      case TYPE_CODE_NAMESPACE:
+      case TYPE_CODE_COMPLEX:
+      case TYPE_CODE_STRING:
+      case TYPE_CODE_BITSTRING:
+      case TYPE_CODE_ERROR:
+      case TYPE_CODE_SET:
+      case TYPE_CODE_RANGE:
+      case TYPE_CODE_UNDEF:
+      default:
+        break;
+    }
+
+  ui_file_delete(memFile);
+}
diff -rupN /home/luke/Projects/gdb-7.0/gdb/b64.h /home/luke/Projects/gdb-trace/gdb/b64.h
--- /home/luke/Projects/gdb-7.0/gdb/b64.h	1970-01-01 12:00:00.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/b64.h	2009-12-02 14:15:34.064775415 +1300
@@ -0,0 +1,34 @@
+#ifndef _B64_H
+#define	_B64_H
+
+#include "defs.h"
+
+struct b64_buf;
+
+void b64_one(const gdb_byte *addr,struct ui_file *stream);
+void b64_part(const gdb_byte *addr,unsigned char mod,struct ui_file *stream);
+int b64_print(const gdb_byte *addr, int len,struct ui_file *stream);
+
+int b64_printf(const gdb_byte *addr, int len);
+void printf_type_b64 (struct type *type, char *name);
+void b64_buf_stdoutput(struct b64_buf *b64_buf);
+
+void b64_buf_init(struct b64_buf *b64_buf, char *mem_buf);
+char *b64_buf_one(const gdb_byte *addr,char *out);
+char *b64_buf_part(const gdb_byte *addr,unsigned char mod,char *out);
+void b64_buf_byte(struct b64_buf *buf,char byte);
+void b64_buf_print(struct b64_buf *buf,const void *addr,int len);
+void b64_buf_output(struct b64_buf *b64_buf,struct ui_file *stream);
+void print_type_b64 (struct type *type, char *name, struct ui_file *stream);
+void print_subtype_b64 (struct type *type, char *name, struct b64_buf *buf);
+
+struct b64_buf
+{
+  gdb_byte in[3];
+  unsigned char in_size;
+  char *current;
+  char *out;
+};
+
+#endif	/* _B64_H */
+
diff -rupN /home/luke/Projects/gdb-7.0/gdb/breakpoint.c /home/luke/Projects/gdb-trace/gdb/breakpoint.c
--- /home/luke/Projects/gdb-7.0/gdb/breakpoint.c	2009-09-15 15:30:04.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/breakpoint.c	2009-12-08 12:47:51.794015827 +1300
@@ -61,6 +61,7 @@
 #include "valprint.h"
 #include "jit.h"
 #include "xml-syscall.h"
+#include "interps.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -219,6 +220,7 @@ static void trace_pass_command (char *, 
 
 static void skip_prologue_sal (struct symtab_and_line *sal);
 
+static void livepoint_evaluate(bpstat bs);
 
 /* Flag indicating that a command has proceeded the inferior past the
    current breakpoint.  */
@@ -352,6 +354,12 @@ static int executing_startup;
   for (B = breakpoint_chain; B; B = B->next)  \
     if ((B)->type == bp_tracepoint)
 
+/* Iterator for livepoints only. */
+
+#define ALL_LIVEPOINTS(B)  \
+  for (B = breakpoint_chain; B; B = B->next)  \
+    if ((B)->type == bp_livepoint)
+
 /* Chains of all breakpoints defined.  */
 
 struct breakpoint *breakpoint_chain;
@@ -370,6 +378,9 @@ int breakpoint_count;
 /* Number of last tracepoint made.  */
 
 int tracepoint_count;
+/* Number of last livepoint made.  */
+
+int livepoint_count;
 
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
@@ -2594,6 +2605,9 @@ print_it_typical (bpstat bs)
     case bp_watchpoint_scope:
     case bp_call_dummy:
     case bp_tracepoint:
+    case bp_livepoint:
+      //don't print a livepoint if by chance it breaks on it;
+      //should never end up here.
     case bp_jit_event:
     default:
       result = PRINT_UNKNOWN;
@@ -3200,7 +3214,8 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
       continue;
 
     if (b->type == bp_thread_event || b->type == bp_overlay_event
-	|| b->type == bp_longjmp_master)
+        || b->type == bp_longjmp_master
+        || b->type == bp_livepoint)
       /* We do not stop for these.  */
       bs->stop = 0;
     else
@@ -3504,6 +3519,11 @@ bpstat_what (bpstat bs)
 	     so infrun.c pops the dummy frame.  */
 	  bs_class = bp_silent;
 	  retval.call_dummy = 1;
+          break;
+        case bp_livepoint:
+          /* Livepoint hit!  Do your work and continue. */
+          livepoint_evaluate(bs);
+          bs_class = bp_nostop;
 	  break;
 	case bp_tracepoint:
 	  /* Tracepoint hits should not be reported back to GDB, and
@@ -3615,6 +3635,7 @@ print_one_breakpoint_location (struct br
     {bp_catchpoint, "catchpoint"},
     {bp_tracepoint, "tracepoint"},
     {bp_jit_event, "jit events"},
+    {bp_livepoint, "livepoint"},
   };
   
   static char bpenables[] = "nynny";
@@ -3744,6 +3765,7 @@ print_one_breakpoint_location (struct br
       case bp_longjmp_master:
       case bp_tracepoint:
       case bp_jit_event:
+      case bp_livepoint:
 	if (opts.addressprint)
 	  {
 	    annotate_field (4);
@@ -3800,9 +3822,11 @@ print_one_breakpoint_location (struct br
       annotate_field (7);
       if (b->type == bp_tracepoint)
 	ui_out_text (uiout, "\ttrace only if ");
+      else if(b->type == bp_livepoint)
+	ui_out_text (uiout, "\tevalute ");
       else
 	ui_out_text (uiout, "\tstop only if ");
-      ui_out_field_string (uiout, "cond", b->cond_string);
+      ui_out_field_string (uiout, b->type==bp_livepoint?"expr":"cond", b->cond_string);
       ui_out_text (uiout, "\n");
     }
 
@@ -3819,6 +3843,8 @@ print_one_breakpoint_location (struct br
       /* FIXME should make an annotation for this */
       if (ep_is_catchpoint (b))
 	ui_out_text (uiout, "\tcatchpoint");
+      else if(b->type==bp_livepoint)
+	ui_out_text (uiout, "\tlivepoint");
       else
 	ui_out_text (uiout, "\tbreakpoint");
       ui_out_text (uiout, " already hit ");
@@ -3833,7 +3859,8 @@ print_one_breakpoint_location (struct br
      mi. FIXME: Should have a better test for this. */
   if (ui_out_is_mi_like_p (uiout))
     if (!part_of_multiple && b->hit_count == 0)
-      ui_out_field_int (uiout, "times", b->hit_count);
+      if(b->type!=bp_livepoint)
+      	ui_out_field_int (uiout, "times", b->hit_count);
 
   if (!part_of_multiple && b->ignore_count)
     {
@@ -3990,6 +4017,7 @@ user_settable_breakpoint (const struct b
 	  || b->type == bp_catchpoint
 	  || b->type == bp_hardware_breakpoint
 	  || b->type == bp_tracepoint
+    || b->type == bp_livepoint
 	  || b->type == bp_watchpoint
 	  || b->type == bp_read_watchpoint
 	  || b->type == bp_access_watchpoint
@@ -4378,6 +4406,7 @@ allocate_bp_location (struct breakpoint 
     {
     case bp_breakpoint:
     case bp_tracepoint:
+    case bp_livepoint:
     case bp_until:
     case bp_finish:
     case bp_longjmp:
@@ -4474,7 +4503,8 @@ set_breakpoint_location_function (struct
 {
   if (loc->owner->type == bp_breakpoint
       || loc->owner->type == bp_hardware_breakpoint
-      || loc->owner->type == bp_tracepoint)
+      || loc->owner->type == bp_tracepoint
+      || loc->owner->type == bp_livepoint)
     {
       find_pc_partial_function (loc->address, &(loc->function_name), 
 				NULL, NULL);
@@ -5643,6 +5673,16 @@ mention (struct breakpoint *b)
 	printf_filtered (_(" %d"), b->number);
 	say_where = 1;
 	break;
+      case bp_livepoint:
+        if (ui_out_is_mi_like_p (uiout))
+          {
+            say_where = 0;
+            break;
+          }
+        printf_filtered (_("Livepoint"));
+        printf_filtered (_(" %d"), b->number);
+        say_where = 1;
+        break;
 
       case bp_until:
       case bp_finish:
@@ -5816,7 +5856,8 @@ create_breakpoint (struct gdbarch *gdbar
 
 	  if (enabled && executing_startup
 	      && (b->type == bp_breakpoint
-		  || b->type == bp_hardware_breakpoint))
+                  || b->type == bp_hardware_breakpoint
+                  || b->type == bp_livepoint))
 	    b->enable_state = bp_startup_disabled;
 
 	  loc = b->loc;
@@ -6157,7 +6198,7 @@ find_condition_and_thread (char *tok, CO
       
       toklen = end_tok - tok;
       
-      if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
+      if (toklen >= 1 && ((strncmp (tok, "if", toklen) == 0) || (strncmp(tok, "eval", toklen) == 0)) )
 	{
 	  struct expression *expr;
 
@@ -6320,9 +6361,10 @@ break_command_really (struct gdbarch *gd
   if (!pending)
     breakpoint_sals_to_pc (&sals, addr_start);
 
-  type_wanted = (traceflag
-		 ? bp_tracepoint
-		 : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
+  type_wanted = (traceflag==1 ? bp_tracepoint :
+                  (traceflag==2 ? bp_livepoint :
+                  (hardwareflag ? bp_hardware_breakpoint :
+                  bp_breakpoint)));
 
   /* Verify that condition can be parsed, before setting any
      breakpoints.  Allocate a separate condition expression for each
@@ -6376,7 +6418,8 @@ break_command_really (struct gdbarch *gd
 
       if (enabled && executing_startup
 	  && (b->type == bp_breakpoint
-	      || b->type == bp_hardware_breakpoint))
+              || b->type == bp_hardware_breakpoint
+              || b->type == bp_livepoint))
 	b->enable_state = bp_startup_disabled;
 
       mention (b);
@@ -8288,6 +8331,7 @@ breakpoint_re_set_one (void *bint)
     case bp_breakpoint:
     case bp_hardware_breakpoint:
     case bp_tracepoint:
+    case bp_livepoint:
       /* Do not attempt to re-set breakpoints disabled during startup.  */
       if (b->enable_state == bp_startup_disabled)
 	return 0;
@@ -8669,6 +8713,7 @@ disable_command (char *args, int from_tt
 	continue;
       case bp_breakpoint:
       case bp_tracepoint:
+      case bp_livepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -8762,6 +8807,7 @@ enable_command (char *args, int from_tty
 	continue;
       case bp_breakpoint:
       case bp_tracepoint:
+      case bp_livepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -9008,6 +9054,261 @@ catch_syscall_completer (struct cmd_list
   return (list == NULL) ? NULL : complete_on_enum (list, text, word);
 }
 
+/* Livepoint-specific operations. */
+
+extern void
+mi_on_live_hit (struct breakpoint *b,struct value *val);
+
+static void cli_on_live_hit(struct breakpoint *b,struct value *val)
+  {
+    struct value_print_options opts;
+    get_user_print_options (&opts);
+    opts.deref_ref = 0;
+
+    get_formatted_print_options (&opts, 0);
+    opts.inspect_it = 0;
+    opts.raw = 0;
+
+    printf_filtered("Livepoint %d, %s = ",b->number,b->cond_string);
+    common_val_print (val, gdb_stdout, 1,&opts,current_language);
+    printf_filtered ("\n");
+  }
+
+static void livepoint_evaluate(struct bpstats *bs)
+  {
+    static int interpreter=0;
+
+    const struct bp_location *bl=bs->breakpoint_at;
+    struct breakpoint *b=bl->owner;
+    struct value *val;
+//***
+    if(interpreter==0)
+      {
+        if(current_interp_named_p(INTERP_CONSOLE))
+          interpreter=1;  //cli
+        else if(current_interp_named_p(INTERP_TUI))
+          interpreter=1;  //cli
+        else
+          interpreter=2;  //mi
+      }
+
+    select_frame (get_current_frame());
+    val = evaluate_expression(bl->cond);
+
+    if(interpreter==1)
+      cli_on_live_hit(b,val);
+    else
+      mi_on_live_hit(b,val);
+
+    b->hit_count++;
+  }
+
+static void
+set_livepoint_count (int num)
+{
+  livepoint_count = num;
+  set_internalvar_integer (lookup_internalvar ("gpnum"), num);
+}
+
+extern void
+mi_cmd_live_bench (int mode);
+
+void
+bench_command (char *arg, int from_tty)
+{
+	int i;
+	mi_cmd_live_bench(atol(arg));
+}
+
+void
+live_command (char *arg, int from_tty)
+{
+  break_command_really (get_current_arch (),
+                        arg,
+                        NULL, 0, 1 /* parse arg */,
+                        0 /* tempflag */, 0 /* hardwareflag */,
+                        2 /* traceflag */,
+                        0 /* Ignore count */,
+                        pending_break_support,
+                        NULL,
+                        from_tty,
+                        1 /* enabled */);
+  set_livepoint_count (breakpoint_count);
+}
+
+void
+set_livepoint (struct gdbarch *gdbarch,
+                char *address, char *expression,
+                int thread, int pending, int enabled)
+{
+  break_command_really (gdbarch,
+                        address, expression, thread,
+                        0 /* condition and thread are valid.  */,
+                        0 /* tempflag */, 0 /* hardwareflag */, 2 /* traceflag */,
+      0 /* ignore_count */,
+                        pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
+                        NULL, 0, enabled);
+}
+
+static void
+livepoints_info (char *gpnum_exp, int from_tty)
+{
+  struct breakpoint *b;
+  int gps_to_list = 0;
+
+  /* In the no-arguments case, say "No gumpoints" if none found.  */
+  if (gpnum_exp == 0)
+    {
+      ALL_LIVEPOINTS (b)
+        {
+                if (b->number >= 0)
+                  {
+                    gps_to_list = 1;
+                    break;
+                  }
+        }
+      if (!gps_to_list)
+              {
+                ui_out_message (uiout, 0, "No livepoints.\n");
+                return;
+              }
+    }
+
+  /* Otherwise be the same as "info break".  */
+  breakpoints_info (gpnum_exp, from_tty);
+}
+
+static void
+enable_live_command (char *args, int from_tty)
+{
+  enable_command (args, from_tty);
+}
+
+static void
+disable_live_command (char *args, int from_tty)
+{
+  disable_command (args, from_tty);
+}
+
+static void
+delete_live_command (char *arg, int from_tty)
+{
+  struct breakpoint *b, *temp;
+
+  dont_repeat ();
+
+  if (arg == 0)
+    {
+      int breaks_to_delete = 0;
+
+      ALL_LIVEPOINTS (b)
+      {
+        if (b->number >= 0)
+          {
+            breaks_to_delete = 1;
+            break;
+          }
+      }
+
+      /* Ask user only if there are some breakpoints to delete.  */
+      if (!from_tty
+          || (breaks_to_delete && query (_("Delete all livepoints? "))))
+        {
+          ALL_BREAKPOINTS_SAFE (b, temp)
+          {
+            if (b->type == bp_livepoint
+                && b->number >= 0)
+              delete_breakpoint (b);
+          }
+        }
+    }
+  else
+    map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+struct breakpoint *
+get_last_livepoint ()
+  {
+    struct breakpoint *gp;
+
+    ALL_LIVEPOINTS(gp)
+      {
+        if(gp->number==breakpoint_count)
+          return gp;
+      }
+
+    return 0;
+  }
+
+struct breakpoint *
+get_livepoint (int num)
+{
+  struct breakpoint *t;
+
+  ALL_LIVEPOINTS (t)
+    if (t->number == num)
+      return t;
+
+  return NULL;
+}
+
+struct breakpoint *
+get_livepoint_by_number (char **arg, int multi_p, int optional_p)
+{
+  extern int livepoint_count;
+  struct breakpoint *g;
+  int gpnum;
+  char *instring = arg == NULL ? NULL : *arg;
+
+  if (arg == NULL || *arg == NULL || ! **arg)
+    {
+      if (optional_p)
+        gpnum = livepoint_count;
+      else
+        error_no_arg (_("livepoint number"));
+    }
+  else
+    gpnum = multi_p ? get_number_or_range (arg) : get_number (arg);
+
+  if (gpnum <= 0)
+    {
+      if (instring && *instring)
+        printf_filtered (_("bad livepoint number at or near '%s'\n"),
+                         instring);
+      else
+        printf_filtered (_("Livepoint argument missing and no previous livepoint\n"));
+      return NULL;
+    }
+
+  ALL_LIVEPOINTS (g)
+    if (g->number == gpnum)
+    {
+      return g;
+    }
+
+  /* FIXME: if we are in the middle of a range we don't want to give
+     a message.  The current interface to get_number_or_range doesn't
+     allow us to discover this.  */
+  printf_unfiltered ("No livepoint number %d.\n", gpnum);
+  return NULL;
+}
+
+VEC(breakpoint_p) *
+all_livepoints ()
+{
+  VEC(breakpoint_p) *gp_vec = 0;
+  struct breakpoint *gp;
+
+  ALL_LIVEPOINTS (gp)
+  {
+    VEC_safe_push (breakpoint_p, gp_vec, gp);
+  }
+
+  return gp_vec;
+}
+
+/* End of Livepoint-specific operations. */
+
 /* Tracepoint-specific operations.  */
 
 /* Set tracepoint count to NUM.  */
@@ -9394,6 +9695,7 @@ _initialize_breakpoint (void)
   breakpoint_count = 0;
 
   tracepoint_count = 0;
+  livepoint_count = 0;
 
   add_com ("ignore", class_breakpoint, ignore_command, _("\
 Set ignore-count of breakpoint number N to COUNT.\n\
@@ -9738,6 +10040,62 @@ hardware.)"),
 
   can_use_hw_watchpoints = 1;
 
+  /* Livepoint manipulation commands. */
+  /* don't bother with a category
+  add_cmd ("livepoints", class_live, NULL,
+    _("Live tracing commands."),
+    &cmdlist);
+  */
+
+  c = add_com("bench",class_breakpoint,bench_command,"Benchmark mode.");
+
+  c = add_com ("live", class_breakpoint, live_command, _("\
+Set a livepoint at specified line or function.\n\
+\n\
+live [LOCATION] [thread THREADNUM] [eval EXPRESSION]\n\
+EXPRESSION can be any valid C/C++ expression.\n\
+LOCATION may be a line number, function name, or \"*\" and an address.\n\
+If a line number is specified, evaluated at start of code for that line.\n\
+If a function is specified, evaluated at start of code for that function.\n\
+If an address is specified, evaluated at that exact address.\n\
+With no LOCATION, uses current execution address of selected stack frame.\n\
+This is useful for evaluating on return to a stack frame.\n\
+\n\
+THREADNUM is the number from \"info threads\".\n\
+CONDITION is a boolean expression.\n\
+\n\
+Multiple livepoints at one place are permitted.\n\
+\n\
+Do \"help livepoints\" for info on other livepoint commands."));
+  set_cmd_completer (c, location_completer);
+
+  add_com_alias ("lp", "live", class_alias, 0);
+
+  add_info ("livepoints", livepoints_info, _("\
+Status of livepoints, or livepoint number NUMBER.\n\
+Convenience variable \"$gpnum\" contains the number of the\n\
+last livepoint set."));
+
+  add_info_alias ("lp", "livepoints", 1);
+
+  add_cmd ("livepoints", class_breakpoint, delete_live_command, _("\
+Delete specified livepoints.\n\
+Arguments are livepoint numbers, separated by spaces.\n\
+No argument means delete all livepoints."),
+    &deletelist);
+
+  c = add_cmd ("livepoints", class_breakpoint, disable_live_command, _("\
+Disable specified livepoints.\n\
+Arguments are livepoint numbers, separated by spaces.\n\
+No argument means disable all livepoints."),
+    &disablelist);
+
+  c = add_cmd ("livepoints", class_breakpoint, enable_live_command, _("\
+Enable specified livepoints.\n\
+Arguments are livepoint numbers, separated by spaces.\n\
+No argument means enable all livepoints."),
+    &enablelist);
+
   /* Tracepoint manipulation commands.  */
 
   c = add_com ("trace", class_breakpoint, trace_command, _("\
diff -rupN /home/luke/Projects/gdb-7.0/gdb/breakpoint.h /home/luke/Projects/gdb-trace/gdb/breakpoint.h
--- /home/luke/Projects/gdb-7.0/gdb/breakpoint.h	2009-09-15 15:30:05.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/breakpoint.h	2009-11-29 16:00:34.946267707 +1300
@@ -124,6 +124,9 @@ enum bptype
 
     /* Event for JIT compiled code generation or deletion.  */
     bp_jit_event,
+
+    /* dummy tracepoint type for new native tracepoints */
+    bp_livepoint,
   };
 
 /* States of enablement of breakpoint. */
@@ -497,6 +500,9 @@ struct breakpoint
 
     /* Chain of action lines to execute when this tracepoint is hit.  */
     struct action_line *actions;
+
+    /* Chain of pointer options for serialization. */
+    struct pointer_options *ptr_opts;
   };
 
 typedef struct breakpoint *breakpoint_p;
@@ -755,6 +761,12 @@ extern void awatch_command_wrapper (char
 extern void rwatch_command_wrapper (char *, int);
 extern void tbreak_command (char *, int);
 
+extern void set_livepoint (struct gdbarch *gdbarch,
+                            char *address, char *expression,
+                            int thread, int pending, int enabled);
+
+struct breakpoint *get_last_livepoint ();
+
 extern void set_breakpoint (struct gdbarch *gdbarch,
 			    char *address, char *condition,
 			    int hardwareflag, int tempflag,
diff -rupN /home/luke/Projects/gdb-7.0/gdb/c-lang.h /home/luke/Projects/gdb-trace/gdb/c-lang.h
--- /home/luke/Projects/gdb-7.0/gdb/c-lang.h	2009-03-21 12:04:30.000000000 +1300
+++ /home/luke/Projects/gdb-trace/gdb/c-lang.h	2009-11-29 15:04:03.281249673 +1300
@@ -27,6 +27,7 @@ struct language_arch_info;
 
 #include "value.h"
 #include "macroexp.h"
+#include "b64.h"
 
 
 /* The various kinds of C string and character.  Note that these
@@ -90,6 +91,7 @@ extern void c_language_arch_info (struct
 /* These are in c-typeprint.c: */
 
 extern void c_type_print_base (struct type *, struct ui_file *, int, int);
+extern void c_print_type_b64 (struct type *type, char *name, struct b64_buf *stream);
 
 /* These are in cp-valprint.c */
 
diff -rupN /home/luke/Projects/gdb-7.0/gdb/Makefile.in /home/luke/Projects/gdb-trace/gdb/Makefile.in
--- /home/luke/Projects/gdb-7.0/gdb/Makefile.in	2009-10-03 11:06:10.000000000 +1300
+++ /home/luke/Projects/gdb-trace/gdb/Makefile.in	2009-11-29 15:16:20.642267692 +1300
@@ -682,6 +682,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	record.c \
 	jit.c \
 	xml-syscall.c \
+	b64.c \
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -833,7 +834,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	prologue-value.o memory-map.o xml-support.o xml-syscall.o \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o \
-	jit.o
+	jit.o \
+	b64.o
 
 # Definitions for the syscall's XML files and dir
 XML_SYSCALLS_DIR = syscalls/
diff -rupN /home/luke/Projects/gdb-7.0/gdb/mi/mi-cmd-break.c /home/luke/Projects/gdb-trace/gdb/mi/mi-cmd-break.c
--- /home/luke/Projects/gdb-7.0/gdb/mi/mi-cmd-break.c	2009-08-04 00:39:00.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/mi/mi-cmd-break.c	2009-12-02 18:09:58.493184810 +1300
@@ -29,6 +29,7 @@
 #include "gdb.h"
 #include "exceptions.h"
 #include "observer.h"
+#include "tracepoint.h"
 
 enum
   {
@@ -59,6 +60,105 @@ enum bp_type
     REGEXP_BP
   };
 
+void
+mi_cmd_live_insert (char *command, char **argv, int argc)
+{
+  char *address = NULL;
+  int thread = -1;
+  char *expression = NULL;
+  int pending = 0;
+  int enabled = 1;
+  struct breakpoint *bp;
+  struct pointer_options *ptr_opts=0;
+  struct pointer_options **current_opts=&ptr_opts;
+
+  struct gdb_exception e;
+
+  enum opt
+    {
+      EXPRESSION_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT, MEMBERSER_OPT, SERIAL_OPT
+    };
+
+  static struct mi_opt opts[] =
+    {
+      {"e", EXPRESSION_OPT, 1},
+      {"p", THREAD_OPT, 1},
+      {"f", PENDING_OPT, 0},
+      {"d", DISABLE_OPT, 0},
+      {"sm", MEMBERSER_OPT,1},
+      {"s", SERIAL_OPT,1},
+      { 0, 0, 0 }
+    };
+
+  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
+     to denote the end of the option list. */
+  int optind = 0;
+  char *optarg;
+  while (1)
+    {
+      int opt = mi_getopt ("mi_cmd_live_insert", argc, argv, opts, &optind, &optarg);
+      if (opt < 0)
+        break;
+      switch ((enum opt) opt)
+        {
+          case EXPRESSION_OPT:
+            expression = optarg;
+            break;
+          case THREAD_OPT:
+            thread = atol (optarg);
+            break;
+          case PENDING_OPT:
+            pending = 1;
+            break;
+          case DISABLE_OPT:
+            enabled = 0;
+			break;
+		  case SERIAL_OPT:
+            (*current_opts)=create_pointer_options(optarg,0);
+            current_opts=&((*current_opts)->next);
+			break;
+          case MEMBERSER_OPT:
+            (*current_opts)=create_pointer_options(optarg,1);
+            current_opts=&((*current_opts)->next);
+            break;
+        }
+    }
+
+  if (optind >= argc)
+    error (_("mi_cmd_live_insert: Missing <location>"));
+  if (optind < argc - 1)
+    error (_("mi_cmd_live_insert: Garbage following <location>"));
+  address = argv[optind];
+
+  // ensure the observers are attached (only happens once)
+  if (! mi_breakpoint_observers_installed)
+    {
+      observer_attach_breakpoint_created (breakpoint_notify);
+      observer_attach_breakpoint_modified (breakpoint_notify);
+      observer_attach_breakpoint_deleted (breakpoint_notify);
+      mi_breakpoint_observers_installed = 1;
+    }
+
+  // output the livepoint via the notifier (breakpoint_notify at the top)
+  mi_can_breakpoint_notify = 1;
+  /* Make sure we restore hooks even if exception is thrown.  */
+  TRY_CATCH (e, RETURN_MASK_ALL)
+    {
+      set_livepoint (get_current_arch (), address, expression,
+          thread, pending, enabled);
+    }
+  if (e.reason < 0)
+    throw_exception (e);
+
+  // ensure the next operation doesn't output.  This is a bloody stupid system.
+  mi_can_breakpoint_notify = 0;
+
+  if(ptr_opts!=0) {
+    bp=get_last_livepoint();
+    bp->ptr_opts=ptr_opts;
+  }
+}
+
 /* Implements the -break-insert command.
    See the MI manual for the list of possible options.  */
 
diff -rupN /home/luke/Projects/gdb-7.0/gdb/mi/mi-cmds.c /home/luke/Projects/gdb-trace/gdb/mi/mi-cmds.c
--- /home/luke/Projects/gdb-7.0/gdb/mi/mi-cmds.c	2009-09-16 06:51:25.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/mi/mi-cmds.c	2009-11-29 23:15:23.261258591 +1300
@@ -43,6 +43,10 @@ struct mi_cmd mi_cmds[] =
   { "break-insert", { NULL, 0 }, mi_cmd_break_insert},
   { "break-list", { "info break", }, NULL },
   { "break-watch", { NULL, 0 }, mi_cmd_break_watch},
+  { "live-insert", {NULL, 0 }, mi_cmd_live_insert},
+  { "live-delete", {"delete breakpoint", 1 }, NULL},
+  { "live-disable", { "disable breakpoint", 1 }, NULL },
+  { "live-enable", { "enable breakpoint", 1 }, NULL },
   { "data-disassemble", { NULL, 0 }, mi_cmd_disassemble},
   { "data-evaluate-expression", { NULL, 0 }, mi_cmd_data_evaluate_expression},
   { "data-list-changed-registers", { NULL, 0 }, mi_cmd_data_list_changed_registers},
diff -rupN /home/luke/Projects/gdb-7.0/gdb/mi/mi-cmds.h /home/luke/Projects/gdb-trace/gdb/mi/mi-cmds.h
--- /home/luke/Projects/gdb-7.0/gdb/mi/mi-cmds.h	2009-09-16 06:51:25.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/mi/mi-cmds.h	2009-11-29 15:49:45.722285702 +1300
@@ -37,6 +37,7 @@ typedef void (mi_cmd_argv_ftype) (char *
 
 /* Function implementing each command */
 extern mi_cmd_argv_ftype mi_cmd_break_insert;
+extern mi_cmd_argv_ftype mi_cmd_live_insert;
 extern mi_cmd_argv_ftype mi_cmd_break_commands;
 extern mi_cmd_argv_ftype mi_cmd_break_watch;
 extern mi_cmd_argv_ftype mi_cmd_disassemble;
diff -rupN /home/luke/Projects/gdb-7.0/gdb/mi/mi-interp.c /home/luke/Projects/gdb-trace/gdb/mi/mi-interp.c
--- /home/luke/Projects/gdb-7.0/gdb/mi/mi-interp.c	2009-05-30 07:06:12.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/mi/mi-interp.c	2009-12-08 13:21:01.854014570 +1300
@@ -35,6 +35,11 @@
 #include "observer.h"
 #include "gdbthread.h"
 #include "solist.h"
+#include "ui-file.h"
+#include "valprint.h"
+#include "b64.h"
+#include "value.h"
+#include "tracepoint.h"
 
 /* These are the interpreter setup, etc. functions for the MI interpreter */
 static void mi_execute_command_wrapper (char *cmd);
@@ -328,6 +333,242 @@ mi_inferior_exit (int pid)
   gdb_flush (mi->event_channel);  
 }
 
+extern struct language_defn *current_language;
+
+#define LIVE_OUT_NEW
+
+int bench_mode=0;
+
+void
+mi_cmd_live_bench (int mode)
+{
+	bench_mode=mode;
+}
+
+void eval_live_actions(struct breakpoint *b,struct value *val)
+{
+  struct pointer_options *opts=b->ptr_opts;
+  struct type *valType=value_type(val);
+  char *nullterm=0;
+  LONGEST len;
+  LONGEST size;
+  CORE_ADDR addr;
+  int counter=0;
+
+#ifndef LIVE_OUT_NEW
+  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+  struct ui_stream *stb = ui_out_stream_new (mi_uiout);
+#endif //LIVE_OUT_NEW
+
+  while(opts)
+    {
+      // we want to call unpack_long from value.c on the length
+      // also call unpack_pointer for the same (unpack_pointer currently =
+      // unpack_long).
+      // I think I will need a sub-struct to store in the action pointer.
+      // i'll need the offset of the length and the offset of the pointer,
+      // as well as the types of both.  that way I can get the valaddr from
+      // the address of the parent struct, to serialize the type.
+
+      //LONGEST unpack_long (struct type *type, const gdb_byte *valaddr)
+
+      if(opts->initialized==0)
+	  {
+		  struct type *elementType;
+		  opts->initialized=1;
+
+		  if(opts->flag=='=')
+		  {
+			//need to set up the expression
+			opts->expr=parse_exp_1(&(opts->parameter),b->exp_valid_block,0);
+		  }
+
+		  if(opts->hasMember)
+		  {
+			  struct value *memberField;
+			  memberField=search_struct_field(opts->member, val, 0, valType, 0);
+			  opts->member_type=value_type(memberField);
+			  opts->member_offset=value_offset(memberField);
+
+			  elementType=check_typedef(opts->member_type->main_type->target_type);
+
+			  if(opts->flag=='#')
+			  {
+				struct value *parameterField;
+				parameterField = search_struct_field (opts->parameter, val, 0, valType, 0);
+				opts->parameter_type=value_type(parameterField);
+				opts->parameter_offset=value_offset(parameterField);
+			  }
+		  }
+		  else
+		  {
+			  elementType=check_typedef(valType->main_type->target_type);
+		  }
+		  opts->element_size=elementType->length;
+		//as this is the first time this has been output, send the target type information
+#ifdef LIVE_OUT_NEW
+		write(1,",ptr_type=\"",11);
+		printf_type_b64(elementType,opts->member);
+		write(1,"\"",1);
+#else
+		print_type_b64(elementType,arrayName,stb->stream);
+        //output the stream as a field
+        ui_out_field_stream (mi_uiout, "ptr_type", stb);
+#endif
+      }
+
+	  if(opts->hasMember)
+	  {
+		  const gdb_byte *structAddr;
+		  // get the address of the target struct
+		  structAddr=value_contents_all(val)+value_embedded_offset(val);
+		  // retrieve the pointer member
+		  addr=unpack_long(opts->member_type,structAddr+opts->member_offset);
+
+		  if(opts->flag=='#')
+		  {
+			  len=unpack_long(opts->parameter_type,structAddr+opts->parameter_offset);
+		  }
+	  }
+	  else
+		  //read the memory address from the expression result itself
+		  addr=unpack_long(value_type(val),value_contents_all(val)+value_embedded_offset(val));
+
+	  if(opts->flag=='=')
+	  {
+		  struct value *lenVal=evaluate_expression(opts->expr);
+		  len=unpack_long(value_type(lenVal),value_contents_all(lenVal)+value_embedded_offset(lenVal));
+	  }
+	  else if(opts->flag==':')
+	  {
+		  // null-terminated!  To do this we need to copy to a temp buffer first,
+		  // then find the length.
+		  //max chars hardcoded at 100 for now.
+		  nullterm=malloc(100);
+	      target_read_memory(addr,nullterm,100);
+		  for(len=0;len<100&&nullterm[len];len++);
+	  }
+
+	  // still need to find the terminating null element to get the size for that option.
+
+      // calculate the array size in bytes
+      size=len*opts->element_size;
+
+      // increase the size of the buffer if necessary
+      // (never decrease buffer size)
+      if(size>opts->mem_size) {
+        // free the memory buffer
+        if(opts->mem) free(opts->mem);
+
+        // free the base64 buffer if allocated
+        if(opts->buf)
+          free(opts->buf->out);
+
+        //allocate the new base64 buffer
+        b64_buf_init(opts->buf,malloc((size+2)*4/3+120));
+
+        //allocate the new memory buffer
+        opts->mem=malloc(size+90);
+        //copy in the name of the pointer member
+        memcpy(opts->mem,opts->member,opts->member_length);
+        opts->mem_size=size;
+      }
+
+      // this is an interesting point.  this bit could be useful for optimization for the
+      // main tracepoint section.  The user could potentially specify an expression and
+      // tick 'revert to memcpy after first evaluation' or similar.  Then it'd just copy
+      // the memory instead of evaluating the expression.  Could be mucho faster, but requires
+      // intelligent use.
+      
+      //save the number of elements in the array
+      *((uint32_t*)(opts->mem+opts->member_length))=len;
+      //save the contents of the array
+	  if(opts->flag==':')
+	  {
+		//if null-terminated, we've already read this.
+		memcpy(opts->mem+opts->member_length+4,nullterm,size);
+		free(nullterm);
+	  }
+	  else
+		target_read_memory(addr,opts->mem+opts->member_length+4,size);
+      //convert to base64
+      b64_buf_print(opts->buf,opts->mem,opts->member_length+size+4);
+	  
+#ifdef LIVE_OUT_NEW
+	  // send to stdout
+	  write(1,",ptr=\"",6);
+	  b64_buf_stdoutput(opts->buf);
+	  write(1,"\"",1);
+#else
+	  //output to the stream
+	  b64_buf_output(opts->buf,stb->stream);
+      //output the stream as a field
+      ui_out_field_stream (mi_uiout, "ptr", stb);
+#endif
+
+      opts=opts->next;
+      counter++;
+    }
+#ifndef LIVE_OUT_NEW
+  //deallocate the field stream
+  ui_out_stream_delete (stb);
+#endif
+}
+
+void
+mi_on_live_hit (struct breakpoint *b,struct value *val)
+{
+#ifdef LIVE_OUT_NEW
+  char *buf=malloc(100);
+  sprintf(buf,"*trace,number=\"%d\",hits=\"%d\",thread-id=\"%d\"",b->number,b->hit_count,pid_to_thread_id(inferior_ptid));
+  write(1,buf,strlen(buf));
+  free(buf);
+
+  if(bench_mode||b->hit_count==0)
+  {
+	write(1,",type=\"",7);
+	printf_type_b64(value_type(val),"");
+	write(1,"\"",1);
+  }
+  write(1,",value=\"",8);
+  b64_printf(value_contents_all(val)+value_embedded_offset(val),TYPE_LENGTH(value_type(val)));
+  write(1,"\"",1);
+
+  //deal with any pointer serializations that have been tagged on.
+  eval_live_actions(b,val);
+
+  write(1,"\n",1);
+#else
+  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+  struct ui_stream *stb = ui_out_stream_new (uiout);
+
+  ui_out_field_int (mi_uiout,"number",b->number);
+  ui_out_field_int (mi_uiout,"hits",b->hit_count);
+  ui_out_field_int (mi_uiout,"thread-id", pid_to_thread_id (inferior_ptid));
+
+  if(bench_mode||b->hit_count==0)
+  {
+    print_type_b64(value_type(val),"",stb->stream);
+    ui_out_field_stream(mi_uiout,"type",stb);
+  }
+
+  b64_print(value_contents_all(val)+value_embedded_offset(val),TYPE_LENGTH(value_type(val)),stb->stream);
+  ui_out_field_stream (mi_uiout, "value", stb);
+
+  //deal with any pointer serializations that have been tagged on.
+  eval_live_actions(b,val);
+
+  fputs_unfiltered ("*trace", raw_stdout);
+  mi_out_put (mi_uiout, raw_stdout);
+  mi_out_rewind (mi_uiout);
+  mi_print_timing_maybe ();
+  fputs_unfiltered ("\n", raw_stdout);
+  gdb_flush (raw_stdout);
+
+  ui_out_stream_delete (stb);
+#endif //LIVE_OUT_NEW
+}
+
 static void
 mi_on_normal_stop (struct bpstats *bs, int print_frame)
 {
diff -rupN /home/luke/Projects/gdb-7.0/gdb/tracepoint.c /home/luke/Projects/gdb-trace/gdb/tracepoint.c
--- /home/luke/Projects/gdb-7.0/gdb/tracepoint.c	2009-07-15 09:40:30.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/tracepoint.c	2009-12-02 22:15:36.185194217 +1300
@@ -44,6 +44,7 @@ extern int remote_supports_cond_tracepoi
 #include "valprint.h"
 #include "gdbcore.h"
 #include "objfiles.h"
+#include "b64.h"
 
 #include "ax.h"
 #include "ax-gdb.h"
@@ -2276,3 +2277,63 @@ depending on target's capabilities."));
   target_buf_size = 2048;
   target_buf = xmalloc (target_buf_size);
 }
+
+struct pointer_options *create_pointer_options(char *args, int type)
+  {
+    struct pointer_options *opts;
+    char *c=args,*parameter=0;
+	char flag;
+    int n;
+
+    opts=malloc(sizeof(struct pointer_options));
+    opts->next=0;
+	opts->hasMember=(char)type;
+	opts->initialized=0;
+	opts->expr=0;
+
+	if(type==1)
+	{
+		//start will be the member name
+		while(*c&&*c!=':'&&*c!='#'&&*c!='=')
+			c++;
+		opts->member_length=c-args;
+		opts->member=malloc(opts->member_length+1);
+		memcpy(opts->member,args,opts->member_length);
+		opts->member[opts->member_length]=0;
+		// needs to include the terminating zero.
+		opts->member_length++;
+	}
+	else
+	{
+		// placeholder
+		opts->member="";
+		opts->member_length=1;
+	}
+
+	//store flag
+	opts->flag=*c++;
+	args=c;
+	while(*c++);
+
+	if(opts->flag!=':')
+	{
+		opts->parameter=malloc(c-args);
+		memcpy(opts->parameter,args,c-args);
+	}
+	else
+		opts->parameter=0;
+    
+    opts->member_type=opts->parameter_type=0;
+    opts->member_offset=opts->parameter_offset=0;
+    opts->element_size=0;
+    opts->mem_size=0;
+
+    // even when the size is zero there needs to be memory available
+    // as the name and number of elements are sent regardless.
+    opts->mem=malloc(90);
+    memcpy(opts->mem,opts->member,opts->member_length);
+    opts->buf=malloc(sizeof(struct b64_buf));
+    b64_buf_init(opts->buf,malloc(120));
+
+    return opts;
+  }
diff -rupN /home/luke/Projects/gdb-7.0/gdb/tracepoint.h /home/luke/Projects/gdb-trace/gdb/tracepoint.h
--- /home/luke/Projects/gdb-7.0/gdb/tracepoint.h	2009-03-31 18:08:32.000000000 +1300
+++ /home/luke/Projects/gdb-trace/gdb/tracepoint.h	2009-12-02 19:24:15.549185164 +1300
@@ -19,6 +19,34 @@
 
 #if !defined (TRACEPOINT_H)
 #define TRACEPOINT_H 1
+/* Holds pointer serialization options */
+struct pointer_options
+{
+  struct pointer_options *next;
+
+  char flag;
+  char hasMember;
+  char initialized;
+
+  char *member;
+  int member_length;
+
+  char *parameter;
+
+  struct type *member_type;
+  int member_offset;
+  struct type *parameter_type;
+  int parameter_offset;
+
+  struct expression *expr;
+
+  unsigned element_size;
+  uint32_t mem_size;
+  gdb_byte *mem;
+  struct b64_buf *buf;
+};
+
+struct pointer_options *create_pointer_options(char *args, int type);
 
 /* The data structure for an action: */
 struct action_line
diff -rupN /home/luke/Projects/gdb-7.0/gdb/valops.c /home/luke/Projects/gdb-trace/gdb/valops.c
--- /home/luke/Projects/gdb-7.0/gdb/valops.c	2009-09-29 13:41:24.000000000 +1300
+++ /home/luke/Projects/gdb-trace/gdb/valops.c	2009-11-29 15:11:59.281249112 +1300
@@ -53,7 +53,7 @@ extern int overload_debug;
 static int typecmp (int staticp, int varargs, int nargs,
 		    struct field t1[], struct value *t2[]);
 
-static struct value *search_struct_field (char *, struct value *, 
+struct value *search_struct_field (char *, struct value *, 
 					  int, struct type *, int);
 
 static struct value *search_struct_method (char *, struct value **,
@@ -1525,12 +1525,14 @@ typecmp (int staticp, int varargs, int n
    If LOOKING_FOR_BASECLASS, then instead of looking for struct
    fields, look for a baseclass named NAME.  */
 
-static struct value *
+struct value *
 search_struct_field (char *name, struct value *arg1, int offset,
 		     struct type *type, int looking_for_baseclass)
 {
   int i;
-  int nbases = TYPE_N_BASECLASSES (type);
+  int nbases=0;
+  if(type->main_type->type_specific.cplus_stuff!=0)
+    nbases = TYPE_N_BASECLASSES (type);
 
   CHECK_TYPEDEF (type);
 
diff -rupN /home/luke/Projects/gdb-7.0/gdb/value.h /home/luke/Projects/gdb-trace/gdb/value.h
--- /home/luke/Projects/gdb-7.0/gdb/value.h	2009-09-01 08:18:45.000000000 +1200
+++ /home/luke/Projects/gdb-trace/gdb/value.h	2009-11-29 15:12:09.257249429 +1300
@@ -429,6 +429,12 @@ extern struct value *value_neg (struct v
 
 extern struct value *value_complement (struct value *arg1);
 
+extern struct value *search_struct_field (char *name,
+                                       struct value *arg1,
+                                       int offset,
+                                       struct type *type,
+                                       int looking_for_baseclass);
+
 extern struct value *value_struct_elt (struct value **argp,
 				       struct value **args,
 				       char *name, int *static_memfuncp,
