| Index: gdb/stap-probe.c
|
| diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
|
| index 506e6c3e0cc9da27e4caebef2e34be0147b553df..e09d5d62a4578e0cb6d6e6122b134d3fc697c2be 100644
|
| --- a/gdb/stap-probe.c
|
| +++ b/gdb/stap-probe.c
|
| @@ -1,6 +1,6 @@
|
| /* SystemTap probe support for GDB.
|
|
|
| - Copyright (C) 2012 Free Software Foundation, Inc.
|
| + Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -53,7 +53,7 @@ static const struct probe_ops stap_probe_ops;
|
| /* Should we display debug information for the probe's argument expression
|
| parsing? */
|
|
|
| -static int stap_expression_debug = 0;
|
| +static unsigned int stap_expression_debug = 0;
|
|
|
| /* The various possibilities of bitness defined for a probe's argument.
|
|
|
| @@ -422,9 +422,11 @@ stap_parse_register_operand (struct stap_parse_info *p)
|
| {
|
| /* The value of the displacement. */
|
| long displacement;
|
| + char *endp;
|
|
|
| disp_p = 1;
|
| - displacement = strtol (p->arg, (char **) &p->arg, 10);
|
| + displacement = strtol (p->arg, &endp, 10);
|
| + p->arg = endp;
|
|
|
| /* Generating the expression for the displacement. */
|
| write_exp_elt_opcode (OP_LONG);
|
| @@ -598,7 +600,12 @@ stap_parse_single_operand (struct stap_parse_info *p)
|
| tmp = skip_spaces_const (tmp);
|
|
|
| if (isdigit (*tmp))
|
| - number = strtol (tmp, (char **) &tmp, 10);
|
| + {
|
| + char *endp;
|
| +
|
| + number = strtol (tmp, &endp, 10);
|
| + tmp = endp;
|
| + }
|
|
|
| if (!reg_ind_prefix
|
| || strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
|
| @@ -627,11 +634,13 @@ stap_parse_single_operand (struct stap_parse_info *p)
|
| {
|
| /* A temporary variable, needed for lookahead. */
|
| const char *tmp = p->arg;
|
| + char *endp;
|
| long number;
|
|
|
| /* We can be dealing with a numeric constant (if `const_prefix' is
|
| NULL), or with a register displacement. */
|
| - number = strtol (tmp, (char **) &tmp, 10);
|
| + number = strtol (tmp, &endp, 10);
|
| + tmp = endp;
|
|
|
| if (p->inside_paren_p)
|
| tmp = skip_spaces_const (tmp);
|
| @@ -667,9 +676,11 @@ stap_parse_single_operand (struct stap_parse_info *p)
|
| {
|
| /* We are dealing with a numeric constant. */
|
| long number;
|
| + char *endp;
|
|
|
| p->arg += const_prefix_len;
|
| - number = strtol (p->arg, (char **) &p->arg, 10);
|
| + number = strtol (p->arg, &endp, 10);
|
| + p->arg = endp;
|
|
|
| write_exp_elt_opcode (OP_LONG);
|
| write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
|
| @@ -903,10 +914,10 @@ stap_parse_argument (const char **arg, struct type *atype,
|
| this information. */
|
|
|
| static void
|
| -stap_parse_probe_arguments (struct stap_probe *probe, struct objfile *objfile)
|
| +stap_parse_probe_arguments (struct stap_probe *probe)
|
| {
|
| const char *cur;
|
| - struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
| + struct gdbarch *gdbarch = get_objfile_arch (probe->p.objfile);
|
|
|
| gdb_assert (!probe->args_parsed);
|
| cur = probe->args_u.text;
|
| @@ -991,15 +1002,34 @@ stap_parse_probe_arguments (struct stap_probe *probe, struct objfile *objfile)
|
| argument string. */
|
|
|
| static unsigned
|
| -stap_get_probe_argument_count (struct probe *probe_generic,
|
| - struct objfile *objfile)
|
| +stap_get_probe_argument_count (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)
|
| - stap_parse_probe_arguments (probe, objfile);
|
| + {
|
| + if (probe_generic->pops->can_evaluate_probe_arguments (probe_generic))
|
| + stap_parse_probe_arguments (probe);
|
| + else
|
| + {
|
| + static int have_warned_stap_incomplete = 0;
|
| +
|
| + if (!have_warned_stap_incomplete)
|
| + {
|
| + warning (_(
|
| +"The SystemTap SDT probe support is not fully implemented on this target;\n"
|
| +"you will not be able to inspect the arguments of the probes.\n"
|
| +"Please report a bug against GDB requesting a port to this target."));
|
| + have_warned_stap_incomplete = 1;
|
| + }
|
| +
|
| + /* Marking the arguments as "already parsed". */
|
| + probe->args_u.vec = NULL;
|
| + probe->args_parsed = 1;
|
| + }
|
| + }
|
|
|
| gdb_assert (probe->args_parsed);
|
| return VEC_length (stap_probe_arg_s, probe->args_u.vec);
|
| @@ -1042,20 +1072,33 @@ stap_is_operator (const char *op)
|
| }
|
|
|
| static struct stap_probe_arg *
|
| -stap_get_arg (struct stap_probe *probe, struct objfile *objfile, unsigned n)
|
| +stap_get_arg (struct stap_probe *probe, unsigned n)
|
| {
|
| if (!probe->args_parsed)
|
| - stap_parse_probe_arguments (probe, objfile);
|
| + stap_parse_probe_arguments (probe);
|
|
|
| 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 = get_objfile_arch (stap_probe->p.objfile);
|
| +
|
| + /* For SystemTap probes, we have to guarantee that the method
|
| + stap_is_single_operand is defined on gdbarch. If it is not, then it
|
| + means that argument evaluation is not implemented on this target. */
|
| + return gdbarch_stap_is_single_operand_p (gdbarch);
|
| +}
|
| +
|
| /* Evaluate the probe's argument N (indexed from 0), returning a value
|
| corresponding to it. Assertion is thrown if N does not exist. */
|
|
|
| static struct value *
|
| -stap_evaluate_probe_argument (struct probe *probe_generic,
|
| - struct objfile *objfile, unsigned n)
|
| +stap_evaluate_probe_argument (struct probe *probe_generic, unsigned n)
|
| {
|
| struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
|
| struct stap_probe_arg *arg;
|
| @@ -1063,7 +1106,7 @@ stap_evaluate_probe_argument (struct probe *probe_generic,
|
|
|
| gdb_assert (probe_generic->pops == &stap_probe_ops);
|
|
|
| - arg = stap_get_arg (stap_probe, objfile, n);
|
| + arg = stap_get_arg (stap_probe, n);
|
| return evaluate_subexp_standard (arg->atype, arg->aexpr, &pos, EVAL_NORMAL);
|
| }
|
|
|
| @@ -1071,9 +1114,8 @@ stap_evaluate_probe_argument (struct probe *probe_generic,
|
| Assertion is thrown if N does not exist. */
|
|
|
| static void
|
| -stap_compile_to_ax (struct probe *probe_generic, struct objfile *objfile,
|
| - struct agent_expr *expr, struct axs_value *value,
|
| - unsigned n)
|
| +stap_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
|
| + struct axs_value *value, unsigned n)
|
| {
|
| struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
|
| struct stap_probe_arg *arg;
|
| @@ -1081,7 +1123,7 @@ stap_compile_to_ax (struct probe *probe_generic, struct objfile *objfile,
|
|
|
| gdb_assert (probe_generic->pops == &stap_probe_ops);
|
|
|
| - arg = stap_get_arg (stap_probe, objfile, n);
|
| + arg = stap_get_arg (stap_probe, n);
|
|
|
| pc = arg->aexpr->elts;
|
| gen_expr (arg->aexpr, &pc, expr, value);
|
| @@ -1124,20 +1166,18 @@ compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar,
|
| struct frame_info *frame = get_selected_frame (_("No frame selected"));
|
| CORE_ADDR pc = get_frame_pc (frame);
|
| int sel = (int) (uintptr_t) data;
|
| - struct objfile *objfile;
|
| struct 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, &objfile);
|
| + pc_probe = find_probe_by_pc (pc);
|
| if (pc_probe == NULL)
|
| error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc));
|
|
|
| - n_args
|
| - = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile,
|
| - pc_probe);
|
| + n_args = get_probe_argument_count (pc_probe);
|
| if (sel == -1)
|
| return value_from_longest (builtin_type (arch)->builtin_int, n_args);
|
|
|
| @@ -1145,9 +1185,7 @@ compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar,
|
| error (_("Invalid probe argument %d -- probe has %u arguments available"),
|
| sel, n_args);
|
|
|
| - return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile,
|
| - pc_probe,
|
| - sel);
|
| + return evaluate_probe_argument (pc_probe, sel);
|
| }
|
|
|
| /* This is called to compile one of the $_probe_arg* convenience
|
| @@ -1159,35 +1197,33 @@ compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr,
|
| {
|
| CORE_ADDR pc = expr->scope;
|
| int sel = (int) (uintptr_t) data;
|
| - struct objfile *objfile;
|
| struct probe *pc_probe;
|
| - int n_probes;
|
| + const struct sym_probe_fns *pc_probe_fns;
|
| + int n_args;
|
|
|
| /* SEL == -1 means "_probe_argc". */
|
| gdb_assert (sel >= -1);
|
|
|
| - pc_probe = find_probe_by_pc (pc, &objfile);
|
| + pc_probe = find_probe_by_pc (pc);
|
| if (pc_probe == NULL)
|
| error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc));
|
|
|
| - n_probes
|
| - = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile,
|
| - pc_probe);
|
| + n_args = get_probe_argument_count (pc_probe);
|
| +
|
| if (sel == -1)
|
| {
|
| value->kind = axs_rvalue;
|
| value->type = builtin_type (expr->gdbarch)->builtin_int;
|
| - ax_const_l (expr, n_probes);
|
| + ax_const_l (expr, n_args);
|
| return;
|
| }
|
|
|
| gdb_assert (sel >= 0);
|
| - if (sel >= n_probes)
|
| + if (sel >= n_args)
|
| error (_("Invalid probe argument %d -- probe has %d arguments available"),
|
| - sel, n_probes);
|
| + sel, n_args);
|
|
|
| - objfile->sf->sym_probe_fns->sym_compile_to_ax (objfile, pc_probe,
|
| - expr, value, sel);
|
| + pc_probe->pops->compile_to_ax (pc_probe, expr, value, sel);
|
| }
|
|
|
|
|
| @@ -1297,16 +1333,18 @@ handle_stap_probe (struct objfile *objfile, struct sdt_note *el,
|
|
|
| ret = obstack_alloc (&objfile->objfile_obstack, sizeof (*ret));
|
| ret->p.pops = &stap_probe_ops;
|
| + ret->p.objfile = objfile;
|
|
|
| /* Provider and the name of the probe. */
|
| - ret->p.provider = &el->data[3 * size];
|
| + ret->p.provider = (char *) &el->data[3 * size];
|
| ret->p.name = memchr (ret->p.provider, '\0',
|
| (char *) el->data + el->size - ret->p.provider);
|
| /* Making sure there is a name. */
|
| if (!ret->p.name)
|
| {
|
| complaint (&symfile_complaints, _("corrupt probe name when "
|
| - "reading `%s'"), objfile->name);
|
| + "reading `%s'"),
|
| + objfile_name (objfile));
|
|
|
| /* There is no way to use a probe without a name or a provider, so
|
| returning zero here makes sense. */
|
| @@ -1345,7 +1383,8 @@ handle_stap_probe (struct objfile *objfile, struct sdt_note *el,
|
| != el->data + el->size - 1))
|
| {
|
| complaint (&symfile_complaints, _("corrupt probe argument when "
|
| - "reading `%s'"), objfile->name);
|
| + "reading `%s'"),
|
| + objfile_name (objfile));
|
| /* If the argument string is NULL, it means some problem happened with
|
| it. So we return 0. */
|
| return;
|
| @@ -1481,15 +1520,16 @@ stap_gen_info_probes_table_header (VEC (info_probe_column_s) **heads)
|
|
|
| static void
|
| stap_gen_info_probes_table_values (struct probe *probe_generic,
|
| - struct objfile *objfile,
|
| VEC (const_char_ptr) **ret)
|
| {
|
| struct stap_probe *probe = (struct stap_probe *) probe_generic;
|
| - struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
| + struct gdbarch *gdbarch;
|
| const char *val = NULL;
|
|
|
| gdb_assert (probe_generic->pops == &stap_probe_ops);
|
|
|
| + gdbarch = get_objfile_arch (probe->p.objfile);
|
| +
|
| if (probe->sem_addr)
|
| val = print_core_address (gdbarch, probe->sem_addr);
|
|
|
| @@ -1504,6 +1544,7 @@ static const struct probe_ops stap_probe_ops =
|
| stap_get_probes,
|
| stap_relocate,
|
| stap_get_probe_argument_count,
|
| + stap_can_evaluate_probe_arguments,
|
| stap_evaluate_probe_argument,
|
| stap_compile_to_ax,
|
| stap_set_semaphore,
|
| @@ -1528,15 +1569,15 @@ _initialize_stap_probe (void)
|
| {
|
| VEC_safe_push (probe_ops_cp, all_probe_ops, &stap_probe_ops);
|
|
|
| - add_setshow_zinteger_cmd ("stap-expression", class_maintenance,
|
| - &stap_expression_debug,
|
| - _("Set SystemTap expression debugging."),
|
| - _("Show SystemTap expression debugging."),
|
| - _("When non-zero, the internal representation "
|
| - "of SystemTap expressions will be printed."),
|
| - NULL,
|
| - show_stapexpressiondebug,
|
| - &setdebuglist, &showdebuglist);
|
| + add_setshow_zuinteger_cmd ("stap-expression", class_maintenance,
|
| + &stap_expression_debug,
|
| + _("Set SystemTap expression debugging."),
|
| + _("Show SystemTap expression debugging."),
|
| + _("When non-zero, the internal representation "
|
| + "of SystemTap expressions will be printed."),
|
| + NULL,
|
| + show_stapexpressiondebug,
|
| + &setdebuglist, &showdebuglist);
|
|
|
| create_internalvar_type_lazy ("_probe_argc", &probe_funcs,
|
| (void *) (uintptr_t) -1);
|
|
|