/* Intel 386 target-dependent stuff.
- Copyright (C) 1988-2020 Free Software Foundation, Inc.
+ Copyright (C) 1988-2021 Free Software Foundation, Inc.
This file is part of GDB.
#include "i387-tdep.h"
#include "gdbsupport/x86-xstate.h"
#include "x86-tdep.h"
+#include "expop.h"
#include "record.h"
#include "record-full.h"
yet, and only the scratch registers %eax, %ecx and %edx can be
touched. */
-struct i386_insn i386_frame_setup_skip_insns[] =
+static i386_insn i386_frame_setup_skip_insns[] =
{
/* Check for `movb imm8, r' and `movl imm32, r'.
/* Static chain passed in register. */
-struct i386_insn i386_tramp_chain_in_reg_insns[] =
+static i386_insn i386_tramp_chain_in_reg_insns[] =
{
/* `movl imm32, %eax' and `movl imm32, %ecx' */
{ 5, { 0xb8 }, { 0xfe } },
/* Static chain passed on stack (when regparm=3). */
-struct i386_insn i386_tramp_chain_on_stack_insns[] =
+static i386_insn i386_tramp_chain_on_stack_insns[] =
{
/* `push imm32' */
{ 5, { 0x68 }, { 0xff } },
gdb_assert (register_size (gdbarch, regnum) == 4);
if (!get_frame_register_bytes (frame, regnum, 0,
- register_size (gdbarch, regnum),
- to, optimizedp, unavailablep))
+ gdb::make_array_view (to,
+ register_size (gdbarch,
+ regnum)),
+ optimizedp, unavailablep))
return 0;
regnum = i386_next_regnum (regnum);
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)
{
int i;
long displacements[3];
const char *start;
- char *regname;
int len;
- struct stoken str;
char *endp;
got_minus[0] = false;
}
if (!isdigit ((unsigned char) *s))
- return false;
+ return {};
displacements[0] = strtol (s, &endp, 10);
s = endp;
if (*s != '+' && *s != '-')
{
/* We are not dealing with a triplet. */
- return false;
+ return {};
}
got_minus[1] = false;
}
if (!isdigit ((unsigned char) *s))
- return false;
+ return {};
displacements[1] = strtol (s, &endp, 10);
s = endp;
if (*s != '+' && *s != '-')
{
/* We are not dealing with a triplet. */
- return false;
+ return {};
}
got_minus[2] = false;
}
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;
++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_const_operation> (long_type, value);
- p->arg = s;
+ 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);
- return true;
+ 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.
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)
{
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;
}
if (offset_minus && !isdigit (*s))
- return false;
+ return {};
if (isdigit (*s))
{
}
if (*s != '(' || s[1] != '%')
- return false;
+ return {};
s += 2;
start = s;
++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;
++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 == ',')
{
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<register_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_const_operation> (long_type, offset);
+ reg = make_operation<add_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<register_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_const_operation> (long_type, size);
+ ind_reg = make_operation<mul_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<add_operation> (std::move (reg),
+ std::move (ind_reg));
- return true;
+ 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
- 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