[PATCH] target attributes [1/5] core and load from target function

Hui Zhu teawater@gmail.com
Sun Sep 2 10:39:00 GMT 2012


On Wed, Aug 29, 2012 at 10:43 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 08/29/2012 04:11 PM, Hui Zhu wrote:
>> +static void
>> +target_attribute_address_handler (struct gdb_xml_parser *parser,
>> +                               const struct gdb_xml_element *element,
>> +                               void *user_data,
>> +                               VEC(gdb_xml_value_s) *attributes)
>> +{
>> +  int i, len;
>> +  struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
>> +  struct target_attribute *ta = *(struct target_attribute **)user_data;
>> +  CORE_ADDR start, end;
>> +  struct target_attribute_address *ta_addr;
>
> I happen to see some compilation warnings on my new Fedora 16 box, while
> these warnings don't appear on my Ubuntu box.
>
> ... -Werror -c -o target-memory.o -MT target-memory.o -MMD -MP -MF .deps/target-memory.Tpo ../../../git/gdb/target-memory.c
> ../../../git/gdb/target-attributes.c: In function ‘target_attribute_address_handler’:
> ../../../git/gdb/target-attributes.c:487:16: error: ‘end’ may be used uninitialized in this function [-Werror=uninitialized]
> ../../../git/gdb/target-attributes.c:486:18: error: ‘start’ may be used uninitialized in this function [-Werror=uninitialized]
> ../../../git/gdb/target-attributes.c: In function ‘target_attribute_attr_handler’:
> ../../../git/gdb/target-attributes.c:376:12: error: ‘type’ may be used uninitialized in this function [-Werror=uninitialized]
> ../../../git/gdb/target-attributes.c: In function ‘target_attribute_type’:
> ../../../git/gdb/target-attributes.c:632:3: error: ‘ret’ may be used uninitialized in this function [-Werror=uninitialized]
> cc1: all warnings being treated as errors
> make: *** [target-attributes.o] Error 1
>
> The gcc I am using is 4.6.3
> $ gcc --version
> gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
>
> We have to get these warnings fixed.
>
>> +
>> +  len = VEC_length (gdb_xml_value_s, attributes);
>> +  for (i = 0; i < len; i++)
>> +    {
>> +      if (strcmp (attrs[i].name, "start") == 0)
>> +        start = * (ULONGEST *) attrs[i].value;
>> +      else if (strcmp (attrs[i].name, "end") == 0)
>> +        end = * (ULONGEST *) attrs[i].value;
>> +      else
>> +        gdb_xml_error (parser, _("Unknown attribute name '%s'."),
>> +                    attrs[i].name);
>> +    }
>> +
>> +  ta_addr = xmalloc (sizeof (struct target_attribute_address));
>> +  ta_addr->start = start;
>> +  ta_addr->end = end;
>> +
>> +  ta_addr->prev = ta->addresses;
>> +  ta->addresses = ta_addr;
>> +}
>
> --
> Yao

Thanks.  I post a new version.

Best,
Hui
-------------- next part --------------
--- a/Makefile.in
+++ b/Makefile.in
@@ -731,7 +731,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	solib.c solib-target.c source.c \
 	stabsread.c stack.c probe.c stap-probe.c std-regs.c \
 	symfile.c symfile-mem.c symmisc.c symtab.c \
-	target.c target-descriptions.c target-memory.c \
+	target.c target-attributes.c target-descriptions.c target-memory.c \
 	thread.c top.c tracepoint.c \
 	trad-frame.c \
 	tramp-frame.c \
@@ -831,7 +831,8 @@ gnulib/import/extra/snippet/warn-on-use.
 gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
 common/format.h common/host-defs.h utils.h \
-common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h gdb_bfd.h
+common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h gdb_bfd.h \
+target-attributes.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -917,7 +918,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	solib.o solib-target.o \
 	prologue-value.o memory-map.o memrange.o \
 	xml-support.o xml-syscall.o xml-utils.o \
-	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+	target-attributes.o target-descriptions.o target-memory.o \
+	xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	gdb_vecs.o jit.o progspace.o skip.o probe.o \
 	common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -700,6 +700,11 @@ struct breakpoint
        there is no condition.  */
     char *cond_string;
 
+    /* If True, the GDB side cannot do the condition check for
+       the condition of this breakpoint and this condition only can
+       be checked in agent side.  */
+    int target_only_cond_check;
+
     /* String form of extra parameters, or NULL if there are none.  */
     char *extra_string;
 
