diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 85cd3f9039..d34b29a5c0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +2017-09-04 Pedro Alves + + * ada-lang.c (resolve_subexp): Handle OP_VAR_MSYM_VALUE. + * ax-gdb.c (gen_msym_var_ref): New function. + (gen_expr): Handle OP_VAR_MSYM_VALUE. + * eval.c (evaluate_var_msym_value): New function. + * eval.c (evaluate_subexp_standard): Handle OP_VAR_MSYM_VALUE. + : Extract function name from symbol/minsym and pass it + to call_function_by_hand. + * expprint.c (print_subexp_standard, dump_subexp_body_standard): + Handle OP_VAR_MSYM_VALUE. + (union exp_element) : New field. + * minsyms.h (struct type): Forward declare. + (find_minsym_type_and_address): Declare. + * parse.c (write_exp_elt_msym): New function. + (write_exp_msymbol): Delete, refactored as ... + (find_minsym_type_and_address): ... this new function. + (write_exp_msymbol): Reimplement using OP_VAR_MSYM_VALUE. + (operator_length_standard, operator_check_standard): Handle + OP_VAR_MSYM_VALUE. + * std-operator.def (OP_VAR_MSYM_VALUE): New. + 2017-09-04 Pedro Alves * ada-lang.c (ada_evaluate_subexp) : Don't handle diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 519dfb1292..86f09b941a 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -3385,6 +3385,7 @@ resolve_subexp (struct expression **expp, int *pos, int deprocedure_p, case OP_LONG: case OP_DOUBLE: case OP_VAR_VALUE: + case OP_VAR_MSYM_VALUE: *pos += 4; break; diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index a72a4586fd..3fdf81afee 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -733,6 +733,23 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var) break; } } + +/* Generate code for a minimal symbol variable reference to AX. The + variable is the symbol MINSYM, of OBJFILE. Set VALUE to describe + the result. */ + +static void +gen_msym_var_ref (agent_expr *ax, axs_value *value, + minimal_symbol *msymbol, objfile *objf) +{ + CORE_ADDR address; + type *t = find_minsym_type_and_address (msymbol, objf, &address); + value->type = t; + value->optimized_out = false; + ax_const_l (ax, address); + value->kind = axs_lvalue_memory; +} + @@ -1964,6 +1981,11 @@ gen_expr (struct expression *exp, union exp_element **pc, (*pc) += 4; break; + case OP_VAR_MSYM_VALUE: + gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile); + (*pc) += 4; + break; + case OP_REGISTER: { const char *name = &(*pc)[2].string; diff --git a/gdb/eval.c b/gdb/eval.c index 1ec67513af..457e280f6b 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -676,6 +676,25 @@ make_params (int num_types, struct type **param_types) return type; } +/* Helper for evaluating an OP_VAR_MSYM_VALUE. */ + +static value * +evaluate_var_msym_value (enum noside noside, + struct objfile *objfile, minimal_symbol *msymbol) +{ + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + type *the_type = find_minsym_type_and_address (msymbol, objfile, NULL); + return value_zero (the_type, not_lval); + } + else + { + CORE_ADDR address; + type *the_type = find_minsym_type_and_address (msymbol, objfile, &address); + return value_at_lazy (the_type, address); + } +} + struct value * evaluate_subexp_standard (struct type *expect_type, struct expression *exp, int *pos, @@ -766,6 +785,11 @@ evaluate_subexp_standard (struct type *expect_type, return ret; } + case OP_VAR_MSYM_VALUE: + (*pos) += 3; + return evaluate_var_msym_value (noside, + exp->elts[pc + 1].objfile, + exp->elts[pc + 2].msymbol); case OP_VAR_ENTRY_VALUE: (*pos) += 2; diff --git a/gdb/expprint.c b/gdb/expprint.c index 9b8ac4c070..4939c01462 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -134,6 +134,13 @@ print_subexp_standard (struct expression *exp, int *pos, } return; + case OP_VAR_MSYM_VALUE: + { + (*pos) += 3; + fputs_filtered (MSYMBOL_PRINT_NAME (exp->elts[pc + 2].msymbol), stream); + } + return; + case OP_VAR_ENTRY_VALUE: { (*pos) += 2; @@ -876,6 +883,15 @@ dump_subexp_body_standard (struct expression *exp, SYMBOL_PRINT_NAME (exp->elts[elt + 1].symbol)); elt += 3; break; + case OP_VAR_MSYM_VALUE: + fprintf_filtered (stream, "Objfile @"); + gdb_print_host_address (exp->elts[elt].objfile, stream); + fprintf_filtered (stream, ", msymbol @"); + gdb_print_host_address (exp->elts[elt + 1].msymbol, stream); + fprintf_filtered (stream, " (%s)", + MSYMBOL_PRINT_NAME (exp->elts[elt + 1].msymbol)); + elt += 3; + break; case OP_VAR_ENTRY_VALUE: fprintf_filtered (stream, "Entry value of symbol @"); gdb_print_host_address (exp->elts[elt].symbol, stream); diff --git a/gdb/expression.h b/gdb/expression.h index 8fe6b07044..9e4ddf5ded 100644 --- a/gdb/expression.h +++ b/gdb/expression.h @@ -64,6 +64,7 @@ union exp_element { enum exp_opcode opcode; struct symbol *symbol; + struct minimal_symbol *msymbol; LONGEST longconst; DOUBLEST doubleconst; gdb_byte decfloatconst[16]; diff --git a/gdb/minsyms.h b/gdb/minsyms.h index e763f62aa3..dc517254e9 100644 --- a/gdb/minsyms.h +++ b/gdb/minsyms.h @@ -20,6 +20,8 @@ #ifndef MINSYMS_H #define MINSYMS_H +struct type; + /* Several lookup functions return both a minimal symbol and the objfile in which it is found. This structure is used in these cases. */ @@ -275,4 +277,11 @@ void iterate_over_minimal_symbols (struct objfile *objf, CORE_ADDR minimal_symbol_upper_bound (struct bound_minimal_symbol minsym); +/* Return the type of MSYMBOL, a minimal symbol of OBJFILE. If + ADDRESS_P is not NULL, set it to the MSYMBOL's resolved + address. */ + +type *find_minsym_type_and_address (minimal_symbol *msymbol, objfile *objf, + CORE_ADDR *address_p); + #endif /* MINSYMS_H */ diff --git a/gdb/parse.c b/gdb/parse.c index abf59d77e8..83bfa4b241 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -255,6 +255,16 @@ write_exp_elt_sym (struct parser_state *ps, struct symbol *expelt) write_exp_elt (ps, &tmp); } +void +write_exp_elt_msym (struct parser_state *ps, minimal_symbol *expelt) +{ + union exp_element tmp; + + memset (&tmp, 0, sizeof (union exp_element)); + tmp.msymbol = expelt; + write_exp_elt (ps, &tmp); +} + void write_exp_elt_block (struct parser_state *ps, const struct block *b) { @@ -470,17 +480,17 @@ write_exp_bitstring (struct parser_state *ps, struct stoken str) write_exp_elt_longcst (ps, (LONGEST) bits); } -/* Add the appropriate elements for a minimal symbol to the end of - the expression. */ +/* Return the type of MSYMBOL, a minimal symbol of OBJFILE. If + ADDRESS_P is not NULL, set it to the MSYMBOL's resolved + address. */ -void -write_exp_msymbol (struct parser_state *ps, - struct bound_minimal_symbol bound_msym) +type * +find_minsym_type_and_address (minimal_symbol *msymbol, + struct objfile *objfile, + CORE_ADDR *address_p) { - struct minimal_symbol *msymbol = bound_msym.minsym; - struct objfile *objfile = bound_msym.objfile; + bound_minimal_symbol bound_msym = {msymbol, objfile}; struct gdbarch *gdbarch = get_objfile_arch (objfile); - CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (bound_msym); struct obj_section *section = MSYMBOL_OBJ_SECTION (objfile, msymbol); enum minimal_symbol_type type = MSYMBOL_TYPE (msymbol); @@ -515,51 +525,54 @@ write_exp_msymbol (struct parser_state *ps, if (overlay_debugging) addr = symbol_overlayed_address (addr, section); - write_exp_elt_opcode (ps, OP_LONG); - /* Let's make the type big enough to hold a 64-bit address. */ - write_exp_elt_type (ps, objfile_type (objfile)->builtin_core_addr); - write_exp_elt_longcst (ps, (LONGEST) addr); - write_exp_elt_opcode (ps, OP_LONG); - if (section && section->the_bfd_section->flags & SEC_THREAD_LOCAL) { - write_exp_elt_opcode (ps, UNOP_MEMVAL_TLS); - write_exp_elt_objfile (ps, objfile); - write_exp_elt_type (ps, objfile_type (objfile)->nodebug_tls_symbol); - write_exp_elt_opcode (ps, UNOP_MEMVAL_TLS); - return; + /* Skip translation if caller does not need the address. */ + if (address_p != NULL) + *address_p = target_translate_tls_address (objfile, addr); + return objfile_type (objfile)->nodebug_tls_symbol; } - write_exp_elt_opcode (ps, UNOP_MEMVAL); + if (address_p != NULL) + *address_p = addr; + + struct type *the_type; + switch (type) { case mst_text: case mst_file_text: case mst_solib_trampoline: - write_exp_elt_type (ps, objfile_type (objfile)->nodebug_text_symbol); - break; + return objfile_type (objfile)->nodebug_text_symbol; case mst_text_gnu_ifunc: - write_exp_elt_type (ps, objfile_type (objfile) - ->nodebug_text_gnu_ifunc_symbol); - break; + return objfile_type (objfile)->nodebug_text_gnu_ifunc_symbol; case mst_data: case mst_file_data: case mst_bss: case mst_file_bss: - write_exp_elt_type (ps, objfile_type (objfile)->nodebug_data_symbol); - break; + return objfile_type (objfile)->nodebug_data_symbol; case mst_slot_got_plt: - write_exp_elt_type (ps, objfile_type (objfile)->nodebug_got_plt_symbol); - break; + return objfile_type (objfile)->nodebug_got_plt_symbol; default: - write_exp_elt_type (ps, objfile_type (objfile)->nodebug_unknown_symbol); - break; + return objfile_type (objfile)->nodebug_unknown_symbol; } - write_exp_elt_opcode (ps, UNOP_MEMVAL); +} + +/* Add the appropriate elements for a minimal symbol to the end of + the expression. */ + +void +write_exp_msymbol (struct parser_state *ps, + struct bound_minimal_symbol bound_msym) +{ + write_exp_elt_opcode (ps, OP_VAR_MSYM_VALUE); + write_exp_elt_objfile (ps, bound_msym.objfile); + write_exp_elt_msym (ps, bound_msym.minsym); + write_exp_elt_opcode (ps, OP_VAR_MSYM_VALUE); } /* Mark the current index as the starting location of a structure @@ -884,6 +897,7 @@ operator_length_standard (const struct expression *expr, int endpos, case OP_DOUBLE: case OP_DECFLOAT: case OP_VAR_VALUE: + case OP_VAR_MSYM_VALUE: oplen = 4; break; @@ -1840,6 +1854,9 @@ operator_check_standard (struct expression *exp, int pos, type = SYMBOL_TYPE (symbol); } break; + case OP_VAR_MSYM_VALUE: + objfile = elts[pos + 1].objfile; + break; } /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */ diff --git a/gdb/std-operator.def b/gdb/std-operator.def index 465072616f..9007dd4848 100644 --- a/gdb/std-operator.def +++ b/gdb/std-operator.def @@ -132,6 +132,12 @@ OP (OP_VAR_VALUE) current function. Implemented via DW_OP_entry_value. */ OP (OP_VAR_ENTRY_VALUE) +/* OP_VAR_MSYM_VALUE takes one struct objfile * in the following + element, and one struct minimal_symbol * in the following + exp_element, followed by another OP_VAR_MSYM_VALUE, making four + exp_elements. */ +OP (OP_VAR_MSYM_VALUE) + /* OP_LAST is followed by an integer in the next exp_element. The integer is zero for the last value printed, or it is the absolute number of a history element.