From d1feda864e0b17c5757197ba1b421e25dac6afd1 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Sat, 3 Mar 2012 03:32:46 +0000 Subject: [PATCH] gdb: * target.h (struct target_ops) : New field. (struct target_ops) : New field. (target_use_agent, target_can_use_agent): New macro. * target.c (update_current_target): Update. * remote.c: New enum `PACKET_QAgent'. (remote_protocol_features): Add a new element. (remote_use_agent, remote_can_use_agent): New. (init_remote_ops): Initialize field `can_use_agent' with remote_can_use_agent. Intiailize field `use_agent' with remote_use_agent. * common/agent.c (use_agent): New global. * common/agent.h: Declare it. * tracepoint.c (info_static_tracepoint_markers_command): Add comment. * Makefile.in (SFILES): Add common/agent.c and agent.c. (COMMON_OBS): Add common/agent.o and agent.o (common-agent.o): New rule. * agent.c: New. gdb/doc: * gdb.texinfo (In-Process Agent): New node. Document new commands. (General Query Packets): Add packet `QAgent'. gdb/gdbserver: * linux-low.c (linux_supports_agent): New. (linux_target_ops): Initialize field `supports_agent' with linux_supports_agent. * target.h (struct target_ops) : New. (target_supports_agent): New macro. * server.c (handle_general_set): Handle packet 'QAgent'. (handle_query): Send `QAgent+'. * Makefile.in (server.o): Depends on agent.h. --- gdb/ChangeLog | 21 +++++++++++ gdb/Makefile.in | 10 ++++-- gdb/agent.c | 73 +++++++++++++++++++++++++++++++++++++++ gdb/common/agent.c | 3 ++ gdb/common/agent.h | 1 + gdb/doc/ChangeLog | 6 ++++ gdb/doc/gdb.texinfo | 71 +++++++++++++++++++++++++++++++++++++ gdb/gdbserver/ChangeLog | 11 ++++++ gdb/gdbserver/Makefile.in | 2 +- gdb/gdbserver/linux-low.c | 7 ++++ gdb/gdbserver/server.c | 28 +++++++++++++++ gdb/gdbserver/target.h | 7 ++++ gdb/remote.c | 36 +++++++++++++++++++ gdb/target.c | 8 +++++ gdb/target.h | 13 +++++++ gdb/tracepoint.c | 6 ++++ 16 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 gdb/agent.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 23ba55838b..3e6e5010cd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2012-03-03 Yao Qi + + * target.h (struct target_ops) : New field. + (struct target_ops) : New field. + (target_use_agent, target_can_use_agent): New macro. + * target.c (update_current_target): Update. + * remote.c: New enum `PACKET_QAgent'. + (remote_protocol_features): Add a new element. + (remote_use_agent, remote_can_use_agent): New. + (init_remote_ops): Initialize field `can_use_agent' with + remote_can_use_agent. Intiailize field `use_agent' with + remote_use_agent. + * common/agent.c (use_agent): New global. + * common/agent.h: Declare it. + * tracepoint.c (info_static_tracepoint_markers_command): Add + comment. + * Makefile.in (SFILES): Add common/agent.c and agent.c. + (COMMON_OBS): Add common/agent.o and agent.o + (common-agent.o): New rule. + * agent.c: New. + 2012-03-03 Yao Qi * common/agent.c: New. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 57ef4369cb..dc473da838 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -684,6 +684,7 @@ TARGET_FLAGS_TO_PASS = \ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ addrmap.c \ auxv.c ax-general.c ax-gdb.c \ + agent.c \ bcache.c \ bfd-target.c \ block.c blockframe.c breakpoint.c buildsym.c \ @@ -740,7 +741,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \ regset.c sol-thread.c windows-termcap.c \ common/common-utils.c common/xml-utils.c \ - common/ptid.c common/buffer.c gdb-dlfcn.c + common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -854,6 +855,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ annotate.o \ addrmap.o \ auxv.o \ + agent.o \ bfd-target.o \ blockframe.o breakpoint.o findvar.o regcache.o \ charset.o continuations.o corelow.o disasm.o dummy-frame.o dfp.o \ @@ -908,7 +910,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ jit.o progspace.o skip.o \ - common-utils.o buffer.o ptid.o gdb-dlfcn.o + common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o TSOBS = inflow.o @@ -1927,6 +1929,10 @@ linux-procfs.o: $(srcdir)/common/linux-procfs.c $(COMPILE) $(srcdir)/common/linux-procfs.c $(POSTCOMPILE) +common-agent.o: $(srcdir)/common/agent.c + $(COMPILE) $(srcdir)/common/agent.c + $(POSTCOMPILE) + # # gdb/tui/ dependencies # diff --git a/gdb/agent.c b/gdb/agent.c new file mode 100644 index 0000000000..b751cfe4c2 --- /dev/null +++ b/gdb/agent.c @@ -0,0 +1,73 @@ +/* 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 . */ + +#include "defs.h" +#include "command.h" +#include "gdbcmd.h" +#include "target.h" +#include "agent.h" + +/* Enum strings for "set|show agent". */ + +static const char can_use_agent_on[] = "on"; +static const char can_use_agent_off[] = "off"; +static const char *can_use_agent_enum[] = +{ + can_use_agent_on, + can_use_agent_off, + NULL, +}; + +static const char *can_use_agent = can_use_agent_off; + +static void +show_can_use_agent (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("Debugger's willingness to use agent in inferior " + "as a helper is %s.\n"), value); +} + +static void +set_can_use_agent (char *args, int from_tty, struct cmd_list_element *c) +{ + if (target_use_agent (can_use_agent == can_use_agent_on) == 0) + /* Something wrong during setting, set flag to default value. */ + can_use_agent = can_use_agent_off; +} + +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_agent; + +void +_initialize_agent (void) +{ + add_setshow_enum_cmd ("agent", class_run, + can_use_agent_enum, + &can_use_agent, _("\ +Set debugger's willingness to use agent as a helper."), _("\ +Show debugger's willingness to use agent as a helper."), _("\ +If on, GDB will delegate some of the debugging operations to the\n\ +agent, if the target supports it. This will speed up those\n\ +operations that are supported by the agent.\n\ +If off, GDB will not use agent, even if such is supported by the\n\ +target."), + set_can_use_agent, + show_can_use_agent, + &setlist, &showlist); +} diff --git a/gdb/common/agent.c b/gdb/common/agent.c index 7553835b67..2bd3206d3e 100644 --- a/gdb/common/agent.c +++ b/gdb/common/agent.c @@ -41,6 +41,9 @@ int debug_agent = 0; fprintf_unfiltered (gdb_stdlog, fmt, ##args); #endif +/* Global flag to determine using agent or not. */ +int use_agent = 0; + /* Addresses of in-process agent's symbols both GDB and GDBserver cares about. */ diff --git a/gdb/common/agent.h b/gdb/common/agent.h index 31c46d9b86..296521579c 100644 --- a/gdb/common/agent.h +++ b/gdb/common/agent.h @@ -35,3 +35,4 @@ int agent_look_up_symbols (void); extern int debug_agent; +extern int use_agent; diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 89ded138f4..f3e483fcab 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2012-03-03 Yao Qi + + * gdb.texinfo (In-Process Agent): New node. + Document new commands. + (General Query Packets): Add packet `QAgent'. + 2012-03-01 Maciej W. Rozycki * gdb.texinfo (MIPS Features): Add org.gnu.gdb.mips.dsp. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index e187b035cb..62c92e9116 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -154,6 +154,7 @@ software in general. We will miss him. * GDB/MI:: @value{GDBN}'s Machine Interface. * Annotations:: @value{GDBN}'s annotation interface. * JIT Interface:: Using the JIT debugging interface. +* In-Process Agent:: In-Process Agent * GDB Bugs:: Reporting bugs in @value{GDBN} @@ -32286,6 +32287,63 @@ frame and to write out the values of the registers in the previous frame. Both have a callback (@code{target_read}) to read bytes off the target's address space. +@node In-Process Agent +@chapter In-Process Agent +@cindex debugging agent +The traditional debugging model is conceptually low-speed, but works fine, +because most bugs can be reproduced in debugging-mode execution. However, +as multi-core or many-core processors are becoming mainstream, and +multi-threaded programs become more and more popular, there should be more +and more bugs that only manifest themselves at normal-mode execution, for +example, thread races, because debugger's interference with the program's +timing may conceal the bugs. On the other hand, in some applications, +it is not feasible for the debugger to interrupt the program's execution +long enough for the developer to learn anything helpful about its behavior. +If the program's correctness depends on its real-time behavior, delays +introduced by a debugger might cause the program to fail, even when the +code itself is correct. It is useful to be able to observe the program's +behavior without interrupting it. + +Therefore, traditional debugging model is too intrusive to reproduce +some bugs. In order to reduce the interference with the program, we can +reduce the number of operations performed by debugger. The +@dfn{In-Process Agent}, a shared library, is running within the same +process with inferior, and is able to perform some debugging operations +itself. As a result, debugger is only involved when necessary, and +performance of debugging can be improved accordingly. Note that +interference with program can be reduced but can't be removed completely, +because the in-process agent will still stop or slow down the program. + +The in-process agent can interpret and execute Agent Expressions +(@pxref{Agent Expressions}) during performing debugging operations. The +agent expressions can be used for different purposes, such as collecting +data in tracepoints, and condition evaluation in breakpoints. + +@anchor{Control Agent} +You can control whether the in-process agent is used as an aid for +debugging with the following commands: + +@table @code +@kindex set agent on +@item set agent on +Causes the in-process agent to perform some operations on behalf of the +debugger. Just which operations requested by the user will be done +by the in-process agent depends on the its capabilities. For example, +if you request to evaluate breakpoint conditions in the in-process agent, +and the in-process agent has such capability as well, then breakpoint +conditions will be evaluated in the in-process agent. + +@kindex set agent off +@item set agent off +Disables execution of debugging operations by the in-process agent. All +of the operations will be performed by @value{GDBN}. + +@kindex show agent +@item show agent +Display the current setting of execution of debugging operations by +the in-process agent. +@end table + @node GDB Bugs @chapter Reporting Bugs in @value{GDBN} @cindex bugs in @value{GDBN} @@ -34623,6 +34681,11 @@ Here are the currently defined query and set packets: @table @samp +@item QAgent:1 +@item QAgent:0 +Turn on or off the agent as a helper to perform some debugging operations +delegated from @value{GDBN} (@pxref{Control Agent}). + @item QAllow:@var{op}:@var{val}@dots{} @cindex @samp{QAllow} packet Specify which operations @value{GDBN} expects to request of the @@ -35207,6 +35270,11 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab No +@item @samp{QAgent} +@tab No +@tab @samp{-} +@tab No + @item @samp{QAllow} @tab No @tab @samp{-} @@ -35345,6 +35413,9 @@ The remote stub accepts and implements the reverse step packet The remote stub understands the @samp{QTDPsrc} packet that supplies the source form of tracepoint definitions. +@item QAgent +The remote stub understands the @samp{QAgent} packet. + @item QAllow The remote stub understands the @samp{QAllow} packet. diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 6cb87899ea..b115b239bb 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,14 @@ +2012-03-03 Yao Qi + + * linux-low.c (linux_supports_agent): New. + (linux_target_ops): Initialize field `supports_agent' with + linux_supports_agent. + * target.h (struct target_ops) : New. + (target_supports_agent): New macro. + * server.c (handle_general_set): Handle packet 'QAgent'. + (handle_query): Send `QAgent+'. + * Makefile.in (server.o): Depends on agent.h. + 2012-03-03 Yao Qi * Makefile.in (OBS): Add agent.o. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 439fd2032e..0dc5e40d9f 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -400,7 +400,7 @@ mem-break.o: mem-break.c $(server_h) $(ax_h) proc-service.o: proc-service.c $(server_h) $(gdb_proc_service_h) regcache.o: regcache.c $(server_h) $(regdef_h) remote-utils.o: remote-utils.c terminal.h $(server_h) -server.o: server.c $(server_h) +server.o: server.c $(server_h) $(agent_h) target.o: target.c $(server_h) thread-db.o: thread-db.c $(server_h) $(linux_low_h) $(gdb_proc_service_h) \ $(gdb_thread_db_h) diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 7638ca334d..b4f3d5ad46 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -4854,6 +4854,12 @@ linux_supports_disable_randomization (void) #endif } +static int +linux_supports_agent (void) +{ + return 1; +} + /* Enumerate spufs IDs for process PID. */ static int spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len) @@ -5576,6 +5582,7 @@ static struct target_ops linux_target_ops = { linux_supports_disable_randomization, linux_get_min_fast_tracepoint_insn_len, linux_qxfer_libraries_svr4, + linux_supports_agent, }; static void diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index e3d1f7cc37..0de3f52f03 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include "server.h" +#include "agent.h" #if HAVE_UNISTD_H #include @@ -529,6 +530,30 @@ handle_general_set (char *own_buf) && handle_tracepoint_general_set (own_buf)) return; + if (strncmp ("QAgent:", own_buf, strlen ("QAgent:")) == 0) + { + char *mode = own_buf + strlen ("QAgent:"); + int req = 0; + + if (strcmp (mode, "0") == 0) + req = 0; + else if (strcmp (mode, "1") == 0) + req = 1; + else + { + /* We don't know what this value is, so complain to GDB. */ + sprintf (own_buf, "E.Unknown QAgent value"); + return; + } + + /* Update the flag. */ + use_agent = req; + if (remote_debug) + fprintf (stderr, "[%s agent]\n", req ? "Enable" : "Disable"); + write_ok (own_buf); + return; + } + /* Otherwise we didn't know what packet it was. Say we didn't understand it. */ own_buf[0] = 0; @@ -1624,6 +1649,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) /* Support target-side breakpoint conditions. */ strcat (own_buf, ";ConditionalBreakpoints+"); + if (target_supports_agent ()) + strcat (own_buf, ";QAgent+"); + return; } diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 03dff0f628..256cfd9049 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -394,6 +394,9 @@ struct target_ops int (*qxfer_libraries_svr4) (const char *annex, unsigned char *readbuf, unsigned const char *writebuf, CORE_ADDR offset, int len); + + /* Return true if target supports debugging agent. */ + int (*supports_agent) (void); }; extern struct target_ops *the_target; @@ -514,6 +517,10 @@ void set_target_ops (struct target_ops *); (the_target->supports_disable_randomization ? \ (*the_target->supports_disable_randomization) () : 0) +#define target_supports_agent() \ + (the_target->supports_agent ? \ + (*the_target->supports_agent) () : 0) + /* Start non-stop mode, returns 0 on success, -1 on failure. */ int start_non_stop (int nonstop); diff --git a/gdb/remote.c b/gdb/remote.c index 09bf18ea4b..8eb975fe57 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -65,6 +65,7 @@ #include "tracepoint.h" #include "ax.h" #include "ax-gdb.h" +#include "agent.h" /* Temp hacks for tracepoint encoding migration. */ static char *target_buf; @@ -1276,6 +1277,7 @@ enum { PACKET_QAllow, PACKET_qXfer_fdpic, PACKET_QDisableRandomization, + PACKET_QAgent, PACKET_MAX }; @@ -3848,6 +3850,7 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_qXfer_fdpic }, { "QDisableRandomization", PACKET_DISABLE, remote_supported_packet, PACKET_QDisableRandomization }, + { "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent}, { "tracenz", PACKET_DISABLE, remote_string_tracing_feature, -1 }, }; @@ -10757,6 +10760,34 @@ remote_set_trace_notes (char *user, char *notes, char *stop_notes) return 1; } +static int +remote_use_agent (int use) +{ + if (remote_protocol_packets[PACKET_QAgent].support != PACKET_DISABLE) + { + struct remote_state *rs = get_remote_state (); + + /* If the stub supports QAgent. */ + sprintf (rs->buf, "QAgent:%d", use); + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + + if (strcmp (rs->buf, "OK") == 0) + { + use_agent = use; + return 1; + } + } + + return 0; +} + +static int +remote_can_use_agent (void) +{ + return (remote_protocol_packets[PACKET_QAgent].support != PACKET_DISABLE); +} + static void init_remote_ops (void) { @@ -10869,6 +10900,8 @@ Specify the serial device it is connected to\n\ remote_ops.to_static_tracepoint_markers_by_strid = remote_static_tracepoint_markers_by_strid; remote_ops.to_traceframe_info = remote_traceframe_info; + remote_ops.to_use_agent = remote_use_agent; + remote_ops.to_can_use_agent = remote_can_use_agent; } /* Set up the extended remote vector by making a copy of the standard @@ -11382,6 +11415,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_QDisableRandomization], "QDisableRandomization", "disable-randomization", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent], + "QAgent", "agent", 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 diff --git a/gdb/target.c b/gdb/target.c index d29d37a1f0..87ecf79fe5 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -698,6 +698,8 @@ update_current_target (void) INHERIT (to_static_tracepoint_marker_at, t); INHERIT (to_static_tracepoint_markers_by_strid, t); INHERIT (to_traceframe_info, t); + INHERIT (to_use_agent, t); + INHERIT (to_can_use_agent, t); INHERIT (to_magic, t); INHERIT (to_supports_evaluation_of_breakpoint_conditions, t); /* Do not inherit to_memory_map. */ @@ -929,6 +931,12 @@ update_current_target (void) de_fault (to_supports_evaluation_of_breakpoint_conditions, (int (*) (void)) return_zero); + de_fault (to_use_agent, + (int (*) (int)) + tcomplain); + de_fault (to_can_use_agent, + (int (*) (void)) + return_zero); de_fault (to_execution_direction, default_execution_direction); #undef de_fault diff --git a/gdb/target.h b/gdb/target.h index e5679b1188..850cb38810 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -836,6 +836,13 @@ struct target_ops re-fetching when necessary. */ struct traceframe_info *(*to_traceframe_info) (void); + /* Ask the target to use or not to use agent according to USE. Return 1 + successful, 0 otherwise. */ + int (*to_use_agent) (int use); + + /* Is the target able to use agent in current state? */ + int (*to_can_use_agent) (void); + int to_magic; /* Need sub-structure for target machine related rather than comm related? */ @@ -1675,6 +1682,12 @@ extern char *target_fileio_read_stralloc (const char *filename); #define target_traceframe_info() \ (*current_target.to_traceframe_info) () +#define target_use_agent(use) \ + (*current_target.to_use_agent) (use) + +#define target_can_use_agent() \ + (*current_target.to_can_use_agent) () + /* Command logging facility. */ #define target_log_command(p) \ diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 0442a6005d..a519ed39a7 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -4883,6 +4883,12 @@ info_static_tracepoint_markers_command (char *arg, int from_tty) struct ui_out *uiout = current_uiout; int i; + /* We don't have to check target_can_use_agent and agent's capability on + static tracepoint here, in order to be compatible with older GDBserver. + We don't check USE_AGENT is true or not, because static tracepoints + don't work without in-process agent, so we don't bother users to type + `set agent on' when to use static tracepoint. */ + old_chain = make_cleanup_ui_out_table_begin_end (uiout, 5, -1, "StaticTracepointMarkersTable"); -- 2.34.1