From 4c5e7a930a46ddd6844eb7aede3ef60df535bc33 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 8 Mar 2021 07:27:57 -0700 Subject: [PATCH] Convert stap probes to create operations This changes the stap probe code to create operations, rather than exp_elements. gdb/ChangeLog 2021-03-08 Tom Tromey * stap-probe.c (binop_maker_ftype): New typedef. (stap_maker_map): New global. (stap_make_binop): New function. (stap_parse_register_operand): Return operation_up. (stap_parse_single_operand, stap_parse_argument_conditionally) (stap_parse_argument_1): Likewise. (stap_parse_argument): Create operations. (stap_probe::parse_arguments): Update. (_initialize_stap_probe): Initialize stap_maker_map. * ppc-linux-tdep.c (ppc_stap_parse_special_token): Change return type. * i386-tdep.h (i386_stap_parse_special_token): Change return type. * i386-tdep.c (i386_stap_parse_special_token_triplet) (i386_stap_parse_special_token_three_arg_disp) (i386_stap_parse_special_token): Change return type. * gdbarch.sh (stap_parse_special_token): Change return type. * gdbarch.c: Rebuild. * gdbarch.h: Rebuild. * arm-linux-tdep.c (arm_stap_parse_special_token): Change return type. * aarch64-linux-tdep.c (aarch64_stap_parse_special_token): Change return type. --- gdb/ChangeLog | 26 +++++ gdb/aarch64-linux-tdep.c | 58 +++++------ gdb/arm-linux-tdep.c | 45 ++++---- gdb/gdbarch.c | 2 +- gdb/gdbarch.h | 4 +- gdb/gdbarch.sh | 2 +- gdb/i386-tdep.c | 214 +++++++++++++++------------------------ gdb/i386-tdep.h | 5 +- gdb/ppc-linux-tdep.c | 24 ++--- gdb/stap-probe.c | 187 ++++++++++++++++++++-------------- 10 files changed, 276 insertions(+), 291 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 87c56158588..5b6493c1b8e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,29 @@ +2021-03-08 Tom Tromey + + * stap-probe.c (binop_maker_ftype): New typedef. + (stap_maker_map): New global. + (stap_make_binop): New function. + (stap_parse_register_operand): Return operation_up. + (stap_parse_single_operand, stap_parse_argument_conditionally) + (stap_parse_argument_1): Likewise. + (stap_parse_argument): Create operations. + (stap_probe::parse_arguments): Update. + (_initialize_stap_probe): Initialize stap_maker_map. + * ppc-linux-tdep.c (ppc_stap_parse_special_token): Change return + type. + * i386-tdep.h (i386_stap_parse_special_token): Change return + type. + * i386-tdep.c (i386_stap_parse_special_token_triplet) + (i386_stap_parse_special_token_three_arg_disp) + (i386_stap_parse_special_token): Change return type. + * gdbarch.sh (stap_parse_special_token): Change return type. + * gdbarch.c: Rebuild. + * gdbarch.h: Rebuild. + * arm-linux-tdep.c (arm_stap_parse_special_token): Change return + type. + * aarch64-linux-tdep.c (aarch64_stap_parse_special_token): Change + return type. + 2021-03-08 Tom Tromey * gdbarch.sh (dtrace_parse_probe_argument): Change return type. diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index b1bbd55e5c3..d8476c907e8 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -31,6 +31,7 @@ #include "tramp-frame.h" #include "trad-frame.h" #include "target/target.h" +#include "expop.h" #include "regcache.h" #include "regset.h" @@ -753,7 +754,7 @@ aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) It returns one if the special token has been parsed successfully, or zero if the current token is not considered special. */ -static int +static expr::operation_up aarch64_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { @@ -764,11 +765,9 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch, char *endp; /* Used to save the register name. */ const char *start; - char *regname; int len; int got_minus = 0; long displacement; - struct stoken str; ++tmp; start = tmp; @@ -778,17 +777,14 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch, ++tmp; if (*tmp != ',') - return 0; + return {}; len = tmp - start; - regname = (char *) alloca (len + 2); - - strncpy (regname, start, len); - regname[len] = '\0'; + std::string regname (start, len); - if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) + if (user_reg_map_name_to_regnum (gdbarch, regname.c_str (), len) == -1) error (_("Invalid register name `%s' on expression `%s'."), - regname, p->saved_arg); + regname.c_str (), p->saved_arg); ++tmp; tmp = skip_spaces (tmp); @@ -806,45 +802,39 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch, ++tmp; if (!isdigit (*tmp)) - return 0; + return {}; displacement = strtol (tmp, &endp, 10); tmp = endp; /* Skipping last `]'. */ if (*tmp++ != ']') - return 0; + return {}; + p->arg = tmp; + + using namespace expr; /* The displacement. */ - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, displacement); - write_exp_elt_opcode (&p->pstate, OP_LONG); + struct type *long_type = builtin_type (gdbarch)->builtin_long; if (got_minus) - write_exp_elt_opcode (&p->pstate, UNOP_NEG); + displacement = -displacement; + operation_up disp = make_operation (long_type, + displacement); /* The register name. */ - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - str.ptr = regname; - str.length = len; - write_exp_string (&p->pstate, str); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); + operation_up reg + = make_operation (std::move (regname)); - write_exp_elt_opcode (&p->pstate, BINOP_ADD); + operation_up sum + = make_operation (std::move (reg), std::move (disp)); /* Casting to the expected type. */ - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - - write_exp_elt_opcode (&p->pstate, UNOP_IND); - - p->arg = tmp; + struct type *arg_ptr_type = lookup_pointer_type (p->arg_type); + sum = make_operation (std::move (sum), + arg_ptr_type); + return make_operation (std::move (sum)); } - else - return 0; - - return 1; + return {}; } /* AArch64 process record-replay constructs: syscall, signal etc. */ diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 20cae5bdc91..773a93384f7 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -32,6 +32,7 @@ #include "breakpoint.h" #include "auxv.h" #include "xml-syscall.h" +#include "expop.h" #include "aarch32-tdep.h" #include "arch/arm.h" @@ -1146,7 +1147,7 @@ arm_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) It returns one if the special token has been parsed successfully, or zero if the current token is not considered special. */ -static int +static expr::operation_up arm_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { @@ -1161,7 +1162,6 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch, int len, offset; int got_minus = 0; long displacement; - struct stoken str; ++tmp; start = tmp; @@ -1171,7 +1171,7 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch, ++tmp; if (*tmp != ',') - return 0; + return {}; len = tmp - start; regname = (char *) alloca (len + 2); @@ -1212,38 +1212,33 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch, /* Skipping last `]'. */ if (*tmp++ != ']') - return 0; + return {}; + p->arg = tmp; + + using namespace expr; /* The displacement. */ - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, displacement); - write_exp_elt_opcode (&p->pstate, OP_LONG); + struct type *long_type = builtin_type (gdbarch)->builtin_long; if (got_minus) - write_exp_elt_opcode (&p->pstate, UNOP_NEG); + displacement = -displacement; + operation_up disp = make_operation (long_type, + displacement); /* The register name. */ - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - str.ptr = regname; - str.length = len; - write_exp_string (&p->pstate, str); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); + operation_up reg + = make_operation (regname); - write_exp_elt_opcode (&p->pstate, BINOP_ADD); + operation_up sum + = make_operation (std::move (reg), std::move (disp)); /* Casting to the expected type. */ - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - - write_exp_elt_opcode (&p->pstate, UNOP_IND); - - p->arg = tmp; + struct type *arg_ptr_type = lookup_pointer_type (p->arg_type); + sum = make_operation (std::move (sum), + arg_ptr_type); + return make_operation (std::move (sum)); } - else - return 0; - return 1; + return {}; } /* ARM process record-replay constructs: syscall, signal etc. */ diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index a233501f5b2..8fa3cbaea3d 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -4589,7 +4589,7 @@ gdbarch_stap_parse_special_token_p (struct gdbarch *gdbarch) return gdbarch->stap_parse_special_token != NULL; } -int +expr::operation_up gdbarch_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 3b9d8da4f61..342c29c5980 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1346,8 +1346,8 @@ extern void set_gdbarch_stap_is_single_operand (struct gdbarch *gdbarch, gdbarch extern bool gdbarch_stap_parse_special_token_p (struct gdbarch *gdbarch); -typedef int (gdbarch_stap_parse_special_token_ftype) (struct gdbarch *gdbarch, struct stap_parse_info *p); -extern int gdbarch_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p); +typedef expr::operation_up (gdbarch_stap_parse_special_token_ftype) (struct gdbarch *gdbarch, struct stap_parse_info *p); +extern expr::operation_up 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); /* Perform arch-dependent adjustments to a register name. diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index d68d3b7a425..84b645e9915 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -994,7 +994,7 @@ M;int;stap_is_single_operand;const char *s;s # if the token was not recognized as a special token (in this case, returning # zero means that the special parser is deferring the parsing to the generic # parser), and should advance the buffer pointer (p->arg). -M;int;stap_parse_special_token;struct stap_parse_info *p;p +M;expr::operation_up;stap_parse_special_token;struct stap_parse_info *p;p # Perform arch-dependent adjustments to a register name. # diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 6386716c3b8..4f8da924073 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -48,6 +48,7 @@ #include "i387-tdep.h" #include "gdbsupport/x86-xstate.h" #include "x86-tdep.h" +#include "expop.h" #include "record.h" #include "record-full.h" @@ -4069,7 +4070,7 @@ i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) Return true if the operand was parsed successfully, false otherwise. */ -static bool +static expr::operation_up i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, struct stap_parse_info *p) { @@ -4081,9 +4082,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, int i; long displacements[3]; const char *start; - char *regname; int len; - struct stoken str; char *endp; got_minus[0] = false; @@ -4096,7 +4095,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, } if (!isdigit ((unsigned char) *s)) - return false; + return {}; displacements[0] = strtol (s, &endp, 10); s = endp; @@ -4104,7 +4103,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, if (*s != '+' && *s != '-') { /* We are not dealing with a triplet. */ - return false; + return {}; } got_minus[1] = false; @@ -4117,7 +4116,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, } if (!isdigit ((unsigned char) *s)) - return false; + return {}; displacements[1] = strtol (s, &endp, 10); s = endp; @@ -4125,7 +4124,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, if (*s != '+' && *s != '-') { /* We are not dealing with a triplet. */ - return false; + return {}; } got_minus[2] = false; @@ -4138,13 +4137,13 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, } if (!isdigit ((unsigned char) *s)) - return false; + return {}; displacements[2] = strtol (s, &endp, 10); s = endp; if (*s != '(' || s[1] != '%') - return false; + return {}; s += 2; start = s; @@ -4153,57 +4152,46 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, ++s; if (*s++ != ')') - return false; + return {}; len = s - start - 1; - regname = (char *) alloca (len + 1); - - strncpy (regname, start, len); - regname[len] = '\0'; + std::string regname (start, len); - if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) + if (user_reg_map_name_to_regnum (gdbarch, regname.c_str (), len) == -1) error (_("Invalid register name `%s' on expression `%s'."), - regname, p->saved_arg); + regname.c_str (), p->saved_arg); + LONGEST value = 0; for (i = 0; i < 3; i++) { - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type - (&p->pstate, builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, displacements[i]); - write_exp_elt_opcode (&p->pstate, OP_LONG); + LONGEST this_val = displacements[i]; if (got_minus[i]) - write_exp_elt_opcode (&p->pstate, UNOP_NEG); + this_val = -this_val; + value += this_val; } - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - str.ptr = regname; - str.length = len; - write_exp_string (&p->pstate, str); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - write_exp_elt_type (&p->pstate, - builtin_type (gdbarch)->builtin_data_ptr); - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - - write_exp_elt_opcode (&p->pstate, BINOP_ADD); - write_exp_elt_opcode (&p->pstate, BINOP_ADD); - write_exp_elt_opcode (&p->pstate, BINOP_ADD); + p->arg = s; - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - write_exp_elt_type (&p->pstate, - lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (&p->pstate, UNOP_CAST); + using namespace expr; - write_exp_elt_opcode (&p->pstate, UNOP_IND); + struct type *long_type = builtin_type (gdbarch)->builtin_long; + operation_up offset + = make_operation (long_type, value); - p->arg = s; + operation_up reg + = make_operation (std::move (regname)); + struct type *void_ptr = builtin_type (gdbarch)->builtin_data_ptr; + reg = make_operation (std::move (reg), void_ptr); - return true; + operation_up sum + = make_operation (std::move (reg), std::move (offset)); + struct type *arg_ptr_type = lookup_pointer_type (p->arg_type); + sum = make_operation (std::move (sum), + arg_ptr_type); + return make_operation (std::move (sum)); } - return false; + return {}; } /* Helper function for i386_stap_parse_special_token. @@ -4215,7 +4203,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, Return true if the operand was parsed successfully, false otherwise. */ -static bool +static expr::operation_up i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, struct stap_parse_info *p) { @@ -4228,11 +4216,8 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, bool size_minus = false; long size = 0; const char *start; - char *base; int len_base; - char *index; int len_index; - struct stoken base_token, index_token; if (*s == '+') ++s; @@ -4243,7 +4228,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, } if (offset_minus && !isdigit (*s)) - return false; + return {}; if (isdigit (*s)) { @@ -4254,7 +4239,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, } if (*s != '(' || s[1] != '%') - return false; + return {}; s += 2; start = s; @@ -4263,16 +4248,14 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, ++s; if (*s != ',' || s[1] != '%') - return false; + return {}; len_base = s - start; - base = (char *) alloca (len_base + 1); - strncpy (base, start, len_base); - base[len_base] = '\0'; + std::string base (start, len_base); - if (user_reg_map_name_to_regnum (gdbarch, base, len_base) == -1) + if (user_reg_map_name_to_regnum (gdbarch, base.c_str (), len_base) == -1) error (_("Invalid register name `%s' on expression `%s'."), - base, p->saved_arg); + base.c_str (), p->saved_arg); s += 2; start = s; @@ -4281,16 +4264,15 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, ++s; len_index = s - start; - index = (char *) alloca (len_index + 1); - strncpy (index, start, len_index); - index[len_index] = '\0'; + std::string index (start, len_index); - if (user_reg_map_name_to_regnum (gdbarch, index, len_index) == -1) + if (user_reg_map_name_to_regnum (gdbarch, index.c_str (), + len_index) == -1) error (_("Invalid register name `%s' on expression `%s'."), - index, p->saved_arg); + index.c_str (), p->saved_arg); if (*s != ',' && *s != ')') - return false; + return {}; if (*s == ',') { @@ -4309,85 +4291,60 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, s = endp; if (*s != ')') - return false; + return {}; } ++s; + p->arg = s; - if (offset) + using namespace expr; + + struct type *long_type = builtin_type (gdbarch)->builtin_long; + operation_up reg = make_operation (std::move (base)); + + if (offset != 0) { - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, - builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, offset); - write_exp_elt_opcode (&p->pstate, OP_LONG); if (offset_minus) - write_exp_elt_opcode (&p->pstate, UNOP_NEG); + offset = -offset; + operation_up value + = make_operation (long_type, offset); + reg = make_operation (std::move (reg), + std::move (value)); } - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - base_token.ptr = base; - base_token.length = len_base; - write_exp_string (&p->pstate, base_token); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - - if (offset) - write_exp_elt_opcode (&p->pstate, BINOP_ADD); - - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - index_token.ptr = index; - index_token.length = len_index; - write_exp_string (&p->pstate, index_token); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); + operation_up ind_reg + = make_operation (std::move (index)); - if (size) + if (size != 0) { - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, - builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, size); - write_exp_elt_opcode (&p->pstate, OP_LONG); if (size_minus) - write_exp_elt_opcode (&p->pstate, UNOP_NEG); - write_exp_elt_opcode (&p->pstate, BINOP_MUL); + size = -size; + operation_up value + = make_operation (long_type, size); + ind_reg = make_operation (std::move (ind_reg), + std::move (value)); } - write_exp_elt_opcode (&p->pstate, BINOP_ADD); - - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - write_exp_elt_type (&p->pstate, - lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - - write_exp_elt_opcode (&p->pstate, UNOP_IND); - - p->arg = s; + operation_up sum + = make_operation (std::move (reg), + std::move (ind_reg)); - return true; + struct type *arg_ptr_type = lookup_pointer_type (p->arg_type); + sum = make_operation (std::move (sum), + arg_ptr_type); + return make_operation (std::move (sum)); } - return false; + return {}; } /* Implementation of `gdbarch_stap_parse_special_token', as defined in gdbarch.h. */ -int +expr::operation_up i386_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { - /* In order to parse special tokens, we use a state-machine that go - through every known token and try to get a match. */ - enum - { - TRIPLET, - THREE_ARG_DISPLACEMENT, - DONE - }; - int current_state; - - current_state = TRIPLET; - /* The special tokens to be parsed here are: - `register base + (register index * size) + offset', as represented @@ -4396,26 +4353,13 @@ i386_stap_parse_special_token (struct gdbarch *gdbarch, - Operands of the form `-8+3+1(%rbp)', which must be interpreted as `*(-8 + 3 - 1 + (void *) $eax)'. */ - while (current_state != DONE) - { - switch (current_state) - { - case TRIPLET: - if (i386_stap_parse_special_token_triplet (gdbarch, p)) - return 1; - break; + expr::operation_up result + = i386_stap_parse_special_token_triplet (gdbarch, p); - case THREE_ARG_DISPLACEMENT: - if (i386_stap_parse_special_token_three_arg_disp (gdbarch, p)) - return 1; - break; - } + if (result == nullptr) + result = i386_stap_parse_special_token_three_arg_disp (gdbarch, p); - /* Advancing to the next state. */ - ++current_state; - } - - return 0; + return result; } /* Implementation of 'gdbarch_stap_adjust_register', as defined in diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index fe0e1185674..ee7655e9861 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -22,6 +22,7 @@ #include "gdbarch.h" #include "infrun.h" +#include "expression.h" struct frame_info; struct gdbarch; @@ -485,7 +486,7 @@ extern int i386bsd_sc_reg_offset[]; extern int i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s); -extern int i386_stap_parse_special_token (struct gdbarch *gdbarch, - struct stap_parse_info *p); +extern expr::operation_up i386_stap_parse_special_token + (struct gdbarch *gdbarch, struct stap_parse_info *p); #endif /* i386-tdep.h */ diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 467d696374c..1e94922f25a 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -52,6 +52,7 @@ #include "linux-record.h" #include "record-full.h" #include "infrun.h" +#include "expop.h" #include "stap-probe.h" #include "ax.h" @@ -1674,7 +1675,7 @@ ppc_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) /* Implementation of `gdbarch_stap_parse_special_token', as defined in gdbarch.h. */ -static int +static expr::operation_up ppc_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { @@ -1686,7 +1687,6 @@ ppc_stap_parse_special_token (struct gdbarch *gdbarch, const char *s = p->arg; char *regname; int len; - struct stoken str; while (isdigit (*s)) ++s; @@ -1695,7 +1695,7 @@ ppc_stap_parse_special_token (struct gdbarch *gdbarch, { /* It is a register displacement indeed. Returning 0 means we are deferring the treatment of this case to the generic parser. */ - return 0; + return {}; } len = s - p->arg; @@ -1710,22 +1710,14 @@ ppc_stap_parse_special_token (struct gdbarch *gdbarch, error (_("Invalid register name `%s' on expression `%s'."), regname, p->saved_arg); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - str.ptr = regname; - str.length = len; - write_exp_string (&p->pstate, str); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - p->arg = s; - } - else - { - /* All the other tokens should be handled correctly by the generic - parser. */ - return 0; + + return expr::make_operation (regname); } - return 1; + /* All the other tokens should be handled correctly by the generic + parser. */ + return {}; } /* Initialize linux_record_tdep if not initialized yet. diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c index 476cbecf994..264d91239af 100644 --- a/gdb/stap-probe.c +++ b/gdb/stap-probe.c @@ -36,6 +36,8 @@ #include "parser-defs.h" #include "language.h" #include "elf-bfd.h" +#include "expop.h" +#include #include @@ -262,10 +264,13 @@ enum stap_operand_prec STAP_OPERAND_PREC_MUL }; -static void stap_parse_argument_1 (struct stap_parse_info *p, bool has_lhs, - enum stap_operand_prec prec); +static expr::operation_up stap_parse_argument_1 (struct stap_parse_info *p, + expr::operation_up &&lhs, + enum stap_operand_prec prec) + ATTRIBUTE_UNUSED_RESULT; -static void stap_parse_argument_conditionally (struct stap_parse_info *p); +static expr::operation_up stap_parse_argument_conditionally + (struct stap_parse_info *p) ATTRIBUTE_UNUSED_RESULT; /* Returns true if *S is an operator, false otherwise. */ @@ -427,6 +432,22 @@ stap_get_opcode (const char **s) return op; } +typedef expr::operation_up binop_maker_ftype (expr::operation_up &&, + expr::operation_up &&); +/* Map from an expression opcode to a function that can create a + binary operation of that type. */ +static std::unordered_map stap_maker_map; + +/* Helper function to create a binary operation. */ +static expr::operation_up +stap_make_binop (enum exp_opcode opcode, expr::operation_up &&lhs, + expr::operation_up &&rhs) +{ + auto iter = stap_maker_map.find (opcode); + gdb_assert (iter != stap_maker_map.end ()); + return iter->second (std::move (lhs), std::move (rhs)); +} + /* Given the bitness of the argument, represented by B, return the corresponding `struct type *', or throw an error if B is unknown. */ @@ -676,19 +697,16 @@ stap_check_register_indirection_suffix (struct gdbarch *gdbarch, const char *s, language (e.g., `15' is the 15th general-purpose register), but inside GDB they have a prefix (the letter `r') appended. */ -static void +static expr::operation_up stap_parse_register_operand (struct stap_parse_info *p) { /* Simple flag to indicate whether we have seen a minus signal before certain number. */ bool got_minus = false; - /* Flags to indicate whether this register access is being displaced and/or + /* Flag to indicate whether this register access is being indirected. */ - bool disp_p = false; bool indirect_p = false; struct gdbarch *gdbarch = p->gdbarch; - /* Needed to generate the register name as a part of an expression. */ - struct stoken str; /* Variables used to extract the register name from the probe's argument. */ const char *start; @@ -699,6 +717,8 @@ stap_parse_register_operand (struct stap_parse_info *p) const char *reg_suffix; const char *reg_ind_suffix; + using namespace expr; + /* Checking for a displacement argument. */ if (*p->arg == '+') { @@ -712,23 +732,21 @@ stap_parse_register_operand (struct stap_parse_info *p) ++p->arg; } + struct type *long_type = builtin_type (gdbarch)->builtin_long; + operation_up disp_op; if (isdigit (*p->arg)) { /* The value of the displacement. */ long displacement; char *endp; - disp_p = true; displacement = strtol (p->arg, &endp, 10); p->arg = endp; /* Generating the expression for the displacement. */ - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, displacement); - write_exp_elt_opcode (&p->pstate, OP_LONG); if (got_minus) - write_exp_elt_opcode (&p->pstate, UNOP_NEG); + displacement = -displacement; + disp_op = make_operation (long_type, displacement); } /* Getting rid of register indirection prefix. */ @@ -738,7 +756,7 @@ stap_parse_register_operand (struct stap_parse_info *p) p->arg += strlen (reg_ind_prefix); } - if (disp_p && !indirect_p) + if (disp_op != nullptr && !indirect_p) error (_("Invalid register displacement syntax on expression `%s'."), p->saved_arg); @@ -796,27 +814,23 @@ stap_parse_register_operand (struct stap_parse_info *p) " (previous name was '%s')"), newregname.c_str (), regname.c_str ()); - regname = newregname; + regname = std::move (newregname); } } - write_exp_elt_opcode (&p->pstate, OP_REGISTER); - str.ptr = regname.c_str (); - str.length = regname.size (); - write_exp_string (&p->pstate, str); - write_exp_elt_opcode (&p->pstate, OP_REGISTER); + operation_up reg = make_operation (std::move (regname)); if (indirect_p) { - if (disp_p) - write_exp_elt_opcode (&p->pstate, BINOP_ADD); + if (disp_op != nullptr) + reg = make_operation (std::move (disp_op), + std::move (reg)); /* Casting to the expected type. */ - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (&p->pstate, UNOP_CAST); - - write_exp_elt_opcode (&p->pstate, UNOP_IND); + struct type *arg_ptr_type = lookup_pointer_type (p->arg_type); + reg = make_operation (std::move (reg), + arg_ptr_type); + reg = make_operation (std::move (reg)); } /* Getting rid of the register name suffix. */ @@ -836,6 +850,8 @@ stap_parse_register_operand (struct stap_parse_info *p) error (_("Missing indirection suffix on expression `%s'."), p->saved_arg); } + + return reg; } /* This function is responsible for parsing a single operand. @@ -853,23 +869,24 @@ stap_parse_register_operand (struct stap_parse_info *p) unrecognized operands, allowing arch-specific parsers to be created. */ -static void +static expr::operation_up stap_parse_single_operand (struct stap_parse_info *p) { struct gdbarch *gdbarch = p->gdbarch; const char *int_prefix = NULL; + using namespace expr; + /* We first try to parse this token as a "special token". */ - if (gdbarch_stap_parse_special_token_p (gdbarch) - && (gdbarch_stap_parse_special_token (gdbarch, p) != 0)) + if (gdbarch_stap_parse_special_token_p (gdbarch)) { - /* If the return value of the above function is not zero, - it means it successfully parsed the special token. - - If it is NULL, we try to parse it using our method. */ - return; + operation_up token = gdbarch_stap_parse_special_token (gdbarch, p); + if (token != nullptr) + return token; } + struct type *long_type = builtin_type (gdbarch)->builtin_long; + operation_up result; if (*p->arg == '-' || *p->arg == '~' || *p->arg == '+' || *p->arg == '!') { char c = *p->arg; @@ -912,20 +929,22 @@ stap_parse_single_operand (struct stap_parse_info *p) error (_("Invalid operator `%c' for register displacement " "on expression `%s'."), c, p->saved_arg); - stap_parse_register_operand (p); + result = stap_parse_register_operand (p); } else { /* This is not a displacement. We skip the operator, and deal with it when the recursion returns. */ ++p->arg; - stap_parse_argument_conditionally (p); + result = stap_parse_argument_conditionally (p); if (c == '-') - write_exp_elt_opcode (&p->pstate, UNOP_NEG); + result = make_operation (std::move (result)); else if (c == '~') - write_exp_elt_opcode (&p->pstate, UNOP_COMPLEMENT); + result = (make_operation + (std::move (result))); else if (c == '!') - write_exp_elt_opcode (&p->pstate, UNOP_LOGICAL_NOT); + result = (make_operation + (std::move (result))); } } else if (isdigit (*p->arg)) @@ -953,11 +972,7 @@ stap_parse_single_operand (struct stap_parse_info *p) const char *int_suffix; /* We are dealing with a numeric constant. */ - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, - builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, number); - write_exp_elt_opcode (&p->pstate, OP_LONG); + result = make_operation (long_type, number); p->arg = tmp; @@ -968,7 +983,7 @@ stap_parse_single_operand (struct stap_parse_info *p) p->saved_arg); } else if (stap_is_register_indirection_prefix (gdbarch, tmp, NULL)) - stap_parse_register_operand (p); + result = stap_parse_register_operand (p); else error (_("Unknown numeric token on expression `%s'."), p->saved_arg); @@ -984,10 +999,7 @@ stap_parse_single_operand (struct stap_parse_info *p) number = strtol (p->arg, &endp, 10); p->arg = endp; - write_exp_elt_opcode (&p->pstate, OP_LONG); - write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (&p->pstate, number); - write_exp_elt_opcode (&p->pstate, OP_LONG); + result = make_operation (long_type, number); if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix)) p->arg += strlen (int_suffix); @@ -997,10 +1009,12 @@ stap_parse_single_operand (struct stap_parse_info *p) } else if (stap_is_register_prefix (gdbarch, p->arg, NULL) || stap_is_register_indirection_prefix (gdbarch, p->arg, NULL)) - stap_parse_register_operand (p); + result = stap_parse_register_operand (p); else error (_("Operator `%c' not recognized on expression `%s'."), *p->arg, p->saved_arg); + + return result; } /* This function parses an argument conditionally, based on single or @@ -1009,15 +1023,16 @@ stap_parse_single_operand (struct stap_parse_info *p) starts with `-', `~', `+' (i.e., unary operators), a digit, or something recognized by `gdbarch_stap_is_single_operand'. */ -static void +static expr::operation_up stap_parse_argument_conditionally (struct stap_parse_info *p) { gdb_assert (gdbarch_stap_is_single_operand_p (p->gdbarch)); + expr::operation_up result; if (*p->arg == '-' || *p->arg == '~' || *p->arg == '+' || *p->arg == '!' || isdigit (*p->arg) || gdbarch_stap_is_single_operand (p->gdbarch, p->arg)) - stap_parse_single_operand (p); + result = stap_parse_single_operand (p); else if (*p->arg == '(') { /* We are dealing with a parenthesized operand. It means we @@ -1027,7 +1042,7 @@ stap_parse_argument_conditionally (struct stap_parse_info *p) p->arg = skip_spaces (p->arg); ++p->inside_paren_p; - stap_parse_argument_1 (p, 0, STAP_OPERAND_PREC_NONE); + result = stap_parse_argument_1 (p, {}, STAP_OPERAND_PREC_NONE); p->arg = skip_spaces (p->arg); if (*p->arg != ')') @@ -1041,13 +1056,16 @@ stap_parse_argument_conditionally (struct stap_parse_info *p) } else error (_("Cannot parse expression `%s'."), p->saved_arg); + + return result; } /* Helper function for `stap_parse_argument'. Please, see its comments to better understand what this function does. */ -static void -stap_parse_argument_1 (struct stap_parse_info *p, bool has_lhs, +static expr::operation_up ATTRIBUTE_UNUSED_RESULT +stap_parse_argument_1 (struct stap_parse_info *p, + expr::operation_up &&lhs_in, enum stap_operand_prec prec) { /* This is an operator-precedence parser. @@ -1061,13 +1079,15 @@ stap_parse_argument_1 (struct stap_parse_info *p, bool has_lhs, if (p->inside_paren_p) p->arg = skip_spaces (p->arg); - if (!has_lhs) + using namespace expr; + operation_up lhs = std::move (lhs_in); + if (lhs == nullptr) { /* We were called without a left-side, either because this is the first call, or because we were called to parse a parenthesized expression. It doesn't really matter; we have to parse the left-side in order to continue the process. */ - stap_parse_argument_conditionally (p); + lhs = stap_parse_argument_conditionally (p); } if (p->inside_paren_p) @@ -1117,12 +1137,12 @@ stap_parse_argument_1 (struct stap_parse_info *p, bool has_lhs, processing this part of the expression before continuing. */ bool paren_subexp = *p->arg == '('; - stap_parse_argument_conditionally (p); + operation_up rhs = stap_parse_argument_conditionally (p); if (p->inside_paren_p) p->arg = skip_spaces (p->arg); if (paren_subexp) { - write_exp_elt_opcode (&p->pstate, opcode); + lhs = stap_make_binop (opcode, std::move (lhs), std::move (rhs)); continue; } @@ -1146,15 +1166,18 @@ stap_parse_argument_1 (struct stap_parse_info *p, bool has_lhs, break; } - /* Parse the right-side of the expression, but since we already - have a left-side at this point, set `has_lhs' to 1. */ - stap_parse_argument_1 (p, 1, lookahead_prec); + /* Parse the right-side of the expression, using the current + right-hand-side as the left-hand-side of the new + subexpression. */ + rhs = stap_parse_argument_1 (p, std::move (rhs), lookahead_prec); if (p->inside_paren_p) p->arg = skip_spaces (p->arg); } - write_exp_elt_opcode (&p->pstate, opcode); + lhs = stap_make_binop (opcode, std::move (lhs), std::move (rhs)); } + + return lhs; } /* Parse a probe's argument. @@ -1194,14 +1217,14 @@ stap_parse_argument (const char **arg, struct type *atype, struct stap_parse_info p (*arg, atype, language_def (language_c), gdbarch); - stap_parse_argument_1 (&p, 0, STAP_OPERAND_PREC_NONE); + using namespace expr; + operation_up result = stap_parse_argument_1 (&p, {}, STAP_OPERAND_PREC_NONE); gdb_assert (p.inside_paren_p == 0); /* Casting the final expression to the appropriate type. */ - write_exp_elt_opcode (&p.pstate, UNOP_CAST); - write_exp_elt_type (&p.pstate, atype); - write_exp_elt_opcode (&p.pstate, UNOP_CAST); + result = make_operation (std::move (result), atype); + p.pstate.set_operation (std::move (result)); p.arg = skip_spaces (p.arg); *arg = p.arg; @@ -1290,12 +1313,6 @@ stap_probe::parse_arguments (struct gdbarch *gdbarch) expression_up expr = stap_parse_argument (&cur, atype, gdbarch); - if (stap_expression_debug) - dump_raw_expression (expr.get (), gdb_stdlog, - "before conversion to prefix form"); - - prefixify_expression (expr.get ()); - if (stap_expression_debug) dump_prefix_expression (expr.get (), gdb_stdlog); @@ -1747,4 +1764,24 @@ NAME matches the probe names.\n\ OBJECT matches the executable or shared library name."), info_probes_cmdlist_get ()); + + using namespace expr; + stap_maker_map[BINOP_ADD] = make_operation; + stap_maker_map[BINOP_BITWISE_AND] = make_operation; + stap_maker_map[BINOP_BITWISE_IOR] = make_operation; + stap_maker_map[BINOP_BITWISE_XOR] = make_operation; + stap_maker_map[BINOP_DIV] = make_operation; + stap_maker_map[BINOP_EQUAL] = make_operation; + stap_maker_map[BINOP_GEQ] = make_operation; + stap_maker_map[BINOP_GTR] = make_operation; + stap_maker_map[BINOP_LEQ] = make_operation; + stap_maker_map[BINOP_LESS] = make_operation; + stap_maker_map[BINOP_LOGICAL_AND] = make_operation; + stap_maker_map[BINOP_LOGICAL_OR] = make_operation; + stap_maker_map[BINOP_LSH] = make_operation; + stap_maker_map[BINOP_MUL] = make_operation; + stap_maker_map[BINOP_NOTEQUAL] = make_operation; + stap_maker_map[BINOP_REM] = make_operation; + stap_maker_map[BINOP_RSH] = make_operation; + stap_maker_map[BINOP_SUB] = make_operation; } -- 2.30.2