--- a/remote.c
+++ b/remote.c
@@ -43,6 +43,7 @@
 #include "cli/cli-setshow.h"
 #include "target-descriptions.h"
 #include "gdb_bfd.h"
+#include "target-attributes.h"
 
 #include <ctype.h>
 #include <sys/time.h>
@@ -1292,6 +1293,7 @@ enum {
   PACKET_qXfer_fdpic,
   PACKET_QDisableRandomization,
   PACKET_QAgent,
+  PACKET_qXfer_target_attributes_read,
   PACKET_MAX
 };
 
@@ -3510,6 +3512,22 @@ remote_start_remote (int from_tty, struc
 	remote_check_symbols (symfile_objfile);
     }
 
+  if (remote_protocol_packets[PACKET_qXfer_target_attributes_read].support
+	!= PACKET_DISABLE)
+    {
+      char *text;
+
+      text = target_read_stralloc (&current_target, TARGET_OBJECT_ATTRIBUTES,
+				   NULL);
+      if (text != NULL)
+	{
+	  struct cleanup *back_to = make_cleanup (xfree, text);
+
+          add_xml_target_attributes (text);
+	  do_cleanups (back_to);
+	}
+    }
+
   /* Possibly the target has been engaged in a trace run started
      previously; find out where things are at.  */
   if (remote_get_trace_status (current_trace_status ()) != -1)
@@ -3946,6 +3964,8 @@ static struct protocol_feature remote_pr
   { "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
   { "tracenz", PACKET_DISABLE,
     remote_string_tracing_feature, -1 },
+  { "qXfer:target-attributes:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_target_attributes_read },
 };
 
 static char *remote_support_xml;
@@ -8672,6 +8692,12 @@ remote_xfer_partial (struct target_ops *
       return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
 				&remote_protocol_packets[PACKET_qXfer_uib]);
 
+    case TARGET_OBJECT_ATTRIBUTES:
+      gdb_assert (annex == NULL);
+      return remote_read_qxfer
+	(ops, "target-attributes", annex, readbuf, offset, len,
+	 &remote_protocol_packets[PACKET_qXfer_target_attributes_read]);
+
     default:
       return -1;
     }
@@ -11637,6 +11663,10 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
 			 "QAgent", "agent", 0);
 
