Convert SystemTap probe interface to C++ (and perform some cleanups)
This patch converts the SystemTap probe interface (gdb/stap-probe.[ch]) to C++, and also performs some cleanups that were on my TODO list for a while. The main changes were the conversion of 'struct stap_probe' to 'class stap_probe', and a new 'class stap_static_probe_ops' to replace the use of 'stap_probe_ops'. Both classes implement the virtual methods exported by their parents, 'class probe' and 'class static_probe_ops', respectively. I believe it's now a bit simpler to understand the logic behind the stap-probe interface. There are several helper functions used to parse parts of a stap probe, and since they are generic and don't need to know about the probe they're working on, I decided to leave them as simple static functions (instead of e.g. converting them to class methods). I've also converted a few uses of "VEC" to "std::vector", which makes the code simpler and easier to maintain. And, as usual, some cleanups here and there. Even though I'm sending a series of patches, they need to be tested and committed as a single unit, because of inter-dependencies. But it should be easier to review in separate logical units. I've regtested this patch on BuildBot, no regressions found. gdb/ChangeLog: 2017-11-22 Sergio Durigan Junior <sergiodj@redhat.com> Simon Marchi <simark@simark.ca> * stap-probe.c (struct probe_ops stap_probe_ops): Delete variable. (struct stap_probe_arg) <stap_probe_arg>: New constructor. <aexpr>: Change type to 'expression_up'. (stap_probe_arg_s): Delete type and VEC. (struct stap_probe): Delete. Replace by... (class stap_static_probe_ops): ...this and... (class stap_probe): ...this. Rename variables to add 'm_' prefix. Do not use 'union' for arguments anymore. (stap_get_expected_argument_type): Receive probe name instead of 'struct stap_probe'. Adjust code. (stap_parse_probe_arguments): Rename to... (stap_probe::parse_arguments): ...this. Adjust code to reflect change. (stap_get_probe_address): Rename to... (stap_probe::get_relocated_address): ...this. Adjust code to reflect change. (stap_get_probe_argument_count): Rename to... (stap_probe::get_argument_count): ...this. Adjust code to reflect change. (stap_get_arg): Rename to... (stap_probe::get_arg_by_number'): ...this. Adjust code to reflect change. (can_evaluate_probe_arguments): Rename to... (stap_probe::can_evaluate_arguments): ...this. Adjust code to reflect change. (stap_evaluate_probe_argument): Rename to... (stap_probe::evaluate_argument): ...this. Adjust code to reflect change. (stap_compile_to_ax): Rename to... (stap_probe::compile_to_ax): ...this. Adjust code to reflect change. (stap_probe_destroy): Delete. (stap_modify_semaphore): Adjust comment. (stap_set_semaphore): Rename to... (stap_probe::set_semaphore): ...this. Adjust code to reflect change. (stap_clear_semaphore): Rename to... (stap_probe::clear_semaphore): ...this. Adjust code to reflect change. (stap_probe::get_static_ops): New method. (handle_stap_probe): Adjust code to create instance of 'stap_probe'. (stap_get_probes): Rename to... (stap_static_probe_ops::get_probes): ...this. Adjust code to reflect change. (stap_probe_is_linespec): Rename to... (stap_static_probe_ops::is_linespec): ...this. Adjust code to reflect change. (stap_type_name): Rename to... (stap_static_probe_ops::type_name): ...this. Adjust code to reflect change. (stap_gen_info_probes_table_header): Rename to... (stap_static_probe_ops::gen_info_probes_table_header): ...this. Adjust code to reflect change. (stap_gen_info_probes_table_values): Rename to... (stap_probe::gen_info_probes_table_values): ...this. Adjust code to reflect change. (struct probe_ops stap_probe_ops): Delete. (info_probes_stap_command): Use 'info_probes_for_spops' instead of 'info_probes_for_ops'. (_initialize_stap_probe): Use 'all_static_probe_ops' instead of 'all_probe_ops'.
This commit is contained in:
parent
935676c92f
commit
0e9ae10f5f
|
@ -1,3 +1,70 @@
|
||||||
|
2017-11-22 Sergio Durigan Junior <sergiodj@redhat.com>
|
||||||
|
Simon Marchi <simark@simark.ca>
|
||||||
|
|
||||||
|
* stap-probe.c (struct probe_ops stap_probe_ops): Delete
|
||||||
|
variable.
|
||||||
|
(struct stap_probe_arg) <stap_probe_arg>: New constructor.
|
||||||
|
<aexpr>: Change type to 'expression_up'.
|
||||||
|
(stap_probe_arg_s): Delete type and VEC.
|
||||||
|
(struct stap_probe): Delete. Replace by...
|
||||||
|
(class stap_static_probe_ops): ...this and...
|
||||||
|
(class stap_probe): ...this. Rename variables to add 'm_'
|
||||||
|
prefix. Do not use 'union' for arguments anymore.
|
||||||
|
(stap_get_expected_argument_type): Receive probe name instead
|
||||||
|
of 'struct stap_probe'. Adjust code.
|
||||||
|
(stap_parse_probe_arguments): Rename to...
|
||||||
|
(stap_probe::parse_arguments): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(stap_get_probe_address): Rename to...
|
||||||
|
(stap_probe::get_relocated_address): ...this. Adjust code
|
||||||
|
to reflect change.
|
||||||
|
(stap_get_probe_argument_count): Rename to...
|
||||||
|
(stap_probe::get_argument_count): ...this. Adjust code
|
||||||
|
to reflect change.
|
||||||
|
(stap_get_arg): Rename to...
|
||||||
|
(stap_probe::get_arg_by_number'): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(can_evaluate_probe_arguments): Rename to...
|
||||||
|
(stap_probe::can_evaluate_arguments): ...this. Adjust code
|
||||||
|
to reflect change.
|
||||||
|
(stap_evaluate_probe_argument): Rename to...
|
||||||
|
(stap_probe::evaluate_argument): ...this. Adjust code
|
||||||
|
to reflect change.
|
||||||
|
(stap_compile_to_ax): Rename to...
|
||||||
|
(stap_probe::compile_to_ax): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(stap_probe_destroy): Delete.
|
||||||
|
(stap_modify_semaphore): Adjust comment.
|
||||||
|
(stap_set_semaphore): Rename to...
|
||||||
|
(stap_probe::set_semaphore): ...this. Adjust code to reflect
|
||||||
|
change.
|
||||||
|
(stap_clear_semaphore): Rename to...
|
||||||
|
(stap_probe::clear_semaphore): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(stap_probe::get_static_ops): New method.
|
||||||
|
(handle_stap_probe): Adjust code to create instance of
|
||||||
|
'stap_probe'.
|
||||||
|
(stap_get_probes): Rename to...
|
||||||
|
(stap_static_probe_ops::get_probes): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(stap_probe_is_linespec): Rename to...
|
||||||
|
(stap_static_probe_ops::is_linespec): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(stap_type_name): Rename to...
|
||||||
|
(stap_static_probe_ops::type_name): ...this. Adjust code to
|
||||||
|
reflect change.
|
||||||
|
(stap_gen_info_probes_table_header): Rename to...
|
||||||
|
(stap_static_probe_ops::gen_info_probes_table_header):
|
||||||
|
...this. Adjust code to reflect change.
|
||||||
|
(stap_gen_info_probes_table_values): Rename to...
|
||||||
|
(stap_probe::gen_info_probes_table_values): ...this. Adjust
|
||||||
|
code to reflect change.
|
||||||
|
(struct probe_ops stap_probe_ops): Delete.
|
||||||
|
(info_probes_stap_command): Use 'info_probes_for_spops'
|
||||||
|
instead of 'info_probes_for_ops'.
|
||||||
|
(_initialize_stap_probe): Use 'all_static_probe_ops' instead
|
||||||
|
of 'all_probe_ops'.
|
||||||
|
|
||||||
2017-11-22 Sergio Durigan Junior <sergiodj@redhat.com>
|
2017-11-22 Sergio Durigan Junior <sergiodj@redhat.com>
|
||||||
|
|
||||||
* break-catch-throw.c (fetch_probe_arguments): Use
|
* break-catch-throw.c (fetch_probe_arguments): Use
|
||||||
|
|
538
gdb/stap-probe.c
538
gdb/stap-probe.c
|
@ -45,10 +45,6 @@
|
||||||
|
|
||||||
#define STAP_BASE_SECTION_NAME ".stapsdt.base"
|
#define STAP_BASE_SECTION_NAME ".stapsdt.base"
|
||||||
|
|
||||||
/* Forward declaration. */
|
|
||||||
|
|
||||||
extern const struct probe_ops stap_probe_ops;
|
|
||||||
|
|
||||||
/* Should we display debug information for the probe's argument expression
|
/* Should we display debug information for the probe's argument expression
|
||||||
parsing? */
|
parsing? */
|
||||||
|
|
||||||
|
@ -85,6 +81,12 @@ enum stap_arg_bitness
|
||||||
|
|
||||||
struct stap_probe_arg
|
struct stap_probe_arg
|
||||||
{
|
{
|
||||||
|
/* Constructor for stap_probe_arg. */
|
||||||
|
stap_probe_arg (enum stap_arg_bitness bitness_, struct type *atype_,
|
||||||
|
expression_up &&aexpr_)
|
||||||
|
: bitness (bitness_), atype (atype_), aexpr (std::move (aexpr_))
|
||||||
|
{}
|
||||||
|
|
||||||
/* The bitness of this argument. */
|
/* The bitness of this argument. */
|
||||||
enum stap_arg_bitness bitness;
|
enum stap_arg_bitness bitness;
|
||||||
|
|
||||||
|
@ -92,35 +94,134 @@ struct stap_probe_arg
|
||||||
struct type *atype;
|
struct type *atype;
|
||||||
|
|
||||||
/* The argument converted to an internal GDB expression. */
|
/* The argument converted to an internal GDB expression. */
|
||||||
struct expression *aexpr;
|
expression_up aexpr;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct stap_probe_arg stap_probe_arg_s;
|
/* Class that implements the static probe methods for "stap" probes. */
|
||||||
DEF_VEC_O (stap_probe_arg_s);
|
|
||||||
|
|
||||||
struct stap_probe
|
class stap_static_probe_ops : public static_probe_ops
|
||||||
{
|
{
|
||||||
/* Generic information about the probe. This shall be the first element
|
public:
|
||||||
of this struct, in order to maintain binary compatibility with the
|
/* See probe.h. */
|
||||||
`struct probe' and be able to fully abstract it. */
|
bool is_linespec (const char **linespecp) const override;
|
||||||
struct probe p;
|
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
void get_probes (std::vector<probe *> *probesp,
|
||||||
|
struct objfile *objfile) const override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
const char *type_name () const override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
std::vector<struct info_probe_column> gen_info_probes_table_header
|
||||||
|
() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SystemTap static_probe_ops. */
|
||||||
|
|
||||||
|
const stap_static_probe_ops stap_static_probe_ops;
|
||||||
|
|
||||||
|
class stap_probe : public probe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* Constructor for stap_probe. */
|
||||||
|
stap_probe (std::string &&name_, std::string &&provider_, CORE_ADDR address_,
|
||||||
|
struct gdbarch *arch_, CORE_ADDR sem_addr, const char *args_text)
|
||||||
|
: probe (std::move (name_), std::move (provider_), address_, arch_),
|
||||||
|
m_sem_addr (sem_addr),
|
||||||
|
m_have_parsed_args (false), m_unparsed_args_text (args_text)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
CORE_ADDR get_relocated_address (struct objfile *objfile) override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
unsigned get_argument_count (struct frame_info *frame) override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
bool can_evaluate_arguments () const override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
struct value *evaluate_argument (unsigned n,
|
||||||
|
struct frame_info *frame) override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
void compile_to_ax (struct agent_expr *aexpr,
|
||||||
|
struct axs_value *axs_value,
|
||||||
|
unsigned n) override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
void set_semaphore (struct objfile *objfile,
|
||||||
|
struct gdbarch *gdbarch) override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
void clear_semaphore (struct objfile *objfile,
|
||||||
|
struct gdbarch *gdbarch) override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
const static_probe_ops *get_static_ops () const override;
|
||||||
|
|
||||||
|
/* See probe.h. */
|
||||||
|
std::vector<const char *> gen_info_probes_table_values () const override;
|
||||||
|
|
||||||
|
/* Return argument N of probe.
|
||||||
|
|
||||||
|
If the probe's arguments have not been parsed yet, parse them. If
|
||||||
|
there are no arguments, throw an exception (error). Otherwise,
|
||||||
|
return the requested argument. */
|
||||||
|
struct stap_probe_arg *get_arg_by_number (unsigned n,
|
||||||
|
struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
if (!m_have_parsed_args)
|
||||||
|
this->parse_arguments (gdbarch);
|
||||||
|
|
||||||
|
gdb_assert (m_have_parsed_args);
|
||||||
|
if (m_parsed_args.empty ())
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
_("Probe '%s' apparently does not have arguments, but \n"
|
||||||
|
"GDB is requesting its argument number %u anyway. "
|
||||||
|
"This should not happen. Please report this bug."),
|
||||||
|
this->get_name ().c_str (), n);
|
||||||
|
|
||||||
|
if (n > m_parsed_args.size ())
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
_("Probe '%s' has %d arguments, but GDB is requesting\n"
|
||||||
|
"argument %u. This should not happen. Please\n"
|
||||||
|
"report this bug."),
|
||||||
|
this->get_name ().c_str (),
|
||||||
|
(int) m_parsed_args.size (), n);
|
||||||
|
|
||||||
|
return &m_parsed_args[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function which parses an argument string from the probe,
|
||||||
|
correctly splitting the arguments and storing their information
|
||||||
|
in properly ways.
|
||||||
|
|
||||||
|
Consider the following argument string (x86 syntax):
|
||||||
|
|
||||||
|
`4@%eax 4@$10'
|
||||||
|
|
||||||
|
We have two arguments, `%eax' and `$10', both with 32-bit
|
||||||
|
unsigned bitness. This function basically handles them, properly
|
||||||
|
filling some structures with this information. */
|
||||||
|
void parse_arguments (struct gdbarch *gdbarch);
|
||||||
|
|
||||||
|
private:
|
||||||
/* If the probe has a semaphore associated, then this is the value of
|
/* If the probe has a semaphore associated, then this is the value of
|
||||||
it, relative to SECT_OFF_DATA. */
|
it, relative to SECT_OFF_DATA. */
|
||||||
CORE_ADDR sem_addr;
|
CORE_ADDR m_sem_addr;
|
||||||
|
|
||||||
/* One if the arguments have been parsed. */
|
/* True if the arguments have been parsed. */
|
||||||
unsigned int args_parsed : 1;
|
bool m_have_parsed_args;
|
||||||
|
|
||||||
union
|
/* The text version of the probe's arguments, unparsed. */
|
||||||
{
|
const char *m_unparsed_args_text;
|
||||||
const char *text;
|
|
||||||
|
|
||||||
/* Information about each argument. This is an array of `stap_probe_arg',
|
/* Information about each argument. This is an array of `stap_probe_arg',
|
||||||
with each entry representing one argument. */
|
with each entry representing one argument. This is only valid if
|
||||||
VEC (stap_probe_arg_s) *vec;
|
M_ARGS_PARSED is true. */
|
||||||
}
|
std::vector<struct stap_probe_arg> m_parsed_args;
|
||||||
args_u;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* When parsing the arguments, we have to establish different precedences
|
/* When parsing the arguments, we have to establish different precedences
|
||||||
|
@ -326,7 +427,7 @@ stap_get_opcode (const char **s)
|
||||||
static struct type *
|
static struct type *
|
||||||
stap_get_expected_argument_type (struct gdbarch *gdbarch,
|
stap_get_expected_argument_type (struct gdbarch *gdbarch,
|
||||||
enum stap_arg_bitness b,
|
enum stap_arg_bitness b,
|
||||||
const struct stap_probe *probe)
|
const char *probe_name)
|
||||||
{
|
{
|
||||||
switch (b)
|
switch (b)
|
||||||
{
|
{
|
||||||
|
@ -361,8 +462,7 @@ stap_get_expected_argument_type (struct gdbarch *gdbarch,
|
||||||
return builtin_type (gdbarch)->builtin_uint64;
|
return builtin_type (gdbarch)->builtin_uint64;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error (_("Undefined bitness for probe '%s'."),
|
error (_("Undefined bitness for probe '%s'."), probe_name);
|
||||||
probe->p.name);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1039,10 +1139,10 @@ stap_parse_argument_1 (struct stap_parse_info *p, int has_lhs,
|
||||||
- If we find an operator, we skip it.
|
- If we find an operator, we skip it.
|
||||||
|
|
||||||
This function can also call a special function that will try to match
|
This function can also call a special function that will try to match
|
||||||
unknown tokens. It will return 1 if the argument has been parsed
|
unknown tokens. It will return the expression_up generated from
|
||||||
successfully, or zero otherwise. */
|
parsing the argument. */
|
||||||
|
|
||||||
static struct expression *
|
static expression_up
|
||||||
stap_parse_argument (const char **arg, struct type *atype,
|
stap_parse_argument (const char **arg, struct type *atype,
|
||||||
struct gdbarch *gdbarch)
|
struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
|
@ -1078,41 +1178,27 @@ stap_parse_argument (const char **arg, struct type *atype,
|
||||||
*arg = p.arg;
|
*arg = p.arg;
|
||||||
|
|
||||||
/* We can safely return EXPOUT here. */
|
/* We can safely return EXPOUT here. */
|
||||||
return p.pstate.expout;
|
return expression_up (p.pstate.expout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function which parses an argument string from PROBE, correctly splitting
|
/* Implementation of 'parse_arguments' method. */
|
||||||
the arguments and storing their information in properly ways.
|
|
||||||
|
|
||||||
Consider the following argument string (x86 syntax):
|
void
|
||||||
|
stap_probe::parse_arguments (struct gdbarch *gdbarch)
|
||||||
`4@%eax 4@$10'
|
|
||||||
|
|
||||||
We have two arguments, `%eax' and `$10', both with 32-bit unsigned bitness.
|
|
||||||
This function basically handles them, properly filling some structures with
|
|
||||||
this information. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
stap_parse_probe_arguments (struct stap_probe *probe, struct gdbarch *gdbarch)
|
|
||||||
{
|
{
|
||||||
const char *cur;
|
const char *cur;
|
||||||
|
|
||||||
gdb_assert (!probe->args_parsed);
|
gdb_assert (!m_have_parsed_args);
|
||||||
cur = probe->args_u.text;
|
cur = m_unparsed_args_text;
|
||||||
probe->args_parsed = 1;
|
m_have_parsed_args = true;
|
||||||
probe->args_u.vec = NULL;
|
|
||||||
|
|
||||||
if (cur == NULL || *cur == '\0' || *cur == ':')
|
if (cur == NULL || *cur == '\0' || *cur == ':')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (*cur != '\0')
|
while (*cur != '\0')
|
||||||
{
|
{
|
||||||
struct stap_probe_arg arg;
|
enum stap_arg_bitness bitness;
|
||||||
enum stap_arg_bitness b;
|
bool got_minus = false;
|
||||||
int got_minus = 0;
|
|
||||||
struct expression *expr;
|
|
||||||
|
|
||||||
memset (&arg, 0, sizeof (arg));
|
|
||||||
|
|
||||||
/* We expect to find something like:
|
/* We expect to find something like:
|
||||||
|
|
||||||
|
@ -1128,30 +1214,30 @@ stap_parse_probe_arguments (struct stap_probe *probe, struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
/* Discard the `-'. */
|
/* Discard the `-'. */
|
||||||
++cur;
|
++cur;
|
||||||
got_minus = 1;
|
got_minus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Defining the bitness. */
|
/* Defining the bitness. */
|
||||||
switch (*cur)
|
switch (*cur)
|
||||||
{
|
{
|
||||||
case '1':
|
case '1':
|
||||||
b = (got_minus ? STAP_ARG_BITNESS_8BIT_SIGNED
|
bitness = (got_minus ? STAP_ARG_BITNESS_8BIT_SIGNED
|
||||||
: STAP_ARG_BITNESS_8BIT_UNSIGNED);
|
: STAP_ARG_BITNESS_8BIT_UNSIGNED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '2':
|
case '2':
|
||||||
b = (got_minus ? STAP_ARG_BITNESS_16BIT_SIGNED
|
bitness = (got_minus ? STAP_ARG_BITNESS_16BIT_SIGNED
|
||||||
: STAP_ARG_BITNESS_16BIT_UNSIGNED);
|
: STAP_ARG_BITNESS_16BIT_UNSIGNED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
b = (got_minus ? STAP_ARG_BITNESS_32BIT_SIGNED
|
bitness = (got_minus ? STAP_ARG_BITNESS_32BIT_SIGNED
|
||||||
: STAP_ARG_BITNESS_32BIT_UNSIGNED);
|
: STAP_ARG_BITNESS_32BIT_UNSIGNED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '8':
|
case '8':
|
||||||
b = (got_minus ? STAP_ARG_BITNESS_64BIT_SIGNED
|
bitness = (got_minus ? STAP_ARG_BITNESS_64BIT_SIGNED
|
||||||
: STAP_ARG_BITNESS_64BIT_UNSIGNED);
|
: STAP_ARG_BITNESS_64BIT_UNSIGNED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1159,67 +1245,60 @@ stap_parse_probe_arguments (struct stap_probe *probe, struct gdbarch *gdbarch)
|
||||||
/* We have an error, because we don't expect anything
|
/* We have an error, because we don't expect anything
|
||||||
except 1, 2, 4 and 8. */
|
except 1, 2, 4 and 8. */
|
||||||
warning (_("unrecognized bitness %s%c' for probe `%s'"),
|
warning (_("unrecognized bitness %s%c' for probe `%s'"),
|
||||||
got_minus ? "`-" : "`", *cur, probe->p.name);
|
got_minus ? "`-" : "`", *cur,
|
||||||
|
this->get_name ().c_str ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arg.bitness = b;
|
|
||||||
|
|
||||||
/* Discard the number and the `@' sign. */
|
/* Discard the number and the `@' sign. */
|
||||||
cur += 2;
|
cur += 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
arg.bitness = STAP_ARG_BITNESS_UNDEFINED;
|
bitness = STAP_ARG_BITNESS_UNDEFINED;
|
||||||
|
|
||||||
arg.atype = stap_get_expected_argument_type (gdbarch, arg.bitness,
|
struct type *atype
|
||||||
probe);
|
= stap_get_expected_argument_type (gdbarch, bitness,
|
||||||
|
this->get_name ().c_str ());
|
||||||
|
|
||||||
expr = stap_parse_argument (&cur, arg.atype, gdbarch);
|
expression_up expr = stap_parse_argument (&cur, atype, gdbarch);
|
||||||
|
|
||||||
if (stap_expression_debug)
|
if (stap_expression_debug)
|
||||||
dump_raw_expression (expr, gdb_stdlog,
|
dump_raw_expression (expr.get (), gdb_stdlog,
|
||||||
"before conversion to prefix form");
|
"before conversion to prefix form");
|
||||||
|
|
||||||
prefixify_expression (expr);
|
prefixify_expression (expr.get ());
|
||||||
|
|
||||||
if (stap_expression_debug)
|
if (stap_expression_debug)
|
||||||
dump_prefix_expression (expr, gdb_stdlog);
|
dump_prefix_expression (expr.get (), gdb_stdlog);
|
||||||
|
|
||||||
arg.aexpr = expr;
|
m_parsed_args.emplace_back (bitness, atype, std::move (expr));
|
||||||
|
|
||||||
/* Start it over again. */
|
/* Start it over again. */
|
||||||
cur = skip_spaces (cur);
|
cur = skip_spaces (cur);
|
||||||
|
|
||||||
VEC_safe_push (stap_probe_arg_s, probe->args_u.vec, &arg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implementation of the get_probe_address method. */
|
/* Implementation of the get_relocated_address method. */
|
||||||
|
|
||||||
static CORE_ADDR
|
CORE_ADDR
|
||||||
stap_get_probe_address (struct probe *probe, struct objfile *objfile)
|
stap_probe::get_relocated_address (struct objfile *objfile)
|
||||||
{
|
{
|
||||||
return probe->address + ANOFFSET (objfile->section_offsets,
|
return this->get_address () + ANOFFSET (objfile->section_offsets,
|
||||||
SECT_OFF_DATA (objfile));
|
SECT_OFF_DATA (objfile));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given PROBE, returns the number of arguments present in that probe's
|
/* Given PROBE, returns the number of arguments present in that probe's
|
||||||
argument string. */
|
argument string. */
|
||||||
|
|
||||||
static unsigned
|
unsigned
|
||||||
stap_get_probe_argument_count (struct probe *probe_generic,
|
stap_probe::get_argument_count (struct frame_info *frame)
|
||||||
struct frame_info *frame)
|
|
||||||
{
|
{
|
||||||
struct stap_probe *probe = (struct stap_probe *) probe_generic;
|
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = get_frame_arch (frame);
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
if (!m_have_parsed_args)
|
||||||
|
|
||||||
if (!probe->args_parsed)
|
|
||||||
{
|
{
|
||||||
if (can_evaluate_probe_arguments (probe_generic))
|
if (this->can_evaluate_arguments ())
|
||||||
stap_parse_probe_arguments (probe, gdbarch);
|
this->parse_arguments (gdbarch);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static int have_warned_stap_incomplete = 0;
|
static int have_warned_stap_incomplete = 0;
|
||||||
|
@ -1234,13 +1313,12 @@ stap_get_probe_argument_count (struct probe *probe_generic,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Marking the arguments as "already parsed". */
|
/* Marking the arguments as "already parsed". */
|
||||||
probe->args_u.vec = NULL;
|
m_have_parsed_args = true;
|
||||||
probe->args_parsed = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gdb_assert (probe->args_parsed);
|
gdb_assert (m_have_parsed_args);
|
||||||
return VEC_length (stap_probe_arg_s, probe->args_u.vec);
|
return m_parsed_args.size ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if OP is a valid operator inside a probe argument, or zero
|
/* Return 1 if OP is a valid operator inside a probe argument, or zero
|
||||||
|
@ -1279,36 +1357,12 @@ stap_is_operator (const char *op)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return argument N of probe PROBE.
|
/* Implement the `can_evaluate_arguments' method. */
|
||||||
|
|
||||||
If the probe's arguments have not been parsed yet, parse them. If
|
bool
|
||||||
there are no arguments, throw an exception (error). Otherwise,
|
stap_probe::can_evaluate_arguments () const
|
||||||
return the requested argument. */
|
|
||||||
|
|
||||||
static struct stap_probe_arg *
|
|
||||||
stap_get_arg (struct stap_probe *probe, unsigned n, struct gdbarch *gdbarch)
|
|
||||||
{
|
{
|
||||||
if (!probe->args_parsed)
|
struct gdbarch *gdbarch = this->get_gdbarch ();
|
||||||
stap_parse_probe_arguments (probe, gdbarch);
|
|
||||||
|
|
||||||
gdb_assert (probe->args_parsed);
|
|
||||||
if (probe->args_u.vec == NULL)
|
|
||||||
internal_error (__FILE__, __LINE__,
|
|
||||||
_("Probe '%s' apparently does not have arguments, but \n"
|
|
||||||
"GDB is requesting its argument number %u anyway. "
|
|
||||||
"This should not happen. Please report this bug."),
|
|
||||||
probe->p.name, n);
|
|
||||||
|
|
||||||
return VEC_index (stap_probe_arg_s, probe->args_u.vec, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implement the `can_evaluate_probe_arguments' method of probe_ops. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
stap_can_evaluate_probe_arguments (struct probe *probe_generic)
|
|
||||||
{
|
|
||||||
struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
|
|
||||||
struct gdbarch *gdbarch = stap_probe->p.arch;
|
|
||||||
|
|
||||||
/* For SystemTap probes, we have to guarantee that the method
|
/* For SystemTap probes, we have to guarantee that the method
|
||||||
stap_is_single_operand is defined on gdbarch. If it is not, then it
|
stap_is_single_operand is defined on gdbarch. If it is not, then it
|
||||||
|
@ -1319,71 +1373,42 @@ stap_can_evaluate_probe_arguments (struct probe *probe_generic)
|
||||||
/* Evaluate the probe's argument N (indexed from 0), returning a value
|
/* Evaluate the probe's argument N (indexed from 0), returning a value
|
||||||
corresponding to it. Assertion is thrown if N does not exist. */
|
corresponding to it. Assertion is thrown if N does not exist. */
|
||||||
|
|
||||||
static struct value *
|
struct value *
|
||||||
stap_evaluate_probe_argument (struct probe *probe_generic, unsigned n,
|
stap_probe::evaluate_argument (unsigned n, struct frame_info *frame)
|
||||||
struct frame_info *frame)
|
|
||||||
{
|
{
|
||||||
struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
|
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
||||||
struct stap_probe_arg *arg;
|
struct stap_probe_arg *arg;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
struct gdbarch *gdbarch = get_frame_arch (frame);
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
arg = this->get_arg_by_number (n, gdbarch);
|
||||||
|
return evaluate_subexp_standard (arg->atype, arg->aexpr.get (), &pos,
|
||||||
arg = stap_get_arg (stap_probe, n, gdbarch);
|
EVAL_NORMAL);
|
||||||
return evaluate_subexp_standard (arg->atype, arg->aexpr, &pos, EVAL_NORMAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile the probe's argument N (indexed from 0) to agent expression.
|
/* Compile the probe's argument N (indexed from 0) to agent expression.
|
||||||
Assertion is thrown if N does not exist. */
|
Assertion is thrown if N does not exist. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
stap_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
|
stap_probe::compile_to_ax (struct agent_expr *expr, struct axs_value *value,
|
||||||
struct axs_value *value, unsigned n)
|
unsigned n)
|
||||||
{
|
{
|
||||||
struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
|
|
||||||
struct stap_probe_arg *arg;
|
struct stap_probe_arg *arg;
|
||||||
union exp_element *pc;
|
union exp_element *pc;
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
arg = this->get_arg_by_number (n, expr->gdbarch);
|
||||||
|
|
||||||
arg = stap_get_arg (stap_probe, n, expr->gdbarch);
|
|
||||||
|
|
||||||
pc = arg->aexpr->elts;
|
pc = arg->aexpr->elts;
|
||||||
gen_expr (arg->aexpr, &pc, expr, value);
|
gen_expr (arg->aexpr.get (), &pc, expr, value);
|
||||||
|
|
||||||
require_rvalue (expr, value);
|
require_rvalue (expr, value);
|
||||||
value->type = arg->atype;
|
value->type = arg->atype;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy (free) the data related to PROBE. PROBE memory itself is not feed
|
|
||||||
as it is allocated on an obstack. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
stap_probe_destroy (struct probe *probe_generic)
|
|
||||||
{
|
|
||||||
struct stap_probe *probe = (struct stap_probe *) probe_generic;
|
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
|
||||||
|
|
||||||
if (probe->args_parsed)
|
|
||||||
{
|
|
||||||
struct stap_probe_arg *arg;
|
|
||||||
int ix;
|
|
||||||
|
|
||||||
for (ix = 0; VEC_iterate (stap_probe_arg_s, probe->args_u.vec, ix, arg);
|
|
||||||
++ix)
|
|
||||||
xfree (arg->aexpr);
|
|
||||||
VEC_free (stap_probe_arg_s, probe->args_u.vec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set or clear a SystemTap semaphore. ADDRESS is the semaphore's
|
/* Set or clear a SystemTap semaphore. ADDRESS is the semaphore's
|
||||||
address. SET is zero if the semaphore should be cleared, or one
|
address. SET is zero if the semaphore should be cleared, or one if
|
||||||
if it should be set. This is a helper function for `stap_semaphore_down'
|
it should be set. This is a helper function for
|
||||||
and `stap_semaphore_up'. */
|
'stap_probe::set_semaphore' and 'stap_probe::clear_semaphore'. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch)
|
stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch)
|
||||||
|
@ -1419,41 +1444,47 @@ stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch)
|
||||||
warning (_("Could not write the value of a SystemTap semaphore."));
|
warning (_("Could not write the value of a SystemTap semaphore."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set a SystemTap semaphore. SEM is the semaphore's address. Semaphores
|
/* Implementation of the 'set_semaphore' method.
|
||||||
act as reference counters, so calls to this function must be paired with
|
|
||||||
calls to `stap_semaphore_down'.
|
|
||||||
|
|
||||||
This function and `stap_semaphore_down' race with another tool changing
|
SystemTap semaphores act as reference counters, so calls to this
|
||||||
the probes, but that is too rare to care. */
|
function must be paired with calls to 'clear_semaphore'.
|
||||||
|
|
||||||
static void
|
This function and 'clear_semaphore' race with another tool
|
||||||
stap_set_semaphore (struct probe *probe_generic, struct objfile *objfile,
|
changing the probes, but that is too rare to care. */
|
||||||
struct gdbarch *gdbarch)
|
|
||||||
|
void
|
||||||
|
stap_probe::set_semaphore (struct objfile *objfile, struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
struct stap_probe *probe = (struct stap_probe *) probe_generic;
|
stap_modify_semaphore (this->get_relocated_address (objfile), 1, gdbarch);
|
||||||
CORE_ADDR addr;
|
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
|
||||||
|
|
||||||
addr = (probe->sem_addr
|
|
||||||
+ ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)));
|
|
||||||
stap_modify_semaphore (addr, 1, gdbarch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear a SystemTap semaphore. SEM is the semaphore's address. */
|
/* Implementation of the 'clear_semaphore' method. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
stap_clear_semaphore (struct probe *probe_generic, struct objfile *objfile,
|
stap_probe::clear_semaphore (struct objfile *objfile, struct gdbarch *gdbarch)
|
||||||
struct gdbarch *gdbarch)
|
|
||||||
{
|
{
|
||||||
struct stap_probe *probe = (struct stap_probe *) probe_generic;
|
stap_modify_semaphore (this->get_relocated_address (objfile), 0, gdbarch);
|
||||||
CORE_ADDR addr;
|
}
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
/* Implementation of the 'get_static_ops' method. */
|
||||||
|
|
||||||
addr = (probe->sem_addr
|
const static_probe_ops *
|
||||||
+ ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile)));
|
stap_probe::get_static_ops () const
|
||||||
stap_modify_semaphore (addr, 0, gdbarch);
|
{
|
||||||
|
return &stap_static_probe_ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implementation of the 'gen_info_probes_table_values' method. */
|
||||||
|
|
||||||
|
std::vector<const char *>
|
||||||
|
stap_probe::gen_info_probes_table_values () const
|
||||||
|
{
|
||||||
|
const char *val = NULL;
|
||||||
|
|
||||||
|
if (m_sem_addr != 0)
|
||||||
|
val = print_core_address (this->get_gdbarch (), m_sem_addr);
|
||||||
|
|
||||||
|
return std::vector<const char *> { val };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function that parses the information contained in a
|
/* Helper function that parses the information contained in a
|
||||||
|
@ -1478,21 +1509,14 @@ handle_stap_probe (struct objfile *objfile, struct sdt_note *el,
|
||||||
int size = bfd_get_arch_size (abfd) / 8;
|
int size = bfd_get_arch_size (abfd) / 8;
|
||||||
struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
||||||
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
|
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
|
||||||
CORE_ADDR base_ref;
|
|
||||||
const char *probe_args = NULL;
|
|
||||||
struct stap_probe *ret;
|
|
||||||
|
|
||||||
ret = XOBNEW (&objfile->per_bfd->storage_obstack, struct stap_probe);
|
|
||||||
ret->p.pops = &stap_probe_ops;
|
|
||||||
ret->p.arch = gdbarch;
|
|
||||||
|
|
||||||
/* Provider and the name of the probe. */
|
/* Provider and the name of the probe. */
|
||||||
ret->p.provider = (char *) &el->data[3 * size];
|
const char *provider = (const char *) &el->data[3 * size];
|
||||||
ret->p.name = ((const char *)
|
const char *name = ((const char *)
|
||||||
memchr (ret->p.provider, '\0',
|
memchr (provider, '\0',
|
||||||
(char *) el->data + el->size - ret->p.provider));
|
(char *) el->data + el->size - provider));
|
||||||
/* Making sure there is a name. */
|
/* Making sure there is a name. */
|
||||||
if (ret->p.name == NULL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
complaint (&symfile_complaints, _("corrupt probe name when "
|
complaint (&symfile_complaints, _("corrupt probe name when "
|
||||||
"reading `%s'"),
|
"reading `%s'"),
|
||||||
|
@ -1503,32 +1527,32 @@ handle_stap_probe (struct objfile *objfile, struct sdt_note *el,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
++ret->p.name;
|
++name;
|
||||||
|
|
||||||
/* Retrieving the probe's address. */
|
/* Retrieving the probe's address. */
|
||||||
ret->p.address = extract_typed_address (&el->data[0], ptr_type);
|
CORE_ADDR address = extract_typed_address (&el->data[0], ptr_type);
|
||||||
|
|
||||||
/* Link-time sh_addr of `.stapsdt.base' section. */
|
/* Link-time sh_addr of `.stapsdt.base' section. */
|
||||||
base_ref = extract_typed_address (&el->data[size], ptr_type);
|
CORE_ADDR base_ref = extract_typed_address (&el->data[size], ptr_type);
|
||||||
|
|
||||||
/* Semaphore address. */
|
/* Semaphore address. */
|
||||||
ret->sem_addr = extract_typed_address (&el->data[2 * size], ptr_type);
|
CORE_ADDR sem_addr = extract_typed_address (&el->data[2 * size], ptr_type);
|
||||||
|
|
||||||
ret->p.address += base - base_ref;
|
address += base - base_ref;
|
||||||
if (ret->sem_addr != 0)
|
if (sem_addr != 0)
|
||||||
ret->sem_addr += base - base_ref;
|
sem_addr += base - base_ref;
|
||||||
|
|
||||||
/* Arguments. We can only extract the argument format if there is a valid
|
/* Arguments. We can only extract the argument format if there is a valid
|
||||||
name for this probe. */
|
name for this probe. */
|
||||||
probe_args = ((const char*)
|
const char *probe_args = ((const char*)
|
||||||
memchr (ret->p.name, '\0',
|
memchr (name, '\0',
|
||||||
(char *) el->data + el->size - ret->p.name));
|
(char *) el->data + el->size - name));
|
||||||
|
|
||||||
if (probe_args != NULL)
|
if (probe_args != NULL)
|
||||||
++probe_args;
|
++probe_args;
|
||||||
|
|
||||||
if (probe_args == NULL
|
if (probe_args == NULL
|
||||||
|| (memchr (probe_args, '\0', (char *) el->data + el->size - ret->p.name)
|
|| (memchr (probe_args, '\0', (char *) el->data + el->size - name)
|
||||||
!= el->data + el->size - 1))
|
!= el->data + el->size - 1))
|
||||||
{
|
{
|
||||||
complaint (&symfile_complaints, _("corrupt probe argument when "
|
complaint (&symfile_complaints, _("corrupt probe argument when "
|
||||||
|
@ -1539,11 +1563,11 @@ handle_stap_probe (struct objfile *objfile, struct sdt_note *el,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->args_parsed = 0;
|
stap_probe *ret = new stap_probe (std::string (name), std::string (provider),
|
||||||
ret->args_u.text = probe_args;
|
address, gdbarch, sem_addr, probe_args);
|
||||||
|
|
||||||
/* Successfully created probe. */
|
/* Successfully created probe. */
|
||||||
probesp->push_back ((struct probe *) ret);
|
probesp->push_back (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function which tries to find the base address of the SystemTap
|
/* Helper function which tries to find the base address of the SystemTap
|
||||||
|
@ -1584,11 +1608,21 @@ get_stap_base_address (bfd *obfd, bfd_vma *base)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function for `elf_get_probes', which gathers information about all
|
/* Implementation of the 'is_linespec' method. */
|
||||||
SystemTap probes from OBJFILE. */
|
|
||||||
|
|
||||||
static void
|
bool
|
||||||
stap_get_probes (std::vector<probe *> *probesp, struct objfile *objfile)
|
stap_static_probe_ops::is_linespec (const char **linespecp) const
|
||||||
|
{
|
||||||
|
static const char *const keywords[] = { "-pstap", "-probe-stap", NULL };
|
||||||
|
|
||||||
|
return probe_is_linespec_by_keyword (linespecp, keywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implementation of the 'get_probes' method. */
|
||||||
|
|
||||||
|
void
|
||||||
|
stap_static_probe_ops::get_probes (std::vector<probe *> *probesp,
|
||||||
|
struct objfile *objfile) const
|
||||||
{
|
{
|
||||||
/* If we are here, then this is the first time we are parsing the
|
/* If we are here, then this is the first time we are parsing the
|
||||||
SystemTap probe's information. We basically have to count how many
|
SystemTap probe's information. We basically have to count how many
|
||||||
|
@ -1640,83 +1674,37 @@ stap_get_probes (std::vector<probe *> *probesp, struct objfile *objfile)
|
||||||
|
|
||||||
/* Implementation of the type_name method. */
|
/* Implementation of the type_name method. */
|
||||||
|
|
||||||
static const char *
|
const char *
|
||||||
stap_type_name (struct probe *probe)
|
stap_static_probe_ops::type_name () const
|
||||||
{
|
{
|
||||||
gdb_assert (probe->pops == &stap_probe_ops);
|
|
||||||
return "stap";
|
return "stap";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/* Implementation of the 'gen_info_probes_table_header' method. */
|
||||||
stap_probe_is_linespec (const char **linespecp)
|
|
||||||
{
|
|
||||||
static const char *const keywords[] = { "-pstap", "-probe-stap", NULL };
|
|
||||||
|
|
||||||
return probe_is_linespec_by_keyword (linespecp, keywords);
|
std::vector<struct info_probe_column>
|
||||||
}
|
stap_static_probe_ops::gen_info_probes_table_header () const
|
||||||
|
|
||||||
static void
|
|
||||||
stap_gen_info_probes_table_header (VEC (info_probe_column_s) **heads)
|
|
||||||
{
|
{
|
||||||
info_probe_column_s stap_probe_column;
|
struct info_probe_column stap_probe_column;
|
||||||
|
|
||||||
stap_probe_column.field_name = "semaphore";
|
stap_probe_column.field_name = "semaphore";
|
||||||
stap_probe_column.print_name = _("Semaphore");
|
stap_probe_column.print_name = _("Semaphore");
|
||||||
|
|
||||||
VEC_safe_push (info_probe_column_s, *heads, &stap_probe_column);
|
return std::vector<struct info_probe_column> { stap_probe_column };
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
stap_gen_info_probes_table_values (struct probe *probe_generic,
|
|
||||||
VEC (const_char_ptr) **ret)
|
|
||||||
{
|
|
||||||
struct stap_probe *probe = (struct stap_probe *) probe_generic;
|
|
||||||
struct gdbarch *gdbarch;
|
|
||||||
const char *val = NULL;
|
|
||||||
|
|
||||||
gdb_assert (probe_generic->pops == &stap_probe_ops);
|
|
||||||
|
|
||||||
gdbarch = probe->p.arch;
|
|
||||||
|
|
||||||
if (probe->sem_addr != 0)
|
|
||||||
val = print_core_address (gdbarch, probe->sem_addr);
|
|
||||||
|
|
||||||
VEC_safe_push (const_char_ptr, *ret, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SystemTap probe_ops. */
|
|
||||||
|
|
||||||
const struct probe_ops stap_probe_ops =
|
|
||||||
{
|
|
||||||
stap_probe_is_linespec,
|
|
||||||
stap_get_probes,
|
|
||||||
stap_get_probe_address,
|
|
||||||
stap_get_probe_argument_count,
|
|
||||||
stap_can_evaluate_probe_arguments,
|
|
||||||
stap_evaluate_probe_argument,
|
|
||||||
stap_compile_to_ax,
|
|
||||||
stap_set_semaphore,
|
|
||||||
stap_clear_semaphore,
|
|
||||||
stap_probe_destroy,
|
|
||||||
stap_type_name,
|
|
||||||
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. */
|
/* Implementation of the `info probes stap' command. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
info_probes_stap_command (const char *arg, int from_tty)
|
info_probes_stap_command (const char *arg, int from_tty)
|
||||||
{
|
{
|
||||||
info_probes_for_ops (arg, from_tty, &stap_probe_ops);
|
info_probes_for_spops (arg, from_tty, &stap_static_probe_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_stap_probe (void)
|
_initialize_stap_probe (void)
|
||||||
{
|
{
|
||||||
all_probe_ops.push_back (&stap_probe_ops);
|
all_static_probe_ops.push_back (&stap_static_probe_ops);
|
||||||
|
|
||||||
add_setshow_zuinteger_cmd ("stap-expression", class_maintenance,
|
add_setshow_zuinteger_cmd ("stap-expression", class_maintenance,
|
||||||
&stap_expression_debug,
|
&stap_expression_debug,
|
||||||
|
|
Loading…
Reference in New Issue