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  <tom@tromey.com>

	* 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.
This commit is contained in:
Tom Tromey 2021-03-08 07:27:57 -07:00
parent 482ddd69c5
commit 4c5e7a930a
10 changed files with 288 additions and 303 deletions

View File

@ -1,3 +1,29 @@
2021-03-08 Tom Tromey <tom@tromey.com>
* 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 <tom@tromey.com>
* gdbarch.sh (dtrace_parse_probe_argument): Change return type.

View File

@ -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);
std::string regname (start, len);
strncpy (regname, start, len);
regname[len] = '\0';
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_const_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<register_operation> (std::move (regname));
write_exp_elt_opcode (&p->pstate, BINOP_ADD);
operation_up sum
= make_operation<add_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<unop_cast_operation> (std::move (sum),
arg_ptr_type);
return make_operation<unop_ind_operation> (std::move (sum));
}
else
return 0;
return 1;
return {};
}
/* AArch64 process record-replay constructs: syscall, signal etc. */

View File

@ -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_const_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<register_operation> (regname);
write_exp_elt_opcode (&p->pstate, BINOP_ADD);
operation_up sum
= make_operation<add_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<unop_cast_operation> (std::move (sum),
arg_ptr_type);
return make_operation<unop_ind_operation> (std::move (sum));
}
else
return 0;
return 1;
return {};
}
/* ARM process record-replay constructs: syscall, signal etc. */

View File

@ -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);

View File

@ -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.

View File

@ -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.
#

View File

@ -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);
std::string regname (start, len);
strncpy (regname, start, len);
regname[len] = '\0';
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);
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;
return true;
using namespace expr;
struct type *long_type = builtin_type (gdbarch)->builtin_long;
operation_up offset
= make_operation<long_const_operation> (long_type, value);
operation_up reg
= make_operation<register_operation> (std::move (regname));
struct type *void_ptr = builtin_type (gdbarch)->builtin_data_ptr;
reg = make_operation<unop_cast_operation> (std::move (reg), void_ptr);
operation_up sum
= make_operation<add_operation> (std::move (reg), std::move (offset));
struct type *arg_ptr_type = lookup_pointer_type (p->arg_type);
sum = make_operation<unop_cast_operation> (std::move (sum),
arg_ptr_type);
return make_operation<unop_ind_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;
if (offset)
{
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);
}
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);
if (size)
{
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);
}
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;
return true;
using namespace expr;
struct type *long_type = builtin_type (gdbarch)->builtin_long;
operation_up reg = make_operation<register_operation> (std::move (base));
if (offset != 0)
{
if (offset_minus)
offset = -offset;
operation_up value
= make_operation<long_const_operation> (long_type, offset);
reg = make_operation<add_operation> (std::move (reg),
std::move (value));
}
operation_up ind_reg
= make_operation<register_operation> (std::move (index));
if (size != 0)
{
if (size_minus)
size = -size;
operation_up value
= make_operation<long_const_operation> (long_type, size);
ind_reg = make_operation<mul_operation> (std::move (ind_reg),
std::move (value));
}
operation_up sum
= make_operation<add_operation> (std::move (reg),
std::move (ind_reg));
struct type *arg_ptr_type = lookup_pointer_type (p->arg_type);
sum = make_operation<unop_cast_operation> (std::move (sum),
arg_ptr_type);
return make_operation<unop_ind_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

View File

@ -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 */

View File

@ -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<expr::register_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.

View File

@ -36,6 +36,8 @@
#include "parser-defs.h"
#include "language.h"
#include "elf-bfd.h"
#include "expop.h"
#include <unordered_map>
#include <ctype.h>
@ -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<exp_opcode, binop_maker_ftype *> 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_const_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<register_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<add_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<unop_cast_operation> (std::move (reg),
arg_ptr_type);
reg = make_operation<unop_ind_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;
/* 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 the return value of the above function is not zero,
it means it successfully parsed the special token.
using namespace expr;
If it is NULL, we try to parse it using our method. */
return;
/* We first try to parse this token as a "special token". */
if (gdbarch_stap_parse_special_token_p (gdbarch))
{
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<unary_neg_operation> (std::move (result));
else if (c == '~')
write_exp_elt_opcode (&p->pstate, UNOP_COMPLEMENT);
result = (make_operation<unary_complement_operation>
(std::move (result)));
else if (c == '!')
write_exp_elt_opcode (&p->pstate, UNOP_LOGICAL_NOT);
result = (make_operation<unary_logical_not_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_const_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_const_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<unop_cast_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<add_operation>;
stap_maker_map[BINOP_BITWISE_AND] = make_operation<bitwise_and_operation>;
stap_maker_map[BINOP_BITWISE_IOR] = make_operation<bitwise_ior_operation>;
stap_maker_map[BINOP_BITWISE_XOR] = make_operation<bitwise_xor_operation>;
stap_maker_map[BINOP_DIV] = make_operation<div_operation>;
stap_maker_map[BINOP_EQUAL] = make_operation<equal_operation>;
stap_maker_map[BINOP_GEQ] = make_operation<geq_operation>;
stap_maker_map[BINOP_GTR] = make_operation<gtr_operation>;
stap_maker_map[BINOP_LEQ] = make_operation<leq_operation>;
stap_maker_map[BINOP_LESS] = make_operation<less_operation>;
stap_maker_map[BINOP_LOGICAL_AND] = make_operation<logical_and_operation>;
stap_maker_map[BINOP_LOGICAL_OR] = make_operation<logical_or_operation>;
stap_maker_map[BINOP_LSH] = make_operation<lsh_operation>;
stap_maker_map[BINOP_MUL] = make_operation<mul_operation>;
stap_maker_map[BINOP_NOTEQUAL] = make_operation<notequal_operation>;
stap_maker_map[BINOP_REM] = make_operation<rem_operation>;
stap_maker_map[BINOP_RSH] = make_operation<rsh_operation>;
stap_maker_map[BINOP_SUB] = make_operation<sub_operation>;
}