+  add_packet_config_cmd
+    (&remote_protocol_packets[PACKET_qXfer_target_attributes_read],
+     "qXfer:target-attributes:read", "target-attributes", 0);
+
   /* Keep the old ``set remote Z-packet ...'' working.  Each individual
      Z sub-packet has its own set and show commands, but users may
      have sets to this variable in their .gdbinit files (or in their
--- /dev/null
+++ b/target-attributes.c
@@ -0,0 +1,669 @@
+/* Target attributes for GDB, the GNU debugger.
+
+   Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "ui-out.h"
+#include "tracepoint.h"
+#include "gdbcmd.h"
+#include "target-attributes.h"
+
+static struct target_attribute *target_attributes_list;
+
+struct target_attribute *
+find_target_attribute_name (const char *name)
+{
+  struct target_attribute *ta;
+
+  for (ta = target_attributes_list; ta; ta = ta->next)
+    {
+      if (strcmp (ta->name, name) == 0)
+	return ta;
+    }
+
+  return NULL;
+}
+
+struct target_attribute *
+find_target_attribute_id (int id)
+{
+  struct target_attribute *ta;
+
+  for (ta = target_attributes_list; ta; ta = ta->next)
+    {
+      if (id == ta->id)
+	return ta;
+    }
+
+  return NULL;
+}
+
+static struct bp_location *check_agent_target_attribute_bl = NULL;
+char *check_agent_target_attribute_error = NULL;
+
+static void
+clear_check_agent_target_attribute (void *unused)
+{
+  check_agent_target_attribute_bl = NULL;
+}
+
+struct cleanup *
+set_check_agent_target_attribute (struct bp_location *bl)
+{
+  check_agent_target_attribute_bl = bl;
+  check_agent_target_attribute_error = NULL;
+
+  return make_cleanup (clear_check_agent_target_attribute, NULL);
+}
+
+void
+check_agent_target_attribute (struct target_attribute *ta, int write)
+{
+  static char error_str[256];
+  check_agent_target_attribute_error = error_str;
+
+  if (write)
+    {
+      if ((ta->agent_access & TARGET_ATTRIBUTE_ACCESS_WRITE) == 0)
+        {
+	  snprintf (error_str, 256, _("$%s cannot be written in agent code."),
+		    ta->name);
+	  error (_("$%s cannot be written in agent code."), ta->name);
+	}
+    }
+  else
+    {
+      if ((ta->agent_access & TARGET_ATTRIBUTE_ACCESS_READ) == 0)
+        {
+	  snprintf (error_str, 256, _("$%s cannot be read in agent code."),
+		    ta->name);
+	  error (_("$%s cannot be read in agent code."), ta->name);
+	}
+    }
+
+  if (check_agent_target_attribute_bl)
+    {
+      struct target_attribute_address *ta_addr;
+
+      if (ta->target_only_cond_check)
+        check_agent_target_attribute_bl->owner->target_only_cond_check = 1;
+
+      switch (check_agent_target_attribute_bl->loc_type)
+	{
+	case bp_loc_software_breakpoint:
+	  if ((ta->support
+	       & TARGET_ATTRIBUTE_SUPPORT_SOFTWARE_BREAKPOINT) == 0)
+	    {
+	      snprintf (error_str, 256,
+			_("$%s cannot be used in software breakpoint."),
+			ta->name);
+	      error (_("$%s cannot be used in software breakpoint."), ta->name);
+	    }
+	  break;
+	case bp_loc_hardware_breakpoint:
+	  if ((ta->support
+	       & TARGET_ATTRIBUTE_SUPPORT_HARDWARE_BREAKPOINT) == 0)
+	    {
+	      snprintf (error_str, 256,
+			_("$%s cannot be used in hardware breakpoint."),
+			ta->name);
+	      error (_("$%s cannot be used in hardware breakpoint."),
+		     ta->name);
+	    }
+	  break;
+	case bp_loc_hardware_watchpoint:
+	  if ((ta->support
+	       & TARGET_ATTRIBUTE_SUPPORT_HARDWARE_WATCHPOINT) == 0)
+	    {
+	      snprintf (error_str, 256,
+			_("$%s cannot be used in hardware watchpoint."),
+			ta->name);
+	      error (_("$%s cannot be used in hardware watchpoint."),
+		     ta->name);
+	    }
+	  break;
+	default:
+	  if (check_agent_target_attribute_bl->owner->type == bp_tracepoint
+	      || check_agent_target_attribute_bl->owner->type
+		   == bp_fast_tracepoint
+	      || check_agent_target_attribute_bl->owner->type
+		   == bp_static_tracepoint)
+	    {
+	      snprintf (error_str, 256,
+			_("$%s cannot be used in tracepoint."), ta->name);
+	      if ((ta->support & TARGET_ATTRIBUTE_SUPPORT_TRACEPOINT) == 0)
+	        error (_("$%s cannot be used in tracepoint."), ta->name);
+	    }
+	  else
+	    {
+	      snprintf (error_str, 256,
+			_("$%s cannot be used in breakpoint %d."),
+			ta->name,
+			check_agent_target_attribute_bl->owner->number);
+	      error (_("$%s cannot be used in breakpoint %d."), ta->name,
+		     check_agent_target_attribute_bl->owner->number);
+	    }
+	  break;
+	}
+
+      if (ta->addresses)
+	{
+          for (ta_addr = ta->addresses; ta_addr; ta_addr = ta_addr->prev)
+	    {
+	      if (check_agent_target_attribute_bl->address >= ta_addr->start
+		  && check_agent_target_attribute_bl->address <= ta_addr->end)
+		break;
+	    }
+	  if (!ta_addr)
+	    {
+	      snprintf (error_str, 256,
+			_("\
+$%s cannot be used in breakpoint %d because the address limit."), ta->name,
+			check_agent_target_attribute_bl->owner->number);
+	      error (_("\
+$%s cannot be used in breakpoint %d because the address limit."), ta->name,
+		   check_agent_target_attribute_bl->owner->number);
+	    }
+	}
+    }
+
+  check_agent_target_attribute_error = NULL;
+}
+
+void
+clear_target_attributes (void *unused)
+{
+  struct target_attribute *ta, *tmp;
+
+  for (ta = target_attributes_list; ta;)
+    {
+      struct target_attribute_address *ta_addr, *tmp_addr;
+
+      tmp = ta;
+      ta = ta->next;
+
+      for (ta_addr = tmp->addresses; ta_addr;)
+        {
+	  tmp_addr = ta_addr;
+	  ta_addr = ta_addr->prev;
+	  xfree (tmp_addr);
+	}
+
+      xfree (tmp);
+    }
+
+  target_attributes_list = NULL;
+}
+
+static void
+info_target_attributes (char *args, int from_tty)
+{
+  struct target_attribute *ta;
+  struct cleanup *back_to;
+  struct ui_out *uiout = current_uiout;
+  int count = 0;
+
+  if (target_attributes_list == NULL)
+    {
+      ui_out_message (uiout, 0, _("No target attributes.\n"));
+      return;
+    }
+
+  for (ta = target_attributes_list; ta; ta = ta->next)
+    count++;
+
+  back_to = make_cleanup_ui_out_table_begin_end (uiout, 6,
+                                                 count, "target-attributes");
+  ui_out_table_header (uiout, 15, ui_left, "name", "Name");
+  ui_out_table_header (uiout, 15, ui_left, "type", "Type");
+  ui_out_table_header (uiout, 15, ui_left, "target-only-cond-check",
+		       "Target-only-cond-check");
+  ui_out_table_header (uiout, 15, ui_left, "agent access", "Agent access");
+  ui_out_table_header (uiout, 15, ui_left, "gdb access", "GDB access");
+  ui_out_table_header (uiout, 15, ui_left, "breakpoint type",
+		       "Breakpoint type");
+
+  ui_out_table_body (uiout);
+  for (ta = target_attributes_list; ta; ta = ta->next)
+    {
+      struct target_attribute_address *ta_addr;
+      char buf[512];
+      struct cleanup *back_to2
+	= make_cleanup_ui_out_tuple_begin_end (uiout, "attributes");
+
+      snprintf (buf, 512, "$%s", ta->name);
+      ui_out_field_string (uiout, "name", buf);
+
+      switch (ta->type)
+        {
+	case TARGET_ATTRIBUTE_TYPE_INT8:
+	  ui_out_field_string (uiout, "type", "int8");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_UINT8:
+	  ui_out_field_string (uiout, "type", "uint8");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_INT16:
+	  ui_out_field_string (uiout, "type", "int16");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_UINT16:
+	  ui_out_field_string (uiout, "type", "uint16");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_INT32:
+	  ui_out_field_string (uiout, "type", "int32");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_UINT32:
+	  ui_out_field_string (uiout, "type", "uint32");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_INT64:
+	  ui_out_field_string (uiout, "type", "int64");
+	  break;
+	case TARGET_ATTRIBUTE_TYPE_UINT64:
+	  ui_out_field_string (uiout, "type", "uint64");
+	  break;
+	}
+
+      ui_out_field_string (uiout, "target-only-cond-check",
+			   ta->target_only_cond_check ? "yes" : "no");
+
+      snprintf (buf, 512, "%s%s",
+		(ta->agent_access
+		 & TARGET_ATTRIBUTE_ACCESS_READ) ? "read " : "",
+		(ta->agent_access
+		 & TARGET_ATTRIBUTE_ACCESS_WRITE) ? "write" : "");
+      ui_out_field_string (uiout, "agent access", buf);
+
+      snprintf (buf, 512, "%s%s",
+		(ta->gdb_access & TARGET_ATTRIBUTE_ACCESS_READ) ? "read " : "",
+		(ta->gdb_access
+		 & TARGET_ATTRIBUTE_ACCESS_WRITE) ? "write" : "");
+      ui_out_field_string (uiout, "gdb access", buf);
+
+      snprintf (buf, 512, "%s%s%s%s",
+		(ta->support & TARGET_ATTRIBUTE_SUPPORT_SOFTWARE_BREAKPOINT)
+		? "software-breakpoint " : "",
+		(ta->support & TARGET_ATTRIBUTE_SUPPORT_HARDWARE_BREAKPOINT)
+		? "hardware-breakpoint " : "",
+		(ta->support & TARGET_ATTRIBUTE_SUPPORT_HARDWARE_WATCHPOINT)
+		? "hardware-watchpoint " : "",
+		(ta->support & TARGET_ATTRIBUTE_SUPPORT_TRACEPOINT)
+		? "tracepoint " : "");
+      ui_out_field_string (uiout, "breakpoint type", buf);
+
+      ui_out_text (uiout, "\n");
+
+      for (ta_addr = ta->addresses; ta_addr; ta_addr = ta_addr->prev)
+        {
+	  ui_out_spaces (uiout, 2);
+	  ui_out_message (uiout, 0, "start:%s end:%s\n",
+			  paddress (target_gdbarch, ta_addr->start),
+			  paddress (target_gdbarch, ta_addr->end));
+	}
+      do_cleanups (back_to2);
+    }
+
+  do_cleanups (back_to);
+}
+
+#if !defined(HAVE_LIBEXPAT)
+
+void
+add_xml_target_attributes (const char *text)
+{
+  if (strlen (text) > 0)
+    warning (_("Can not parse XML target attributes; XML support "
+	       "was disabled at compile time"));
+}
+
+#else
+
+#include "xml-support.h"
+
+static void
+target_attribute_attr_handler (struct gdb_xml_parser *parser,
+			       const struct gdb_xml_element *element,
+			       void *user_data,
+			       VEC(gdb_xml_value_s) *attributes)
+{
+  char *name = NULL;
+  int i, len, id = -1, type = 0, target_only_cond_check = 0;
+  struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
+  struct target_attribute *ta, **tap = user_data;
+
+  len = VEC_length (gdb_xml_value_s, attributes);
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (attrs[i].name, "name") == 0)
+        name = attrs[i].value;
+      else if (strcmp (attrs[i].name, "id") == 0)
+        id = * (ULONGEST *) attrs[i].value;
+      else if (strcmp (attrs[i].name, "type") == 0)
+        type = * (ULONGEST *) attrs[i].value;
+      else if (strcmp (attrs[i].name, "target-only-cond-check") == 0)
+        target_only_cond_check = * (ULONGEST *) attrs[i].value;
+      else
+        gdb_xml_error (parser, _("Unknown attribute name '%s'."),
+		       attrs[i].name);
+    }
+
+  if (!name || id < 0)
+    gdb_xml_error (parser, _("\"name\" or \"id\" is missed."));
+
+  if (find_target_attribute_name (name))
+    gdb_xml_error (parser,_("\
+name \"%s\" is same with a target attribute."), name);
+  if (find_target_attribute_id (id))
+    gdb_xml_error (parser,_("id \"%d\" is same with a target attribute."), id);
+
+  ta = xzalloc (sizeof (struct target_attribute));
+  ta->name = xstrdup (name);
+  ta->id = id;
+  ta->type = type;
+  ta->target_only_cond_check = target_only_cond_check;
+
+  if (*tap)
+    (*tap)->next = ta;
+  else
+    target_attributes_list = ta;
+  *tap = ta;
+
+  user_data = &ta;
+}
+
+static void
+target_attribute_access_children_handler (struct gdb_xml_parser *parser,
+					  const struct gdb_xml_element *element,
+					  void *user_data,
+					  VEC(gdb_xml_value_s) *attributes)
+{
+  struct target_attribute *ta = *(struct target_attribute **)user_data;
+  int i, len, ta_access = 0;
+  struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
+
+  len = VEC_length (gdb_xml_value_s, attributes);
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (attrs[i].name, "read") == 0)
+        {
+	  if (* (ULONGEST *) attrs[i].value)
+            ta_access |= TARGET_ATTRIBUTE_ACCESS_READ;
+	}
+      else if (strcmp (attrs[i].name, "write") == 0)
+        {
+	  if (* (ULONGEST *) attrs[i].value)
+            ta_access |= TARGET_ATTRIBUTE_ACCESS_WRITE;
+	}
+      else
+        gdb_xml_error (parser, _("Unknown attribute name '%s'."),
+		       attrs[i].name);
+    }
+
+  if (strcmp (element->name, "agent") == 0)
+    ta->agent_access = ta_access;
+  else
+    ta->gdb_access = ta_access;
+}
+
+static void
+target_attribute_support_attr_handler (struct gdb_xml_parser *parser,
+				       const struct gdb_xml_element *element,
+				       void *user_data,
+				       VEC(gdb_xml_value_s) *attributes)
+{
+  struct target_attribute *ta = *(struct target_attribute **)user_data;
+  int i, len = 0;
+  struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
+
+  len = VEC_length (gdb_xml_value_s, attributes);
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (attrs[i].name, "software-breakpoint") == 0)
+        {
+	  if (* (ULONGEST *) attrs[i].value)
+            ta->support |= TARGET_ATTRIBUTE_SUPPORT_SOFTWARE_BREAKPOINT;
+	}
+      else if (strcmp (attrs[i].name, "hardware-breakpoint") == 0)
+        {
+	  if (* (ULONGEST *) attrs[i].value)
+            ta->support |= TARGET_ATTRIBUTE_SUPPORT_HARDWARE_BREAKPOINT;
+	}
+      else if (strcmp (attrs[i].name, "hardware-watchpoint") == 0)
+        {
+	  if (* (ULONGEST *) attrs[i].value)
+            ta->support |= TARGET_ATTRIBUTE_SUPPORT_HARDWARE_WATCHPOINT;
+	}
+      else if (strcmp (attrs[i].name, "tracepoint") == 0)
+        {
+	  if (* (ULONGEST *) attrs[i].value)
+            ta->support |= TARGET_ATTRIBUTE_SUPPORT_TRACEPOINT;
+	}
+      else
+        gdb_xml_error (parser, _("Unknown attribute name '%s'."),
+		       attrs[i].name);
+    }
+}
+
+static void
+target_attribute_address_handler (struct gdb_xml_parser *parser,
+				  const struct gdb_xml_element *element,
+				  void *user_data,
+				  VEC(gdb_xml_value_s) *attributes)
+{
+  int i, len;
+  struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
+  struct target_attribute *ta = *(struct target_attribute **)user_data;
+  CORE_ADDR start = 0, end = 0;
+  struct target_attribute_address *ta_addr;
+
+  len = VEC_length (gdb_xml_value_s, attributes);
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (attrs[i].name, "start") == 0)
+        start = * (ULONGEST *) attrs[i].value;
+      else if (strcmp (attrs[i].name, "end") == 0)
+        end = * (ULONGEST *) attrs[i].value;
+      else
+        gdb_xml_error (parser, _("Unknown attribute name '%s'."),
+		       attrs[i].name);
+    }
+
+  ta_addr = xmalloc (sizeof (struct target_attribute_address));
+  ta_addr->start = start;
+  ta_addr->end = end;
+
+  ta_addr->prev = ta->addresses;
+  ta->addresses = ta_addr;
+}
+
+const struct gdb_xml_enum target_attribute_type_enums[] = {
+  { "int8", TARGET_ATTRIBUTE_TYPE_INT8 },
+  { "uint8", TARGET_ATTRIBUTE_TYPE_UINT8 },
+  { "int16", TARGET_ATTRIBUTE_TYPE_INT16 },
+  { "uint16", TARGET_ATTRIBUTE_TYPE_UINT16 },
+  { "int32", TARGET_ATTRIBUTE_TYPE_INT32 },
+  { "uint32", TARGET_ATTRIBUTE_TYPE_UINT32 },
+  { "int64", TARGET_ATTRIBUTE_TYPE_INT64 },
+  { "uint64", TARGET_ATTRIBUTE_TYPE_UINT64 },
+  { NULL, 0 }
+};
+
+static const struct gdb_xml_attribute target_attribute_attr[] = {
+  { "name", GDB_XML_AF_NONE, NULL, NULL },
+  { "id", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { "type", GDB_XML_AF_NONE, gdb_xml_parse_attr_enum,
+    target_attribute_type_enums },
+  { "target-only-cond-check", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute
+			target_attribute_access_children_attr[] = {
+  { "read", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { "write", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element target_attribute_access_children[] = {
+  { "agent", target_attribute_access_children_attr, NULL,
+    GDB_XML_EF_OPTIONAL, target_attribute_access_children_handler, NULL },
+  { "gdb", target_attribute_access_children_attr, NULL,
+    GDB_XML_EF_OPTIONAL, target_attribute_access_children_handler, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute target_attribute_support_attr[] = {
+  { "software-breakpoint", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { "hardware-breakpoint", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { "hardware-watchpoint", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { "tracepoint", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute target_attribute_address_attr[] = {
+  { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element target_attribute_addresses_children[] = {
+  { "address", target_attribute_address_attr, NULL,
+    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+    target_attribute_address_handler, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element target_attribute_elements[] = {
+  { "access", NULL, target_attribute_access_children,
+    GDB_XML_EF_NONE, NULL, NULL },
+  { "support", target_attribute_support_attr, NULL,
+    GDB_XML_EF_OPTIONAL, target_attribute_support_attr_handler, NULL },
+  { "addresses", NULL, target_attribute_addresses_children,
+    GDB_XML_EF_OPTIONAL, NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element target_attributes_children[] = {
+  { "target-attribute", target_attribute_attr, target_attribute_elements,
+    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+    target_attribute_attr_handler, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element target_attributes_elements[] = {
+  { "target-attributes", NULL, target_attributes_children,
+    GDB_XML_EF_NONE, NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+void
+add_xml_target_attributes (const char *text)
+{
+  struct target_attribute *ta = NULL;
+  struct cleanup *back_to = make_cleanup (clear_target_attributes, NULL);
+
+  clear_target_attributes(NULL);
+  if (gdb_xml_parse_quick (_("target attributes"), NULL,
+			   target_attributes_elements, text, &ta) == 0)
+    {
+      discard_cleanups (back_to);
+      trace_variable_number_check ();
+    }
+  else
+    do_cleanups (back_to);
+}
+
+#endif
+
+struct type *
+target_attribute_type (struct gdbarch *gdbarch, struct target_attribute *ta)
+{
+  struct type *ret = builtin_type (gdbarch)->builtin_uint64;
+
+  switch (ta->type)
+    {
+    case TARGET_ATTRIBUTE_TYPE_INT8:
+      ret = builtin_type (gdbarch)->builtin_int8;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_UINT8:
+      ret = builtin_type (gdbarch)->builtin_uint8;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_INT16:
+      ret = builtin_type (gdbarch)->builtin_int16;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_UINT16:
+      ret = builtin_type (gdbarch)->builtin_uint16;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_INT32:
+      ret = builtin_type (gdbarch)->builtin_int32;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_UINT32:
+      ret = builtin_type (gdbarch)->builtin_uint32;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_INT64:
+      ret = builtin_type (gdbarch)->builtin_int64;
+      break;
+    case TARGET_ATTRIBUTE_TYPE_UINT64:
+      ret = builtin_type (gdbarch)->builtin_uint64;
+      break;
+    }
+
+  return ret;
+}
+
+static void
+load_target_attributes_command (char *exp, int from_tty)
+{
+  char *text = xml_fetch_content_from_file (exp, NULL);
+
+  if (text == NULL)
+    error (_("Could not open \"%s\""), exp);
+  add_xml_target_attributes (text);
+}
+
+static void
+clear_target_attributes_command (char *exp, int from_tty)
+{
+  clear_target_attributes (NULL);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_targets_attributes;
+
+void
+_initialize_targets_attributes (void)
+{
+  add_cmd ("load-target-attributes", class_maintenance,
+	   load_target_attributes_command,
+	   _("Load target attributes from a XML file."),
+	   &maintenancelist);
+
+  add_cmd ("clear-target-attributes", class_maintenance,
+	   clear_target_attributes_command,
+	   _("Remove all target attributes."),
+	   &maintenancelist);
+
+  add_info ("target-attributes", info_target_attributes, _("\
+Status of target attributes."));
+}
--- /dev/null
+++ b/target-attributes.h
@@ -0,0 +1,104 @@
+/* Target attributes for GDB, the GNU debugger.
+
+   Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef TARGET_ATTRIBUTES_H
+#define TARGET_ATTRIBUTES_H 1
+
+enum
+{
+  TARGET_ATTRIBUTE_TYPE_INT8,
+  TARGET_ATTRIBUTE_TYPE_UINT8,
+  TARGET_ATTRIBUTE_TYPE_INT16,
+  TARGET_ATTRIBUTE_TYPE_UINT16,
+  TARGET_ATTRIBUTE_TYPE_INT32,
+  TARGET_ATTRIBUTE_TYPE_UINT32,
+  TARGET_ATTRIBUTE_TYPE_INT64,
+  TARGET_ATTRIBUTE_TYPE_UINT64,
+};
+
+#define TARGET_ATTRIBUTE_ACCESS_READ	0x1
+#define TARGET_ATTRIBUTE_ACCESS_WRITE	0x2
+
+#define TARGET_ATTRIBUTE_SUPPORT_SOFTWARE_BREAKPOINT	0x1
+#define TARGET_ATTRIBUTE_SUPPORT_HARDWARE_BREAKPOINT	0x2
+#define TARGET_ATTRIBUTE_SUPPORT_HARDWARE_WATCHPOINT	0x4
+#define TARGET_ATTRIBUTE_SUPPORT_TRACEPOINT		0x8
+
+struct target_attribute_address
+  {
+    struct target_attribute_address *prev;
+    CORE_ADDR	start;
+    CORE_ADDR	end;
+  };
+
+/* This is the core struct of a target attribute.
+   When GDB get a target attribute from XML,
+   it will alloc a struct for it.  */
+
+struct target_attribute
+  {
+    struct target_attribute *next;
+    char *name;
+    int id;
+    int type;
+    int target_only_cond_check;
+    unsigned int agent_access;
+    unsigned int gdb_access;
+    unsigned int support;
+    struct target_attribute_address *addresses;
+  };
+
+/* This is the error report string for function
+   check_agent_target_attribute.
+   Because some function call check_agent_target_attribute
+   with TRY_CATCH.  Use this string report error.  */
+
+extern char *check_agent_target_attribute_error;
+
+extern struct target_attribute *find_target_attribute_name (const char *name);
+extern struct target_attribute *find_target_attribute_id (int id);
+
+/* Set BL for function check_agent_target_attribute
+   before translate a string to agent expression bytecode.  */
+
+extern struct cleanup *set_check_agent_target_attribute
+			(struct bp_location *bl);
+
+/* The function that translate a string to agent expression bytecode call
+   check_agent_target_attribute to check if TA is OK to use with
+   BL that set by set_check_agent_target_attribute.  */
+
+extern void check_agent_target_attribute (struct target_attribute *ta,
+					  int write);
+
+/* Remove all the target attributes inside the GDB.  */
+
+extern void clear_target_attributes (void *unused);
+
+/* Parse target attributes out from XML formart string TEXT
+   and add them to GDB.  */
+
+extern void add_xml_target_attributes (const char *text);
+
+/* Return the type of TA.  */
+
+extern struct type *target_attribute_type (struct gdbarch *gdbarch,
+					   struct target_attribute *ta);
+
+#endif /* TARGET_ATTRIBUTES_H */
--- a/target.h
+++ b/target.h
@@ -286,7 +286,9 @@ enum target_object
   /* Darwin dynamic linker info data.  */
   TARGET_OBJECT_DARWIN_DYLD_INFO,
   /* OpenVMS Unwind Information Block.  */
