📄 eval.c
字号:
/* Evaluate expressions for GDB. Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "symtab.h"#include "gdbtypes.h"#include "value.h"#include "expression.h"#include "target.h"#include "frame.h"/* Values of NOSIDE argument to eval_subexp. */enum noside{ EVAL_NORMAL, EVAL_SKIP, /* Only effect is to increment pos. */ EVAL_AVOID_SIDE_EFFECTS /* Don't modify any variables or call any functions. The value returned will have the correct type, and will have an approximately correct lvalue type (inaccuracy: anything that is listed as being in a register in the function in which it was declared will be lval_register). */};/* Prototypes for local functions. */static valueevaluate_subexp_for_sizeof PARAMS ((struct expression *, int *));static valueevaluate_subexp_with_coercion PARAMS ((struct expression *, int *, enum noside));static valueevaluate_subexp_for_address PARAMS ((struct expression *, int *, enum noside));static valueevaluate_subexp PARAMS ((struct type *, struct expression *, int *, enum noside));/* Parse the string EXP as a C expression, evaluate it, and return the result as a number. */CORE_ADDRparse_and_eval_address (exp) char *exp;{ struct expression *expr = parse_expression (exp); register CORE_ADDR addr; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); addr = value_as_pointer (evaluate_expression (expr)); do_cleanups (old_chain); return addr;}/* Like parse_and_eval_address but takes a pointer to a char * variable and advanced that variable across the characters parsed. */CORE_ADDRparse_and_eval_address_1 (expptr) char **expptr;{ struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0); register CORE_ADDR addr; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); addr = value_as_pointer (evaluate_expression (expr)); do_cleanups (old_chain); return addr;}valueparse_and_eval (exp) char *exp;{ struct expression *expr = parse_expression (exp); register value val; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); val = evaluate_expression (expr); do_cleanups (old_chain); return val;}/* Parse up to a comma (or to a closeparen) in the string EXPP as an expression, evaluate it, and return the value. EXPP is advanced to point to the comma. */valueparse_to_comma_and_eval (expp) char **expp;{ struct expression *expr = parse_exp_1 (expp, (struct block *) 0, 1); register value val; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); val = evaluate_expression (expr); do_cleanups (old_chain); return val;}/* Evaluate an expression in internal prefix form such as is constructed by parse.y. See expression.h for info on the format of an expression. */static value evaluate_subexp ();static value evaluate_subexp_for_address ();static value evaluate_subexp_for_sizeof ();static value evaluate_subexp_with_coercion ();/* return true if 'var' has an address in inferior's memory. */static intvalue_has_lval(var) register struct symbol *var;{ switch (SYMBOL_CLASS(var)) { case LOC_STATIC: case LOC_LABEL: case LOC_ARG: case LOC_REF_ARG: case LOC_LOCAL: case LOC_BLOCK: return (1); } return (0);}valueevaluate_expression (exp) struct expression *exp;{ int pc = 0; return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);}/* Evaluate an expression, avoiding all memory references and getting a value whose type alone is correct. */valueevaluate_type (exp) struct expression *exp;{ int pc = 0; return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);}static valueevaluate_subexp (expect_type, exp, pos, noside) struct type *expect_type; register struct expression *exp; register int *pos; enum noside noside;{ enum exp_opcode op; int tem; register int pc, pc2, oldpos; register value arg1, arg2, arg3; struct type *type; int nargs; value *argvec; pc = (*pos)++; op = exp->elts[pc].opcode; switch (op) { case OP_SCOPE: tem = strlen (&exp->elts[pc + 2].string); (*pos) += 3 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type, 0, exp->elts[pc + 1].type, &exp->elts[pc + 2].string, expect_type); if (arg1 == NULL) error ("There is no field named %s", &exp->elts[pc + 2].string); return arg1; case OP_LONG: (*pos) += 3; return value_from_longest (exp->elts[pc + 1].type, exp->elts[pc + 2].longconst); case OP_DOUBLE: (*pos) += 3; return value_from_double (exp->elts[pc + 1].type, exp->elts[pc + 2].doubleconst); case OP_VAR_VALUE: (*pos) += 2; if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) { struct symbol * sym = exp->elts[pc + 1].symbol; enum lval_type lv; switch (SYMBOL_CLASS (sym)) { case LOC_CONST: case LOC_LABEL: case LOC_CONST_BYTES: lv = not_lval; break; case LOC_REGISTER: case LOC_REGPARM: lv = lval_register; break; default: lv = lval_memory; break; } return value_zero (SYMBOL_TYPE (sym), lv); } else return value_of_variable (exp->elts[pc + 1].symbol); case OP_LAST: (*pos) += 2; return access_value_history (longest_to_int (exp->elts[pc + 1].longconst)); case OP_REGISTER: (*pos) += 2; return value_of_register (longest_to_int (exp->elts[pc + 1].longconst)); case OP_INTERNALVAR: (*pos) += 2; return value_of_internalvar (exp->elts[pc + 1].internalvar); case OP_STRING: tem = strlen (&exp->elts[pc + 1].string); (*pos) += 2 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); if (noside == EVAL_SKIP) goto nosideret; return value_string (&exp->elts[pc + 1].string, tem); case TERNOP_COND: /* Skip third and second args to evaluate the first one. */ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (value_zerop (arg1)) { evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); return evaluate_subexp (NULL_TYPE, exp, pos, noside); } else { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); return arg2; } case OP_FUNCALL: (*pos) += 2; op = exp->elts[*pos].opcode; if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { int fnptr; nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1; /* First, evaluate the structure into arg2 */ pc2 = (*pos)++; if (noside == EVAL_SKIP) goto nosideret; if (op == STRUCTOP_MEMBER) { arg2 = evaluate_subexp_for_address (exp, pos, noside); } else { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); } /* If the function is a virtual function, then the aggregate value (providing the structure) plays its part by providing the vtable. Otherwise, it is just along for the ride: call the function directly. */ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); fnptr = longest_to_int (value_as_long (arg1)); if (METHOD_PTR_IS_VIRTUAL(fnptr)) { int fnoffset = METHOD_PTR_TO_VOFFSET(fnptr); struct type *basetype; struct type *domain_type = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))); int i, j; basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2)); if (domain_type != basetype) arg2 = value_cast(lookup_pointer_type (domain_type), arg2); basetype = TYPE_VPTR_BASETYPE (domain_type); for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--) { struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i); /* If one is virtual, then all are virtual. */ if (TYPE_FN_FIELD_VIRTUAL_P (f, 0)) for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j) if (TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset) { value temp = value_ind (arg2); arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0); arg2 = value_addr (temp); goto got_it; } } if (i < 0) error ("virtual function at index %d not found", fnoffset); } else { VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))); } got_it: /* Now, say which argument to start evaluating from */ tem = 2; } else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) { /* Hair for method invocations */ int tem2; nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1; /* First, evaluate the structure into arg2 */ pc2 = (*pos)++; tem2 = strlen (&exp->elts[pc2 + 1].string); *pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element); if (noside == EVAL_SKIP) goto nosideret; if (op == STRUCTOP_STRUCT) { arg2 = evaluate_subexp_for_address (exp, pos, noside); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -