[PATCH] target attributes [1/5] core and load from target function
Hui Zhu
teawater@gmail.com
Mon Feb 18 10:02:00 GMT 2013
On Fri, Nov 30, 2012 at 2:03 PM, Abid, Hafiz <Hafiz_Abid@mentor.com> wrote:
> Hi,
>
>>+ ta = xzalloc (sizeof (struct target_attribute));
>>+ ta->name = xstrdup (name);
> This name is not freed and will leak.
Added xfree in clear_target_attributes.
>
>>+ if (*tap)
>>+ (*tap)->next = ta;
>>+ else
>>+ target_attributes_list = ta;
>>+ *tap = ta;
>>+
>>+ user_data = &ta;
>
> So you are assigning ta to (*tap) and (*tap)->next. Then user_data is also being assigned. It did not look right to me. I wanted to bring it in your attention in case it is a typo.
user_data will always point to the last one of target_attributes_list.
Could you tell me which part is wrong?
>
>>+ unsigned int agent_access;
>>+ unsigned int gdb_access;
> I can understand the access mode for GDB. But what agent_access means and how it will effect a user?
There is the introduce of agent
http://sourceware.org/gdb/current/onlinedocs/gdb/Agent-Expressions.html
Post a new version according to your review.
Thanks,
Hui
2013-02-18 Hui Zhu <hui_zhu@mentor.com>
* Makefile.in (SFILES): Add target-attributes.c.
(HFILES_NO_SRCDIR): Add target-attributes.h.
(COMMON_OBS): Add target-attributes.o.
* breakpoint.h (breakpoint): Add target_only_cond_check.
* remote.c (target-attributes.h): New include.
(PACKET_qXfer_target_attributes_read): New enum.
(remote_start_remote): Add handler for target attributes.
(remote_protocol_features): Add "qXfer:target-attributes:read".
(remote_xfer_partial): Add handler for TARGET_OBJECT_ATTRIBUTES.
(_initialize_remote): Add command
"set remote target-attributes-packet".
(target-attributes.c, target-attributes.h): New files.
* tracepoint.c (target-attributes.h): New include.
(find_trace_state_variable_number,
trace_variable_number_check_1,
trace_variable_number_check): New functions.
(trace_variable_command): Call trace_variable_number_check_1.
(merge_uploaded_trace_state_variables): Call
trace_variable_number_check.
tracepoint.h (trace_variable_number_check): New extern.
>
>> -----Original Message-----
>> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
>> owner@sourceware.org] On Behalf Of Hui Zhu
>> Sent: Wednesday, November 21, 2012 8:55 AM
>> To: Qi, Yao
>> Cc: Zhu, Hui; gdb-patches ml
>> Subject: Re: [PATCH] target attributes [1/5] core and load from target
>> function
>>
>> On Sun, Sep 2, 2012 at 6:37 PM, Hui Zhu <teawater@gmail.com> wrote:
>> > 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
>>
>> Got some error when built with trunk. Post a new version for this
>> error.
>>
>> Thanks,
>> Hui
-------------- next part --------------
--- a/Makefile.in
+++ b/Makefile.in
@@ -742,7 +742,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 \
@@ -835,7 +835,7 @@ gnulib/import/stddef.in.h gnulib/import/
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
common/format.h common/host-defs.h utils.h common/queue.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
-gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h
+gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h target-attributes.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -924,7 +924,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
@@ -726,6 +726,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
@@ -44,6 +44,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>
@@ -1284,6 +1285,7 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_qXfer_target_attributes_read,
PACKET_MAX
};
@@ -3559,6 +3561,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 (¤t_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)
@@ -3995,6 +4013,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;
@@ -8796,6 +8816,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;
}
@@ -11755,6 +11781,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,670 @@
+/* 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->name)
+ 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"
@@ -342,6 +343,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)
{
@@ -386,6 +402,41 @@ validate_trace_state_variable_name (cons
error (_("$%s is not a valid trace state variable name"), 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. */
@@ -443,6 +494,8 @@ trace_variable_command (char *args, int
observer_notify_tsv_created (tsv);
+ trace_variable_number_check_1 (tsv);
+
printf_filtered (_("Trace state variable $%s "
"created, with initial value %s.\n"),
tsv->name, plongest (tsv->initial_value));
@@ -3674,6 +3727,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
@@ -248,6 +248,8 @@ extern void validate_trace_state_variabl
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