-  TARGET_OBJECT_OPENVMS_UIB
+  TARGET_OBJECT_OPENVMS_UIB,
+  /* Target attributes.  */
+  TARGET_OBJECT_ATTRIBUTES,
   /* Possible future objects: TARGET_OBJECT_FILE, ...  */
 };
 
--- a/tracepoint.c
+++ b/tracepoint.c
@@ -53,6 +53,7 @@
 #include "exceptions.h"
 #include "cli/cli-utils.h"
 #include "probe.h"
+#include "target-attributes.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -348,6 +349,21 @@ find_trace_state_variable (const char *n
   return NULL;
 }
 
+/* Look for a trace state variable of the given number.  */
+
+static struct trace_state_variable *
+find_trace_state_variable_number (int number)
+{
+  struct trace_state_variable *tsv;
+  int ix;
+
+  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+    if (number == tsv->number)
+      return tsv;
+
+  return NULL;
+}
+
 static void
 delete_trace_state_variable (const char *name)
 {
@@ -365,6 +381,41 @@ delete_trace_state_variable (const char
   warning (_("No trace variable named \"$%s\", not deleting"), name);
 }
 
+static int
+trace_variable_number_check_1 (struct trace_state_variable *tsv)
+{
+  if (find_target_attribute_id (tsv->number))
+    {
+      int new_number = tsv->number + 1;
+      tsv->number = 0;
+      while (find_target_attribute_id (new_number)
+	     || find_trace_state_variable_number (new_number))
+	new_number++;
+      tsv->number = new_number;
+
+      return 1;
+    }
+
+  return 0;
+}
+
+void
+trace_variable_number_check (void)
+{
+  struct trace_state_variable *tsv;
+  int ix;
+
+  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+    {
+      if (trace_variable_number_check_1 (tsv))
+        {
+	  warning (_("\
+number of trace variable $%s is same with a tsv compatible \n\
+target attribute.  So it is changed to %d."), tsv->name, tsv->number);
+	}
+    }
+}
+
 /* The 'tvariable' command collects a name and optional expression to
    evaluate into an initial value.  */
 
@@ -423,6 +474,8 @@ trace_variable_command (char *args, int
   tsv = create_trace_state_variable (internalvar_name (intvar));
   tsv->initial_value = initval;
 
+  trace_variable_number_check_1 (tsv);
+
   printf_filtered (_("Trace state variable $%s "
 		     "created, with initial value %s.\n"),
 		   tsv->name, plongest (tsv->initial_value));
@@ -3602,6 +3655,8 @@ merge_uploaded_trace_state_variables (st
     if (tsv->number == 0)
       tsv->number = highest++;
 
+  trace_variable_number_check();
+
   free_uploaded_tsvs (uploaded_tsvs);
 }
 
--- a/tracepoint.h
+++ b/tracepoint.h
@@ -250,6 +250,8 @@ extern void while_stepping_pseudocommand
 extern struct trace_state_variable *find_trace_state_variable (const char *name);
 extern struct trace_state_variable *create_trace_state_variable (const char *name);
 
+extern void trace_variable_number_check(void);
+
 extern int encode_source_string (int num, ULONGEST addr,
 				 char *srctype, char *src,
 				 char *buf, int buf_size);


More information about the Gdb-patches mailing list