* [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
` (5 preceding siblings ...)
2014-10-10 17:18 ` [PATCH V2 8/9] Documentation for DTrace USDT probes Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-10 18:15 ` Eli Zaretskii
` (2 more replies)
2014-10-10 17:18 ` [PATCH V2 9/9] Announce the DTrace USDT probes support in NEWS Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 7/9] Simple testsuite for DTrace USDT probes Jose E. Marchesi
8 siblings, 3 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch adds the above-mentioned commands to the generic probe
abstraction implemented in probe.[ch]. The effects associated to
enabling or disabling a probe depend on the type of probe being
handled, and is triggered by invoking two back-end hooks in
`probe_ops'.
In case some particular probe type does not support the notion of
enabling and/or disabling, the corresponding fields on `probe_ops' can
be initialized to NULL. This is the case of SystemTap probes.
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* stap-probe.c (stap_probe_ops): Add NULLs in the static
stap_probe_ops for `enable_probe' and `disable_probe'.
* probe.c (enable_probes_command): New function.
(disable_probes_command): Likewise.
(_initialize_probe): Define the cli commands `enable probe' and
`disable probe'.
(parse_probe_linespec): New function.
(info_probes_for_ops): Use parse_probe_linespec.
* probe.h (probe_ops): New hooks `enable_probe' and
`disable_probe'.
gdb/doc/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* gdb.texinfo (Static Probe Points): Cover the `enable probe' and
`disable probe' commands.
---
gdb/ChangeLog | 13 +++++
gdb/doc/ChangeLog | 5 ++
gdb/doc/gdb.texinfo | 30 ++++++++++
gdb/probe.c | 153 +++++++++++++++++++++++++++++++++++++++++++++------
gdb/probe.h | 12 ++++
gdb/stap-probe.c | 2 +
6 files changed, 199 insertions(+), 16 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 429c650..a9c70b0 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4976,6 +4976,36 @@ given, all object files are considered.
List the available static probes, from all types.
@end table
+@cindex enabling and disabling probes
+Some probe points can be enabled and/or disabled. The effects
+associated to enabling or disabling a probe depend on the type of
+probe being handled. @code{SystemTap} probes do not support these
+notions.
+
+You can enable (or disable) one or more probes using the following
+commands, with optional arguments:
+
+@table @code
+@kindex enable probes
+@item enable probes @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
+If given, @var{provider} is a regular expression used to match against
+provider names when selecting which probes to enable. If omitted,
+probes by all probes from all providers are enabled.
+
+If given, @var{name} is a regular expression to match against probe
+names when selecting which probes to enable. If omitted, probe names
+are not considered when deciding whether to enable them.
+
+If given, @var{objfile} is a regular expression used to select which
+object files (executable or shared libraries) to examine. If not
+given, all object files are considered.
+
+@kindex disable probes
+@item disable probes @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
+See the @code{enable probes} command above for a description of the
+optional arguments accepted by this command.
+@end table
+
@vindex $_probe_arg@r{, convenience variable}
A probe may specify up to twelve arguments. These are available at the
point at which the probe is defined---that is, when the current PC is
diff --git a/gdb/probe.c b/gdb/probe.c
index 69ca0aa..c548b27 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -527,6 +527,24 @@ exists_probe_with_pops (VEC (bound_probe_s) *probes,
return 0;
}
+/* Helper function that parses a probe linespec of the form [PROVIDER
+ [PROBE [OBJNAME]]] from the provided string STR. */
+
+static void
+parse_probe_linespec (const char *str, char **provider,
+ char **probe_name, char **objname)
+{
+ *probe_name = *objname = NULL;
+
+ *provider = extract_arg_const (&str);
+ if (*provider)
+ {
+ *probe_name = extract_arg_const (&str);
+ if (*probe_name)
+ *objname = extract_arg_const (&str);
+ }
+}
+
/* See comment in probe.h. */
void
@@ -545,22 +563,10 @@ info_probes_for_ops (const char *arg, int from_tty,
struct bound_probe *probe;
struct gdbarch *gdbarch = get_current_arch ();
- /* Do we have a `provider:probe:objfile' style of linespec? */
- provider = extract_arg_const (&arg);
- if (provider)
- {
- make_cleanup (xfree, provider);
-
- probe_name = extract_arg_const (&arg);
- if (probe_name)
- {
- make_cleanup (xfree, probe_name);
-
- objname = extract_arg_const (&arg);
- if (objname)
- make_cleanup (xfree, objname);
- }
- }
+ parse_probe_linespec (arg, &provider, &probe_name, &objname);
+ make_cleanup (xfree, provider);
+ make_cleanup (xfree, probe_name);
+ make_cleanup (xfree, objname);
probes = collect_probes (objname, provider, probe_name, pops);
make_cleanup (VEC_cleanup (probe_p), &probes);
@@ -682,6 +688,98 @@ info_probes_command (char *arg, int from_tty)
info_probes_for_ops (arg, from_tty, NULL);
}
+/* Implementation of the `enable probes' command. */
+
+static void
+enable_probes_command (char *arg, int from_tty)
+{
+ char *provider, *probe_name = NULL, *objname = NULL;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+ VEC (bound_probe_s) *probes;
+ struct bound_probe *probe;
+ int i;
+
+ parse_probe_linespec ((const char *) arg, &provider, &probe_name, &objname);
+ make_cleanup (xfree, provider);
+ make_cleanup (xfree, probe_name);
+ make_cleanup (xfree, objname);
+
+ probes = collect_probes (objname, provider, probe_name, NULL);
+ if (VEC_empty (bound_probe_s, probes))
+ {
+ ui_out_message (current_uiout, 0, _("No probes matched.\n"));
+ do_cleanups (cleanup);
+ return;
+ }
+
+ /* Enable the selected probes, provided their backends support the
+ notion of enabling a probe. */
+ for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i)
+ {
+ const struct probe_ops *pops = probe->probe->pops;
+
+ if (pops->enable_probe != NULL)
+ {
+ pops->enable_probe (probe->probe);
+ ui_out_message (current_uiout, 0,
+ _("Probe %s:%s enabled.\n"),
+ probe->probe->provider, probe->probe->name);
+ }
+ else
+ ui_out_message (current_uiout, 0,
+ _("Probe %s:%s cannot be enabled.\n"),
+ probe->probe->provider, probe->probe->name);
+ }
+
+ do_cleanups (cleanup);
+}
+
+/* Implementation of the `disable probes' command. */
+
+static void
+disable_probes_command (char *arg, int from_tty)
+{
+ char *provider, *probe_name = NULL, *objname = NULL;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+ VEC (bound_probe_s) *probes;
+ struct bound_probe *probe;
+ int i;
+
+ parse_probe_linespec ((const char *) arg, &provider, &probe_name, &objname);
+ make_cleanup (xfree, provider);
+ make_cleanup (xfree, probe_name);
+ make_cleanup (xfree, objname);
+
+ probes = collect_probes (objname, provider, probe_name, NULL /* pops */);
+ if (VEC_empty (bound_probe_s, probes))
+ {
+ ui_out_message (current_uiout, 0, _("No probes matched.\n"));
+ do_cleanups (cleanup);
+ return;
+ }
+
+ /* Disable the selected probes, provided their backends support the
+ notion of enabling a probe. */
+ for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i)
+ {
+ const struct probe_ops *pops = probe->probe->pops;
+
+ if (pops->disable_probe != NULL)
+ {
+ pops->disable_probe (probe->probe);
+ ui_out_message (current_uiout, 0,
+ _("Probe %s:%s disabled.\n"),
+ probe->probe->provider, probe->probe->name);
+ }
+ else
+ ui_out_message (current_uiout, 0,
+ _("Probe %s:%s cannot be disabled.\n"),
+ probe->probe->provider, probe->probe->name);
+ }
+
+ do_cleanups (cleanup);
+}
+
/* See comments in probe.h. */
CORE_ADDR
@@ -943,4 +1041,27 @@ _initialize_probe (void)
_("\
Show information about all type of probes."),
info_probes_cmdlist_get ());
+
+ add_cmd ("probes", class_breakpoint, enable_probes_command, _("\
+Enable probes.\n\
+Usage: enable probes [PROVIDER [NAME [OBJECT]]]\n\
+Each argument is a regular expression, used to select probes.\n\
+PROVIDER matches probe provider names.\n\
+NAME matches the probe names.\n\
+OBJECT matches the executable or shared library name.\n\
+If you do not specify any argument then the command will enable\n\
+all defined probes."),
+ &enablelist);
+
+ add_cmd ("probes", class_breakpoint, disable_probes_command, _("\
+Disable probes.\n\
+Usage: disable probes [PROVIDER [NAME [OBJECT]]]\n\
+Each argument is a regular expression, used to select probes.\n\
+PROVIDER matches probe provider names.\n\
+NAME matches the probe names.\n\
+OBJECT matches the executable or shared library name.\n\
+If you do not specify any argument then the command will disable\n\
+all defined probes."),
+ &disablelist);
+
}
diff --git a/gdb/probe.h b/gdb/probe.h
index b4ff0a6..3f27d0d 100644
--- a/gdb/probe.h
+++ b/gdb/probe.h
@@ -132,6 +132,18 @@ struct probe_ops
void (*gen_info_probes_table_values) (struct probe *probe,
VEC (const_char_ptr) **values);
+
+ /* Enable a probe. The semantics of "enabling" a probe depend on
+ the specific backend and the field can be NULL in case enabling
+ probes is not supported. */
+
+ void (*enable_probe) (struct probe *probe);
+
+ /* Disable a probe. The semantics of "disabling" a probe depend
+ on the specific backend and the field can be NULL in case
+ disabling probes is not supported. */
+
+ void (*disable_probe) (struct probe *probe);
};
/* Definition of a vector of probe_ops. */
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index bcbb42f..43dc248 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -1674,6 +1674,8 @@ static const struct probe_ops stap_probe_ops =
stap_probe_destroy,
stap_gen_info_probes_table_header,
stap_gen_info_probes_table_values,
+ NULL, /* enable_probe */
+ NULL /* disable_probe */
};
/* Implementation of the `info probes stap' command. */
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 1/9] Adapt `info probes' to support printing probes of different types.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 5/9] New probe type: DTrace USDT probes Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets Jose E. Marchesi
` (6 subsequent siblings)
8 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
A "probe type" (backend for the probe abstraction implemented in
probe.[ch]) can extend the information printed by `info probes' by
defining additional columns. This means that when `info probes' is
used to print all the probes regardless of their types, some of the
columns will be "not applicable" to some of the probes (like, say, the
Semaphore column only makes sense for SystemTap probes). This patch
makes `info probes' fill these slots with "n/a" marks (currently it
breaks the table) and not include headers for which no actual probe
has been found in the list of defined probes.
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* probe.c (print_ui_out_not_applicables): New function.
(exists_probe_with_pops): Likewise.
(info_probes_for_ops): Do not include column headers for probe
types for which no probe has been actually found on any object.
Also invoke `print_ui_out_not_applicables' in order to match the
column rows with the header when probes of several types are
listed.
---
gdb/ChangeLog | 10 +++++++++
gdb/probe.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 66 insertions(+), 7 deletions(-)
diff --git a/gdb/probe.c b/gdb/probe.c
index 3b8882e..47f5dc2 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -410,6 +410,31 @@ gen_ui_out_table_header_info (VEC (bound_probe_s) *probes,
do_cleanups (c);
}
+/* Helper function to print not-applicable strings for all the extra
+ columns defined in a probe_ops. */
+
+static void
+print_ui_out_not_applicables (const struct probe_ops *pops)
+{
+ struct cleanup *c;
+ VEC (info_probe_column_s) *headings = NULL;
+ info_probe_column_s *column;
+ int ix;
+
+ if (pops->gen_info_probes_table_header == NULL)
+ return;
+
+ c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings);
+ pops->gen_info_probes_table_header (&headings);
+
+ for (ix = 0;
+ VEC_iterate (info_probe_column_s, headings, ix, column);
+ ++ix)
+ ui_out_field_string (current_uiout, column->field_name, _("n/a"));
+
+ do_cleanups (c);
+}
+
/* Helper function to print extra information about a probe and an objfile
represented by PROBE. */
@@ -482,6 +507,23 @@ get_number_extra_fields (const struct probe_ops *pops)
return n;
}
+/* Helper function that returns 1 if there is a probe in PROBES
+ featuring the given POPS. It returns 0 otherwise. */
+
+static int
+exists_probe_with_pops (VEC (bound_probe_s) *probes,
+ const struct probe_ops *pops)
+{
+ struct bound_probe *probe;
+ int ix;
+
+ for (ix = 0; VEC_iterate (bound_probe_s, probes, ix, probe); ++ix)
+ if (probe->probe->pops == pops)
+ return 1;
+
+ return 0;
+}
+
/* See comment in probe.h. */
void
@@ -517,6 +559,9 @@ info_probes_for_ops (const char *arg, int from_tty,
}
}
+ probes = collect_probes (objname, provider, probe_name, pops);
+ make_cleanup (VEC_cleanup (probe_p), &probes);
+
if (pops == NULL)
{
const struct probe_ops *po;
@@ -529,16 +574,16 @@ info_probes_for_ops (const char *arg, int from_tty,
To do that, we iterate over all probe_ops, querying each one about
its extra fields, and incrementing `ui_out_extra_fields' to reflect
- that number. */
+ that number. But note that we ignore the probe_ops for which no probes
+ are defined with the given search criteria. */
for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix)
- ui_out_extra_fields += get_number_extra_fields (po);
+ if (exists_probe_with_pops (probes, po))
+ ui_out_extra_fields += get_number_extra_fields (po);
}
else
ui_out_extra_fields = get_number_extra_fields (pops);
- probes = collect_probes (objname, provider, probe_name, pops);
- make_cleanup (VEC_cleanup (probe_p), &probes);
make_cleanup_ui_out_table_begin_end (current_uiout,
4 + ui_out_extra_fields,
VEC_length (bound_probe_s, probes),
@@ -571,10 +616,12 @@ info_probes_for_ops (const char *arg, int from_tty,
const struct probe_ops *po;
int ix;
- /* We have to generate the table header for each new probe type that we
- will print. */
+ /* We have to generate the table header for each new probe type
+ that we will print. Note that this excludes probe types not
+ having any defined probe with the search criteria. */
for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix)
- gen_ui_out_table_header_info (probes, po);
+ if (exists_probe_with_pops (probes, po))
+ gen_ui_out_table_header_info (probes, po);
}
else
gen_ui_out_table_header_info (probes, pops);
@@ -604,6 +651,8 @@ info_probes_for_ops (const char *arg, int from_tty,
++ix)
if (probe->probe->pops == po)
print_ui_out_info (probe->probe);
+ else if (exists_probe_with_pops (probes, po))
+ print_ui_out_not_applicables (po);
}
else
print_ui_out_info (probe->probe);
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 7/9] Simple testsuite for DTrace USDT probes.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
` (7 preceding siblings ...)
2014-10-10 17:18 ` [PATCH V2 9/9] Announce the DTrace USDT probes support in NEWS Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-16 22:36 ` Pedro Alves
8 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch adds some simple tests testing the support for DTrace USDT
probes. The testsuite will be skipped as unsupported in case the user
does not have DTrace installed on her system. The tests included in
the test suite test breakpointing on DTrace probes, enabling and
disabling probes, printing of probe arguments of several types and
also breakpointing on several probes with the same name.
gdb/testsuite/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* gdb.base/dtrace-probe.exp: New file.
(dtrace_build_test_program): New function.
(dtrace_test): Likewise.
* gdb.base/dtrace-probe.d: New file.
(test): New DTrace provider with two probes: `progress-counter'
and `two-locations'.
* gdb.base/dtrace-probe.c: New file.
(main): New function.
---
gdb/testsuite/ChangeLog | 11 +++
gdb/testsuite/gdb.base/dtrace-probe.c | 38 ++++++++
gdb/testsuite/gdb.base/dtrace-probe.d | 21 +++++
gdb/testsuite/gdb.base/dtrace-probe.exp | 154 +++++++++++++++++++++++++++++++
4 files changed, 224 insertions(+)
create mode 100644 gdb/testsuite/gdb.base/dtrace-probe.c
create mode 100644 gdb/testsuite/gdb.base/dtrace-probe.d
create mode 100644 gdb/testsuite/gdb.base/dtrace-probe.exp
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.c b/gdb/testsuite/gdb.base/dtrace-probe.c
new file mode 100644
index 0000000..45a77c5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dtrace-probe.c
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ 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 "dtrace-probe.h"
+
+int
+main ()
+{
+ char *name = "application";
+
+ TEST_TWO_LOCATIONS ();
+
+ int i = 0;
+ while (i < 10)
+ {
+ i++;
+ if (TEST_PROGRESS_COUNTER_ENABLED ())
+ TEST_PROGRESS_COUNTER (name, i);
+ }
+
+ TEST_TWO_LOCATIONS ();
+
+ return 0; /* last break here */
+}
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.d b/gdb/testsuite/gdb.base/dtrace-probe.d
new file mode 100644
index 0000000..df8e6bb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dtrace-probe.d
@@ -0,0 +1,21 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ 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/>. */
+
+provider test {
+ probe progress__counter (char *name, int);
+ probe two__locations ();
+};
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.exp b/gdb/testsuite/gdb.base/dtrace-probe.exp
new file mode 100644
index 0000000..b563cdb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dtrace-probe.exp
@@ -0,0 +1,154 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+
+# 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/>.
+
+standard_testfile
+
+# Generate the test program with DTrace USDT probes.
+# This returns -1 on failure to build, 0 otherwise
+proc dtrace_build_test_program {} {
+ global testfile hex srcdir subdir srcfile binfile
+
+ # Make sure that dtrace is installed, it is the real one (not the
+ # script installed by SystemTap, for example) and of the right
+ # version (>= 0.4.0).
+
+ set dtrace "dtrace"
+
+ set result [catch "exec $dtrace -V" output]
+ if {$result != 0 || ![regexp {^dtrace: Sun D [0-9]\.[0-9]\.[0-9]$} $output]} {
+ untested dtrace-probe.exp
+ return -1
+ }
+
+ # Generate the demo program, which contains USDT probes. This
+ # involves running the `dtrace' program in order to generate some
+ # auxiliary files: a header file and an object file with the ELF
+ # sections containing the probes information.
+
+ set dscript_file "${srcdir}/${subdir}/${testfile}.d"
+ set out_header_file "${srcdir}/${subdir}/${testfile}.h"
+ set result \
+ [catch "exec $dtrace -h -s $dscript_file -o $out_header_file" output]
+ verbose -log $output
+ if {$result != 0} {
+ fail "invoke dtrace -h to generate the header file for USDT probes"
+ return -1
+ }
+
+ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object {debug}] != ""} {
+ fail "compile ${binfile}.o"
+ return -1
+ }
+
+ set result \
+ [catch "exec $dtrace -G -s $dscript_file ${binfile}.o -o ${binfile}-p.o" output]
+ verbose -log $output
+ if {$result != 0} {
+ fail "invoke dtrace -G to generate the object file with probe information"
+ return -1
+ }
+
+ if {[gdb_compile "${binfile}.o ${binfile}-p.o" ${binfile} executable {debug}] != ""} {
+ fail "compile ${binfile}"
+ return -1
+ }
+}
+
+# Run the tests.
+# This returns -1 on failure to compile or start, 0 otherwise.
+proc dtrace_test {} {
+ global testfile hex srcfile binfile
+
+ if {[dtrace_build_test_program] == -1} {
+ return -1
+ }
+
+ clean_restart ${binfile}
+
+ if ![runto_main] {
+ return -1
+ }
+
+ gdb_test "print \$_probe_argc" "No probe at PC $hex" \
+ "check argument not at probe point"
+
+ # Test the 'info probes' command.
+ gdb_test "info probes dtrace" \
+ "test *progress-counter *$hex +no.*test *two-locations *$hex +always.*test *two-locations *$hex +always.*" \
+ "info probes dtrace"
+
+ # Disabling the probe test:two-locations shall have no effect,
+ # since no is-enabled probes are defined for it in the object
+ # file.
+
+ gdb_test "disable probe test two-locations" \
+ "Probe test:two-locations cannot be disabled.*" \
+ "disable probe test two-locations"
+
+ # On the other hand, the probe test:progress-counter can be
+ # enabled and then disabled again.
+
+ gdb_test "enable probe test progress-counter" \
+ "Probe test:progress-counter enabled.*" \
+ "enable probe test progress-counter"
+
+ gdb_test "disable probe test progress-counter" \
+ "Probe test:progress-counter disabled.*" \
+ "disable probe test progress-counter"
+
+ # Since test:progress-counter is disabled we can run to the second
+ # instance of the test:two-locations probe.
+
+ if {![runto "-probe-dtrace test:two-locations"]} {
+ fail "run to the first test:two-locations probe point"
+ }
+ gdb_test "continue" \
+ "Breakpoint \[0-9\]+, main \\(\\) at.*TEST_TWO_LOCATIONS.*" \
+ "run to the second test:two-locations probe point"
+
+ # Go back to the breakpoint on main() and enable the
+ # test:progress-counter probe. Set a breakpoint on it and see
+ # that it gets reached.
+
+ if ![runto_main] {
+ return -1
+ }
+
+ gdb_test "enable probe test progress-counter" \
+ "Probe test:progress-counter enabled.*" \
+ "enable probe test progress-counter"
+
+ gdb_test "break -probe-dtrace test:progress-counter" \
+ ".*Breakpoint \[0-9\]+ .*" "set breakpoint in test:progress-counter"
+ gdb_continue_to_breakpoint "test:progress-counter"
+
+ # Test probe arguments.
+ gdb_test "print \$_probe_argc" " = 2" \
+ "print \$_probe_argc for probe progress-counter"
+ gdb_test "print \$_probe_arg0" \
+ " = $hex \"application\"" \
+ "print \$_probe_arg0 for probe progress-counter"
+ gdb_test "print \$_probe_arg1" " = 1" \
+ "print \$_probe_arg1 for probe progress-counter"
+
+ # Set a breakpoint with multiple probe locations.
+ gdb_test "break -pdtrace test:two-locations" \
+ "Breakpoint \[0-9\]+ at $hex.*2 locations.*" \
+ "set multii-location probe breakpoint (probe two-locations)"
+
+ return 0
+}
+
+dtrace_test
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 9/9] Announce the DTrace USDT probes support in NEWS.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
` (6 preceding siblings ...)
2014-10-10 17:18 ` [PATCH V2 3/9] New commands `enable probe' and `disable probe' Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-10 18:16 ` Eli Zaretskii
2014-10-10 17:18 ` [PATCH V2 7/9] Simple testsuite for DTrace USDT probes Jose E. Marchesi
8 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch simply adds a small entry to `Changes since GDB 7.8' announcing the
support for dtrace probes.
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* NEWS: Announce the support for DTrace SDT probes.
---
gdb/ChangeLog | 4 ++++
gdb/NEWS | 3 +++
2 files changed, 7 insertions(+)
diff --git a/gdb/NEWS b/gdb/NEWS
index b56fe8e..518be28 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -45,6 +45,9 @@ queue-signal signal-name-or-number
** The -list-thread-groups command outputs an exit-code field for
inferiors that have exited.
+* GDB now has support for DTrace USDT (Userland Static Defined
+ Tracing) probes. The supported targets are x86_64-*-linux-gnu.
+
*** Changes in GDB 7.8
* New command line options
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 8/9] Documentation for DTrace USDT probes.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
` (4 preceding siblings ...)
2014-10-10 17:18 ` [PATCH V2 2/9] Move `compute_probe_arg' and `compile_probe_arg' to probe.c Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-10 18:18 ` Eli Zaretskii
2014-10-10 17:18 ` [PATCH V2 3/9] New commands `enable probe' and `disable probe' Jose E. Marchesi
` (2 subsequent siblings)
8 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch modifies the `Static Probe Points' section on the GDB
manual in order to cover the support for DTrace USDT probes, in
addition to SystemTap SDT probes.
gdb/doc/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* gdb.texinfo (Static Probe Points): Add cindex `static probe
point, DTrace'.
(Static Probe Points): Modified to cover DTrace probes in addition
to SystemTap probes. Also modified to cover the `enable probe'
and `disable probe' commands.
---
gdb/doc/ChangeLog | 8 +++++++
gdb/doc/gdb.texinfo | 58 +++++++++++++++++++++++++++++++++------------------
2 files changed, 46 insertions(+), 20 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a9c70b0..8cf550a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4932,34 +4932,49 @@ that can no longer be recreated.
@subsection Static Probe Points
@cindex static probe point, SystemTap
+@cindex static probe point, DTrace
@value{GDBN} supports @dfn{SDT} probes in the code. @acronym{SDT} stands
for Statically Defined Tracing, and the probes are designed to have a tiny
-runtime code and data footprint, and no dynamic relocations. They are
-usable from assembly, C and C@t{++} languages. See
-@uref{http://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation}
-for a good reference on how the @acronym{SDT} probes are implemented.
+runtime code and data footprint, and no dynamic relocations.
+
+Currently, the following types of probes are supported on
+ELF-compatible systems:
-Currently, @code{SystemTap} (@uref{http://sourceware.org/systemtap/})
-@acronym{SDT} probes are supported on ELF-compatible systems. See
+@itemize @bullet
+@item @code{SystemTap} (@uref{http://sourceware.org/systemtap/})
+@acronym{SDT} probes@footnote{See
@uref{http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps}
-for more information on how to add @code{SystemTap} @acronym{SDT} probes
-in your applications.
+for more information on how to add @code{SystemTap} @acronym{SDT}
+probes in your applications.}. @code{SystemTap} probes are usable
+from assembly, C and C@t{++} languages@footnote{See
+@uref{http://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation}
+for a good reference on how the @acronym{SDT} probes are implemented.}.
+@item @code{DTrace} (@uref{http://oss.oracle.com/projects/DTrace})
+@acronym{USDT} probes. @code{DTrace} probes are usable from C and
+C@t{++} languages.
+@end itemize
@cindex semaphores on static probe points
-Some probes have an associated semaphore variable; for instance, this
-happens automatically if you defined your probe using a DTrace-style
-@file{.d} file. If your probe has a semaphore, @value{GDBN} will
-automatically enable it when you specify a breakpoint using the
-@samp{-probe-stap} notation. But, if you put a breakpoint at a probe's
-location by some other method (e.g., @code{break file:line}), then
-@value{GDBN} will not automatically set the semaphore.
+Some @code{SystemTap} probes have an associated semaphore variable;
+for instance, this happens automatically if you defined your probe
+using a DTrace-style @file{.d} file. If your probe has a semaphore,
+@value{GDBN} will automatically enable it when you specify a
+breakpoint using the @samp{-probe-stap} notation. But, if you put a
+breakpoint at a probe's location by some other method (e.g.,
+@code{break file:line}), then @value{GDBN} will not automatically set
+the semaphore. @code{DTrace} probes do not support the notion of
+semaphores.
You can examine the available static static probes using @code{info
probes}, with optional arguments:
@table @code
@kindex info probes
-@item info probes stap @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
+@item info probes @r{[}@var{type}@r{]} @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
+If given, @var{type} is either @code{stap} for listing
+@code{SystemTap} probes or @code{dtrace} for listing @code{DTrace}
+probes. If omitted all probes are listed regardless of their types.
+
If given, @var{provider} is a regular expression used to match against provider
names when selecting which probes to list. If omitted, probes by all
probes from all providers are listed.
@@ -4979,8 +4994,8 @@ List the available static probes, from all types.
@cindex enabling and disabling probes
Some probe points can be enabled and/or disabled. The effects
associated to enabling or disabling a probe depend on the type of
-probe being handled. @code{SystemTap} probes do not support these
-notions.
+probe being handled. Some @code{DTrace} probes can be enabled or
+disabled, but @code{SystemTap} probes do not support these notions.
You can enable (or disable) one or more probes using the following
commands, with optional arguments:
@@ -5011,8 +5026,11 @@ A probe may specify up to twelve arguments. These are available at the
point at which the probe is defined---that is, when the current PC is
at the probe's location. The arguments are available using the
convenience variables (@pxref{Convenience Vars})
-@code{$_probe_arg0}@dots{}@code{$_probe_arg11}. Each probe argument is
-an integer of the appropriate size; types are not preserved. The
+@code{$_probe_arg0}@dots{}@code{$_probe_arg11}. In @code{SystemTap}
+probes each probe argument is an integer of the appropriate size;
+types are not preserved. In @code{DTrace} probes types are preserved
+provided that they are recognized as such by @value{GDBN}; otherwise
+the value of the probe argument will be a long integer. The
convenience variable @code{$_probe_argc} holds the number of arguments
at the current probe point.
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 5/9] New probe type: DTrace USDT probes.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-14 19:01 ` Sergio Durigan Junior
2014-10-10 17:18 ` [PATCH V2 1/9] Adapt `info probes' to support printing probes of different types Jose E. Marchesi
` (7 subsequent siblings)
8 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch adds a new type of probe to GDB: the DTrace USDT probes. The new
type is added by providing functions implementing all the entries of the
`probe_ops' structure defined in `probe.h'. The implementation is
self-contained and does not depend on DTrace source code in any way.
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* breakpoint.c (BREAK_ARGS_HELP): help string updated to mention
the -probe-dtrace new vpossible value for PROBE_MODIFIER.
* configure.ac (CONFIG_OBS): dtrace-probe.o added if BFD can
handle ELF files.
* Makefile.in (SFILES): dtrace-probe.c added.
* configure: Regenerate.
* dtrace-probe.c: New file.
(SHT_SUNW_dof): New constant.
(dtrace_probe_type): New enum.
(dtrace_probe_arg): New struct.
(dtrace_probe_arg_s): New typedef.
(struct dtrace_probe_enabler): New struct.
(dtrace_probe_enabler_s): New typedef.
(dtrace_probe): New struct.
(dtrace_probe_is_linespec): New function.
(dtrace_dof_sect_type): New enum.
(dtrace_dof_dofh_ident): Likewise.
(dtrace_dof_encoding): Likewise.
(DTRACE_DOF_ENCODE_LSB): Likewise.
(DTRACE_DOF_ENCODE_MSB): Likewise.
(dtrace_dof_hdr): New struct.
(dtrace_dof_sect): Likewise.
(dtrace_dof_provider): Likewise.
(dtrace_dof_probe): Likewise.
(DOF_UINT): New macro.
(DTRACE_DOF_PTR): Likewise.
(DTRACE_DOF_SECT): Likewise.
(dtrace_process_dof_probe): New function.
(dtrace_process_dof): Likewise.
(dtrace_build_arg_exprs): Likewise.
(dtrace_get_arg): Likewise.
(dtrace_get_probes): Likewise.
(dtrace_get_probe_argument_count): Likewise.
(dtrace_can_evaluate_probe_arguments): Likewise.
(dtrace_evaluate_probe_argument): Likewise.
(dtrace_compile_to_ax): Likewise.
(dtrace_set_semaphore): Likewise.
(dtrace_clear_semaphore): Likewise.
(dtrace_probe_destroy): Likewise.
(dtrace_gen_info_probes_table_header): Likewise.
(dtrace_gen_info_probes_table_values): Likewise.
(dtrace_probe_is_enabled): Likewise.
(dtrace_probe_ops): New variable.
(info_probes_dtrace_command): New function.
(_initialize_dtrace_probe): Likewise.
---
gdb/ChangeLog | 48 +++
gdb/Makefile.in | 3 +-
gdb/breakpoint.c | 3 +-
gdb/configure | 2 +-
gdb/configure.ac | 2 +-
gdb/dtrace-probe.c | 854 ++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 908 insertions(+), 4 deletions(-)
create mode 100644 gdb/dtrace-probe.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 1ffa62a..7414ac4 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -800,7 +800,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
d-exp.y d-lang.c d-support.c d-valprint.c \
cp-name-parser.y \
- dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
+ dbxread.c demangle.c dictionary.c disasm.c doublest.c \
+ dtrace-probe.c dummy-frame.c \
dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
dwarf2-frame-tailcall.c \
elfread.c environ.c eval.c event-loop.c event-top.c \
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 3044916..0198183 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -16195,7 +16195,8 @@ all_tracepoints (void)
command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]\n\
PROBE_MODIFIER shall be present if the command is to be placed in a\n\
probe point. Accepted values are `-probe' (for a generic, automatically\n\
-guessed probe type) or `-probe-stap' (for a SystemTap probe).\n\
+guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
+`-probe-dtrace' (for a DTrace probe).\n\
LOCATION may be a line number, function name, or \"*\" and an address.\n\
If a line number is specified, break at start of code for that line.\n\
If a function is specified, break at start of code for that function.\n\
diff --git a/gdb/configure b/gdb/configure
index 6e7435f..ecd0cff 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -13281,7 +13281,7 @@ $as_echo "$gdb_cv_var_elf" >&6; }
LDFLAGS=$OLD_LDFLAGS
LIBS=$OLD_LIBS
if test $gdb_cv_var_elf = yes; then
- CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o"
+ CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o"
$as_echo "#define HAVE_ELF 1" >>confdefs.h
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 4f5fb7b..7b1133a 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -2103,7 +2103,7 @@ AC_SUBST(WIN32LIBS)
GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_elf,
[bfd_get_elf_phdr_upper_bound (NULL)], elf-bfd.h)
if test $gdb_cv_var_elf = yes; then
- CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o"
+ CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o"
AC_DEFINE(HAVE_ELF, 1,
[Define if ELF support should be included.])
# -ldl is provided by bfd/Makfile.am (LIBDL) <PLUGINS>.
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
new file mode 100644
index 0000000..e94f66b
--- /dev/null
+++ b/gdb/dtrace-probe.c
@@ -0,0 +1,854 @@
+/* DTrace probe support for GDB.
+
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Contributed by Oracle, 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 "probe.h"
+#include "vec.h"
+#include "elf-bfd.h"
+#include "gdbtypes.h"
+#include "obstack.h"
+#include "objfiles.h"
+#include "complaints.h"
+#include "value.h"
+#include "ax.h"
+#include "ax-gdb.h"
+#include "language.h"
+#include "parser-defs.h"
+#include "inferior.h"
+
+/* The type of the ELF sections where we will find the DOF programs
+ with information about probes. */
+
+#ifndef SHT_SUNW_dof
+# define SHT_SUNW_dof 0x6ffffff4
+#endif
+
+/* Forward declaration. */
+
+static const struct probe_ops dtrace_probe_ops;
+
+/* The following structure represents a single argument for the
+ probe. */
+
+struct dtrace_probe_arg
+{
+ /* The type of the probe argument. */
+ struct type *type;
+
+ /* A string describing the type. */
+ char *type_str;
+
+ /* The argument converted to an internal GDB expression. */
+ struct expression *expr;
+};
+
+typedef struct dtrace_probe_arg dtrace_probe_arg_s;
+DEF_VEC_O (dtrace_probe_arg_s);
+
+/* The following structure represents an enabler for a probe. */
+
+struct dtrace_probe_enabler
+{
+ /* Program counter where the is-enabled probe is installed. The
+ contents (nops, whatever...) stored at this address are
+ architecture dependent. */
+ CORE_ADDR address;
+};
+
+typedef struct dtrace_probe_enabler dtrace_probe_enabler_s;
+DEF_VEC_O (dtrace_probe_enabler_s);
+
+/* The following structure represents a dtrace probe. */
+
+struct dtrace_probe
+{
+ /* Generic information about the probe. This must be the first
+ element of this struct, in order to maintain binary compatibility
+ with the `struct probe' and be able to fully abstract it. */
+ struct probe p;
+
+ /* A probe can have zero or more arguments. */
+ int probe_argc;
+ VEC (dtrace_probe_arg_s) *args;
+
+ /* A probe can have zero or more "enablers" associated with it. */
+ VEC (dtrace_probe_enabler_s) *enablers;
+
+ /* Whether the expressions for the arguments have been built. */
+ int args_expr_built : 1;
+};
+
+/* Implementation of the probe_is_linespec method. */
+
+static int
+dtrace_probe_is_linespec (const char **linespecp)
+{
+ static const char *const keywords[] = { "-pdtrace", "-probe-dtrace", NULL };
+
+ return probe_is_linespec_by_keyword (linespecp, keywords);
+}
+
+/* DOF programs can contain an arbitrary number of sections of 26
+ different types. In order to support DTrace USDT probes we only
+ need to handle a subset of these section types, fortunately. These
+ section types are defined in the following enumeration.
+
+ See linux/dtrace/dof_defines.h for a complete list of section types
+ along with their values. */
+
+enum dtrace_dof_sect_type
+{
+ DTRACE_DOF_SECT_TYPE_NONE = 0, /* Null section. */
+ DTRACE_DOF_SECT_TYPE_ECBDESC = 3, /* A dof_ecbdesc_t. */
+ DTRACE_DOF_SECT_TYPE_STRTAB = 8, /* A string table. */
+ DTRACE_DOF_SECT_TYPE_PROVIDER = 15, /* A dof_provider_t */
+ DTRACE_DOF_SECT_TYPE_PROBES = 16, /* Array of dof_probe_t */
+ DTRACE_DOF_SECT_TYPE_PRARGS = 17, /* An array of probe arg
+ mappings. */
+ DTRACE_DOF_SECT_TYPE_PROFFS = 18, /* An array of probe arg
+ offsets. */
+ DTRACE_DOF_SECT_TYPE_PRENOFFS = 26 /* An array of probe is-enabled
+ offsets. */
+};
+
+/* The following collection of data structures map the structure of
+ DOF entities. Again, we only cover the subset of DOF used to
+ implement USDT probes.
+
+ See linux/dtrace/dof.h header for a complete list of data
+ structures. */
+
+/* Offsets to index the dofh_ident[] array defined below. */
+
+enum dtrace_dof_ident
+{
+ DTRACE_DOF_ID_MAG0 = 0, /* First byte of the magic number. */
+ DTRACE_DOF_ID_MAG1 = 1, /* Second byte of the magic number. */
+ DTRACE_DOF_ID_MAG2 = 2, /* Third byte of the magic number. */
+ DTRACE_DOF_ID_MAG3 = 3, /* Fourth byte of the magic number. */
+ DTRACE_DOF_ID_ENCODING = 5 /* An enum_dof_encoding value. */
+};
+
+/* Possible values for dofh_ident[DOF_ID_ENCODING]. */
+
+enum dtrace_dof_encoding
+{
+ DTRACE_DOF_ENCODE_LSB = 1, /* The DOF program is little-endian. */
+ DTRACE_DOF_ENCODE_MSB = 2 /* The DOF program is big-endian. */
+};
+
+/* A DOF header, which describes the contents of a DOF program: number
+ of sections, size, etc. */
+
+struct dtrace_dof_hdr
+{
+ uint8_t dofh_ident[16]; /* Identification bytes (see above). */
+ uint32_t dofh_flags; /* File attribute flags (if any). */
+ uint32_t dofh_hdrsize; /* Size of file header in bytes. */
+ uint32_t dofh_secsize; /* Size of section header in bytes. */
+ uint32_t dofh_secnum; /* Number of section headers. */
+ uint64_t dofh_secoff; /* File offset of section headers. */
+ uint64_t dofh_loadsz; /* File size of loadable portion. */
+ uint64_t dofh_filesz; /* File size of entire DOF file. */
+ uint64_t dofh_pad; /* Reserved for future use. */
+};
+
+/* A DOF section, whose contents depend on its type. The several
+ supported section types are described in the enum
+ dtrace_dof_sect_type above. */
+
+struct dtrace_dof_sect
+{
+ uint32_t dofs_type; /* Section type (see the define above). */
+ uint32_t dofs_align; /* Section data memory alignment. */
+ uint32_t dofs_flags; /* Section flags (if any). */
+ uint32_t dofs_entsize; /* Size of section entry (if table). */
+ uint64_t dofs_offset; /* DOF + offset points to the section data. */
+ uint64_t dofs_size; /* Size of section data in bytes. */
+};
+
+/* A DOF provider, which is the provider of a probe. */
+
+struct dtrace_dof_provider
+{
+ uint32_t dofpv_strtab; /* Link to a DTRACE_DOF_SECT_TYPE_STRTAB section. */
+ uint32_t dofpv_probes; /* Link to a DTRACE_DOF_SECT_TYPE_PROBES section. */
+ uint32_t dofpv_prargs; /* Link to a DTRACE_DOF_SECT_TYPE_PRARGS section. */
+ uint32_t dofpv_proffs; /* Link to a DTRACE_DOF_SECT_TYPE_PROFFS section. */
+ uint32_t dofpv_name; /* Provider name string. */
+ uint32_t dofpv_provattr; /* Provider attributes. */
+ uint32_t dofpv_modattr; /* Module attributes. */
+ uint32_t dofpv_funcattr; /* Function attributes. */
+ uint32_t dofpv_nameattr; /* Name attributes. */
+ uint32_t dofpv_argsattr; /* Args attributes. */
+ uint32_t dofpv_prenoffs; /* Link to a DTRACE_DOF_SECT_PRENOFFS section. */
+};
+
+/* A set of DOF probes and is-enabled probes sharing a base address
+ and several attributes. The particular locations and attributes of
+ each probe are maintained in arrays in several other DOF sections.
+ See the comment in dtrace_process_dof_probe for details on how
+ these attributes are stored. */
+
+struct dtrace_dof_probe
+{
+ uint64_t dofpr_addr; /* Probe base address or offset. */
+ uint32_t dofpr_func; /* Probe function string. */
+ uint32_t dofpr_name; /* Probe name string. */
+ uint32_t dofpr_nargv; /* Native argument type strings. */
+ uint32_t dofpr_xargv; /* Translated argument type strings. */
+ uint32_t dofpr_argidx; /* Index of first argument mapping. */
+ uint32_t dofpr_offidx; /* Index of first offset entry. */
+ uint8_t dofpr_nargc; /* Native argument count. */
+ uint8_t dofpr_xargc; /* Translated argument count. */
+ uint16_t dofpr_noffs; /* Number of offset entries for probe. */
+ uint32_t dofpr_enoffidx; /* Index of first is-enabled offset. */
+ uint16_t dofpr_nenoffs; /* Number of is-enabled offsets. */
+ uint16_t dofpr_pad1; /* Reserved for future use. */
+ uint32_t dofpr_pad2; /* Reserved for future use. */
+};
+
+/* DOF supports two different encodings: MSB (big-endian) and LSB
+ (little-endian). The encoding is itself encoded in the DOF header.
+ The following function returns an unsigned value in the host
+ endianness. */
+
+#define DOF_UINT(dof, field) \
+ extract_unsigned_integer ((gdb_byte *) &(field), \
+ sizeof ((field)), \
+ (((dof)->dofh_ident[DTRACE_DOF_ID_ENCODING] \
+ == DTRACE_DOF_ENCODE_MSB) \
+ ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE))
+
+/* The following macro applies a given byte offset to a DOF (a pointer
+ to a dtrace_dof_hdr structure) and returns the resulting
+ address. */
+
+#define DTRACE_DOF_PTR(dof, offset) (&((char *) (dof))[(offset)])
+
+/* The following macro returns a pointer to the beginning of a given
+ section in a DOF object. The section is referred to by its index
+ in the sections array. */
+
+#define DTRACE_DOF_SECT(dof, idx) \
+ ((struct dtrace_dof_sect *) \
+ DTRACE_DOF_PTR ((dof), \
+ DOF_UINT ((dof), (dof)->dofh_secoff) \
+ + ((idx) * DOF_UINT ((dof), (dof)->dofh_secsize))))
+
+/* Helper function to examine the probe described by the given PROBE
+ and PROVIDER data structures and add it to the PROBESP vector.
+ STRTAB, OFFTAB, EOFFTAB and ARGTAB are pointers to tables in the
+ DOF program containing the attributes for the probe. */
+
+static void
+dtrace_process_dof_probe (struct objfile *objfile,
+ struct gdbarch *gdbarch, VEC (probe_p) **probesp,
+ struct dtrace_dof_hdr *dof,
+ struct dtrace_dof_probe *probe,
+ struct dtrace_dof_provider *provider,
+ char *strtab, char *offtab, char *eofftab,
+ char *argtab, uint64_t strtab_size)
+{
+ int i, j, num_probes, num_enablers;
+ VEC (dtrace_probe_enabler_s) *enablers;
+ char *p;
+
+ /* Each probe section can define zero or more probes of two
+ different types:
+
+ - probe->dofpr_noffs regular probes whose program counters are
+ stored in 32bit words starting at probe->dofpr_addr +
+ offtab[probe->dofpr_offidx].
+
+ - probe->dofpr_nenoffs is-enabled probes whose program counters
+ are stored in 32bit words starting at probe->dofpr_addr +
+ eofftab[probe->dofpr_enoffidx].
+
+ However is-enabled probes are not probes per-se, but an
+ optimization hack that is implemented in the kernel in a very
+ similar way than normal probes. This is how we support
+ is-enabled probes on GDB:
+
+ - Our probes are always DTrace regular probes.
+
+ - Our probes can be associated with zero or more "enablers". The
+ list of enablers is built from the is-enabled probes defined in
+ the Probe section.
+
+ - Probes having a non-empty list of enablers can be enabled or
+ disabled using the `enable probe' and `disable probe' commands
+ respectively. The `Enabled' column in the output of `info
+ probes' will read `yes' if the enablers are activated, `no'
+ otherwise.
+
+ - Probes having an empty list of enablers are always enabled.
+ The `Enabled' column in the output of `info probes' will
+ read `always'.
+
+ It follows that if there are DTrace is-enabled probes defined for
+ some provider/name but no DTrace regular probes defined then the
+ GDB user wont be able to enable/disable these conditionals. */
+
+ num_probes = DOF_UINT (dof, probe->dofpr_noffs);
+ if (num_probes == 0)
+ return;
+
+ /* Build the list of enablers for the probes defined in this Probe
+ DOF section. */
+ enablers = NULL;
+ num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs);
+ for (i = 0; i < num_enablers; i++)
+ {
+ struct dtrace_probe_enabler enabler;
+ uint32_t enabler_offset
+ = ((uint32_t *) eofftab)[DOF_UINT (dof, probe->dofpr_enoffidx) + i];
+
+ enabler.address = DOF_UINT (dof, probe->dofpr_addr)
+ + DOF_UINT (dof, enabler_offset);
+ VEC_safe_push (dtrace_probe_enabler_s, enablers, &enabler);
+ }
+
+ for (i = 0; i < num_probes; i++)
+ {
+ uint32_t probe_offset
+ = ((uint32_t *) offtab)[DOF_UINT (dof, probe->dofpr_offidx) + i];
+ struct dtrace_probe *ret
+ = obstack_alloc (&objfile->per_bfd->storage_obstack, sizeof (*ret));
+
+ ret->p.pops = &dtrace_probe_ops;
+ ret->p.arch = gdbarch;
+ ret->args_expr_built = 0;
+
+ /* Set the provider and the name of the probe. */
+ ret->p.provider
+ = xstrdup (strtab + DOF_UINT (dof, provider->dofpv_name));
+ ret->p.name = xstrdup (strtab + DOF_UINT (dof, probe->dofpr_name));
+
+ /* The probe address. */
+ ret->p.address
+ = DOF_UINT (dof, probe->dofpr_addr) + DOF_UINT (dof, probe_offset);
+
+ /* Number of arguments in the probe. */
+ ret->probe_argc = DOF_UINT (dof, probe->dofpr_nargc);
+
+ /* Store argument type descriptions. A description of the type
+ of the argument is in the (J+1)th null-terminated string
+ starting at 'strtab' + 'probe->dofpr_nargv'. */
+ ret->args = NULL;
+ p = strtab + DOF_UINT (dof, probe->dofpr_nargv);
+ for (j = 0; j < ret->probe_argc; j++)
+ {
+ struct dtrace_probe_arg arg;
+ struct expression *expr;
+
+ arg.type_str = xstrdup (p);
+
+ /* Use strtab_size as a sentinel. */
+ while (*p++ != '\0' && p - strtab < strtab_size);
+
+ /* Try to parse a type expression from the type string. If
+ this does not work then we set the type to `long
+ int'. */
+ arg.type = builtin_type (gdbarch)->builtin_long;
+ expr = parse_expression (arg.type_str);
+ if (expr->elts[0].opcode == OP_TYPE)
+ arg.type = expr->elts[1].type;
+
+ VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg);
+ }
+
+ /* Add the vector of enablers to this probe, if any. */
+ ret->enablers = enablers;
+
+ /* Successfully created probe. */
+ VEC_safe_push (probe_p, *probesp, (struct probe *) ret);
+ }
+}
+
+/* Helper function to collect the probes described in the DOF program
+ whose header is pointed by DOF and add them to the PROBESP vector.
+ SECT is the ELF section containing the DOF program and OBJFILE is
+ its containing object file. */
+
+static void
+dtrace_process_dof (asection *sect, struct objfile *objfile,
+ VEC (probe_p) **probesp, struct dtrace_dof_hdr *dof)
+{
+ bfd *abfd = objfile->obfd;
+ int size = bfd_get_arch_size (abfd) / 8;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct dtrace_dof_sect *section;
+ int i;
+
+ /* The first step is to check for the DOF magic number. If no valid
+ DOF data is found in the section then a complaint is issued to
+ the user and the section skipped. */
+ if (dof->dofh_ident[DTRACE_DOF_ID_MAG0] != 0x7F
+ || dof->dofh_ident[DTRACE_DOF_ID_MAG1] != 'D'
+ || dof->dofh_ident[DTRACE_DOF_ID_MAG2] != 'O'
+ || dof->dofh_ident[DTRACE_DOF_ID_MAG3] != 'F')
+ goto invalid_dof_data;
+
+ /* Make sure this DOF is not an enabling DOF, i.e. there are no ECB
+ Description sections. */
+ section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
+ DOF_UINT (dof, dof->dofh_secoff));
+ for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
+ if (section->dofs_type == DTRACE_DOF_SECT_TYPE_ECBDESC)
+ return;
+
+ /* Iterate over any section of type Provider and extract the probe
+ information from them. If there are no "provider" sections on
+ the DOF then we just return. */
+ section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
+ DOF_UINT (dof, dof->dofh_secoff));
+ for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
+ if (DOF_UINT (dof, section->dofs_type) == DTRACE_DOF_SECT_TYPE_PROVIDER)
+ {
+ struct dtrace_dof_provider *provider = (struct dtrace_dof_provider *)
+ DTRACE_DOF_PTR (dof, DOF_UINT (dof, section->dofs_offset));
+ struct dtrace_dof_sect *strtab_s
+ = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_strtab));
+ struct dtrace_dof_sect *probes_s
+ = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_probes));
+ struct dtrace_dof_sect *args_s
+ = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prargs));
+ struct dtrace_dof_sect *offsets_s
+ = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_proffs));
+ struct dtrace_dof_sect *eoffsets_s
+ = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prenoffs));
+ char *strtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, strtab_s->dofs_offset));
+ char *offtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, offsets_s->dofs_offset));
+ char *eofftab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, eoffsets_s->dofs_offset));
+ char *argtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, args_s->dofs_offset));
+ unsigned int entsize = DOF_UINT (dof, probes_s->dofs_entsize);
+ int num_probes;
+
+ /* Very, unlikely, but could crash gdb if not handled
+ properly. */
+ if (entsize == 0)
+ goto invalid_dof_data;
+
+ num_probes = DOF_UINT (dof, probes_s->dofs_size) / entsize;
+
+ for (i = 0; i < num_probes; i++)
+ {
+ struct dtrace_dof_probe *probe = (struct dtrace_dof_probe *)
+ DTRACE_DOF_PTR (dof, DOF_UINT (dof, probes_s->dofs_offset)
+ + (i * DOF_UINT (dof, probes_s->dofs_entsize)));
+
+ dtrace_process_dof_probe (objfile,
+ gdbarch, probesp,
+ dof, probe,
+ provider, strtab, offtab, eofftab, argtab,
+ DOF_UINT (dof, strtab_s->dofs_size));
+ }
+ }
+
+ return;
+
+ invalid_dof_data:
+ complaint (&symfile_complaints,
+ _("skipping section '%s' which does not contain valid DOF data."),
+ sect->name);
+}
+
+/* Helper function to build the GDB internal expressiosn that, once
+ evaluated, will calculate the values of the arguments of a given
+ PROBE. */
+
+static void
+dtrace_build_arg_exprs (struct dtrace_probe *probe,
+ struct gdbarch *gdbarch)
+{
+ struct parser_state pstate;
+ struct dtrace_probe_arg *arg;
+ int i;
+
+ probe->args_expr_built = 1;
+
+ /* Iterate over the arguments in the probe and build the
+ corresponding GDB internal expression that will generate the
+ value of the argument when executed at the PC of the probe. */
+ for (i = 0; i < probe->probe_argc; i++)
+ {
+ struct cleanup *back_to;
+
+ arg = VEC_index (dtrace_probe_arg_s, probe->args, i);
+
+ /* Initialize the expression buffer in the parser state. The
+ language does not matter, since we are using our own
+ parser. */
+ initialize_expout (&pstate, 10, current_language, gdbarch);
+ back_to = make_cleanup (free_current_contents, &pstate.expout);
+
+ /* The argument value, which is ABI dependent and casted to
+ `long int'. */
+ gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, i);
+
+ discard_cleanups (back_to);
+
+ /* Casting to the expected type, but only if the type was
+ recognized at probe load time. Otherwise the argument will
+ be evaluated as the long integer passed to the probe. */
+ if (arg->type != NULL)
+ {
+ write_exp_elt_opcode (&pstate, UNOP_CAST);
+ write_exp_elt_type (&pstate, arg->type);
+ write_exp_elt_opcode (&pstate, UNOP_CAST);
+ }
+
+ reallocate_expout (&pstate);
+ arg->expr = pstate.expout;
+ prefixify_expression (arg->expr);
+ }
+}
+
+/* Helper function to return the Nth argument of a given PROBE. */
+
+static struct dtrace_probe_arg *
+dtrace_get_arg (struct dtrace_probe *probe, unsigned n,
+ struct gdbarch *gdbarch)
+{
+ if (!probe->args_expr_built)
+ dtrace_build_arg_exprs (probe, gdbarch);
+
+ return VEC_index (dtrace_probe_arg_s, probe->args, n);
+}
+
+/* Implementation of the get_probes method. */
+
+static void
+dtrace_get_probes (VEC (probe_p) **probesp, struct objfile *objfile)
+{
+ bfd *abfd = objfile->obfd;
+ asection *sect = NULL;
+
+ /* Do nothing in case this is a .debug file, instead of the objfile
+ itself. */
+ if (objfile->separate_debug_objfile_backlink != NULL)
+ return;
+
+ /* Iterate over the sections in OBJFILE looking for DTrace
+ information. */
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
+ {
+ if (elf_section_data (sect)->this_hdr.sh_type == SHT_SUNW_dof)
+ {
+ struct dtrace_dof_hdr *dof;
+
+ /* Read the contents of the DOF section and then process it to
+ extract the information of any probe defined into it. */
+ if (!bfd_malloc_and_get_section (abfd, sect, (bfd_byte **) &dof))
+ complaint (&symfile_complaints,
+ _("could not obtain the contents of"
+ "section '%s' in objfile `%s'."),
+ sect->name, abfd->filename);
+
+ dtrace_process_dof (sect, objfile, probesp, dof);
+ xfree (dof);
+ }
+ }
+}
+
+/* Helper function to determine whether a given probe is "enabled" or
+ "disabled". A disabled probe is a probe in which one or more
+ enablers are disabled. */
+
+static int
+dtrace_probe_is_enabled (struct dtrace_probe *probe)
+{
+ int i;
+ struct gdbarch *gdbarch = probe->p.arch;
+ struct dtrace_probe_enabler *enabler;
+
+ for (i = 0;
+ VEC_iterate (dtrace_probe_enabler_s, probe->enablers, i, enabler);
+ i++)
+ if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler->address))
+ return 0;
+
+ return 1;
+}
+
+/* Implementation of the get_probe_address method. */
+
+static CORE_ADDR
+dtrace_get_probe_address (struct probe *probe, struct objfile *objfile)
+{
+ gdb_assert (probe->pops == &dtrace_probe_ops);
+ return probe->address + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_DATA (objfile));
+}
+
+/* Implementation of the get_probe_argument_count method. */
+
+static unsigned
+dtrace_get_probe_argument_count (struct probe *probe_generic,
+ struct frame_info *frame)
+{
+ struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
+
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+ return dtrace_probe->probe_argc;
+}
+
+/* Implementation of the can_evaluate_probe_arguments method. */
+
+static int
+dtrace_can_evaluate_probe_arguments (struct probe *probe_generic)
+{
+ struct gdbarch *gdbarch = probe_generic->arch;
+
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+ return gdbarch_dtrace_parse_probe_argument_p (gdbarch);
+}
+
+/* Implementation of the evaluate_probe_argument method. */
+
+static struct value *
+dtrace_evaluate_probe_argument (struct probe *probe_generic, unsigned n,
+ struct frame_info *frame)
+{
+ struct gdbarch *gdbarch = probe_generic->arch;
+ struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
+ struct dtrace_probe_arg *arg;
+ int pos = 0;
+
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+ arg = dtrace_get_arg (dtrace_probe, n, gdbarch);
+ return evaluate_subexp_standard (arg->type, arg->expr, &pos, EVAL_NORMAL);
+}
+
+/* Implementation of the compile_to_ax method. */
+
+static void
+dtrace_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
+ struct axs_value *value, unsigned n)
+{
+ struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
+ struct dtrace_probe_arg *arg;
+ union exp_element *pc;
+
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+ arg = dtrace_get_arg (dtrace_probe, n, expr->gdbarch);
+
+ pc = arg->expr->elts;
+ gen_expr (arg->expr, &pc, expr, value);
+
+ require_rvalue (expr, value);
+ value->type = arg->type;
+}
+
+/* Implementation of the set_semaphore method. */
+
+static void
+dtrace_set_semaphore (struct probe *probe_generic, struct objfile *objfile,
+ struct gdbarch *gdbarch)
+{
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+}
+
+/* Implementation of the clear_semaphore method. */
+
+static void
+dtrace_clear_semaphore (struct probe *probe_generic, struct objfile *objfile,
+ struct gdbarch *gdbarch)
+{
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+}
+
+/* Implementation of the probe_destroy method. */
+
+static void
+dtrace_probe_destroy (struct probe *probe_generic)
+{
+ struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
+ struct dtrace_probe_arg *arg;
+ int i;
+
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+ for (i = 0; VEC_iterate (dtrace_probe_arg_s, probe->args, i, arg); i++)
+ {
+ xfree (arg->type_str);
+ xfree (arg->expr);
+ }
+
+ VEC_free (dtrace_probe_enabler_s, probe->enablers);
+ VEC_free (dtrace_probe_arg_s, probe->args);
+}
+
+/* Implementation of the gen_info_probes_table_header method. */
+
+static void
+dtrace_gen_info_probes_table_header (VEC (info_probe_column_s) **heads)
+{
+ info_probe_column_s dtrace_probe_column;
+
+ dtrace_probe_column.field_name = "enabled";
+ dtrace_probe_column.print_name = _("Enabled");
+
+ VEC_safe_push (info_probe_column_s, *heads, &dtrace_probe_column);
+}
+
+/* Implementation of the gen_info_probes_table_values method. */
+
+static void
+dtrace_gen_info_probes_table_values (struct probe *probe_generic,
+ VEC (const_char_ptr) **ret)
+{
+ struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
+ const char *val = NULL;
+
+ gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+ if (VEC_empty (dtrace_probe_enabler_s, probe->enablers))
+ val = "always";
+ else if (!gdbarch_dtrace_probe_is_enabled_p (probe_generic->arch))
+ val = "unknown";
+ else if (dtrace_probe_is_enabled (probe))
+ val = "yes";
+ else
+ val = "no";
+
+ VEC_safe_push (const_char_ptr, *ret, val);
+}
+
+/* Implementation of the enable_probe method. */
+
+static void
+dtrace_enable_probe (struct probe *probe)
+{
+ struct gdbarch *gdbarch = probe->arch;
+ struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
+ struct dtrace_probe_enabler *enabler;
+ int i;
+
+ gdb_assert (probe->pops == &dtrace_probe_ops);
+
+ /* Enabling a dtrace probe implies patching the text section of the
+ running process, so make sure the inferior is indeed running. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ error (_("No inferior running"));
+
+ /* Fast path. */
+ if (dtrace_probe_is_enabled (dtrace_probe))
+ return;
+
+ /* Iterate over all defined enabler in the given probe and enable
+ them all using the corresponding gdbarch hook. */
+
+ for (i = 0;
+ VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
+ i++)
+ if (gdbarch_dtrace_enable_probe_p (gdbarch))
+ gdbarch_dtrace_enable_probe (gdbarch, enabler->address);
+}
+
+
+/* Implementation of the disable_probe method. */
+
+static void
+dtrace_disable_probe (struct probe *probe)
+{
+ struct gdbarch *gdbarch = probe->arch;
+ struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
+ struct dtrace_probe_enabler *enabler;
+ int i;
+
+ gdb_assert (probe->pops == &dtrace_probe_ops);
+
+ /* Disabling a dtrace probe implies patching the text section of the
+ running process, so make sure the inferior is indeed running. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ error (_("No inferior running"));
+
+ /* Fast path. */
+ if (!dtrace_probe_is_enabled (dtrace_probe))
+ return;
+
+ /* Are we trying to disable a probe that does not have any enabler
+ associated? */
+ if (VEC_empty (dtrace_probe_enabler_s, dtrace_probe->enablers))
+ error (_("Probe %s:%s cannot be disabled."), probe->provider, probe->name);
+
+ /* Iterate over all defined enabler in the given probe and disable
+ them all using the corresponding gdbarch hook. */
+
+ for (i = 0;
+ VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
+ i++)
+ {
+ if (gdbarch_dtrace_disable_probe_p (gdbarch))
+ gdbarch_dtrace_disable_probe (gdbarch, enabler->address);
+ }
+}
+
+/* DTrace probe_ops. */
+
+static const struct probe_ops dtrace_probe_ops =
+{
+ dtrace_probe_is_linespec,
+ dtrace_get_probes,
+ dtrace_get_probe_address,
+ dtrace_get_probe_argument_count,
+ dtrace_can_evaluate_probe_arguments,
+ dtrace_evaluate_probe_argument,
+ dtrace_compile_to_ax,
+ dtrace_set_semaphore,
+ dtrace_clear_semaphore,
+ dtrace_probe_destroy,
+ dtrace_gen_info_probes_table_header,
+ dtrace_gen_info_probes_table_values,
+ dtrace_enable_probe,
+ dtrace_disable_probe
+};
+
+/* Implementation of the `info probes dtrace' command. */
+
+static void
+info_probes_dtrace_command (char *arg, int from_tty)
+{
+ info_probes_for_ops (arg, from_tty, &dtrace_probe_ops);
+}
+
+void _initialize_dtrace_probe (void);
+
+void
+_initialize_dtrace_probe (void)
+{
+ VEC_safe_push (probe_ops_cp, all_probe_ops, &dtrace_probe_ops);
+
+ add_cmd ("dtrace", class_info, info_probes_dtrace_command,
+ _("\
+Show information about DTrace static probes.\n\
+Usage: info probes dtrace [PROVIDER [NAME [OBJECT]]]\n\
+Each argument is a regular expression, used to select probes.\n\
+PROVIDER matches probe provider names.\n\
+NAME matches the probe names.\n\
+OBJECT matches the executable or shared library name."),
+ info_probes_cmdlist_get ());
+}
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 0/9] Add support for DTrace USDT probes to gdb
@ 2014-10-10 17:18 Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 5/9] New probe type: DTrace USDT probes Jose E. Marchesi
` (8 more replies)
0 siblings, 9 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
[Changes in this version of the patch series:
- ChangeLog entries are not included in the diffs.
- Blank lines separating file blocks in ChangeLogs have been removed.
- Varios formatting changes suggested/requested by Sergio and Eli.
- Documentation fixes suggested by Eli.
- Avoid implicit comparisons in conditionals.
- probe.c:get_num_probes_with_pops function renamed to exists_probes_with_pops.
- Some #defines have been replaced by enums.
- Missing documentation comments for functions and enum entries added.
- Code parsing probe linespecs factorized into a new function.
- The gdbarch function dtrace_probe_argument has been renamed to
dtrace_parse_probe_argument.
- Other minor changes suggested in the mailing list.]
This patch series introduces support in GDB for a new type of probe:
DTrace USDT probes.
The first three patches do some changes to the existing probe.[ch]
code, fixing some minor problems associated to support several probe
types, having several probes of different types defined in the same
object and supporting the notion of enabling and disabling probes.
The rest of the patches are the implementation of the new probe type,
including target support for x86_64 targets, a testsuite and
documentation.
Tested on x86_64-*-linux-gnu.
No visible regressions.
Jose E. Marchesi (9):
Adapt `info probes' to support printing probes of different types.
Move `compute_probe_arg' and `compile_probe_arg' to probe.c
New commands `enable probe' and `disable probe'.
New gdbarch functions: dtrace_parse_probe_argument,
dtrace_probe_is_enabled, dtrace_enable_probe, dtrace_disable_probe.
New probe type: DTrace USDT probes.
Support for DTrace USDT probes in x86_64 targets.
Simple testsuite for DTrace USDT probes.
Documentation for DTrace USDT probes.
Announce the DTrace USDT probes support in NEWS.
gdb/ChangeLog | 107 ++++
gdb/Makefile.in | 3 +-
gdb/NEWS | 3 +
gdb/amd64-linux-tdep.c | 158 ++++++
gdb/amd64-linux-tdep.h | 11 +
gdb/breakpoint.c | 3 +-
gdb/configure | 2 +-
gdb/configure.ac | 2 +-
gdb/doc/ChangeLog | 13 +
gdb/doc/gdb.texinfo | 84 ++-
gdb/dtrace-probe.c | 854 +++++++++++++++++++++++++++++++
gdb/gdbarch.c | 128 +++++
gdb/gdbarch.h | 36 ++
gdb/gdbarch.sh | 16 +
gdb/probe.c | 327 +++++++++++-
gdb/probe.h | 12 +
gdb/stap-probe.c | 111 +---
gdb/testsuite/ChangeLog | 17 +
gdb/testsuite/gdb.base/dtrace-probe.c | 38 ++
gdb/testsuite/gdb.base/dtrace-probe.d | 21 +
gdb/testsuite/gdb.base/dtrace-probe.exp | 154 ++++++
gdb/testsuite/gdb.base/stap-probe.exp | 2 +-
22 files changed, 1947 insertions(+), 155 deletions(-)
create mode 100644 gdb/dtrace-probe.c
create mode 100644 gdb/testsuite/gdb.base/dtrace-probe.c
create mode 100644 gdb/testsuite/gdb.base/dtrace-probe.d
create mode 100644 gdb/testsuite/gdb.base/dtrace-probe.exp
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 2/9] Move `compute_probe_arg' and `compile_probe_arg' to probe.c
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
` (3 preceding siblings ...)
2014-10-10 17:18 ` [PATCH V2 4/9] New gdbarch functions: dtrace_parse_probe_argument, dtrace_probe_is_enabled, dtrace_enable_probe, dtrace_disable_probe Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 8/9] Documentation for DTrace USDT probes Jose E. Marchesi
` (3 subsequent siblings)
8 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch moves the `compute_probe_arg' and `compile_probe_arg' functions
from stap-probe.c to probe.c. The rationale is that it is reasonable to
assume that all backends will provide the `$_probe_argN' convenience
variables, and that the user must be placed on the PC of the probe when
requesting that information. The value and type of the argument can still be
determined by the probe backend via the `pops->evaluate_probe_argument' and
`pops->compile_to_ax' handlers.
Note that a test in gdb.base/stap-probe.exp had to be adjusted because the "No
SystemTap probe at PC" messages are now "No probe at PC".
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* probe.c (compute_probe_arg): Moved from stap-probe.c
(compile_probe_arg): Likewise.
(probe_funcs): Likewise.
* stap-probe.c (compute_probe_arg): Moved to probe.c.
(compile_probe_arg): Likewise.
(probe_funcs): Likewise.
gdb/testsuite/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* gdb.base/stap-probe.exp (stap_test): Remove "SystemTap" from
expected message when trying to access $_probe_* convenience
variables while not on a probe.
---
gdb/ChangeLog | 9 +++
gdb/probe.c | 111 +++++++++++++++++++++++++++++++++
gdb/stap-probe.c | 109 --------------------------------
gdb/testsuite/ChangeLog | 6 ++
gdb/testsuite/gdb.base/stap-probe.exp | 2 +-
5 files changed, 127 insertions(+), 110 deletions(-)
diff --git a/gdb/probe.c b/gdb/probe.c
index 47f5dc2..69ca0aa 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -30,6 +30,9 @@
#include "gdb_regex.h"
#include "frame.h"
#include "arch-utils.h"
+#include "value.h"
+#include "ax.h"
+#include "ax-gdb.h"
#include <ctype.h>
typedef struct bound_probe bound_probe_s;
@@ -819,6 +822,87 @@ will show information about all types of probes."),
return &info_probes_cmdlist;
}
+\f
+
+/* This is called to compute the value of one of the $_probe_arg*
+ convenience variables. */
+
+static struct value *
+compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar,
+ void *data)
+{
+ struct frame_info *frame = get_selected_frame (_("No frame selected"));
+ CORE_ADDR pc = get_frame_pc (frame);
+ int sel = (int) (uintptr_t) data;
+ struct bound_probe pc_probe;
+ const struct sym_probe_fns *pc_probe_fns;
+ unsigned n_args;
+
+ /* SEL == -1 means "_probe_argc". */
+ gdb_assert (sel >= -1);
+
+ pc_probe = find_probe_by_pc (pc);
+ if (pc_probe.probe == NULL)
+ error (_("No probe at PC %s"), core_addr_to_string (pc));
+
+ n_args = get_probe_argument_count (pc_probe.probe, frame);
+ if (sel == -1)
+ return value_from_longest (builtin_type (arch)->builtin_int, n_args);
+
+ if (sel >= n_args)
+ error (_("Invalid probe argument %d -- probe has %u arguments available"),
+ sel, n_args);
+
+ return evaluate_probe_argument (pc_probe.probe, sel, frame);
+}
+
+/* This is called to compile one of the $_probe_arg* convenience
+ variables into an agent expression. */
+
+static void
+compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr,
+ struct axs_value *value, void *data)
+{
+ CORE_ADDR pc = expr->scope;
+ int sel = (int) (uintptr_t) data;
+ struct bound_probe pc_probe;
+ const struct sym_probe_fns *pc_probe_fns;
+ int n_args;
+ struct frame_info *frame = get_selected_frame (NULL);
+
+ /* SEL == -1 means "_probe_argc". */
+ gdb_assert (sel >= -1);
+
+ pc_probe = find_probe_by_pc (pc);
+ if (pc_probe.probe == NULL)
+ error (_("No probe at PC %s"), core_addr_to_string (pc));
+
+ n_args = get_probe_argument_count (pc_probe.probe, frame);
+
+ if (sel == -1)
+ {
+ value->kind = axs_rvalue;
+ value->type = builtin_type (expr->gdbarch)->builtin_int;
+ ax_const_l (expr, n_args);
+ return;
+ }
+
+ gdb_assert (sel >= 0);
+ if (sel >= n_args)
+ error (_("Invalid probe argument %d -- probe has %d arguments available"),
+ sel, n_args);
+
+ pc_probe.probe->pops->compile_to_ax (pc_probe.probe, expr, value, sel);
+}
+
+static const struct internalvar_funcs probe_funcs =
+{
+ compute_probe_arg,
+ compile_probe_arg,
+ NULL
+};
+
+
VEC (probe_ops_cp) *all_probe_ops;
void _initialize_probe (void);
@@ -828,6 +912,33 @@ _initialize_probe (void)
{
VEC_safe_push (probe_ops_cp, all_probe_ops, &probe_ops_any);
+ create_internalvar_type_lazy ("_probe_argc", &probe_funcs,
+ (void *) (uintptr_t) -1);
+ create_internalvar_type_lazy ("_probe_arg0", &probe_funcs,
+ (void *) (uintptr_t) 0);
+ create_internalvar_type_lazy ("_probe_arg1", &probe_funcs,
+ (void *) (uintptr_t) 1);
+ create_internalvar_type_lazy ("_probe_arg2", &probe_funcs,
+ (void *) (uintptr_t) 2);
+ create_internalvar_type_lazy ("_probe_arg3", &probe_funcs,
+ (void *) (uintptr_t) 3);
+ create_internalvar_type_lazy ("_probe_arg4", &probe_funcs,
+ (void *) (uintptr_t) 4);
+ create_internalvar_type_lazy ("_probe_arg5", &probe_funcs,
+ (void *) (uintptr_t) 5);
+ create_internalvar_type_lazy ("_probe_arg6", &probe_funcs,
+ (void *) (uintptr_t) 6);
+ create_internalvar_type_lazy ("_probe_arg7", &probe_funcs,
+ (void *) (uintptr_t) 7);
+ create_internalvar_type_lazy ("_probe_arg8", &probe_funcs,
+ (void *) (uintptr_t) 8);
+ create_internalvar_type_lazy ("_probe_arg9", &probe_funcs,
+ (void *) (uintptr_t) 9);
+ create_internalvar_type_lazy ("_probe_arg10", &probe_funcs,
+ (void *) (uintptr_t) 10);
+ create_internalvar_type_lazy ("_probe_arg11", &probe_funcs,
+ (void *) (uintptr_t) 11);
+
add_cmd ("all", class_info, info_probes_command,
_("\
Show information about all type of probes."),
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index a51bf8b..bcbb42f 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -1365,79 +1365,6 @@ stap_probe_destroy (struct probe *probe_generic)
\f
-/* This is called to compute the value of one of the $_probe_arg*
- convenience variables. */
-
-static struct value *
-compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar,
- void *data)
-{
- struct frame_info *frame = get_selected_frame (_("No frame selected"));
- CORE_ADDR pc = get_frame_pc (frame);
- int sel = (int) (uintptr_t) data;
- struct bound_probe pc_probe;
- const struct sym_probe_fns *pc_probe_fns;
- unsigned n_args;
-
- /* SEL == -1 means "_probe_argc". */
- gdb_assert (sel >= -1);
-
- pc_probe = find_probe_by_pc (pc);
- if (pc_probe.probe == NULL)
- error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc));
-
- n_args = get_probe_argument_count (pc_probe.probe, frame);
- if (sel == -1)
- return value_from_longest (builtin_type (arch)->builtin_int, n_args);
-
- if (sel >= n_args)
- error (_("Invalid probe argument %d -- probe has %u arguments available"),
- sel, n_args);
-
- return evaluate_probe_argument (pc_probe.probe, sel, frame);
-}
-
-/* This is called to compile one of the $_probe_arg* convenience
- variables into an agent expression. */
-
-static void
-compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr,
- struct axs_value *value, void *data)
-{
- CORE_ADDR pc = expr->scope;
- int sel = (int) (uintptr_t) data;
- struct bound_probe pc_probe;
- const struct sym_probe_fns *pc_probe_fns;
- int n_args;
- struct frame_info *frame = get_selected_frame (NULL);
-
- /* SEL == -1 means "_probe_argc". */
- gdb_assert (sel >= -1);
-
- pc_probe = find_probe_by_pc (pc);
- if (pc_probe.probe == NULL)
- error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc));
-
- n_args = get_probe_argument_count (pc_probe.probe, frame);
-
- if (sel == -1)
- {
- value->kind = axs_rvalue;
- value->type = builtin_type (expr->gdbarch)->builtin_int;
- ax_const_l (expr, n_args);
- return;
- }
-
- gdb_assert (sel >= 0);
- if (sel >= n_args)
- error (_("Invalid probe argument %d -- probe has %d arguments available"),
- sel, n_args);
-
- pc_probe.probe->pops->compile_to_ax (pc_probe.probe, expr, value, sel);
-}
-
-\f
-
/* Set or clear a SystemTap semaphore. ADDRESS is the semaphore's
address. SET is zero if the semaphore should be cleared, or one
if it should be set. This is a helper function for `stap_semaphore_down'
@@ -1514,15 +1441,6 @@ stap_clear_semaphore (struct probe *probe_generic, struct objfile *objfile,
stap_modify_semaphore (addr, 0, gdbarch);
}
-/* Implementation of `$_probe_arg*' set of variables. */
-
-static const struct internalvar_funcs probe_funcs =
-{
- compute_probe_arg,
- compile_probe_arg,
- NULL
-};
-
/* Helper function that parses the information contained in a
SystemTap's probe. Basically, the information consists in:
@@ -1783,33 +1701,6 @@ _initialize_stap_probe (void)
show_stapexpressiondebug,
&setdebuglist, &showdebuglist);
- create_internalvar_type_lazy ("_probe_argc", &probe_funcs,
- (void *) (uintptr_t) -1);
- create_internalvar_type_lazy ("_probe_arg0", &probe_funcs,
- (void *) (uintptr_t) 0);
- create_internalvar_type_lazy ("_probe_arg1", &probe_funcs,
- (void *) (uintptr_t) 1);
- create_internalvar_type_lazy ("_probe_arg2", &probe_funcs,
- (void *) (uintptr_t) 2);
- create_internalvar_type_lazy ("_probe_arg3", &probe_funcs,
- (void *) (uintptr_t) 3);
- create_internalvar_type_lazy ("_probe_arg4", &probe_funcs,
- (void *) (uintptr_t) 4);
- create_internalvar_type_lazy ("_probe_arg5", &probe_funcs,
- (void *) (uintptr_t) 5);
- create_internalvar_type_lazy ("_probe_arg6", &probe_funcs,
- (void *) (uintptr_t) 6);
- create_internalvar_type_lazy ("_probe_arg7", &probe_funcs,
- (void *) (uintptr_t) 7);
- create_internalvar_type_lazy ("_probe_arg8", &probe_funcs,
- (void *) (uintptr_t) 8);
- create_internalvar_type_lazy ("_probe_arg9", &probe_funcs,
- (void *) (uintptr_t) 9);
- create_internalvar_type_lazy ("_probe_arg10", &probe_funcs,
- (void *) (uintptr_t) 10);
- create_internalvar_type_lazy ("_probe_arg11", &probe_funcs,
- (void *) (uintptr_t) 11);
-
add_cmd ("stap", class_info, info_probes_stap_command,
_("\
Show information about SystemTap static probes.\n\
diff --git a/gdb/testsuite/gdb.base/stap-probe.exp b/gdb/testsuite/gdb.base/stap-probe.exp
index 7710bc3..9f71d1d 100644
--- a/gdb/testsuite/gdb.base/stap-probe.exp
+++ b/gdb/testsuite/gdb.base/stap-probe.exp
@@ -30,7 +30,7 @@ proc stap_test {exec_name {arg ""}} {
return -1
}
- gdb_test "print \$_probe_argc" "No SystemTap probe at PC $hex" \
+ gdb_test "print \$_probe_argc" "No probe at PC $hex" \
"check argument not at probe point"
gdb_test "info probes stap" \
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 5/9] New probe type: DTrace USDT probes Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 1/9] Adapt `info probes' to support printing probes of different types Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-16 22:07 ` Pedro Alves
` (2 more replies)
2014-10-10 17:18 ` [PATCH V2 4/9] New gdbarch functions: dtrace_parse_probe_argument, dtrace_probe_is_enabled, dtrace_enable_probe, dtrace_disable_probe Jose E. Marchesi
` (5 subsequent siblings)
8 siblings, 3 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch adds the target-specific code in order to support the
calculation of DTrace probes arguments in x86_64 targets, and also the
enabling and disabling of probes. This is done by implementing the
`dtrace_*' gdbarch handlers.
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* amd64-linux-tdep.h: Prototypes for
`amd64_dtrace_parse_probe_argument', `amd64_dtrace_enable_probe',
`amd64_dtrace_disable_probe' and
`gdbarch_dtrace_probe_is_enabled'.
* amd64-linux-tdep.c (amd64_dtrace_parse_probe_argument): New function.
(amd64_dtrace_probe_is_enabled): Likewise.
(amd64_dtrace_enable_probe): Likewise.
(amd64_dtrace_disable_probe): Likewise.
(amd64_linux_init_abi): Register the
`gdbarch_dtrace_probe_argument', `gdbarch_dtrace_enable_probe',
`gdbarch_dtrace_disable_probe' and `gdbarch_dtrace_probe_is_enabled'.
---
gdb/ChangeLog | 14 +++++
gdb/amd64-linux-tdep.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++
gdb/amd64-linux-tdep.h | 11 ++++
3 files changed, 183 insertions(+)
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index edbb1b3..04b3140 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -28,6 +28,8 @@
#include "gdbtypes.h"
#include "reggroups.h"
#include "regset.h"
+#include "parser-defs.h"
+#include "user-regs.h"
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
@@ -1643,6 +1645,156 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
&amd64_linux_xstateregset, "XSAVE extended state", cb_data);
}
+/* Implementation of `gdbarch_dtrace_probe_is_enabled', as defined in
+ gdbarch.h. */
+
+int
+amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_byte buf[5];
+ read_memory (addr - 3, buf, 5);
+
+ /* The instruction sequence used in x86_64 machines for a disabled
+ is-enabled probe is:
+
+ xor %rax, %rax => 48 33 C0
+ ADDR: nop => 90
+ nop => 90
+
+ or
+
+ xor %rax, %rax => 48 33 C0
+ ADDR: ret => c3
+ nop => 90
+
+ This function returns 1 if the instructions at ADDR do _not_
+ follow any of these patterns.
+
+ Note that ADDR is offset 3 bytes from the beginning of these
+ sequences. */
+
+ return !((buf[0] == 0x48) && (buf[1] == 0x33) && (buf[2] == 0xc0) /* xor */
+ && ((buf[3] == 0x90) || (buf[3] == 0xc3)) /* nop | ret */
+ && (buf[4] == 0x90)); /* nop */
+}
+
+/* Implementation of `gdbarch_dtrace_enable_probe', as defined in
+ gdbarch.h. */
+
+void
+amd64_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* We use the following instruction sequence for enabling an
+ is-enabled probe:
+
+ mov $0x1, %eax => b8 01 00 00 00
+
+ Note also that ADDR is offset 3 bytes from the beginning of the
+ sequence. */
+
+ gdb_byte buf[5];
+
+ buf[0] = 0xb8;
+ buf[1] = 0x01;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+
+ write_memory (addr - 3, buf, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_disable_probe', as defined in
+ gdbarch.h. */
+
+void
+amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* We use the following instruction sequence for disabling an
+ is-enabled probe:
+
+ xor %rax, %rax; nop; nop => 48 33 C0 90 90
+
+ Note that ADDR is offset 3 bytes from the beginning of the
+ sequence. */
+
+ gdb_byte buf[5];
+
+ buf[0] = 0x48;
+ buf[1] = 0x33;
+ buf[2] = 0xc0;
+ buf[3] = 0x90;
+ buf[4] = 0x90;
+
+ write_memory (addr - 3, buf, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_parse_probe_argument', as defined
+ in gdbarch.h. */
+
+void
+amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
+ struct parser_state *pstate,
+ int narg)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ struct frame_info *this_frame = get_selected_frame (NULL);
+ struct stoken str;
+ static int arg_reg_map[6] =
+ {
+ AMD64_RDI_REGNUM, /* Arg 1. */
+ AMD64_RSI_REGNUM, /* Arg 2. */
+ AMD64_RDX_REGNUM, /* Arg 3. */
+ AMD64_RCX_REGNUM, /* Arg 4. */
+ AMD64_R8_REGNUM, /* Arg 5. */
+ AMD64_R9_REGNUM /* Arg 6. */
+ };
+
+ /* DTrace probe arguments can be found on the ABI-defined places for
+ regular arguments at the current PC. The probe abstraction
+ currently supports up to 12 arguments for probes. */
+
+ if (narg < 6)
+ {
+ int regno = arg_reg_map[narg];
+ const char *regname = user_reg_map_regnum_to_name (gdbarch, regno);
+
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+ str.ptr = regname;
+ str.length = strlen (regname);
+ write_exp_string (pstate, str);
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+ }
+ else
+ {
+ /* Additional arguments are passed on the stack. */
+ CORE_ADDR sp;
+ const char *regname = user_reg_map_regnum_to_name (gdbarch, AMD64_RSP_REGNUM);
+
+ /* Displacement. */
+ write_exp_elt_opcode (pstate, OP_LONG);
+ write_exp_elt_type (pstate, builtin_type (gdbarch)->builtin_long);
+ write_exp_elt_longcst (pstate, narg - 6);
+ write_exp_elt_opcode (pstate, OP_LONG);
+
+ /* Register: SP. */
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+ str.ptr = regname;
+ str.length = strlen (regname);
+ write_exp_string (pstate, str);
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+
+ write_exp_elt_opcode (pstate, BINOP_ADD);
+
+ /* Cast to long. */
+ write_exp_elt_opcode (pstate, UNOP_CAST);
+ write_exp_elt_type (pstate,
+ lookup_pointer_type (builtin_type (gdbarch)->builtin_long));
+ write_exp_elt_opcode (pstate, UNOP_CAST);
+
+ write_exp_elt_opcode (pstate, UNOP_IND);
+ }
+}
+
static void
amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1907,6 +2059,12 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
+
+ /* Register DTrace handlers. */
+ set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
+ set_gdbarch_dtrace_probe_is_enabled (gdbarch, amd64_dtrace_probe_is_enabled);
+ set_gdbarch_dtrace_enable_probe (gdbarch, amd64_dtrace_enable_probe);
+ set_gdbarch_dtrace_disable_probe (gdbarch, amd64_dtrace_disable_probe);
}
static void
diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h
index 25563b8..1edb83b 100644
--- a/gdb/amd64-linux-tdep.h
+++ b/gdb/amd64-linux-tdep.h
@@ -594,4 +594,15 @@ enum amd64_x32_syscall {
amd64_x32_sys_getsockopt = (amd64_x32_syscall_bit + 542),
};
+/* DTrace related functions. */
+
+extern void amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
+ struct parser_state *pstate,
+ int narg);
+
+extern int amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr);
+
+extern void amd64_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr);
+
#endif /* amd64-linux-tdep.h */
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH V2 4/9] New gdbarch functions: dtrace_parse_probe_argument, dtrace_probe_is_enabled, dtrace_enable_probe, dtrace_disable_probe.
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
` (2 preceding siblings ...)
2014-10-10 17:18 ` [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets Jose E. Marchesi
@ 2014-10-10 17:18 ` Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 2/9] Move `compute_probe_arg' and `compile_probe_arg' to probe.c Jose E. Marchesi
` (4 subsequent siblings)
8 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-10 17:18 UTC (permalink / raw)
To: gdb-patches
This patch adds several gdbarch functions (along with the
corresponding predicates): `dtrace_parse_probe_argument',
`dtrace_probe_is_enabled', `dtrace_enable_probe' and
`dtrace_disable_probe'. These functions will be implemented by
target-specific code, and called from the DTrace probes implementation
in order to calculate the value of probe arguments, and manipulate
is-enabled probes.
gdb/ChangeLog:
2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
* gdbarch.sh (dtrace_parse_probe_argument): New.
(dtrace_probe_is_enabled): Likewise.
(dtrace_enable_probe): Likewise.
(dtrace_disable_probe): Likewise.
* gdbarch.c: Regenerate.
* gdbarch.h: Regenerate.
---
gdb/ChangeLog | 9 ++++
gdb/gdbarch.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/gdbarch.h | 36 ++++++++++++++++
gdb/gdbarch.sh | 16 +++++++
4 files changed, 189 insertions(+)
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index e96d651..d04dadb 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -298,6 +298,10 @@ struct gdbarch
const char * stap_gdb_register_suffix;
gdbarch_stap_is_single_operand_ftype *stap_is_single_operand;
gdbarch_stap_parse_special_token_ftype *stap_parse_special_token;
+ gdbarch_dtrace_parse_probe_argument_ftype *dtrace_parse_probe_argument;
+ gdbarch_dtrace_probe_is_enabled_ftype *dtrace_probe_is_enabled;
+ gdbarch_dtrace_enable_probe_ftype *dtrace_enable_probe;
+ gdbarch_dtrace_disable_probe_ftype *dtrace_disable_probe;
int has_global_solist;
int has_global_breakpoints;
gdbarch_has_shared_address_space_ftype *has_shared_address_space;
@@ -610,6 +614,10 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of stap_gdb_register_suffix, invalid_p == 0 */
/* Skip verify of stap_is_single_operand, has predicate. */
/* Skip verify of stap_parse_special_token, has predicate. */
+ /* Skip verify of dtrace_parse_probe_argument, has predicate. */
+ /* Skip verify of dtrace_probe_is_enabled, has predicate. */
+ /* Skip verify of dtrace_enable_probe, has predicate. */
+ /* Skip verify of dtrace_disable_probe, has predicate. */
/* Skip verify of has_global_solist, invalid_p == 0 */
/* Skip verify of has_global_breakpoints, invalid_p == 0 */
/* Skip verify of has_shared_address_space, invalid_p == 0 */
@@ -815,6 +823,30 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: double_format = %s\n",
pformat (gdbarch->double_format));
fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_dtrace_disable_probe_p() = %d\n",
+ gdbarch_dtrace_disable_probe_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: dtrace_disable_probe = <%s>\n",
+ host_address_to_string (gdbarch->dtrace_disable_probe));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_dtrace_enable_probe_p() = %d\n",
+ gdbarch_dtrace_enable_probe_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: dtrace_enable_probe = <%s>\n",
+ host_address_to_string (gdbarch->dtrace_enable_probe));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_dtrace_parse_probe_argument_p() = %d\n",
+ gdbarch_dtrace_parse_probe_argument_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: dtrace_parse_probe_argument = <%s>\n",
+ host_address_to_string (gdbarch->dtrace_parse_probe_argument));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_dtrace_probe_is_enabled_p() = %d\n",
+ gdbarch_dtrace_probe_is_enabled_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: dtrace_probe_is_enabled = <%s>\n",
+ host_address_to_string (gdbarch->dtrace_probe_is_enabled));
+ fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_dummy_id_p() = %d\n",
gdbarch_dummy_id_p (gdbarch));
fprintf_unfiltered (file,
@@ -4075,6 +4107,102 @@ set_gdbarch_stap_parse_special_token (struct gdbarch *gdbarch,
}
int
+gdbarch_dtrace_parse_probe_argument_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->dtrace_parse_probe_argument != NULL;
+}
+
+void
+gdbarch_dtrace_parse_probe_argument (struct gdbarch *gdbarch, struct parser_state *pstate, int narg)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->dtrace_parse_probe_argument != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_dtrace_parse_probe_argument called\n");
+ gdbarch->dtrace_parse_probe_argument (gdbarch, pstate, narg);
+}
+
+void
+set_gdbarch_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
+ gdbarch_dtrace_parse_probe_argument_ftype dtrace_parse_probe_argument)
+{
+ gdbarch->dtrace_parse_probe_argument = dtrace_parse_probe_argument;
+}
+
+int
+gdbarch_dtrace_probe_is_enabled_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->dtrace_probe_is_enabled != NULL;
+}
+
+int
+gdbarch_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->dtrace_probe_is_enabled != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_dtrace_probe_is_enabled called\n");
+ return gdbarch->dtrace_probe_is_enabled (gdbarch, addr);
+}
+
+void
+set_gdbarch_dtrace_probe_is_enabled (struct gdbarch *gdbarch,
+ gdbarch_dtrace_probe_is_enabled_ftype dtrace_probe_is_enabled)
+{
+ gdbarch->dtrace_probe_is_enabled = dtrace_probe_is_enabled;
+}
+
+int
+gdbarch_dtrace_enable_probe_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->dtrace_enable_probe != NULL;
+}
+
+void
+gdbarch_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->dtrace_enable_probe != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_dtrace_enable_probe called\n");
+ gdbarch->dtrace_enable_probe (gdbarch, addr);
+}
+
+void
+set_gdbarch_dtrace_enable_probe (struct gdbarch *gdbarch,
+ gdbarch_dtrace_enable_probe_ftype dtrace_enable_probe)
+{
+ gdbarch->dtrace_enable_probe = dtrace_enable_probe;
+}
+
+int
+gdbarch_dtrace_disable_probe_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->dtrace_disable_probe != NULL;
+}
+
+void
+gdbarch_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->dtrace_disable_probe != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_dtrace_disable_probe called\n");
+ gdbarch->dtrace_disable_probe (gdbarch, addr);
+}
+
+void
+set_gdbarch_dtrace_disable_probe (struct gdbarch *gdbarch,
+ gdbarch_dtrace_disable_probe_ftype dtrace_disable_probe)
+{
+ gdbarch->dtrace_disable_probe = dtrace_disable_probe;
+}
+
+int
gdbarch_has_global_solist (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 6e84004..e1c3b08 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -57,6 +57,7 @@ struct syscall;
struct agent_expr;
struct axs_value;
struct stap_parse_info;
+struct parser_state;
struct ravenscar_arch_ops;
struct elf_internal_linux_prpsinfo;
@@ -1182,6 +1183,41 @@ typedef int (gdbarch_stap_parse_special_token_ftype) (struct gdbarch *gdbarch, s
extern int gdbarch_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p);
extern void set_gdbarch_stap_parse_special_token (struct gdbarch *gdbarch, gdbarch_stap_parse_special_token_ftype *stap_parse_special_token);
+/* DTrace related functions.
+ The expression to compute the NARTGth+1 argument to a DTrace USDT probe.
+ NARG must be >= 0. */
+
+extern int gdbarch_dtrace_parse_probe_argument_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_dtrace_parse_probe_argument_ftype) (struct gdbarch *gdbarch, struct parser_state *pstate, int narg);
+extern void gdbarch_dtrace_parse_probe_argument (struct gdbarch *gdbarch, struct parser_state *pstate, int narg);
+extern void set_gdbarch_dtrace_parse_probe_argument (struct gdbarch *gdbarch, gdbarch_dtrace_parse_probe_argument_ftype *dtrace_parse_probe_argument);
+
+/* True if the given ADDR does not contain the instruction sequence
+ corresponding to a disabled DTrace is-enabled probe. */
+
+extern int gdbarch_dtrace_probe_is_enabled_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_dtrace_probe_is_enabled_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern int gdbarch_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void set_gdbarch_dtrace_probe_is_enabled (struct gdbarch *gdbarch, gdbarch_dtrace_probe_is_enabled_ftype *dtrace_probe_is_enabled);
+
+/* Enable a DTrace is-enabled probe at ADDR. */
+
+extern int gdbarch_dtrace_enable_probe_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_dtrace_enable_probe_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void gdbarch_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void set_gdbarch_dtrace_enable_probe (struct gdbarch *gdbarch, gdbarch_dtrace_enable_probe_ftype *dtrace_enable_probe);
+
+/* Disable a DTrace is-enabled probe at ADDR. */
+
+extern int gdbarch_dtrace_disable_probe_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_dtrace_disable_probe_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void gdbarch_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void set_gdbarch_dtrace_disable_probe (struct gdbarch *gdbarch, gdbarch_dtrace_disable_probe_ftype *dtrace_disable_probe);
+
/* True if the list of shared libraries is one and only for all
processes, as opposed to a list of shared libraries per inferior.
This usually means that all processes, although may or may not share
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index c785887..1119c4b 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -945,6 +945,21 @@ M:int:stap_is_single_operand:const char *s:s
# parser), and should advance the buffer pointer (p->arg).
M:int:stap_parse_special_token:struct stap_parse_info *p:p
+# DTrace related functions.
+
+# The expression to compute the NARTGth+1 argument to a DTrace USDT probe.
+# NARG must be >= 0.
+M:void:dtrace_parse_probe_argument:struct parser_state *pstate, int narg:pstate, narg
+
+# True if the given ADDR does not contain the instruction sequence
+# corresponding to a disabled DTrace is-enabled probe.
+M:int:dtrace_probe_is_enabled:CORE_ADDR addr:addr
+
+# Enable a DTrace is-enabled probe at ADDR.
+M:void:dtrace_enable_probe:CORE_ADDR addr:addr
+
+# Disable a DTrace is-enabled probe at ADDR.
+M:void:dtrace_disable_probe:CORE_ADDR addr:addr
# True if the list of shared libraries is one and only for all
# processes, as opposed to a list of shared libraries per inferior.
@@ -1147,6 +1162,7 @@ struct syscall;
struct agent_expr;
struct axs_value;
struct stap_parse_info;
+struct parser_state;
struct ravenscar_arch_ops;
struct elf_internal_linux_prpsinfo;
--
1.7.10.4
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-10 17:18 ` [PATCH V2 3/9] New commands `enable probe' and `disable probe' Jose E. Marchesi
@ 2014-10-10 18:15 ` Eli Zaretskii
2014-10-10 22:03 ` Doug Evans
2014-10-14 18:53 ` Sergio Durigan Junior
2 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2014-10-10 18:15 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
> From: "Jose E. Marchesi" <jose.marchesi@oracle.com>
> Date: Fri, 10 Oct 2014 19:22:46 +0200
>
> +Some probe points can be enabled and/or disabled. The effects
> +associated to enabling or disabling a probe depend on the type of
Just "the effect of enabling or disabling a probe" is enough, and much
more clear.
> +probe being handled. @code{SystemTap} probes do not support these
^^
Two spaces between sentences.
Also, I think we agreed to say SystemTap probes cannot be disabled.
> +@item enable probes @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
> +If given, @var{provider} is a regular expression used to match against
> +provider names when selecting which probes to enable. If omitted,
> +probes by all probes from all providers are enabled.
"Probes by all probes"? Something is wrong here.
Thanks.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 9/9] Announce the DTrace USDT probes support in NEWS.
2014-10-10 17:18 ` [PATCH V2 9/9] Announce the DTrace USDT probes support in NEWS Jose E. Marchesi
@ 2014-10-10 18:16 ` Eli Zaretskii
0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2014-10-10 18:16 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
> From: "Jose E. Marchesi" <jose.marchesi@oracle.com>
> Date: Fri, 10 Oct 2014 19:22:52 +0200
>
> This patch simply adds a small entry to `Changes since GDB 7.8' announcing the
> support for dtrace probes.
>
> gdb/ChangeLog:
>
> 2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
>
> * NEWS: Announce the support for DTrace SDT probes.
> ---
> gdb/ChangeLog | 4 ++++
> gdb/NEWS | 3 +++
> 2 files changed, 7 insertions(+)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index b56fe8e..518be28 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -45,6 +45,9 @@ queue-signal signal-name-or-number
> ** The -list-thread-groups command outputs an exit-code field for
> inferiors that have exited.
>
> +* GDB now has support for DTrace USDT (Userland Static Defined
> + Tracing) probes. The supported targets are x86_64-*-linux-gnu.
> +
OK, thanks.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 8/9] Documentation for DTrace USDT probes.
2014-10-10 17:18 ` [PATCH V2 8/9] Documentation for DTrace USDT probes Jose E. Marchesi
@ 2014-10-10 18:18 ` Eli Zaretskii
0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2014-10-10 18:18 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
> From: "Jose E. Marchesi" <jose.marchesi@oracle.com>
> Date: Fri, 10 Oct 2014 19:22:51 +0200
>
> This patch modifies the `Static Probe Points' section on the GDB
> manual in order to cover the support for DTrace USDT probes, in
> addition to SystemTap SDT probes.
Thanks.
> -Currently, @code{SystemTap} (@uref{http://sourceware.org/systemtap/})
> -@acronym{SDT} probes are supported on ELF-compatible systems. See
> +@itemize @bullet
> +@item @code{SystemTap} (@uref{http://sourceware.org/systemtap/})
> +@acronym{SDT} probes@footnote{See
> @uref{http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps}
> -for more information on how to add @code{SystemTap} @acronym{SDT} probes
> -in your applications.
> +for more information on how to add @code{SystemTap} @acronym{SDT}
> +probes in your applications.}. @code{SystemTap} probes are usable
> +from assembly, C and C@t{++} languages@footnote{See
> +@uref{http://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation}
> +for a good reference on how the @acronym{SDT} probes are implemented.}.
> +@item @code{DTrace} (@uref{http://oss.oracle.com/projects/DTrace})
> +@acronym{USDT} probes. @code{DTrace} probes are usable from C and
> +C@t{++} languages.
> +@end itemize
Please insert an empty line before each @item in the above list.
> +the semaphore. @code{DTrace} probes do not support the notion of
> +semaphores. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^
I thought we agreed on a different wording of this.
> +probe being handled. Some @code{DTrace} probes can be enabled or
> +disabled, but @code{SystemTap} probes do not support these notions.
Likewise here.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-10 17:18 ` [PATCH V2 3/9] New commands `enable probe' and `disable probe' Jose E. Marchesi
2014-10-10 18:15 ` Eli Zaretskii
@ 2014-10-10 22:03 ` Doug Evans
2014-10-11 6:35 ` Jose E. Marchesi
2014-10-11 17:04 ` Sergio Durigan Junior
2014-10-14 18:53 ` Sergio Durigan Junior
2 siblings, 2 replies; 40+ messages in thread
From: Doug Evans @ 2014-10-10 22:03 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
Jose E. Marchesi writes:
> This patch adds the above-mentioned commands to the generic probe
> abstraction implemented in probe.[ch]. The effects associated to
> enabling or disabling a probe depend on the type of probe being
> handled, and is triggered by invoking two back-end hooks in
> `probe_ops'.
>
> In case some particular probe type does not support the notion of
> enabling and/or disabling, the corresponding fields on `probe_ops' can
> be initialized to NULL. This is the case of SystemTap probes.
>
> gdb/ChangeLog:
>
> 2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
>
> * stap-probe.c (stap_probe_ops): Add NULLs in the static
> stap_probe_ops for `enable_probe' and `disable_probe'.
> * probe.c (enable_probes_command): New function.
> (disable_probes_command): Likewise.
> (_initialize_probe): Define the cli commands `enable probe' and
> `disable probe'.
> (parse_probe_linespec): New function.
> (info_probes_for_ops): Use parse_probe_linespec.
> * probe.h (probe_ops): New hooks `enable_probe' and
> `disable_probe'.
>
> gdb/doc/ChangeLog:
>
> 2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
>
> * gdb.texinfo (Static Probe Points): Cover the `enable probe' and
> `disable probe' commands.
Hi.
Would it be useful to have "info probes" show
the enable/disable state of each probe?
Or at least know which ones have been disabled.
I can imagine wanting to know this information if something
wasn't working the way I expected.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-10 22:03 ` Doug Evans
@ 2014-10-11 6:35 ` Jose E. Marchesi
2014-10-13 16:41 ` Doug Evans
2014-10-17 0:36 ` Pedro Alves
2014-10-11 17:04 ` Sergio Durigan Junior
1 sibling, 2 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-11 6:35 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches
Hi Doug.
Would it be useful to have "info probes" show
the enable/disable state of each probe?
Or at least know which ones have been disabled.
Right, `info probes' actually tells you the "Enabled" status of the
probes, provided there is at least one dtrace probe in the executable.
For example:
(gdb) info probes
Provider Name Where Semaphore Enabled Object
demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
In the example above demo:am-main is a systemtap probe, for which
"Enabled" reads n/a. demo:another is a dtrace probe which cannot be
disabled (it does not have any associated enabler) and
demo:progress-counter is a dtrace probe which is disabled.
This is the source code used for the example above:
#include "stap-sdt.h"
#include "demo.h"
int main(int argc, char *argv[]) {
int i=0;
long int foo = 666;
char *jaja = "oh yeah";
while (i < 10) {
i++;
if (DEMO_PROGRESS_COUNTER_ENABLED())
DEMO_PROGRESS_COUNTER (i, foo, jaja);
DEMO_ANOTHER (i);
}
STAP_PROBE3(demo, am-main, i, foo, jaja);
i = 0;
}
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-10 22:03 ` Doug Evans
2014-10-11 6:35 ` Jose E. Marchesi
@ 2014-10-11 17:04 ` Sergio Durigan Junior
1 sibling, 0 replies; 40+ messages in thread
From: Sergio Durigan Junior @ 2014-10-11 17:04 UTC (permalink / raw)
To: Doug Evans; +Cc: Jose E. Marchesi, gdb-patches
On Friday, October 10 2014, Doug Evans wrote:
> Would it be useful to have "info probes" show
> the enable/disable state of each probe?
> Or at least know which ones have been disabled.
>
> I can imagine wanting to know this information if something
> wasn't working the way I expected.
The patch does that already. :-)
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-11 6:35 ` Jose E. Marchesi
@ 2014-10-13 16:41 ` Doug Evans
2014-10-14 19:02 ` Sergio Durigan Junior
2014-10-17 0:36 ` Pedro Alves
1 sibling, 1 reply; 40+ messages in thread
From: Doug Evans @ 2014-10-13 16:41 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
On Fri, Oct 10, 2014 at 11:39 PM, Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
> Hi Doug.
>
> Would it be useful to have "info probes" show
> the enable/disable state of each probe?
> Or at least know which ones have been disabled.
>
> Right, `info probes' actually tells you the "Enabled" status of the
> probes, provided there is at least one dtrace probe in the executable.
> For example:
>
> (gdb) info probes
> Provider Name Where Semaphore Enabled Object
> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
> demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
> demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
Thanks. I couldn't find it, where should I look?
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-10 17:18 ` [PATCH V2 3/9] New commands `enable probe' and `disable probe' Jose E. Marchesi
2014-10-10 18:15 ` Eli Zaretskii
2014-10-10 22:03 ` Doug Evans
@ 2014-10-14 18:53 ` Sergio Durigan Junior
2014-10-15 13:28 ` Jose E. Marchesi
2 siblings, 1 reply; 40+ messages in thread
From: Sergio Durigan Junior @ 2014-10-14 18:53 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
Hi Jose,
Thanks for the v2! Looks great. Just a minor nit.
On Friday, October 10 2014, Jose E. Marchesi wrote:
> diff --git a/gdb/probe.c b/gdb/probe.c
> index 69ca0aa..c548b27 100644
> --- a/gdb/probe.c
> +++ b/gdb/probe.c
> @@ -527,6 +527,24 @@ exists_probe_with_pops (VEC (bound_probe_s) *probes,
> return 0;
> }
>
> +/* Helper function that parses a probe linespec of the form [PROVIDER
> + [PROBE [OBJNAME]]] from the provided string STR. */
> +
> +static void
> +parse_probe_linespec (const char *str, char **provider,
> + char **probe_name, char **objname)
> +{
> + *probe_name = *objname = NULL;
> +
> + *provider = extract_arg_const (&str);
> + if (*provider)
Ops, another implicit comparison :-).
> + {
> + *probe_name = extract_arg_const (&str);
> + if (*probe_name)
Here too.
> + *objname = extract_arg_const (&str);
> + }
> +}
> +
Looks good to me otherwise.
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 5/9] New probe type: DTrace USDT probes.
2014-10-10 17:18 ` [PATCH V2 5/9] New probe type: DTrace USDT probes Jose E. Marchesi
@ 2014-10-14 19:01 ` Sergio Durigan Junior
2014-10-15 13:28 ` Jose E. Marchesi
0 siblings, 1 reply; 40+ messages in thread
From: Sergio Durigan Junior @ 2014-10-14 19:01 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
Thanks for the patch, Jose. I just have a few comments.
On Friday, October 10 2014, Jose E. Marchesi wrote:
> diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
> new file mode 100644
> index 0000000..e94f66b
> --- /dev/null
> +++ b/gdb/dtrace-probe.c
> @@ -0,0 +1,854 @@
> +/* DTrace probe support for GDB.
> +
> + Copyright (C) 2014 Free Software Foundation, Inc.
> +
> + Contributed by Oracle, 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 "probe.h"
> +#include "vec.h"
> +#include "elf-bfd.h"
> +#include "gdbtypes.h"
> +#include "obstack.h"
> +#include "objfiles.h"
> +#include "complaints.h"
> +#include "value.h"
> +#include "ax.h"
> +#include "ax-gdb.h"
> +#include "language.h"
> +#include "parser-defs.h"
> +#include "inferior.h"
> +
> +/* The type of the ELF sections where we will find the DOF programs
> + with information about probes. */
> +
> +#ifndef SHT_SUNW_dof
> +# define SHT_SUNW_dof 0x6ffffff4
> +#endif
> +
> +/* Forward declaration. */
> +
> +static const struct probe_ops dtrace_probe_ops;
> +
> +/* The following structure represents a single argument for the
> + probe. */
> +
> +struct dtrace_probe_arg
> +{
> + /* The type of the probe argument. */
> + struct type *type;
> +
> + /* A string describing the type. */
> + char *type_str;
> +
> + /* The argument converted to an internal GDB expression. */
> + struct expression *expr;
> +};
> +
> +typedef struct dtrace_probe_arg dtrace_probe_arg_s;
> +DEF_VEC_O (dtrace_probe_arg_s);
> +
> +/* The following structure represents an enabler for a probe. */
> +
> +struct dtrace_probe_enabler
> +{
> + /* Program counter where the is-enabled probe is installed. The
> + contents (nops, whatever...) stored at this address are
> + architecture dependent. */
> + CORE_ADDR address;
> +};
> +
> +typedef struct dtrace_probe_enabler dtrace_probe_enabler_s;
> +DEF_VEC_O (dtrace_probe_enabler_s);
> +
> +/* The following structure represents a dtrace probe. */
> +
> +struct dtrace_probe
> +{
> + /* Generic information about the probe. This must be the first
> + element of this struct, in order to maintain binary compatibility
> + with the `struct probe' and be able to fully abstract it. */
> + struct probe p;
> +
> + /* A probe can have zero or more arguments. */
> + int probe_argc;
> + VEC (dtrace_probe_arg_s) *args;
> +
> + /* A probe can have zero or more "enablers" associated with it. */
> + VEC (dtrace_probe_enabler_s) *enablers;
> +
> + /* Whether the expressions for the arguments have been built. */
> + int args_expr_built : 1;
You want "unsigned int" here.
> +};
> +
> +/* Implementation of the probe_is_linespec method. */
> +
> +static int
> +dtrace_probe_is_linespec (const char **linespecp)
> +{
> + static const char *const keywords[] = { "-pdtrace", "-probe-dtrace", NULL };
> +
> + return probe_is_linespec_by_keyword (linespecp, keywords);
> +}
> +
> +/* DOF programs can contain an arbitrary number of sections of 26
> + different types. In order to support DTrace USDT probes we only
> + need to handle a subset of these section types, fortunately. These
> + section types are defined in the following enumeration.
> +
> + See linux/dtrace/dof_defines.h for a complete list of section types
> + along with their values. */
> +
> +enum dtrace_dof_sect_type
> +{
> + DTRACE_DOF_SECT_TYPE_NONE = 0, /* Null section. */
> + DTRACE_DOF_SECT_TYPE_ECBDESC = 3, /* A dof_ecbdesc_t. */
> + DTRACE_DOF_SECT_TYPE_STRTAB = 8, /* A string table. */
> + DTRACE_DOF_SECT_TYPE_PROVIDER = 15, /* A dof_provider_t */
> + DTRACE_DOF_SECT_TYPE_PROBES = 16, /* Array of dof_probe_t */
> + DTRACE_DOF_SECT_TYPE_PRARGS = 17, /* An array of probe arg
> + mappings. */
> + DTRACE_DOF_SECT_TYPE_PROFFS = 18, /* An array of probe arg
> + offsets. */
> + DTRACE_DOF_SECT_TYPE_PRENOFFS = 26 /* An array of probe is-enabled
> + offsets. */
> +};
I think there is a convention we follow that says that comments should
go on top of each item. It would be nice if you did that :-).
> +
> +/* The following collection of data structures map the structure of
> + DOF entities. Again, we only cover the subset of DOF used to
> + implement USDT probes.
> +
> + See linux/dtrace/dof.h header for a complete list of data
> + structures. */
> +
> +/* Offsets to index the dofh_ident[] array defined below. */
> +
> +enum dtrace_dof_ident
> +{
> + DTRACE_DOF_ID_MAG0 = 0, /* First byte of the magic number. */
> + DTRACE_DOF_ID_MAG1 = 1, /* Second byte of the magic number. */
> + DTRACE_DOF_ID_MAG2 = 2, /* Third byte of the magic number. */
> + DTRACE_DOF_ID_MAG3 = 3, /* Fourth byte of the magic number. */
> + DTRACE_DOF_ID_ENCODING = 5 /* An enum_dof_encoding value. */
> +};
Likewise.
> +
> +/* Possible values for dofh_ident[DOF_ID_ENCODING]. */
> +
> +enum dtrace_dof_encoding
> +{
> + DTRACE_DOF_ENCODE_LSB = 1, /* The DOF program is little-endian. */
> + DTRACE_DOF_ENCODE_MSB = 2 /* The DOF program is big-endian. */
> +};
Likewise.
> +
> +/* A DOF header, which describes the contents of a DOF program: number
> + of sections, size, etc. */
> +
> +struct dtrace_dof_hdr
> +{
> + uint8_t dofh_ident[16]; /* Identification bytes (see above). */
> + uint32_t dofh_flags; /* File attribute flags (if any). */
> + uint32_t dofh_hdrsize; /* Size of file header in bytes. */
> + uint32_t dofh_secsize; /* Size of section header in bytes. */
> + uint32_t dofh_secnum; /* Number of section headers. */
> + uint64_t dofh_secoff; /* File offset of section headers. */
> + uint64_t dofh_loadsz; /* File size of loadable portion. */
> + uint64_t dofh_filesz; /* File size of entire DOF file. */
> + uint64_t dofh_pad; /* Reserved for future use. */
> +};
Likewise.
> +
> +/* A DOF section, whose contents depend on its type. The several
> + supported section types are described in the enum
> + dtrace_dof_sect_type above. */
> +
> +struct dtrace_dof_sect
> +{
> + uint32_t dofs_type; /* Section type (see the define above). */
> + uint32_t dofs_align; /* Section data memory alignment. */
> + uint32_t dofs_flags; /* Section flags (if any). */
> + uint32_t dofs_entsize; /* Size of section entry (if table). */
> + uint64_t dofs_offset; /* DOF + offset points to the section data. */
> + uint64_t dofs_size; /* Size of section data in bytes. */
> +};
Likewise.
> +
> +/* A DOF provider, which is the provider of a probe. */
> +
> +struct dtrace_dof_provider
> +{
> + uint32_t dofpv_strtab; /* Link to a DTRACE_DOF_SECT_TYPE_STRTAB section. */
> + uint32_t dofpv_probes; /* Link to a DTRACE_DOF_SECT_TYPE_PROBES section. */
> + uint32_t dofpv_prargs; /* Link to a DTRACE_DOF_SECT_TYPE_PRARGS section. */
> + uint32_t dofpv_proffs; /* Link to a DTRACE_DOF_SECT_TYPE_PROFFS section. */
> + uint32_t dofpv_name; /* Provider name string. */
> + uint32_t dofpv_provattr; /* Provider attributes. */
> + uint32_t dofpv_modattr; /* Module attributes. */
> + uint32_t dofpv_funcattr; /* Function attributes. */
> + uint32_t dofpv_nameattr; /* Name attributes. */
> + uint32_t dofpv_argsattr; /* Args attributes. */
> + uint32_t dofpv_prenoffs; /* Link to a DTRACE_DOF_SECT_PRENOFFS section. */
> +};
Likewise.
> +
> +/* A set of DOF probes and is-enabled probes sharing a base address
> + and several attributes. The particular locations and attributes of
> + each probe are maintained in arrays in several other DOF sections.
> + See the comment in dtrace_process_dof_probe for details on how
> + these attributes are stored. */
> +
> +struct dtrace_dof_probe
> +{
> + uint64_t dofpr_addr; /* Probe base address or offset. */
> + uint32_t dofpr_func; /* Probe function string. */
> + uint32_t dofpr_name; /* Probe name string. */
> + uint32_t dofpr_nargv; /* Native argument type strings. */
> + uint32_t dofpr_xargv; /* Translated argument type strings. */
> + uint32_t dofpr_argidx; /* Index of first argument mapping. */
> + uint32_t dofpr_offidx; /* Index of first offset entry. */
> + uint8_t dofpr_nargc; /* Native argument count. */
> + uint8_t dofpr_xargc; /* Translated argument count. */
> + uint16_t dofpr_noffs; /* Number of offset entries for probe. */
> + uint32_t dofpr_enoffidx; /* Index of first is-enabled offset. */
> + uint16_t dofpr_nenoffs; /* Number of is-enabled offsets. */
> + uint16_t dofpr_pad1; /* Reserved for future use. */
> + uint32_t dofpr_pad2; /* Reserved for future use. */
> +};
Likewise.
> +
> +/* DOF supports two different encodings: MSB (big-endian) and LSB
> + (little-endian). The encoding is itself encoded in the DOF header.
> + The following function returns an unsigned value in the host
> + endianness. */
> +
> +#define DOF_UINT(dof, field) \
> + extract_unsigned_integer ((gdb_byte *) &(field), \
> + sizeof ((field)), \
> + (((dof)->dofh_ident[DTRACE_DOF_ID_ENCODING] \
> + == DTRACE_DOF_ENCODE_MSB) \
> + ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE))
> +
> +/* The following macro applies a given byte offset to a DOF (a pointer
> + to a dtrace_dof_hdr structure) and returns the resulting
> + address. */
> +
> +#define DTRACE_DOF_PTR(dof, offset) (&((char *) (dof))[(offset)])
> +
> +/* The following macro returns a pointer to the beginning of a given
> + section in a DOF object. The section is referred to by its index
> + in the sections array. */
> +
> +#define DTRACE_DOF_SECT(dof, idx) \
> + ((struct dtrace_dof_sect *) \
> + DTRACE_DOF_PTR ((dof), \
> + DOF_UINT ((dof), (dof)->dofh_secoff) \
> + + ((idx) * DOF_UINT ((dof), (dof)->dofh_secsize))))
> +
> +/* Helper function to examine the probe described by the given PROBE
> + and PROVIDER data structures and add it to the PROBESP vector.
> + STRTAB, OFFTAB, EOFFTAB and ARGTAB are pointers to tables in the
> + DOF program containing the attributes for the probe. */
> +
> +static void
> +dtrace_process_dof_probe (struct objfile *objfile,
> + struct gdbarch *gdbarch, VEC (probe_p) **probesp,
> + struct dtrace_dof_hdr *dof,
> + struct dtrace_dof_probe *probe,
> + struct dtrace_dof_provider *provider,
> + char *strtab, char *offtab, char *eofftab,
> + char *argtab, uint64_t strtab_size)
> +{
> + int i, j, num_probes, num_enablers;
> + VEC (dtrace_probe_enabler_s) *enablers;
> + char *p;
> +
> + /* Each probe section can define zero or more probes of two
> + different types:
> +
> + - probe->dofpr_noffs regular probes whose program counters are
> + stored in 32bit words starting at probe->dofpr_addr +
> + offtab[probe->dofpr_offidx].
> +
> + - probe->dofpr_nenoffs is-enabled probes whose program counters
> + are stored in 32bit words starting at probe->dofpr_addr +
> + eofftab[probe->dofpr_enoffidx].
> +
> + However is-enabled probes are not probes per-se, but an
> + optimization hack that is implemented in the kernel in a very
> + similar way than normal probes. This is how we support
> + is-enabled probes on GDB:
> +
> + - Our probes are always DTrace regular probes.
> +
> + - Our probes can be associated with zero or more "enablers". The
> + list of enablers is built from the is-enabled probes defined in
> + the Probe section.
> +
> + - Probes having a non-empty list of enablers can be enabled or
> + disabled using the `enable probe' and `disable probe' commands
> + respectively. The `Enabled' column in the output of `info
> + probes' will read `yes' if the enablers are activated, `no'
> + otherwise.
> +
> + - Probes having an empty list of enablers are always enabled.
> + The `Enabled' column in the output of `info probes' will
> + read `always'.
> +
> + It follows that if there are DTrace is-enabled probes defined for
> + some provider/name but no DTrace regular probes defined then the
> + GDB user wont be able to enable/disable these conditionals. */
> +
> + num_probes = DOF_UINT (dof, probe->dofpr_noffs);
> + if (num_probes == 0)
> + return;
> +
> + /* Build the list of enablers for the probes defined in this Probe
> + DOF section. */
> + enablers = NULL;
> + num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs);
> + for (i = 0; i < num_enablers; i++)
> + {
> + struct dtrace_probe_enabler enabler;
> + uint32_t enabler_offset
> + = ((uint32_t *) eofftab)[DOF_UINT (dof, probe->dofpr_enoffidx) + i];
> +
> + enabler.address = DOF_UINT (dof, probe->dofpr_addr)
> + + DOF_UINT (dof, enabler_offset);
> + VEC_safe_push (dtrace_probe_enabler_s, enablers, &enabler);
> + }
> +
> + for (i = 0; i < num_probes; i++)
> + {
> + uint32_t probe_offset
> + = ((uint32_t *) offtab)[DOF_UINT (dof, probe->dofpr_offidx) + i];
> + struct dtrace_probe *ret
> + = obstack_alloc (&objfile->per_bfd->storage_obstack, sizeof (*ret));
> +
> + ret->p.pops = &dtrace_probe_ops;
> + ret->p.arch = gdbarch;
> + ret->args_expr_built = 0;
> +
> + /* Set the provider and the name of the probe. */
> + ret->p.provider
> + = xstrdup (strtab + DOF_UINT (dof, provider->dofpv_name));
> + ret->p.name = xstrdup (strtab + DOF_UINT (dof, probe->dofpr_name));
> +
> + /* The probe address. */
> + ret->p.address
> + = DOF_UINT (dof, probe->dofpr_addr) + DOF_UINT (dof, probe_offset);
> +
> + /* Number of arguments in the probe. */
> + ret->probe_argc = DOF_UINT (dof, probe->dofpr_nargc);
> +
> + /* Store argument type descriptions. A description of the type
> + of the argument is in the (J+1)th null-terminated string
> + starting at 'strtab' + 'probe->dofpr_nargv'. */
> + ret->args = NULL;
> + p = strtab + DOF_UINT (dof, probe->dofpr_nargv);
> + for (j = 0; j < ret->probe_argc; j++)
> + {
> + struct dtrace_probe_arg arg;
> + struct expression *expr;
> +
> + arg.type_str = xstrdup (p);
> +
> + /* Use strtab_size as a sentinel. */
> + while (*p++ != '\0' && p - strtab < strtab_size);
> +
> + /* Try to parse a type expression from the type string. If
> + this does not work then we set the type to `long
> + int'. */
> + arg.type = builtin_type (gdbarch)->builtin_long;
> + expr = parse_expression (arg.type_str);
> + if (expr->elts[0].opcode == OP_TYPE)
> + arg.type = expr->elts[1].type;
> +
> + VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg);
> + }
> +
> + /* Add the vector of enablers to this probe, if any. */
> + ret->enablers = enablers;
> +
> + /* Successfully created probe. */
> + VEC_safe_push (probe_p, *probesp, (struct probe *) ret);
> + }
> +}
> +
> +/* Helper function to collect the probes described in the DOF program
> + whose header is pointed by DOF and add them to the PROBESP vector.
> + SECT is the ELF section containing the DOF program and OBJFILE is
> + its containing object file. */
> +
> +static void
> +dtrace_process_dof (asection *sect, struct objfile *objfile,
> + VEC (probe_p) **probesp, struct dtrace_dof_hdr *dof)
> +{
> + bfd *abfd = objfile->obfd;
> + int size = bfd_get_arch_size (abfd) / 8;
> + struct gdbarch *gdbarch = get_objfile_arch (objfile);
> + struct dtrace_dof_sect *section;
> + int i;
> +
> + /* The first step is to check for the DOF magic number. If no valid
> + DOF data is found in the section then a complaint is issued to
> + the user and the section skipped. */
> + if (dof->dofh_ident[DTRACE_DOF_ID_MAG0] != 0x7F
> + || dof->dofh_ident[DTRACE_DOF_ID_MAG1] != 'D'
> + || dof->dofh_ident[DTRACE_DOF_ID_MAG2] != 'O'
> + || dof->dofh_ident[DTRACE_DOF_ID_MAG3] != 'F')
> + goto invalid_dof_data;
> +
> + /* Make sure this DOF is not an enabling DOF, i.e. there are no ECB
> + Description sections. */
> + section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
> + DOF_UINT (dof, dof->dofh_secoff));
> + for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
> + if (section->dofs_type == DTRACE_DOF_SECT_TYPE_ECBDESC)
> + return;
> +
> + /* Iterate over any section of type Provider and extract the probe
> + information from them. If there are no "provider" sections on
> + the DOF then we just return. */
> + section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
> + DOF_UINT (dof, dof->dofh_secoff));
> + for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
> + if (DOF_UINT (dof, section->dofs_type) == DTRACE_DOF_SECT_TYPE_PROVIDER)
> + {
> + struct dtrace_dof_provider *provider = (struct dtrace_dof_provider *)
> + DTRACE_DOF_PTR (dof, DOF_UINT (dof, section->dofs_offset));
> + struct dtrace_dof_sect *strtab_s
> + = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_strtab));
> + struct dtrace_dof_sect *probes_s
> + = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_probes));
> + struct dtrace_dof_sect *args_s
> + = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prargs));
> + struct dtrace_dof_sect *offsets_s
> + = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_proffs));
> + struct dtrace_dof_sect *eoffsets_s
> + = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prenoffs));
> + char *strtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, strtab_s->dofs_offset));
> + char *offtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, offsets_s->dofs_offset));
> + char *eofftab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, eoffsets_s->dofs_offset));
> + char *argtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, args_s->dofs_offset));
> + unsigned int entsize = DOF_UINT (dof, probes_s->dofs_entsize);
> + int num_probes;
> +
> + /* Very, unlikely, but could crash gdb if not handled
> + properly. */
> + if (entsize == 0)
> + goto invalid_dof_data;
> +
> + num_probes = DOF_UINT (dof, probes_s->dofs_size) / entsize;
> +
> + for (i = 0; i < num_probes; i++)
> + {
> + struct dtrace_dof_probe *probe = (struct dtrace_dof_probe *)
> + DTRACE_DOF_PTR (dof, DOF_UINT (dof, probes_s->dofs_offset)
> + + (i * DOF_UINT (dof, probes_s->dofs_entsize)));
> +
> + dtrace_process_dof_probe (objfile,
> + gdbarch, probesp,
> + dof, probe,
> + provider, strtab, offtab, eofftab, argtab,
> + DOF_UINT (dof, strtab_s->dofs_size));
> + }
> + }
> +
> + return;
> +
> + invalid_dof_data:
> + complaint (&symfile_complaints,
> + _("skipping section '%s' which does not contain valid DOF data."),
> + sect->name);
> +}
> +
> +/* Helper function to build the GDB internal expressiosn that, once
> + evaluated, will calculate the values of the arguments of a given
> + PROBE. */
> +
> +static void
> +dtrace_build_arg_exprs (struct dtrace_probe *probe,
> + struct gdbarch *gdbarch)
> +{
> + struct parser_state pstate;
> + struct dtrace_probe_arg *arg;
> + int i;
> +
> + probe->args_expr_built = 1;
> +
> + /* Iterate over the arguments in the probe and build the
> + corresponding GDB internal expression that will generate the
> + value of the argument when executed at the PC of the probe. */
> + for (i = 0; i < probe->probe_argc; i++)
> + {
> + struct cleanup *back_to;
> +
> + arg = VEC_index (dtrace_probe_arg_s, probe->args, i);
> +
> + /* Initialize the expression buffer in the parser state. The
> + language does not matter, since we are using our own
> + parser. */
> + initialize_expout (&pstate, 10, current_language, gdbarch);
> + back_to = make_cleanup (free_current_contents, &pstate.expout);
> +
> + /* The argument value, which is ABI dependent and casted to
> + `long int'. */
> + gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, i);
> +
> + discard_cleanups (back_to);
> +
> + /* Casting to the expected type, but only if the type was
> + recognized at probe load time. Otherwise the argument will
> + be evaluated as the long integer passed to the probe. */
> + if (arg->type != NULL)
> + {
> + write_exp_elt_opcode (&pstate, UNOP_CAST);
> + write_exp_elt_type (&pstate, arg->type);
> + write_exp_elt_opcode (&pstate, UNOP_CAST);
> + }
> +
> + reallocate_expout (&pstate);
> + arg->expr = pstate.expout;
> + prefixify_expression (arg->expr);
> + }
> +}
> +
> +/* Helper function to return the Nth argument of a given PROBE. */
> +
> +static struct dtrace_probe_arg *
> +dtrace_get_arg (struct dtrace_probe *probe, unsigned n,
> + struct gdbarch *gdbarch)
> +{
> + if (!probe->args_expr_built)
> + dtrace_build_arg_exprs (probe, gdbarch);
> +
> + return VEC_index (dtrace_probe_arg_s, probe->args, n);
> +}
> +
> +/* Implementation of the get_probes method. */
> +
> +static void
> +dtrace_get_probes (VEC (probe_p) **probesp, struct objfile *objfile)
> +{
> + bfd *abfd = objfile->obfd;
> + asection *sect = NULL;
> +
> + /* Do nothing in case this is a .debug file, instead of the objfile
> + itself. */
> + if (objfile->separate_debug_objfile_backlink != NULL)
> + return;
> +
> + /* Iterate over the sections in OBJFILE looking for DTrace
> + information. */
> + for (sect = abfd->sections; sect != NULL; sect = sect->next)
> + {
> + if (elf_section_data (sect)->this_hdr.sh_type == SHT_SUNW_dof)
> + {
> + struct dtrace_dof_hdr *dof;
> +
> + /* Read the contents of the DOF section and then process it to
> + extract the information of any probe defined into it. */
> + if (!bfd_malloc_and_get_section (abfd, sect, (bfd_byte **) &dof))
> + complaint (&symfile_complaints,
> + _("could not obtain the contents of"
> + "section '%s' in objfile `%s'."),
> + sect->name, abfd->filename);
> +
> + dtrace_process_dof (sect, objfile, probesp, dof);
> + xfree (dof);
> + }
> + }
> +}
> +
> +/* Helper function to determine whether a given probe is "enabled" or
> + "disabled". A disabled probe is a probe in which one or more
> + enablers are disabled. */
> +
> +static int
> +dtrace_probe_is_enabled (struct dtrace_probe *probe)
> +{
> + int i;
> + struct gdbarch *gdbarch = probe->p.arch;
> + struct dtrace_probe_enabler *enabler;
> +
> + for (i = 0;
> + VEC_iterate (dtrace_probe_enabler_s, probe->enablers, i, enabler);
> + i++)
> + if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler->address))
> + return 0;
> +
> + return 1;
> +}
> +
> +/* Implementation of the get_probe_address method. */
> +
> +static CORE_ADDR
> +dtrace_get_probe_address (struct probe *probe, struct objfile *objfile)
> +{
> + gdb_assert (probe->pops == &dtrace_probe_ops);
> + return probe->address + ANOFFSET (objfile->section_offsets,
> + SECT_OFF_DATA (objfile));
> +}
> +
> +/* Implementation of the get_probe_argument_count method. */
> +
> +static unsigned
> +dtrace_get_probe_argument_count (struct probe *probe_generic,
> + struct frame_info *frame)
> +{
> + struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
> +
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> + return dtrace_probe->probe_argc;
> +}
> +
> +/* Implementation of the can_evaluate_probe_arguments method. */
> +
> +static int
> +dtrace_can_evaluate_probe_arguments (struct probe *probe_generic)
> +{
> + struct gdbarch *gdbarch = probe_generic->arch;
> +
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> + return gdbarch_dtrace_parse_probe_argument_p (gdbarch);
> +}
> +
> +/* Implementation of the evaluate_probe_argument method. */
> +
> +static struct value *
> +dtrace_evaluate_probe_argument (struct probe *probe_generic, unsigned n,
> + struct frame_info *frame)
> +{
> + struct gdbarch *gdbarch = probe_generic->arch;
> + struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
> + struct dtrace_probe_arg *arg;
> + int pos = 0;
> +
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> + arg = dtrace_get_arg (dtrace_probe, n, gdbarch);
> + return evaluate_subexp_standard (arg->type, arg->expr, &pos, EVAL_NORMAL);
> +}
> +
> +/* Implementation of the compile_to_ax method. */
> +
> +static void
> +dtrace_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
> + struct axs_value *value, unsigned n)
> +{
> + struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
> + struct dtrace_probe_arg *arg;
> + union exp_element *pc;
> +
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> + arg = dtrace_get_arg (dtrace_probe, n, expr->gdbarch);
> +
> + pc = arg->expr->elts;
> + gen_expr (arg->expr, &pc, expr, value);
> +
> + require_rvalue (expr, value);
> + value->type = arg->type;
> +}
> +
> +/* Implementation of the set_semaphore method. */
> +
> +static void
> +dtrace_set_semaphore (struct probe *probe_generic, struct objfile *objfile,
> + struct gdbarch *gdbarch)
> +{
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +}
> +
> +/* Implementation of the clear_semaphore method. */
> +
> +static void
> +dtrace_clear_semaphore (struct probe *probe_generic, struct objfile *objfile,
> + struct gdbarch *gdbarch)
> +{
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +}
> +
> +/* Implementation of the probe_destroy method. */
> +
> +static void
> +dtrace_probe_destroy (struct probe *probe_generic)
> +{
> + struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
> + struct dtrace_probe_arg *arg;
> + int i;
> +
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> + for (i = 0; VEC_iterate (dtrace_probe_arg_s, probe->args, i, arg); i++)
> + {
> + xfree (arg->type_str);
> + xfree (arg->expr);
> + }
> +
> + VEC_free (dtrace_probe_enabler_s, probe->enablers);
> + VEC_free (dtrace_probe_arg_s, probe->args);
> +}
> +
> +/* Implementation of the gen_info_probes_table_header method. */
> +
> +static void
> +dtrace_gen_info_probes_table_header (VEC (info_probe_column_s) **heads)
> +{
> + info_probe_column_s dtrace_probe_column;
> +
> + dtrace_probe_column.field_name = "enabled";
> + dtrace_probe_column.print_name = _("Enabled");
> +
> + VEC_safe_push (info_probe_column_s, *heads, &dtrace_probe_column);
> +}
> +
> +/* Implementation of the gen_info_probes_table_values method. */
> +
> +static void
> +dtrace_gen_info_probes_table_values (struct probe *probe_generic,
> + VEC (const_char_ptr) **ret)
> +{
> + struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
> + const char *val = NULL;
> +
> + gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> + if (VEC_empty (dtrace_probe_enabler_s, probe->enablers))
> + val = "always";
> + else if (!gdbarch_dtrace_probe_is_enabled_p (probe_generic->arch))
> + val = "unknown";
> + else if (dtrace_probe_is_enabled (probe))
> + val = "yes";
> + else
> + val = "no";
> +
> + VEC_safe_push (const_char_ptr, *ret, val);
> +}
> +
> +/* Implementation of the enable_probe method. */
> +
> +static void
> +dtrace_enable_probe (struct probe *probe)
> +{
> + struct gdbarch *gdbarch = probe->arch;
> + struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
> + struct dtrace_probe_enabler *enabler;
> + int i;
> +
> + gdb_assert (probe->pops == &dtrace_probe_ops);
> +
> + /* Enabling a dtrace probe implies patching the text section of the
> + running process, so make sure the inferior is indeed running. */
> + if (ptid_equal (inferior_ptid, null_ptid))
> + error (_("No inferior running"));
> +
> + /* Fast path. */
> + if (dtrace_probe_is_enabled (dtrace_probe))
> + return;
> +
> + /* Iterate over all defined enabler in the given probe and enable
> + them all using the corresponding gdbarch hook. */
> +
> + for (i = 0;
> + VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
> + i++)
> + if (gdbarch_dtrace_enable_probe_p (gdbarch))
> + gdbarch_dtrace_enable_probe (gdbarch, enabler->address);
> +}
> +
> +
> +/* Implementation of the disable_probe method. */
> +
> +static void
> +dtrace_disable_probe (struct probe *probe)
> +{
> + struct gdbarch *gdbarch = probe->arch;
> + struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
> + struct dtrace_probe_enabler *enabler;
> + int i;
> +
> + gdb_assert (probe->pops == &dtrace_probe_ops);
> +
> + /* Disabling a dtrace probe implies patching the text section of the
> + running process, so make sure the inferior is indeed running. */
> + if (ptid_equal (inferior_ptid, null_ptid))
> + error (_("No inferior running"));
> +
> + /* Fast path. */
> + if (!dtrace_probe_is_enabled (dtrace_probe))
> + return;
> +
> + /* Are we trying to disable a probe that does not have any enabler
> + associated? */
> + if (VEC_empty (dtrace_probe_enabler_s, dtrace_probe->enablers))
> + error (_("Probe %s:%s cannot be disabled."), probe->provider, probe->name);
> +
> + /* Iterate over all defined enabler in the given probe and disable
> + them all using the corresponding gdbarch hook. */
> +
> + for (i = 0;
> + VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
> + i++)
> + {
> + if (gdbarch_dtrace_disable_probe_p (gdbarch))
> + gdbarch_dtrace_disable_probe (gdbarch, enabler->address);
> + }
> +}
> +
> +/* DTrace probe_ops. */
> +
> +static const struct probe_ops dtrace_probe_ops =
> +{
> + dtrace_probe_is_linespec,
> + dtrace_get_probes,
> + dtrace_get_probe_address,
> + dtrace_get_probe_argument_count,
> + dtrace_can_evaluate_probe_arguments,
> + dtrace_evaluate_probe_argument,
> + dtrace_compile_to_ax,
> + dtrace_set_semaphore,
> + dtrace_clear_semaphore,
> + dtrace_probe_destroy,
> + dtrace_gen_info_probes_table_header,
> + dtrace_gen_info_probes_table_values,
> + dtrace_enable_probe,
> + dtrace_disable_probe
> +};
> +
> +/* Implementation of the `info probes dtrace' command. */
> +
> +static void
> +info_probes_dtrace_command (char *arg, int from_tty)
> +{
> + info_probes_for_ops (arg, from_tty, &dtrace_probe_ops);
> +}
> +
> +void _initialize_dtrace_probe (void);
> +
> +void
> +_initialize_dtrace_probe (void)
> +{
> + VEC_safe_push (probe_ops_cp, all_probe_ops, &dtrace_probe_ops);
> +
> + add_cmd ("dtrace", class_info, info_probes_dtrace_command,
> + _("\
> +Show information about DTrace static probes.\n\
> +Usage: info probes dtrace [PROVIDER [NAME [OBJECT]]]\n\
> +Each argument is a regular expression, used to select probes.\n\
> +PROVIDER matches probe provider names.\n\
> +NAME matches the probe names.\n\
> +OBJECT matches the executable or shared library name."),
> + info_probes_cmdlist_get ());
> +}
> --
> 1.7.10.4
Otherwise, looks good to me (still waiting for the testcase, though
:-P).
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-13 16:41 ` Doug Evans
@ 2014-10-14 19:02 ` Sergio Durigan Junior
2014-10-17 0:07 ` Doug Evans
0 siblings, 1 reply; 40+ messages in thread
From: Sergio Durigan Junior @ 2014-10-14 19:02 UTC (permalink / raw)
To: Doug Evans; +Cc: Jose E. Marchesi, gdb-patches
On Monday, October 13 2014, Doug Evans wrote:
> On Fri, Oct 10, 2014 at 11:39 PM, Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>> Hi Doug.
>>
>> Would it be useful to have "info probes" show
>> the enable/disable state of each probe?
>> Or at least know which ones have been disabled.
>>
>> Right, `info probes' actually tells you the "Enabled" status of the
>> probes, provided there is at least one dtrace probe in the executable.
>> For example:
>>
>> (gdb) info probes
>> Provider Name Where Semaphore Enabled Object
>> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>> demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
>> demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
>
> Thanks. I couldn't find it, where should I look?
This is on patch 1/9.
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 5/9] New probe type: DTrace USDT probes.
2014-10-14 19:01 ` Sergio Durigan Junior
@ 2014-10-15 13:28 ` Jose E. Marchesi
0 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-15 13:28 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: gdb-patches
> +enum dtrace_dof_sect_type
> +{
> + DTRACE_DOF_SECT_TYPE_NONE = 0, /* Null section. */
> + DTRACE_DOF_SECT_TYPE_ECBDESC = 3, /* A dof_ecbdesc_t. */
> + DTRACE_DOF_SECT_TYPE_STRTAB = 8, /* A string table. */
> + DTRACE_DOF_SECT_TYPE_PROVIDER = 15, /* A dof_provider_t */
> + DTRACE_DOF_SECT_TYPE_PROBES = 16, /* Array of dof_probe_t */
> + DTRACE_DOF_SECT_TYPE_PRARGS = 17, /* An array of probe arg
> + mappings. */
> + DTRACE_DOF_SECT_TYPE_PROFFS = 18, /* An array of probe arg
> + offsets. */
> + DTRACE_DOF_SECT_TYPE_PRENOFFS = 26 /* An array of probe is-enabled
> + offsets. */
> +};
I think there is a convention we follow that says that comments should
go on top of each item. It would be nice if you did that :-).
I don't really have a strong preference of either style, so I changed
the comments in the enums and structs to go on top of the documented
item.
Otherwise, looks good to me (still waiting for the testcase, though
:-P).
I am working on that... patience :)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-14 18:53 ` Sergio Durigan Junior
@ 2014-10-15 13:28 ` Jose E. Marchesi
0 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-15 13:28 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: gdb-patches
> +/* Helper function that parses a probe linespec of the form [PROVIDER
> + [PROBE [OBJNAME]]] from the provided string STR. */
> +
> +static void
> +parse_probe_linespec (const char *str, char **provider,
> + char **probe_name, char **objname)
> +{
> + *probe_name = *objname = NULL;
> +
> + *provider = extract_arg_const (&str);
> + if (*provider)
Ops, another implicit comparison :-).
I changed these comparisons to be explicit.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-10 17:18 ` [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets Jose E. Marchesi
2014-10-16 22:07 ` Pedro Alves
@ 2014-10-16 22:07 ` Pedro Alves
2014-10-16 22:17 ` Pedro Alves
2 siblings, 0 replies; 40+ messages in thread
From: Pedro Alves @ 2014-10-16 22:07 UTC (permalink / raw)
To: Jose E. Marchesi, gdb-patches
> +amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
> +{
> + gdb_byte buf[5];
> + read_memory (addr - 3, buf, 5);
> +
> + /* The instruction sequence used in x86_64 machines for a disabled
> + is-enabled probe is:
> +
> + xor %rax, %rax => 48 33 C0
> + ADDR: nop => 90
> + nop => 90
> +
Please use read_code when reading code, so that these reads go through
the code cache.
> + /* We use the following instruction sequence for disabling an
> + is-enabled probe:
> +
> + xor %rax, %rax; nop; nop => 48 33 C0 90 90
> +
> + Note that ADDR is offset 3 bytes from the beginning of the
> + sequence. */
> +
> + gdb_byte buf[5];
> +
> + buf[0] = 0x48;
> + buf[1] = 0x33;
> + buf[2] = 0xc0;
> + buf[3] = 0x90;
> + buf[4] = 0x90;
> +
> + write_memory (addr - 3, buf, 5);
These code sequences are duplicated in lots of places.
Writing like this instead is both shorter and less error prone:
const gdb_byte buf[] = { 0x48, 0x33, 0xc0, 0x90, 0x90 };
write_memory (addr - 3, buf, sizeof (buf));
... and IMO eliminates the need to have the sequence duplicated in the
comment above.
Going further, we can make these sequences be globals, like:
/* The instruction sequences used in x86_64 machines for a
disabled is-enabled probe. */
const gdb_byte amd64_dtrace_disabled_probe_sequence_1[] = {
/* xor %rax, %rax */ 0x48, 0x33, 0xc0,
/* ADDR: nop */ 0x90,
/* nop */ 0x90
};
const gdb_byte amd64_dtrace_disabled_probe_sequence_2[] = {
/* xor %rax, %rax */ 0x48, 0x33, 0xc0,
/* ADDR: ret */ 0xc3,
/* nop */ 0x90
};
etc. And then instead of:
> +amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
> +{
> + gdb_byte buf[5];
> + read_memory (addr - 3, buf, 5);
> +
> + /* The instruction sequence used in x86_64 machines for a disabled
> + is-enabled probe is:
> +
> + xor %rax, %rax => 48 33 C0
> + ADDR: nop => 90
> + nop => 90
> +
> + or
> +
> + xor %rax, %rax => 48 33 C0
> + ADDR: ret => c3
> + nop => 90
> +
> + This function returns 1 if the instructions at ADDR do _not_
> + follow any of these patterns.
> +
> + Note that ADDR is offset 3 bytes from the beginning of these
> + sequences. */
> +
> + return !((buf[0] == 0x48) && (buf[1] == 0x33) && (buf[2] == 0xc0) /* xor */
> + && ((buf[3] == 0x90) || (buf[3] == 0xc3)) /* nop | ret */
> + && (buf[4] == 0x90)); /* nop */
> +}
Simply write:
amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
{
gdb_byte buf[5];
read_code (addr - 3, buf, 5);
return (memcmp (buf, amd64_dtrace_disabled_probe_sequence_1) != 0
&& memcmp (buf, amd64_dtrace_disabled_probe_sequence_2) != 0)
}
... etc.
Let the compiler worry about optimizing those memcmps if necessary.
> + static int arg_reg_map[6] =
write:
static const int arg_reg_map[] =
> + {
> + AMD64_RDI_REGNUM, /* Arg 1. */
> + AMD64_RSI_REGNUM, /* Arg 2. */
> + AMD64_RDX_REGNUM, /* Arg 3. */
> + AMD64_RCX_REGNUM, /* Arg 4. */
> + AMD64_R8_REGNUM, /* Arg 5. */
> + AMD64_R9_REGNUM /* Arg 6. */
> + };
+
+ /* DTrace probe arguments can be found on the ABI-defined places for
+ regular arguments at the current PC. The probe abstraction
+ currently supports up to 12 arguments for probes. */
+
+ if (narg < 6)
+ {
I'd suggest putting the arg_reg_map array within this if block.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-10 17:18 ` [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets Jose E. Marchesi
@ 2014-10-16 22:07 ` Pedro Alves
2014-10-17 12:35 ` Jose E. Marchesi
2014-10-16 22:07 ` Pedro Alves
2014-10-16 22:17 ` Pedro Alves
2 siblings, 1 reply; 40+ messages in thread
From: Pedro Alves @ 2014-10-16 22:07 UTC (permalink / raw)
To: Jose E. Marchesi, gdb-patches
> +amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
> +{
> + gdb_byte buf[5];
> + read_memory (addr - 3, buf, 5);
> +
> + /* The instruction sequence used in x86_64 machines for a disabled
> + is-enabled probe is:
> +
> + xor %rax, %rax => 48 33 C0
> + ADDR: nop => 90
> + nop => 90
> +
Please use read_code when reading code, so that these reads go through
the code cache.
> + /* We use the following instruction sequence for disabling an
> + is-enabled probe:
> +
> + xor %rax, %rax; nop; nop => 48 33 C0 90 90
> +
> + Note that ADDR is offset 3 bytes from the beginning of the
> + sequence. */
> +
> + gdb_byte buf[5];
> +
> + buf[0] = 0x48;
> + buf[1] = 0x33;
> + buf[2] = 0xc0;
> + buf[3] = 0x90;
> + buf[4] = 0x90;
> +
> + write_memory (addr - 3, buf, 5);
These code sequences are duplicated in lots of places.
Writing like this instead is both shorter and less error prone:
const gdb_byte buf[] = { 0x48, 0x33, 0xc0, 0x90, 0x90 };
write_memory (addr - 3, buf, sizeof (buf));
... and IMO eliminates the need to have the sequence duplicated in the
comment above.
Going further, we can make these sequences be globals, like:
/* The instruction sequences used in x86_64 machines for a
disabled is-enabled probe. */
const gdb_byte amd64_dtrace_disabled_probe_sequence_1[] = {
/* xor %rax, %rax */ 0x48, 0x33, 0xc0,
/* ADDR: nop */ 0x90,
/* nop */ 0x90
};
const gdb_byte amd64_dtrace_disabled_probe_sequence_2[] = {
/* xor %rax, %rax */ 0x48, 0x33, 0xc0,
/* ADDR: ret */ 0xc3,
/* nop */ 0x90
};
etc. And then instead of:
> +amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
> +{
> + gdb_byte buf[5];
> + read_memory (addr - 3, buf, 5);
> +
> + /* The instruction sequence used in x86_64 machines for a disabled
> + is-enabled probe is:
> +
> + xor %rax, %rax => 48 33 C0
> + ADDR: nop => 90
> + nop => 90
> +
> + or
> +
> + xor %rax, %rax => 48 33 C0
> + ADDR: ret => c3
> + nop => 90
> +
> + This function returns 1 if the instructions at ADDR do _not_
> + follow any of these patterns.
> +
> + Note that ADDR is offset 3 bytes from the beginning of these
> + sequences. */
> +
> + return !((buf[0] == 0x48) && (buf[1] == 0x33) && (buf[2] == 0xc0) /* xor */
> + && ((buf[3] == 0x90) || (buf[3] == 0xc3)) /* nop | ret */
> + && (buf[4] == 0x90)); /* nop */
> +}
Simply write:
amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
{
gdb_byte buf[5];
read_code (addr - 3, buf, 5);
return (memcmp (buf, amd64_dtrace_disabled_probe_sequence_1) != 0
&& memcmp (buf, amd64_dtrace_disabled_probe_sequence_2) != 0)
}
... etc.
Let the compiler worry about optimizing those memcmps if necessary.
> + static int arg_reg_map[6] =
write:
static const int arg_reg_map[] =
> + {
> + AMD64_RDI_REGNUM, /* Arg 1. */
> + AMD64_RSI_REGNUM, /* Arg 2. */
> + AMD64_RDX_REGNUM, /* Arg 3. */
> + AMD64_RCX_REGNUM, /* Arg 4. */
> + AMD64_R8_REGNUM, /* Arg 5. */
> + AMD64_R9_REGNUM /* Arg 6. */
> + };
+
+ /* DTrace probe arguments can be found on the ABI-defined places for
+ regular arguments at the current PC. The probe abstraction
+ currently supports up to 12 arguments for probes. */
+
+ if (narg < 6)
+ {
I'd suggest putting the arg_reg_map array within this if block.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-10 17:18 ` [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets Jose E. Marchesi
2014-10-16 22:07 ` Pedro Alves
2014-10-16 22:07 ` Pedro Alves
@ 2014-10-16 22:17 ` Pedro Alves
2 siblings, 0 replies; 40+ messages in thread
From: Pedro Alves @ 2014-10-16 22:17 UTC (permalink / raw)
To: Jose E. Marchesi, gdb-patches
I forgot:
On 10/10/2014 06:22 PM, Jose E. Marchesi wrote:
> 2014-10-10 Jose E. Marchesi <jose.marchesi@oracle.com>
>
> * amd64-linux-tdep.h: Prototypes for
> `amd64_dtrace_parse_probe_argument', `amd64_dtrace_enable_probe',
> `amd64_dtrace_disable_probe' and
> `gdbarch_dtrace_probe_is_enabled'.
Typo: gdbarch_dtrace_probe_is_enabled: gdbarch => amd64_dtrace.
Write it like this:
* amd64-linux-tdep.h (amd64_dtrace_parse_probe_argument)
(amd64_dtrace_enable_probe, amd64_dtrace_disable_probe)
(amd64_dtrace_probe_is_enabled): New declarations.
But, I don't see why these functions are extern, they're defined
and used in the same file. So make them static and don't touch
amd64-linux-tdep.h.
OTOH, does DTrace on Solaris use this exact same sequences?
If so, then better put these new functions somewhere
non-Linux-specific instead, like e.g., amd64-tdep.c.
> * amd64-linux-tdep.c (amd64_dtrace_parse_probe_argument): New function.
> (amd64_dtrace_probe_is_enabled): Likewise.
> (amd64_dtrace_enable_probe): Likewise.
> (amd64_dtrace_disable_probe): Likewise.
> (amd64_linux_init_abi): Register the
> `gdbarch_dtrace_probe_argument', `gdbarch_dtrace_enable_probe',
> `gdbarch_dtrace_disable_probe' and `gdbarch_dtrace_probe_is_enabled'.
Register the ... _hooks_?
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 7/9] Simple testsuite for DTrace USDT probes.
2014-10-10 17:18 ` [PATCH V2 7/9] Simple testsuite for DTrace USDT probes Jose E. Marchesi
@ 2014-10-16 22:36 ` Pedro Alves
2014-10-17 12:01 ` Jose E. Marchesi
0 siblings, 1 reply; 40+ messages in thread
From: Pedro Alves @ 2014-10-16 22:36 UTC (permalink / raw)
To: Jose E. Marchesi, gdb-patches
Hi Jose,
> + set result [catch "exec $dtrace -V" output]
Please use "remote_exec host" to invoke tools on the host.
> + set dscript_file "${srcdir}/${subdir}/${testfile}.d"
> + set out_header_file "${srcdir}/${subdir}/${testfile}.h"
Generating files in the ${srcdir} is a no-no.
Use standard_output_file to put this in the build dir, and to
make it parallel safe.
> + set result \
> + [catch "exec $dtrace -h -s $dscript_file -o $out_header_file" output]
> + verbose -log $output
> + if {$result != 0} {
> + fail "invoke dtrace -h to generate the header file for USDT probes"
> + return -1
> + }
> +
> + if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object {debug}] != ""} {
> + fail "compile ${binfile}.o"
> + return -1
> + }
> +
> + set result \
> + [catch "exec $dtrace -G -s $dscript_file ${binfile}.o -o ${binfile}-p.o" output]
> + verbose -log $output
> + if {$result != 0} {
> + fail "invoke dtrace -G to generate the object file with probe information"
> + return -1
> + }
> +
> + if {[gdb_compile "${binfile}.o ${binfile}-p.o" ${binfile} executable {debug}] != ""} {
> + fail "compile ${binfile}"
> + return -1
> + }
Seems like this routine may be general enough that it'd be reused for other
tests. How about putting it a new testsuite/lib/dtrace.exp file?
It's not usual that failure to compile generates a FAIL. Do we need that?
Instead, it's more usual for the caller of a routine that builds
the test to call "untested" on build failure.
> + gdb_test "break -pdtrace test:two-locations" \
> + "Breakpoint \[0-9\]+ at $hex.*2 locations.*" \
> + "set multii-location probe breakpoint (probe two-locations)"
typo "multii".
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-14 19:02 ` Sergio Durigan Junior
@ 2014-10-17 0:07 ` Doug Evans
0 siblings, 0 replies; 40+ messages in thread
From: Doug Evans @ 2014-10-17 0:07 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: Jose E. Marchesi, gdb-patches
On Tue, Oct 14, 2014 at 12:01 PM, Sergio Durigan Junior
<sergiodj@redhat.com> wrote:
> On Monday, October 13 2014, Doug Evans wrote:
>
>> On Fri, Oct 10, 2014 at 11:39 PM, Jose E. Marchesi
>> <jose.marchesi@oracle.com> wrote:
>>>
>>> Hi Doug.
>>>
>>> Would it be useful to have "info probes" show
>>> the enable/disable state of each probe?
>>> Or at least know which ones have been disabled.
>>>
>>> Right, `info probes' actually tells you the "Enabled" status of the
>>> probes, provided there is at least one dtrace probe in the executable.
>>> For example:
>>>
>>> (gdb) info probes
>>> Provider Name Where Semaphore Enabled Object
>>> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>>> demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
>>> demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
>>
>> Thanks. I couldn't find it, where should I look?
>
> This is on patch 1/9.
Thanks.
I found the details of the "Enabled" column in 5/9.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-11 6:35 ` Jose E. Marchesi
2014-10-13 16:41 ` Doug Evans
@ 2014-10-17 0:36 ` Pedro Alves
2014-10-17 0:43 ` Pedro Alves
2014-10-17 0:55 ` Sergio Durigan Junior
1 sibling, 2 replies; 40+ messages in thread
From: Pedro Alves @ 2014-10-17 0:36 UTC (permalink / raw)
To: Jose E. Marchesi, Doug Evans; +Cc: gdb-patches
On 10/11/2014 07:39 AM, Jose E. Marchesi wrote:
>
> (gdb) info probes
> Provider Name Where Semaphore Enabled Object
> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
> demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
> demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
>
> In the example above demo:am-main is a systemtap probe, for which
> "Enabled" reads n/a. demo:another is a dtrace probe which cannot be
> disabled (it does not have any associated enabler) and
> demo:progress-counter is a dtrace probe which is disabled.
Shouldn't we explicitly say which probe is stap, vs dprobe (vs whatever
other probe type)? Like, either a new column:
~~~
Type Provider Name Where Semaphore Enabled Object
stap demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
dtrace demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
dtrace demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
~~~
or, sort output by probe type:
~~~
Stap probes:
Type Provider Name Where Semaphore Enabled Object
stap demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
Dtrace probes:
Type Provider Name Where Semaphore Enabled Object
dtrace demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
dtrace demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
~~~
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-17 0:36 ` Pedro Alves
@ 2014-10-17 0:43 ` Pedro Alves
2014-10-17 2:31 ` Sergio Durigan Junior
2014-10-17 0:55 ` Sergio Durigan Junior
1 sibling, 1 reply; 40+ messages in thread
From: Pedro Alves @ 2014-10-17 0:43 UTC (permalink / raw)
To: Jose E. Marchesi, Doug Evans; +Cc: gdb-patches
On 10/17/2014 01:36 AM, Pedro Alves wrote:
> On 10/11/2014 07:39 AM, Jose E. Marchesi wrote:
>>
>> (gdb) info probes
>> Provider Name Where Semaphore Enabled Object
>> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>> demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
>> demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
>>
>> In the example above demo:am-main is a systemtap probe, for which
>> "Enabled" reads n/a. demo:another is a dtrace probe which cannot be
>> disabled (it does not have any associated enabler) and
>> demo:progress-counter is a dtrace probe which is disabled.
>
> Shouldn't we explicitly say which probe is stap, vs dprobe (vs whatever
> other probe type)? Like, either a new column:
>
> ~~~
> Type Provider Name Where Semaphore Enabled Object
> stap demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
> dtrace demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
> dtrace demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
> ~~~
>
> or, sort output by probe type:
>
> ~~~
> Stap probes:
>
> Type Provider Name Where Semaphore Enabled Object
> stap demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>
> Dtrace probes:
>
> Type Provider Name Where Semaphore Enabled Object
> dtrace demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
> dtrace demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
> ~~~
This also raises the question, can't we have both a stap
probe and a dtrace probe with the name provider and name? Like,
using the proposed output that doesn't distinguish the probe types,
can't the user end up with the confusing:
Provider Name Where Semaphore Enabled Object
demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
demo am-main 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
Does GDB cope correctly with this? Will the user have
trouble specifying the probe he wants with the current UI?
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-17 0:36 ` Pedro Alves
2014-10-17 0:43 ` Pedro Alves
@ 2014-10-17 0:55 ` Sergio Durigan Junior
2014-10-17 5:52 ` Jose E. Marchesi
1 sibling, 1 reply; 40+ messages in thread
From: Sergio Durigan Junior @ 2014-10-17 0:55 UTC (permalink / raw)
To: Pedro Alves; +Cc: Jose E. Marchesi, Doug Evans, gdb-patches
On Thursday, October 16 2014, Pedro Alves wrote:
> On 10/11/2014 07:39 AM, Jose E. Marchesi wrote:
>>
>> (gdb) info probes
>> Provider Name Where Semaphore Enabled Object
>> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>> demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
>> demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
>>
>> In the example above demo:am-main is a systemtap probe, for which
>> "Enabled" reads n/a. demo:another is a dtrace probe which cannot be
>> disabled (it does not have any associated enabler) and
>> demo:progress-counter is a dtrace probe which is disabled.
>
> Shouldn't we explicitly say which probe is stap, vs dprobe (vs whatever
> other probe type)? Like, either a new column:
This is actually a nice idea, and if I say that I thought about it while
testing the patch, but then forgot to mention, would it seem strange? :-)
> ~~~
> Type Provider Name Where Semaphore Enabled Object
> stap demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
> dtrace demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
> dtrace demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
> ~~~
>
> or, sort output by probe type:
I prefer a new column.
> ~~~
> Stap probes:
>
> Type Provider Name Where Semaphore Enabled Object
> stap demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>
> Dtrace probes:
>
> Type Provider Name Where Semaphore Enabled Object
> dtrace demo another 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
> dtrace demo progress-counter 0x0000000000400c81 n/a no /home/jemarch/oracle/usdt/demo
> ~~~
Thanks.
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-17 0:43 ` Pedro Alves
@ 2014-10-17 2:31 ` Sergio Durigan Junior
2014-10-17 11:23 ` Pedro Alves
0 siblings, 1 reply; 40+ messages in thread
From: Sergio Durigan Junior @ 2014-10-17 2:31 UTC (permalink / raw)
To: Pedro Alves; +Cc: Jose E. Marchesi, Doug Evans, gdb-patches
On Thursday, October 16 2014, Pedro Alves wrote:
> This also raises the question, can't we have both a stap
> probe and a dtrace probe with the name provider and name? Like,
> using the proposed output that doesn't distinguish the probe types,
> can't the user end up with the confusing:
>
> Provider Name Where Semaphore Enabled Object
> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
> demo am-main 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
>
> Does GDB cope correctly with this? Will the user have
> trouble specifying the probe he wants with the current UI?
Aha, a good question :-P.
Well, you can actually test this with current GDB, without even needing
dtrace:
(gdb) info probes
Provider Name Where Semaphore Object
test bla 0x00000000004004f4 a.out
test bla 0x00000000004004f5 a.out
(gdb) b -p bla
Breakpoint 1 at 0x4004f4 (2 locations)
You have basically two ways of specifying where the probe breakpoint is
going to be located: either by using -probe (or -p), or using
-probe-[type] (or -p[type]). The second way is not problematic, because
you tell GDB that type you want explicitly, so there is no confusion.
However, in the first way, you put a breakpoint in a "probe" (the type
is not important here, only the probe name/provider). GDB will then try
to see if any of the probe backends have probes with this name, and will
put a breakpoint on every probe it finds (again, no matter which type).
The logic for this is in gdb/probe.c:parse_probes, if you are
interested.
This is already working (as you can see in my example above), and Jose's
patch does not touch it, so we are pretty much covered in this area.
Nonetheless, I think it is a good idea to add one more field to the
output of 'info probes', specifying the probe type.
Thanks,
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-17 0:55 ` Sergio Durigan Junior
@ 2014-10-17 5:52 ` Jose E. Marchesi
0 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-17 5:52 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: Pedro Alves, Doug Evans, gdb-patches
> Shouldn't we explicitly say which probe is stap, vs dprobe (vs whatever
> other probe type)? Like, either a new column:
This is actually a nice idea, and if I say that I thought about it while
testing the patch, but then forgot to mention, would it seem
strange? :-)
Noooo ;)
I like the idea of having a new column with the type. I will add an
extra patch to the patch series.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 3/9] New commands `enable probe' and `disable probe'.
2014-10-17 2:31 ` Sergio Durigan Junior
@ 2014-10-17 11:23 ` Pedro Alves
0 siblings, 0 replies; 40+ messages in thread
From: Pedro Alves @ 2014-10-17 11:23 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: Jose E. Marchesi, Doug Evans, gdb-patches
On 10/17/2014 03:31 AM, Sergio Durigan Junior wrote:
> On Thursday, October 16 2014, Pedro Alves wrote:
>
>> This also raises the question, can't we have both a stap
>> probe and a dtrace probe with the name provider and name? Like,
>> using the proposed output that doesn't distinguish the probe types,
>> can't the user end up with the confusing:
>>
>> Provider Name Where Semaphore Enabled Object
>> demo am-main 0x0000000000400c96 n/a /home/jemarch/oracle/usdt/demo
>> demo am-main 0x0000000000400c8b n/a always /home/jemarch/oracle/usdt/demo
>>
>> Does GDB cope correctly with this? Will the user have
>> trouble specifying the probe he wants with the current UI?
>
> Aha, a good question :-P.
>
> Well, you can actually test this with current GDB, without even needing
> dtrace:
>
> (gdb) info probes
> Provider Name Where Semaphore Object
> test bla 0x00000000004004f4 a.out
> test bla 0x00000000004004f5 a.out
> (gdb) b -p bla
> Breakpoint 1 at 0x4004f4 (2 locations)
>
> You have basically two ways of specifying where the probe breakpoint is
> going to be located: either by using -probe (or -p), or using
> -probe-[type] (or -p[type]). The second way is not problematic, because
> you tell GDB that type you want explicitly, so there is no confusion.
> However, in the first way, you put a breakpoint in a "probe" (the type
> is not important here, only the probe name/provider). GDB will then try
> to see if any of the probe backends have probes with this name, and will
> put a breakpoint on every probe it finds (again, no matter which type).
>
> The logic for this is in gdb/probe.c:parse_probes, if you are
> interested.
>
> This is already working (as you can see in my example above), and Jose's
> patch does not touch it, so we are pretty much covered in this area.
Excellent, thank you.
> Nonetheless, I think it is a good idea to add one more field to the
> output of 'info probes', specifying the probe type.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 7/9] Simple testsuite for DTrace USDT probes.
2014-10-16 22:36 ` Pedro Alves
@ 2014-10-17 12:01 ` Jose E. Marchesi
2014-10-17 12:18 ` Pedro Alves
0 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-17 12:01 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Hi Pedro.
Thanks for your suggestions. Please take a look to this new version of
the patch. I think it addresses all your concerns :)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index feb3ab1..f44404b 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,17 @@
2014-10-17 Jose E. Marchesi <jose.marchesi@oracle.com>
+ * lib/dtrace.exp: New file.
+ * gdb.base/dtrace-probe.exp: Likewise.
+ * gdb.base/dtrace-probe.d: Likewise.
+ * gdb.base/dtrace-probe.c: Likewise.
+
+2014-10-17 Jose E. Marchesi <jose.marchesi@oracle.com>
+
* gdb.base/stap-probe.exp (stap_test): Remove "SystemTap" from
expected message when trying to access $_probe_* convenience
variables while not on a probe.
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.c b/gdb/testsuite/gdb.base/dtrace-probe.c
new file mode 100644
index 0000000..45a77c5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dtrace-probe.c
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ 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 "dtrace-probe.h"
+
+int
+main ()
+{
+ char *name = "application";
+
+ TEST_TWO_LOCATIONS ();
+
+ int i = 0;
+ while (i < 10)
+ {
+ i++;
+ if (TEST_PROGRESS_COUNTER_ENABLED ())
+ TEST_PROGRESS_COUNTER (name, i);
+ }
+
+ TEST_TWO_LOCATIONS ();
+
+ return 0; /* last break here */
+}
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.d b/gdb/testsuite/gdb.base/dtrace-probe.d
new file mode 100644
index 0000000..df8e6bb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dtrace-probe.d
@@ -0,0 +1,21 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ 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/>. */
+
+provider test {
+ probe progress__counter (char *name, int);
+ probe two__locations ();
+};
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.exp b/gdb/testsuite/gdb.base/dtrace-probe.exp
new file mode 100644
index 0000000..ebbb5ff
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dtrace-probe.exp
@@ -0,0 +1,106 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+
+# 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/>.
+
+load_lib "dtrace.exp"
+
+# Run the tests.
+# This returns -1 on failure to compile or start, 0 otherwise.
+proc dtrace_test {} {
+ global testfile hex srcfile binfile
+
+ standard_testfile
+
+ if {[dtrace_build_usdt_test_program] == -1} {
+ untested ${testfile}.exp
+ return -1
+ }
+
+ clean_restart ${binfile}
+
+ if ![runto_main] {
+ return -1
+ }
+
+ gdb_test "print \$_probe_argc" "No probe at PC $hex" \
+ "check argument not at probe point"
+
+ # Test the 'info probes' command.
+ gdb_test "info probes dtrace" \
+ "test *progress-counter *$hex +no.*test *two-locations *$hex +always.*test *two-locations *$hex +always.*" \
+ "info probes dtrace"
+
+ # Disabling the probe test:two-locations shall have no effect,
+ # since no is-enabled probes are defined for it in the object
+ # file.
+
+ gdb_test "disable probe test two-locations" \
+ "Probe test:two-locations cannot be disabled.*" \
+ "disable probe test two-locations"
+
+ # On the other hand, the probe test:progress-counter can be
+ # enabled and then disabled again.
+
+ gdb_test "enable probe test progress-counter" \
+ "Probe test:progress-counter enabled.*" \
+ "enable probe test progress-counter"
+
+ gdb_test "disable probe test progress-counter" \
+ "Probe test:progress-counter disabled.*" \
+ "disable probe test progress-counter"
+
+ # Since test:progress-counter is disabled we can run to the second
+ # instance of the test:two-locations probe.
+
+ if {![runto "-probe-dtrace test:two-locations"]} {
+ fail "run to the first test:two-locations probe point"
+ }
+ gdb_test "continue" \
+ "Breakpoint \[0-9\]+, main \\(\\) at.*TEST_TWO_LOCATIONS.*" \
+ "run to the second test:two-locations probe point"
+
+ # Go back to the breakpoint on main() and enable the
+ # test:progress-counter probe. Set a breakpoint on it and see
+ # that it gets reached.
+
+ if ![runto_main] {
+ return -1
+ }
+
+ gdb_test "enable probe test progress-counter" \
+ "Probe test:progress-counter enabled.*" \
+ "enable probe test progress-counter"
+
+ gdb_test "break -probe-dtrace test:progress-counter" \
+ ".*Breakpoint \[0-9\]+ .*" "set breakpoint in test:progress-counter"
+ gdb_continue_to_breakpoint "test:progress-counter"
+
+ # Test probe arguments.
+ gdb_test "print \$_probe_argc" " = 2" \
+ "print \$_probe_argc for probe progress-counter"
+ gdb_test "print \$_probe_arg0" \
+ " = $hex \"application\"" \
+ "print \$_probe_arg0 for probe progress-counter"
+ gdb_test "print \$_probe_arg1" " = 1" \
+ "print \$_probe_arg1 for probe progress-counter"
+
+ # Set a breakpoint with multiple probe locations.
+ gdb_test "break -pdtrace test:two-locations" \
+ "Breakpoint \[0-9\]+ at $hex.*2 locations.*" \
+ "set multi-location probe breakpoint (probe two-locations)"
+
+ return 0
+}
+
+dtrace_test
diff --git a/gdb/testsuite/lib/dtrace.exp b/gdb/testsuite/lib/dtrace.exp
new file mode 100644
index 0000000..b0310d8
--- /dev/null
+++ b/gdb/testsuite/lib/dtrace.exp
@@ -0,0 +1,68 @@
+# Copyright 2014 Free Software Foundation, Inc.
+#
+# 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/>.
+
+# Generate a test program containing DTrace USDT probes, whose sources
+# are ${srcfile} and ${testfile}.d. The sequence of commands used to
+# generate the test program is:
+#
+# 1. Generate a header file from ${testfile}.d using dtrace -h.
+# 2. Compile ${srcfile}.c.
+# 3. Generate an object file containing a DOF program using dtrace -G.
+# 4. Link everything together to get the test program.
+#
+# This function requires 'testfile', 'srcfile' and 'binfile' to be
+# properly set.
+#
+# This function returns -1 on failure, 0 otherwise
+proc dtrace_build_usdt_test_program {} {
+ global testfile hex srcdir srcfile subdir binfile
+
+ # Make sure that dtrace is installed, it is the real one (not the
+ # script installed by SystemTap, for example) and of the right
+ # version (>= 0.4.0).
+
+ set dtrace "dtrace"
+ set result [remote_exec host "$dtrace -V"]
+ if {[lindex $result 0] != 0 || ![regexp {^dtrace: Sun D [0-9]\.[0-9]\.[0-9]} [lindex $result 1]]} {
+ return -1
+ }
+ set dscript_file "${srcdir}/${subdir}/${testfile}.d"
+
+ # 1. Generate a header file from testprogram.d using dtrace -h.
+ set out_header_file [standard_output_file "${testfile}.h"]
+ set result [remote_exec host "$dtrace -h -s $dscript_file -o $out_header_file"]
+ verbose -log [lindex $result 1]
+ if {[lindex $result 0] != 0} {
+ return -1
+ }
+
+ # 2. Compile testprogram.c.
+ set options [list debug additional_flags=-I[file dirname $out_header_file]]
+ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object ${options}] != ""} {
+ return -1
+ }
+
+ # 3. Generate an object file containing a DOF program using dtrace -G.
+ set result [remote_exec host "$dtrace -G -s $dscript_file ${binfile}.o -o ${binfile}-p.o"]
+ verbose -log [lindex $result 1]
+ if {[lindex $result 0] != 0} {
+ return -1
+ }
+
+ # 4. Link everything together to get the test program.
+ if {[gdb_compile "${binfile}.o ${binfile}-p.o" ${binfile} executable {debug}] != ""} {
+ return -1
+ }
+}
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 7/9] Simple testsuite for DTrace USDT probes.
2014-10-17 12:01 ` Jose E. Marchesi
@ 2014-10-17 12:18 ` Pedro Alves
0 siblings, 0 replies; 40+ messages in thread
From: Pedro Alves @ 2014-10-17 12:18 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
Hi Jose,
On 10/17/2014 01:02 PM, Jose E. Marchesi wrote:
> Thanks for your suggestions. Please take a look to this new version of
> the patch. I think it addresses all your concerns :)
Indeed it does. Thanks much.
One tiny nit:
> + if {[dtrace_build_usdt_test_program] == -1} {
> + untested ${testfile}.exp
> + return -1
> + }
Something odd with indentation there.
"untested ${testfile}.exp" is an anti-idiom in lots of tests :-)
See https://sourceware.org/gdb/wiki/GDBTestcaseCookbook#A.22untested.22_calls .
Write instead:
untested "could not compile test program"
Otherwise looks good.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-16 22:07 ` Pedro Alves
@ 2014-10-17 12:35 ` Jose E. Marchesi
2014-10-17 12:42 ` Pedro Alves
0 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-17 12:35 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Hi Pedro.
Thanks for your suggestions. I updated the patch addressing them.
Support for DTrace USDT probes in x86_64 targets.
This patch adds the target-specific code in order to support the
calculation of DTrace probes arguments in x86_64 targets, and also the
enabling and disabling of probes. This is done by implementing the
`dtrace_*' gdbarch handlers.
gdb/ChangeLog:
2014-10-17 Jose E. Marchesi <jose.marchesi@oracle.com>
* amd64-linux-tdep.c (amd64_dtrace_parse_probe_argument): New function.
(amd64_dtrace_probe_is_enabled): Likewise.
(amd64_dtrace_enable_probe): Likewise.
(amd64_dtrace_disable_probe): Likewise.
(amd64_linux_init_abi): Register the
`gdbarch_dtrace_probe_argument', `gdbarch_dtrace_enable_probe',
`gdbarch_dtrace_disable_probe' and
`gdbarch_dtrace_probe_is_enabled' hooks.
(amd64_dtrace_disabled_probe_sequence_1): New constant.
(amd64_dtrace_disabled_probe_sequence_2): Likewise.
(amd64_dtrace_enable_probe_sequence): Likewise.
(amd64_dtrace_disable_probe_sequence): Likewise.
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a2251a3..1bbe3c1 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,20 @@
2014-10-17 Jose E. Marchesi <jose.marchesi@oracle.com>
+ * amd64-linux-tdep.c (amd64_dtrace_parse_probe_argument): New function.
+ (amd64_dtrace_probe_is_enabled): Likewise.
+ (amd64_dtrace_enable_probe): Likewise.
+ (amd64_dtrace_disable_probe): Likewise.
+ (amd64_linux_init_abi): Register the
+ `gdbarch_dtrace_probe_argument', `gdbarch_dtrace_enable_probe',
+ `gdbarch_dtrace_disable_probe' and
+ `gdbarch_dtrace_probe_is_enabled' hooks.
+ (amd64_dtrace_disabled_probe_sequence_1): New constant.
+ (amd64_dtrace_disabled_probe_sequence_2): Likewise.
+ (amd64_dtrace_enable_probe_sequence): Likewise.
+ (amd64_dtrace_disable_probe_sequence): Likewise.
+
+2014-10-17 Jose E. Marchesi <jose.marchesi@oracle.com>
+
* breakpoint.c (BREAK_ARGS_HELP): help string updated to mention
the -probe-dtrace new vpossible value for PROBE_MODIFIER.
* configure.ac (CONFIG_OBS): dtrace-probe.o added if BFD can
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index edbb1b3..9fe68b9 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -28,6 +28,8 @@
#include "gdbtypes.h"
#include "reggroups.h"
#include "regset.h"
+#include "parser-defs.h"
+#include "user-regs.h"
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
@@ -1643,6 +1645,146 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
&amd64_linux_xstateregset, "XSAVE extended state", cb_data);
}
+/* The instruction sequences used in x86_64 machines for a
+ disabled is-enabled probe. */
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_1[] = {
+ /* xor %rax, %rax */ 0x48, 0x33, 0xc0,
+ /* nop */ 0x90,
+ /* nop */ 0x90
+};
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_2[] = {
+ /* xor %rax, %rax */ 0x48, 0x33, 0xc0,
+ /* ret */ 0xc3,
+ /* nop */ 0x90
+};
+
+/* The instruction sequence used in x86_64 machines for enabling a
+ DTrace is-enabled probe. */
+
+const gdb_byte amd64_dtrace_enable_probe_sequence[] = {
+ /* mov $0x1, %eax */ 0xb8, 0x01, 0x00, 0x00, 0x00
+};
+
+/* The instruction sequence used in x86_64 machines for disabling a
+ DTrace is-enabled probe. */
+
+const gdb_byte amd64_dtrace_disable_probe_sequence[] = {
+ /* xor %rax, %rax; nop; nop */ 0x48, 0x33, 0xC0, 0x90, 0x90
+};
+
+/* Implementation of `gdbarch_dtrace_probe_is_enabled', as defined in
+ gdbarch.h. */
+
+static int
+amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_byte buf[5];
+
+ /* This function returns 1 if the instructions at ADDR do _not_
+ follow any of the amd64_dtrace_disabled_probe_sequence_*
+ patterns.
+
+ Note that ADDR is offset 3 bytes from the beginning of these
+ sequences. */
+
+ read_code (addr - 3, buf, 5);
+ return (memcmp (buf, amd64_dtrace_disabled_probe_sequence_1, 5) != 0
+ && memcmp (buf, amd64_dtrace_disabled_probe_sequence_2, 5) != 0);
+}
+
+/* Implementation of `gdbarch_dtrace_enable_probe', as defined in
+ gdbarch.h. */
+
+static void
+amd64_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* Note also that ADDR is offset 3 bytes from the beginning of
+ amd64_dtrace_enable_probe_sequence. */
+
+ write_memory (addr - 3, amd64_dtrace_enable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_disable_probe', as defined in
+ gdbarch.h. */
+
+static void
+amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* Note also that ADDR is offset 3 bytes from the beginning of
+ amd64_dtrace_disable_probe_sequence. */
+
+ write_memory (addr - 3, amd64_dtrace_disable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_parse_probe_argument', as defined
+ in gdbarch.h. */
+
+static void
+amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
+ struct parser_state *pstate,
+ int narg)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ struct frame_info *this_frame = get_selected_frame (NULL);
+ struct stoken str;
+
+ /* DTrace probe arguments can be found on the ABI-defined places for
+ regular arguments at the current PC. The probe abstraction
+ currently supports up to 12 arguments for probes. */
+
+ if (narg < 6)
+ {
+ static const int arg_reg_map[6] =
+ {
+ AMD64_RDI_REGNUM, /* Arg 1. */
+ AMD64_RSI_REGNUM, /* Arg 2. */
+ AMD64_RDX_REGNUM, /* Arg 3. */
+ AMD64_RCX_REGNUM, /* Arg 4. */
+ AMD64_R8_REGNUM, /* Arg 5. */
+ AMD64_R9_REGNUM /* Arg 6. */
+ };
+ int regno = arg_reg_map[narg];
+ const char *regname = user_reg_map_regnum_to_name (gdbarch, regno);
+
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+ str.ptr = regname;
+ str.length = strlen (regname);
+ write_exp_string (pstate, str);
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+ }
+ else
+ {
+ /* Additional arguments are passed on the stack. */
+ CORE_ADDR sp;
+ const char *regname = user_reg_map_regnum_to_name (gdbarch, AMD64_RSP_REGNUM);
+
+ /* Displacement. */
+ write_exp_elt_opcode (pstate, OP_LONG);
+ write_exp_elt_type (pstate, builtin_type (gdbarch)->builtin_long);
+ write_exp_elt_longcst (pstate, narg - 6);
+ write_exp_elt_opcode (pstate, OP_LONG);
+
+ /* Register: SP. */
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+ str.ptr = regname;
+ str.length = strlen (regname);
+ write_exp_string (pstate, str);
+ write_exp_elt_opcode (pstate, OP_REGISTER);
+
+ write_exp_elt_opcode (pstate, BINOP_ADD);
+
+ /* Cast to long. */
+ write_exp_elt_opcode (pstate, UNOP_CAST);
+ write_exp_elt_type (pstate,
+ lookup_pointer_type (builtin_type (gdbarch)->builtin_long));
+ write_exp_elt_opcode (pstate, UNOP_CAST);
+
+ write_exp_elt_opcode (pstate, UNOP_IND);
+ }
+}
+
static void
amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1907,6 +2049,12 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
+
+ /* Register DTrace handlers. */
+ set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
+ set_gdbarch_dtrace_probe_is_enabled (gdbarch, amd64_dtrace_probe_is_enabled);
+ set_gdbarch_dtrace_enable_probe (gdbarch, amd64_dtrace_enable_probe);
+ set_gdbarch_dtrace_disable_probe (gdbarch, amd64_dtrace_disable_probe);
}
static void
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-17 12:35 ` Jose E. Marchesi
@ 2014-10-17 12:42 ` Pedro Alves
2014-10-17 12:47 ` Jose E. Marchesi
0 siblings, 1 reply; 40+ messages in thread
From: Pedro Alves @ 2014-10-17 12:42 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
On 10/17/2014 01:40 PM, Jose E. Marchesi wrote:
>
> Hi Pedro.
>
> Thanks for your suggestions. I updated the patch addressing them.
>
Thanks, looks good. I'm left wondering about the Solaris
question though. :-)
Just a minor detail I missed first time around:
> --- a/gdb/amd64-linux-tdep.c
> +++ b/gdb/amd64-linux-tdep.c
> @@ -28,6 +28,8 @@
> #include "gdbtypes.h"
> #include "reggroups.h"
> #include "regset.h"
> +#include "parser-defs.h"
> +#include "user-regs.h"
Please also mention these include in the CL, like:
* amd64-linux-tdep.c: Include "parser-defs.h" and "user-regs.h".
(amd64_dtrace_parse_probe_argument): New function.
...
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-17 12:42 ` Pedro Alves
@ 2014-10-17 12:47 ` Jose E. Marchesi
2014-10-17 12:53 ` Pedro Alves
0 siblings, 1 reply; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-17 12:47 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> Thanks for your suggestions. I updated the patch addressing them.
>
Thanks, looks good. I'm left wondering about the Solaris
question though. :-)
I did not address that yet because I don't know the answer myself, so I
emailed the DTrace hackers :)
If they confirm that the instruction sequences are the same in Solaris
then I will move the x86_64 stuff to amd64-tdep.c
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-17 12:47 ` Jose E. Marchesi
@ 2014-10-17 12:53 ` Pedro Alves
2014-10-17 19:48 ` Jose E. Marchesi
0 siblings, 1 reply; 40+ messages in thread
From: Pedro Alves @ 2014-10-17 12:53 UTC (permalink / raw)
To: Jose E. Marchesi; +Cc: gdb-patches
On 10/17/2014 01:52 PM, Jose E. Marchesi wrote:
>
> > Thanks for your suggestions. I updated the patch addressing them.
> >
>
> Thanks, looks good. I'm left wondering about the Solaris
> question though. :-)
>
> I did not address that yet because I don't know the answer myself, so I
> emailed the DTrace hackers :)
>
> If they confirm that the instruction sequences are the same in Solaris
> then I will move the x86_64 stuff to amd64-tdep.c
Ah, thanks. :-)
Pedro Alves
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets.
2014-10-17 12:53 ` Pedro Alves
@ 2014-10-17 19:48 ` Jose E. Marchesi
0 siblings, 0 replies; 40+ messages in thread
From: Jose E. Marchesi @ 2014-10-17 19:48 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> Thanks, looks good. I'm left wondering about the Solaris
> question though. :-)
>
> I did not address that yet because I don't know the answer myself, so I
> emailed the DTrace hackers :)
>
> If they confirm that the instruction sequences are the same in Solaris
> then I will move the x86_64 stuff to amd64-tdep.c
Ah, thanks. :-)
The DTrace hackers tell me that they use different enabling/disabling
instruction sequences in Solaris/x86_64, so looks like
amd64-linux-tdep.c is the proper place for the functions after all.
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2014-10-17 19:48 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-10 17:18 [PATCH V2 0/9] Add support for DTrace USDT probes to gdb Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 5/9] New probe type: DTrace USDT probes Jose E. Marchesi
2014-10-14 19:01 ` Sergio Durigan Junior
2014-10-15 13:28 ` Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 1/9] Adapt `info probes' to support printing probes of different types Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 6/9] Support for DTrace USDT probes in x86_64 targets Jose E. Marchesi
2014-10-16 22:07 ` Pedro Alves
2014-10-17 12:35 ` Jose E. Marchesi
2014-10-17 12:42 ` Pedro Alves
2014-10-17 12:47 ` Jose E. Marchesi
2014-10-17 12:53 ` Pedro Alves
2014-10-17 19:48 ` Jose E. Marchesi
2014-10-16 22:07 ` Pedro Alves
2014-10-16 22:17 ` Pedro Alves
2014-10-10 17:18 ` [PATCH V2 4/9] New gdbarch functions: dtrace_parse_probe_argument, dtrace_probe_is_enabled, dtrace_enable_probe, dtrace_disable_probe Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 2/9] Move `compute_probe_arg' and `compile_probe_arg' to probe.c Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 8/9] Documentation for DTrace USDT probes Jose E. Marchesi
2014-10-10 18:18 ` Eli Zaretskii
2014-10-10 17:18 ` [PATCH V2 3/9] New commands `enable probe' and `disable probe' Jose E. Marchesi
2014-10-10 18:15 ` Eli Zaretskii
2014-10-10 22:03 ` Doug Evans
2014-10-11 6:35 ` Jose E. Marchesi
2014-10-13 16:41 ` Doug Evans
2014-10-14 19:02 ` Sergio Durigan Junior
2014-10-17 0:07 ` Doug Evans
2014-10-17 0:36 ` Pedro Alves
2014-10-17 0:43 ` Pedro Alves
2014-10-17 2:31 ` Sergio Durigan Junior
2014-10-17 11:23 ` Pedro Alves
2014-10-17 0:55 ` Sergio Durigan Junior
2014-10-17 5:52 ` Jose E. Marchesi
2014-10-11 17:04 ` Sergio Durigan Junior
2014-10-14 18:53 ` Sergio Durigan Junior
2014-10-15 13:28 ` Jose E. Marchesi
2014-10-10 17:18 ` [PATCH V2 9/9] Announce the DTrace USDT probes support in NEWS Jose E. Marchesi
2014-10-10 18:16 ` Eli Zaretskii
2014-10-10 17:18 ` [PATCH V2 7/9] Simple testsuite for DTrace USDT probes Jose E. Marchesi
2014-10-16 22:36 ` Pedro Alves
2014-10-17 12:01 ` Jose E. Marchesi
2014-10-17 12:18 ` Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox