diff options
45 files changed, 1003 insertions, 155 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5dd90e7..8746f60 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,112 @@ +2015-08-25 Pierre-Marie de Rodat <derodat@adacore.com> + + * ada-lang.c (ada_read_var_value): Add a var_block argument + and pass it to default_read_var_value. + * block.c (block_static_link): New accessor. + * block.h (block_static_link): Declare it. + * buildsym.c (finish_block_internal): Add a static_link + argument. If there is a static link, associate it to the new + block. + (finish_block): Add a static link argument and pass it to + finish_block_internal. + (end_symtab_get_static_block): Update calls to finish_block and + to finish_block_internal. + (end_symtab_with_blockvector): Update call to + finish_block_internal. + * buildsym.h: Forward-declare struct dynamic_prop. + (struct context_stack): Add a static_link field. + (finish_block): Add a static link argument. + * c-exp.y: Remove an obsolete comment (evaluation of variables + already start from the selected frame, and now they climb *up* + the call stack) and propagate the block information to the + produced expression. + * d-exp.y: Likewise. + * f-exp.y: Likewise. + * go-exp.y: Likewise. + * jv-exp.y: Likewise. + * m2-exp.y: Likewise. + * p-exp.y: Likewise. + * coffread.c (coff_symtab_read): Update calls to finish_block. + * dbxread.c (process_one_symbol): Likewise. + * xcoffread.c (read_xcoff_symtab): Likewise. + * compile/compile-c-symbols.c (convert_one_symbol): Promote the + "sym" parameter to struct block_symbol, update its uses and pass + its block to calls to read_var_value. + (convert_symbol_sym): Update the calls to convert_one_symbol. + * compile/compile-loc2c.c (do_compile_dwarf_expr_to_c): Update + call to read_var_value. + * dwarf2loc.c (block_op_get_frame_base): New. + (dwarf2_block_frame_base_locexpr_funcs): Implement the + get_frame_base method. + (dwarf2_block_frame_base_loclist_funcs): Likewise. + (dwarf2locexpr_baton_eval): Add a frame argument and use it + instead of the selected frame in order to evaluate the + expression. + (dwarf2_evaluate_property): Add a frame argument. Update call + to dwarf2_locexpr_baton_eval to provide a frame in available and + to handle the absence of address stack. + * dwarf2loc.h (dwarf2_evaluate_property): Add a frame argument. + * dwarf2read.c (attr_to_dynamic_prop): Add a forward + declaration. + (read_func_scope): Record any available static link description. + Update call to finish_block. + (read_lexical_block_scope): Update call to finish_block. + * findvar.c (follow_static_link): New. + (get_hosting_frame): New. + (default_read_var_value): Add a var_block argument. Use + get_hosting_frame to handle non-local references. + (read_var_value): Add a var_block argument and pass it to the + LA_READ_VAR_VALUE method. + * gdbtypes.c (resolve_dynamic_range): Update calls to + dwarf2_evaluate_property. + (resolve_dynamic_type_internal): Likewise. + * guile/scm-frame.c (gdbscm_frame_read_var): Update call to + read_var_value, passing it the block coming from symbol lookup. + * guile/scm-symbol.c (gdbscm_symbol_value): Update call to + read_var_value (TODO). + * infcmd.c (finish_command_continuation): Update call to + read_var_value, passing it the block coming from symbol lookup. + * infrun.c (insert_exception_resume_breakpoint): Likewise. + * language.h (struct language_defn): Add a var_block argument to + the LA_READ_VAR_VALUE method. + * objfiles.c (struct static_link_htab_entry): New. + (static_link_htab_entry_hash): New. + (static_link_htab_entry_eq): New. + (objfile_register_static_link): New. + (objfile_lookup_static_link): New. + (free_objfile): Free the STATIC_LINKS hashed map if needed. + * objfiles.h: Include hashtab.h. + (struct objfile): Add a static_links field. + (objfile_register_static_link): New. + (objfile_lookup_static_link): New. + * printcmd.c (print_variable_and_value): Update call to + read_var_value. + * python/py-finishbreakpoint.c (bpfinishpy_init): Likewise. + * python/py-frame.c (frapy_read_var): Update call to + read_var_value, passing it the block coming from symbol lookup. + * python/py-framefilter.c (extract_sym): Add a sym_block + parameter and set the pointed value to NULL (TODO). + (enumerate_args): Update call to extract_sym. + (enumerate_locals): Update calls to extract_sym and to + read_var_value. + * python/py-symbol.c (sympy_value): Update call to + read_var_value (TODO). + * stack.c (read_frame_local): Update call to read_var_value. + (read_frame_arg): Likewise. + (return_command): Likewise. + * symtab.h (struct symbol_block_ops): Add a get_frame_base + method. + (struct symbol): Add a block field. + (SYMBOL_BLOCK): New accessor. + * valops.c (value_of_variable): Remove frame/block handling and + pass the block argument to read_var_value, which does this job + now. + (value_struct_elt_for_reference): Update calls to + read_var_value. + (value_of_this): Pass the block found to read_var_value. + * value.h (read_var_value): Add a var_block argument. + (default_read_var_value): Likewise. + 2015-08-25 Yao Qi <yao.qi@linaro.org> * aarch64-linux-nat.c (aarch64_linux_new_thread): Move it to ... diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 1fa6524..4d7d22e 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -13844,7 +13844,8 @@ ada_get_symbol_name_cmp (const char *lookup_name) /* Implement the "la_read_var_value" language_defn method for Ada. */ static struct value * -ada_read_var_value (struct symbol *var, struct frame_info *frame) +ada_read_var_value (struct symbol *var, const struct block *var_block, + struct frame_info *frame) { const struct block *frame_block = NULL; struct symbol *renaming_sym = NULL; @@ -13860,7 +13861,7 @@ ada_read_var_value (struct symbol *var, struct frame_info *frame) /* This is a typical case where we expect the default_read_var_value function to work. */ - return default_read_var_value (var, frame); + return default_read_var_value (var, var_block, frame); } const struct language_defn ada_language_defn = { diff --git a/gdb/block.c b/gdb/block.c index f7621aa..f4b8e4f 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -428,6 +428,21 @@ set_block_compunit_symtab (struct block *block, struct compunit_symtab *cu) gb->compunit_symtab = cu; } +/* See block.h. */ + +struct dynamic_prop * +block_static_link (const struct block *block) +{ + struct objfile *objfile = block_objfile (block); + + /* Only objfile-owned blocks that materialize top function scopes can have + static links. */ + if (objfile == NULL || BLOCK_FUNCTION (block) == NULL) + return NULL; + + return (struct dynamic_prop *) objfile_lookup_static_link (objfile, block); +} + /* Return the compunit of the global block. */ static struct compunit_symtab * diff --git a/gdb/block.h b/gdb/block.h index 3dbcbcb..c15114b 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -179,6 +179,17 @@ extern struct block *allocate_global_block (struct obstack *obstack); extern void set_block_compunit_symtab (struct block *, struct compunit_symtab *); +/* Return a property to evaluate the static link associated to BLOCK. + + In the context of nested functions (available in Pascal, Ada and GNU C, for + instance), a static link (as in DWARF's DW_AT_static_link attribute) for a + function is a way to get the frame corresponding to the enclosing function. + + Note that only objfile-owned and function-level blocks can have a static + link. Return NULL if there is no such property. */ + +extern struct dynamic_prop *block_static_link (const struct block *block); + /* A block iterator. This structure should be treated as though it were opaque; it is only defined here because we want to support stack allocation of iterators. */ diff --git a/gdb/buildsym.c b/gdb/buildsym.c index 92c42d5..36ec62f 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -331,8 +331,10 @@ free_pending_blocks (void) file). Put the block on the list of pending blocks. */ static struct block * -finish_block_internal (struct symbol *symbol, struct pending **listhead, +finish_block_internal (struct symbol *symbol, + struct pending **listhead, struct pending_block *old_blocks, + const struct dynamic_prop *static_link, CORE_ADDR start, CORE_ADDR end, int is_global, int expandable) { @@ -422,6 +424,9 @@ finish_block_internal (struct symbol *symbol, struct pending **listhead, BLOCK_FUNCTION (block) = NULL; } + if (static_link != NULL) + objfile_register_static_link (objfile, block, static_link); + /* Now "free" the links of the list, and empty the list. */ for (next = *listhead; next; next = next1) @@ -519,11 +524,13 @@ finish_block_internal (struct symbol *symbol, struct pending **listhead, } struct block * -finish_block (struct symbol *symbol, struct pending **listhead, +finish_block (struct symbol *symbol, + struct pending **listhead, struct pending_block *old_blocks, + const struct dynamic_prop *static_link, CORE_ADDR start, CORE_ADDR end) { - return finish_block_internal (symbol, listhead, old_blocks, + return finish_block_internal (symbol, listhead, old_blocks, static_link, start, end, 0, 0); } @@ -1229,7 +1236,7 @@ end_symtab_get_static_block (CORE_ADDR end_addr, int expandable, int required) struct context_stack *cstk = pop_context (); /* Make a block for the local symbols within. */ - finish_block (cstk->name, &local_symbols, cstk->old_blocks, + finish_block (cstk->name, &local_symbols, cstk->old_blocks, NULL, cstk->start_addr, end_addr); if (context_stack_depth > 0) @@ -1301,7 +1308,7 @@ end_symtab_get_static_block (CORE_ADDR end_addr, int expandable, int required) else { /* Define the STATIC_BLOCK. */ - return finish_block_internal (NULL, &file_symbols, NULL, + return finish_block_internal (NULL, &file_symbols, NULL, NULL, last_source_start_addr, end_addr, 0, expandable); } @@ -1329,7 +1336,7 @@ end_symtab_with_blockvector (struct block *static_block, end_addr = BLOCK_END (static_block); /* Create the GLOBAL_BLOCK and build the blockvector. */ - finish_block_internal (NULL, &global_symbols, NULL, + finish_block_internal (NULL, &global_symbols, NULL, NULL, last_source_start_addr, end_addr, 1, expandable); blockvector = make_blockvector (); diff --git a/gdb/buildsym.h b/gdb/buildsym.h index 4c0ec15..b1eda8c 100644 --- a/gdb/buildsym.h +++ b/gdb/buildsym.h @@ -39,6 +39,8 @@ struct compunit_symtab; struct block; struct pending_block; +struct dynamic_prop; + #ifndef EXTERN #define EXTERN extern #endif @@ -145,6 +147,11 @@ struct context_stack struct symbol *name; + /* Expression that computes the frame base of the lexically enclosing + function, if any. NULL otherwise. */ + + struct dynamic_prop *static_link; + /* PC where this context starts */ CORE_ADDR start_addr; @@ -196,9 +203,11 @@ extern struct symbol *find_symbol_in_list (struct pending *list, char *name, int length); extern struct block *finish_block (struct symbol *symbol, - struct pending **listhead, - struct pending_block *old_blocks, - CORE_ADDR start, CORE_ADDR end); + struct pending **listhead, + struct pending_block *old_blocks, + const struct dynamic_prop *static_link, + CORE_ADDR start, + CORE_ADDR end); extern void record_block_range (struct block *, CORE_ADDR start, CORE_ADDR end_inclusive); diff --git a/gdb/c-exp.y b/gdb/c-exp.y index a8a4caf..351505e 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -1072,10 +1072,7 @@ variable: name_not_typename } write_exp_elt_opcode (pstate, OP_VAR_VALUE); - /* We want to use the selected frame, not - another more inner frame which happens to - be in the same block. */ - write_exp_elt_block (pstate, NULL); + write_exp_elt_block (pstate, sym.block); write_exp_elt_sym (pstate, sym.symbol); write_exp_elt_opcode (pstate, OP_VAR_VALUE); } diff --git a/gdb/coffread.c b/gdb/coffread.c index 7722cdb..c0f4267 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -1144,8 +1144,8 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line, objfile); - finish_block (newobj->name, &local_symbols, - newobj->old_blocks, newobj->start_addr, + finish_block (newobj->name, &local_symbols, newobj->old_blocks, + NULL, newobj->start_addr, fcn_cs_saved.c_value + fcn_aux_saved.x_sym.x_misc.x_fsize + ANOFFSET (objfile->section_offsets, @@ -1188,7 +1188,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, newobj->old_blocks, + finish_block (0, &local_symbols, newobj->old_blocks, NULL, newobj->start_addr, tmpaddr); } /* Now pop locals of block just finished. */ diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c index 21ce655..355b063 100644 --- a/gdb/compile/compile-c-symbols.c +++ b/gdb/compile/compile-c-symbols.c @@ -143,26 +143,26 @@ symbol_substitution_name (struct symbol *sym) static void convert_one_symbol (struct compile_c_instance *context, - struct symbol *sym, + struct block_symbol sym, int is_global, int is_local) { gcc_type sym_type; - const char *filename = symbol_symtab (sym)->filename; - unsigned short line = SYMBOL_LINE (sym); + const char *filename = symbol_symtab (sym.symbol)->filename; + unsigned short line = SYMBOL_LINE (sym.symbol); - error_symbol_once (context, sym); + error_symbol_once (context, sym.symbol); - if (SYMBOL_CLASS (sym) == LOC_LABEL) + if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL) sym_type = 0; else - sym_type = convert_type (context, SYMBOL_TYPE (sym)); + sym_type = convert_type (context, SYMBOL_TYPE (sym.symbol)); - if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN) + if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN) { /* Binding a tag, so we don't need to build a decl. */ C_CTX (context)->c_ops->tagbind (C_CTX (context), - SYMBOL_NATURAL_NAME (sym), + SYMBOL_NATURAL_NAME (sym.symbol), sym_type, filename, line); } else @@ -172,7 +172,7 @@ convert_one_symbol (struct compile_c_instance *context, CORE_ADDR addr = 0; char *symbol_name = NULL; - switch (SYMBOL_CLASS (sym)) + switch (SYMBOL_CLASS (sym.symbol)) { case LOC_TYPEDEF: kind = GCC_C_SYMBOL_TYPEDEF; @@ -180,45 +180,46 @@ convert_one_symbol (struct compile_c_instance *context, case LOC_LABEL: kind = GCC_C_SYMBOL_LABEL; - addr = SYMBOL_VALUE_ADDRESS (sym); + addr = SYMBOL_VALUE_ADDRESS (sym.symbol); break; case LOC_BLOCK: kind = GCC_C_SYMBOL_FUNCTION; - addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); - if (is_global && TYPE_GNU_IFUNC (SYMBOL_TYPE (sym))) + addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol)); + if (is_global && TYPE_GNU_IFUNC (SYMBOL_TYPE (sym.symbol))) addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr); break; case LOC_CONST: - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM) + if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_ENUM) { /* Already handled by convert_enum. */ return; } - C_CTX (context)->c_ops->build_constant (C_CTX (context), sym_type, - SYMBOL_NATURAL_NAME (sym), - SYMBOL_VALUE (sym), - filename, line); + C_CTX (context)->c_ops->build_constant + (C_CTX (context), + sym_type, SYMBOL_NATURAL_NAME (sym.symbol), + SYMBOL_VALUE (sym.symbol), + filename, line); return; case LOC_CONST_BYTES: error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); case LOC_UNDEF: internal_error (__FILE__, __LINE__, _("LOC_UNDEF found for \"%s\"."), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); case LOC_COMMON_BLOCK: error (_("Fortran common block is unsupported for compilation " "evaluaton of symbol \"%s\"."), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); case LOC_OPTIMIZED_OUT: error (_("Symbol \"%s\" cannot be used for compilation evaluation " "as it is optimized out."), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); case LOC_COMPUTED: if (is_local) @@ -227,7 +228,7 @@ convert_one_symbol (struct compile_c_instance *context, warning (_("Symbol \"%s\" is thread-local and currently can only " "be referenced from the current thread in " "compiled code."), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); /* FALLTHROUGH */ case LOC_UNRESOLVED: /* 'symbol_name' cannot be used here as that one is used only for @@ -238,20 +239,20 @@ convert_one_symbol (struct compile_c_instance *context, struct value *val; struct frame_info *frame = NULL; - if (symbol_read_needs_frame (sym)) + if (symbol_read_needs_frame (sym.symbol)) { frame = get_selected_frame (NULL); if (frame == NULL) error (_("Symbol \"%s\" cannot be used because " "there is no selected frame"), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); } - val = read_var_value (sym, frame); + val = read_var_value (sym.symbol, sym.block, frame); if (VALUE_LVAL (val) != lval_memory) error (_("Symbol \"%s\" cannot be used for compilation " "evaluation as its address has not been found."), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); kind = GCC_C_SYMBOL_VARIABLE; addr = value_address (val); @@ -266,12 +267,12 @@ convert_one_symbol (struct compile_c_instance *context, case LOC_LOCAL: substitution: kind = GCC_C_SYMBOL_VARIABLE; - symbol_name = symbol_substitution_name (sym); + symbol_name = symbol_substitution_name (sym.symbol); break; case LOC_STATIC: kind = GCC_C_SYMBOL_VARIABLE; - addr = SYMBOL_VALUE_ADDRESS (sym); + addr = SYMBOL_VALUE_ADDRESS (sym.symbol); break; case LOC_FINAL_VALUE: @@ -284,12 +285,13 @@ convert_one_symbol (struct compile_c_instance *context, if (context->base.scope != COMPILE_I_RAW_SCOPE || symbol_name == NULL) { - decl = C_CTX (context)->c_ops->build_decl (C_CTX (context), - SYMBOL_NATURAL_NAME (sym), - kind, - sym_type, - symbol_name, addr, - filename, line); + decl = C_CTX (context)->c_ops->build_decl + (C_CTX (context), + SYMBOL_NATURAL_NAME (sym.symbol), + kind, + sym_type, + symbol_name, addr, + filename, line); C_CTX (context)->c_ops->bind (C_CTX (context), decl, is_global); } @@ -338,7 +340,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier, fprintf_unfiltered (gdb_stdlog, "gcc_convert_symbol \"%s\": global symbol\n", identifier); - convert_one_symbol (context, global_sym.symbol, 1, 0); + convert_one_symbol (context, global_sym, 1, 0); } } @@ -346,7 +348,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier, fprintf_unfiltered (gdb_stdlog, "gcc_convert_symbol \"%s\": local symbol\n", identifier); - convert_one_symbol (context, sym.symbol, 0, is_local_symbol); + convert_one_symbol (context, sym, 0, is_local_symbol); } /* Convert a minimal symbol to its gcc form. CONTEXT is the compiler diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c index b201d13..8058cbd 100644 --- a/gdb/compile/compile-loc2c.c +++ b/gdb/compile/compile-loc2c.c @@ -636,7 +636,7 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream, "there is no selected frame"), SYMBOL_PRINT_NAME (sym)); - val = read_var_value (sym, frame); + val = read_var_value (sym, NULL, frame); if (VALUE_LVAL (val) != lval_memory) error (_("Symbol \"%s\" cannot be used for compilation evaluation " "as its address has not been found."), diff --git a/gdb/dbxread.c b/gdb/dbxread.c index 1d00432..fdf4e09 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -2756,7 +2756,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, /* Make a block for the local symbols within. */ block = finish_block (newobj->name, &local_symbols, - newobj->old_blocks, + newobj->old_blocks, NULL, newobj->start_addr, newobj->start_addr + valu); /* For C++, set the block's scope. */ @@ -2857,7 +2857,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, newobj->start_addr = valu; } /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, newobj->old_blocks, + finish_block (0, &local_symbols, newobj->old_blocks, NULL, newobj->start_addr, valu); } } @@ -3155,8 +3155,8 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name, newobj = pop_context (); /* Make a block for the local symbols within. */ block = finish_block (newobj->name, &local_symbols, - newobj->old_blocks, newobj->start_addr, - valu); + newobj->old_blocks, NULL, + newobj->start_addr, valu); /* For C++, set the block's scope. */ if (SYMBOL_LANGUAGE (newobj->name) == language_cplus) diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index d8e432e..efe4357 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -381,12 +381,47 @@ locexpr_find_frame_base_location (struct symbol *framefunc, CORE_ADDR pc, *start = symbaton->data; } +/* Implement the struct symbol_block_ops::get_frame_base method. */ + +static CORE_ADDR +block_op_get_frame_base (struct symbol *framefunc, struct frame_info *frame) +{ + struct gdbarch *gdbarch; + struct type *type; + struct dwarf2_locexpr_baton *dlbaton; + const gdb_byte *start; + size_t length; + struct value *result; + + /* If this method is called, then FRAMEFUNC is supposed to be a DWARF block. + Thus, it's supposed to provide the find_frame_base_location method as + well. */ + gdb_assert (SYMBOL_BLOCK_OPS (framefunc)->find_frame_base_location != NULL); + + gdbarch = get_frame_arch (frame); + type = builtin_type (gdbarch)->builtin_data_ptr; + dlbaton = SYMBOL_LOCATION_BATON (framefunc); + + SYMBOL_BLOCK_OPS (framefunc)->find_frame_base_location + (framefunc, get_frame_pc (frame), &start, &length); + result = dwarf2_evaluate_loc_desc (type, frame, start, length, + dlbaton->per_cu); + + /* The DW_AT_frame_base attribute contains a location description which + computes the base address itself. However, the call to + dwarf2_evaluate_loc_desc returns a value representing a variable at + that address. The frame base address is thus this variable's + address. */ + return value_address (result); +} + /* Vector for inferior functions as represented by LOC_BLOCK, if the inferior function uses DWARF expression for its DW_AT_frame_base. */ const struct symbol_block_ops dwarf2_block_frame_base_locexpr_funcs = { - locexpr_find_frame_base_location + locexpr_find_frame_base_location, + block_op_get_frame_base }; /* Implement find_frame_base_location method for LOC_BLOCK functions using @@ -406,7 +441,8 @@ loclist_find_frame_base_location (struct symbol *framefunc, CORE_ADDR pc, const struct symbol_block_ops dwarf2_block_frame_base_loclist_funcs = { - loclist_find_frame_base_location + loclist_find_frame_base_location, + block_op_get_frame_base }; /* See dwarf2loc.h. */ @@ -2396,13 +2432,14 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, } /* Evaluates a dwarf expression and stores the result in VAL, expecting - that the dwarf expression only produces a single CORE_ADDR. ADDR is a - context (location of a variable) and might be needed to evaluate the - location expression. + that the dwarf expression only produces a single CORE_ADDR. FRAME is the + frame in which the expression is evaluated. ADDR is a context (location of + a variable) and might be needed to evaluate the location expression. Returns 1 on success, 0 otherwise. */ static int dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, + struct frame_info *frame, CORE_ADDR addr, CORE_ADDR *valp) { @@ -2417,7 +2454,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, ctx = new_dwarf_expr_context (); cleanup = make_cleanup_free_dwarf_expr_context (ctx); - baton.frame = get_selected_frame (NULL); + baton.frame = frame; baton.per_cu = dlbaton->per_cu; baton.obj_address = addr; @@ -2461,19 +2498,24 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, int dwarf2_evaluate_property (const struct dynamic_prop *prop, + struct frame_info *frame, struct property_addr_info *addr_stack, CORE_ADDR *value) { if (prop == NULL) return 0; + if (frame == NULL && has_stack_frames ()) + frame = get_selected_frame (NULL); + switch (prop->kind) { case PROP_LOCEXPR: { const struct dwarf2_property_baton *baton = prop->data.baton; - if (dwarf2_locexpr_baton_eval (&baton->locexpr, addr_stack->addr, + if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, + addr_stack ? addr_stack->addr : 0, value)) { if (baton->referenced_type) @@ -2490,7 +2532,6 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop, case PROP_LOCLIST: { struct dwarf2_property_baton *baton = prop->data.baton; - struct frame_info *frame = get_selected_frame (NULL); CORE_ADDR pc = get_frame_address_in_block (frame); const gdb_byte *data; struct value *val; diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index f3630ac..2415656 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -122,12 +122,19 @@ struct property_addr_info struct property_addr_info *next; }; -/* Converts a dynamic property into a static one. ADDR_STACK is the stack - of addresses that might be needed to evaluate the property. +/* Converts a dynamic property into a static one. FRAME is the frame in which + the property is evaluated; if NULL, the selected frame (if any) is used + instead. + + ADDR_STACK is the stack of addresses that might be needed to evaluate the + property. When evaluating a property that is not related to a type, it can + be NULL. + Returns 1 if PROP could be converted and the static value is passed back into VALUE, otherwise returns 0. */ int dwarf2_evaluate_property (const struct dynamic_prop *prop, + struct frame_info *frame, struct property_addr_info *addr_stack, CORE_ADDR *value); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 67b4a6d..77d37dd 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1743,6 +1743,10 @@ static void load_full_type_unit (struct dwarf2_per_cu_data *per_cu); static void read_signatured_type (struct signatured_type *); +static int attr_to_dynamic_prop (const struct attribute *attr, + struct die_info *die, struct dwarf2_cu *cu, + struct dynamic_prop *prop); + /* memory allocation interface */ static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *); @@ -11392,6 +11396,16 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) if (attr) dwarf2_symbol_mark_computed (attr, newobj->name, cu, 1); + /* If there is a location for the static link, record it. */ + newobj->static_link = NULL; + attr = dwarf2_attr (die, DW_AT_static_link, cu); + if (attr) + { + newobj->static_link = obstack_alloc (&objfile->objfile_obstack, + sizeof (*newobj->static_link)); + attr_to_dynamic_prop (attr, die, cu, newobj->static_link); + } + cu->list_in_scope = &local_symbols; if (die->child != NULL) @@ -11443,7 +11457,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) newobj = pop_context (); /* Make a block for the local symbols within. */ block = finish_block (newobj->name, &local_symbols, newobj->old_blocks, - lowpc, highpc); + newobj->static_link, lowpc, highpc); /* For C++, set the block's scope. */ if ((cu->language == language_cplus @@ -11528,7 +11542,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) if (local_symbols != NULL || local_using_directives != NULL) { struct block *block - = finish_block (0, &local_symbols, newobj->old_blocks, + = finish_block (0, &local_symbols, newobj->old_blocks, NULL, newobj->start_addr, highpc); /* Note that recording ranges after traversing children, as we diff --git a/gdb/f-exp.y b/gdb/f-exp.y index 3c486ef..56629dc 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -521,10 +521,7 @@ variable: name_not_typename innermost_block = sym.block; } write_exp_elt_opcode (pstate, OP_VAR_VALUE); - /* We want to use the selected frame, not - another more inner frame which happens to - be in the same block. */ - write_exp_elt_block (pstate, NULL); + write_exp_elt_block (pstate, sym.block); write_exp_elt_sym (pstate, sym.symbol); write_exp_elt_opcode (pstate, OP_VAR_VALUE); break; diff --git a/gdb/findvar.c b/gdb/findvar.c index 83b4fca..1c077f7 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -32,6 +32,7 @@ #include "block.h" #include "objfiles.h" #include "language.h" +#include "dwarf2loc.h" /* Basic byte-swapping routines. All 'extract' functions return a host-format integer from a target-format integer at ADDR which is @@ -409,11 +410,166 @@ minsym_lookup_iterator_cb (struct objfile *objfile, void *cb_data) return (data->result.minsym != NULL); } +/* Given static link expression and the frame it lives in, look for the frame + the static links points to and return it. Return NULL if we could not find + such a frame. */ + +static struct frame_info * +follow_static_link (struct frame_info *frame, + const struct dynamic_prop *static_link) +{ + CORE_ADDR upper_frame_base; + + if (!dwarf2_evaluate_property (static_link, frame, NULL, &upper_frame_base)) + return NULL; + + /* Now climb up the stack frame until we reach the frame we are interested + in. */ + for (; frame != NULL; frame = get_prev_frame (frame)) + { + struct symbol *framefunc = get_frame_function (frame); + + /* Stacks can be quite deep: give the user a chance to stop this. */ + QUIT; + + /* If we don't know how to compute FRAME's base address, don't give up: + maybe the frame we are looking for is upper in the stace frame. */ + if (framefunc != NULL + && SYMBOL_BLOCK_OPS (framefunc)->get_frame_base != NULL + && (SYMBOL_BLOCK_OPS (framefunc)->get_frame_base (framefunc, frame) + == upper_frame_base)) + break; + } + + return frame; +} + +/* Assuming VAR is a symbol that can be reached from FRAME thanks to lexical + rules, look for the frame that is actually hosting VAR and return it. If, + for some reason, we found no such frame, return NULL. + + This kind of computation is necessary to correctly handle lexically nested + functions. + + Note that in some cases, we know what scope VAR comes from but we cannot + reach the specific frame that hosts the instance of VAR we are looking for. + For backward compatibility purposes (with old compilers), we then look for + the first frame that can host it. */ + +static struct frame_info * +get_hosting_frame (struct symbol *var, const struct block *var_block, + struct frame_info *frame) +{ + const struct block *frame_block = NULL; + + if (!symbol_read_needs_frame (var)) + return NULL; + + /* Some symbols for local variables have no block: this happens when they are + not produced by a debug information reader, for instance when GDB creates + synthetic symbols. Without block information, we must assume they are + local to FRAME. In this case, there is nothing to do. */ + else if (var_block == NULL) + return frame; + + /* We currently assume that all symbols with a location list need a frame. + This is true in practice because selecting the location description + requires to compute the CFA, hence requires a frame. However we have + tests that embed global/static symbols with null location lists. + We want to get <optimized out> instead of <frame required> when evaluating + them so return a frame instead of raising an error. */ + else if (var_block == block_global_block (var_block) + || var_block == block_static_block (var_block)) + return frame; + + /* We have to handle the "my_func::my_local_var" notation. This requires us + to look for upper frames when we find no block for the current frame: here + and below, handle when frame_block == NULL. */ + if (frame != NULL) + frame_block = get_frame_block (frame, NULL); + + /* Climb up the call stack until reaching the frame we are looking for. */ + while (frame != NULL && frame_block != var_block) + { + /* Stacks can be quite deep: give the user a chance to stop this. */ + QUIT; + + if (frame_block == NULL) + { + frame = get_prev_frame (frame); + if (frame == NULL) + break; + frame_block = get_frame_block (frame, NULL); + } + + /* If we failed to find the proper frame, fallback to the heuristic + method below. */ + else if (frame_block == block_global_block (frame_block)) + { + frame = NULL; + break; + } + + /* Assuming we have a block for this frame: if we are at the function + level, the immediate upper lexical block is in an outer function: + follow the static link. */ + else if (BLOCK_FUNCTION (frame_block)) + { + const struct dynamic_prop *static_link + = block_static_link (frame_block); + int could_climb_up = 0; + + if (static_link != NULL) + { + frame = follow_static_link (frame, static_link); + if (frame != NULL) + { + frame_block = get_frame_block (frame, NULL); + could_climb_up = frame_block != NULL; + } + } + if (!could_climb_up) + { + frame = NULL; + break; + } + } + + else + /* We must be in some function nested lexical block. Just get the + outer block: both must share the same frame. */ + frame_block = BLOCK_SUPERBLOCK (frame_block); + } + + /* Old compilers may not provide a static link, or they may provide an + invalid one. For such cases, fallback on the old way to evaluate + non-local references: just climb up the call stack and pick the first + frame that contains the variable we are looking for. */ + if (frame == NULL) + { + frame = block_innermost_frame (var_block); + if (frame == NULL) + { + if (BLOCK_FUNCTION (var_block) + && !block_inlined_p (var_block) + && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block))) + error (_("No frame is currently executing in block %s."), + SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block))); + else + error (_("No frame is currently executing in specified" + " block")); + } + } + + return frame; +} + /* A default implementation for the "la_read_var_value" hook in the language vector which should work in most situations. */ struct value * -default_read_var_value (struct symbol *var, struct frame_info *frame) +default_read_var_value (struct symbol *var, const struct block *var_block, + struct frame_info *frame) { struct value *v; struct type *type = SYMBOL_TYPE (var); @@ -427,7 +583,10 @@ default_read_var_value (struct symbol *var, struct frame_info *frame) check_typedef (type); if (symbol_read_needs_frame (var)) - gdb_assert (frame); + gdb_assert (frame != NULL); + + if (frame != NULL) + frame = get_hosting_frame (var, var_block, frame); if (SYMBOL_COMPUTED_OPS (var) != NULL) return SYMBOL_COMPUTED_OPS (var)->read_variable (var, frame); @@ -610,14 +769,15 @@ default_read_var_value (struct symbol *var, struct frame_info *frame) /* Calls VAR's language la_read_var_value hook with the given arguments. */ struct value * -read_var_value (struct symbol *var, struct frame_info *frame) +read_var_value (struct symbol *var, const struct block *var_block, + struct frame_info *frame) { const struct language_defn *lang = language_def (SYMBOL_LANGUAGE (var)); gdb_assert (lang != NULL); gdb_assert (lang->la_read_var_value != NULL); - return lang->la_read_var_value (var, frame); + return lang->la_read_var_value (var, var_block, frame); } /* Install default attributes for register values. */ diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 125af01..301c6fc 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1885,7 +1885,7 @@ resolve_dynamic_range (struct type *dyn_range_type, gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE); prop = &TYPE_RANGE_DATA (dyn_range_type)->low; - if (dwarf2_evaluate_property (prop, addr_stack, &value)) + if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value)) { low_bound.kind = PROP_CONST; low_bound.data.const_val = value; @@ -1897,7 +1897,7 @@ resolve_dynamic_range (struct type *dyn_range_type, } prop = &TYPE_RANGE_DATA (dyn_range_type)->high; - if (dwarf2_evaluate_property (prop, addr_stack, &value)) + if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value)) { high_bound.kind = PROP_CONST; high_bound.data.const_val = value; @@ -2139,7 +2139,8 @@ resolve_dynamic_type_internal (struct type *type, /* Resolve data_location attribute. */ prop = TYPE_DATA_LOCATION (resolved_type); - if (prop != NULL && dwarf2_evaluate_property (prop, addr_stack, &value)) + if (prop != NULL + && dwarf2_evaluate_property (prop, NULL, addr_stack, &value)) { TYPE_DYN_PROP_ADDR (prop) = value; TYPE_DYN_PROP_KIND (prop) = PROP_CONST; diff --git a/gdb/go-exp.y b/gdb/go-exp.y index c1ddfa9..4e017fe 100644 --- a/gdb/go-exp.y +++ b/gdb/go-exp.y @@ -611,10 +611,7 @@ variable: name_not_typename } write_exp_elt_opcode (pstate, OP_VAR_VALUE); - /* We want to use the selected frame, not - another more inner frame which happens to - be in the same block. */ - write_exp_elt_block (pstate, NULL); + write_exp_elt_block (pstate, sym.block); write_exp_elt_sym (pstate, sym.symbol); write_exp_elt_opcode (pstate, OP_VAR_VALUE); } diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c index 64ac0c0..de77c21 100644 --- a/gdb/guile/scm-frame.c +++ b/gdb/guile/scm-frame.c @@ -855,6 +855,7 @@ gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest) SCM block_scm = SCM_UNDEFINED; struct frame_info *frame = NULL; struct symbol *var = NULL; + const struct block *block = NULL; struct value *value = NULL; f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME); @@ -909,9 +910,13 @@ gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest) TRY { + struct block_symbol lookup_sym; + if (block == NULL) block = get_frame_block (frame, NULL); - var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL).symbol; + lookup_sym = lookup_symbol (var_name, block, VAR_DOMAIN, NULL); + var = lookup_sym.symbol; + block = lookup_sym.block; } CATCH (ex, RETURN_MASK_ALL) { @@ -940,7 +945,7 @@ gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest) TRY { - value = read_var_value (var, frame); + value = read_var_value (var, block, frame); } CATCH (except, RETURN_MASK_ALL) { diff --git a/gdb/guile/scm-symbol.c b/gdb/guile/scm-symbol.c index 01c9eb1..0970a72 100644 --- a/gdb/guile/scm-symbol.c +++ b/gdb/guile/scm-symbol.c @@ -550,7 +550,11 @@ gdbscm_symbol_value (SCM self, SCM rest) if (symbol_read_needs_frame (symbol) && frame_info == NULL) error (_("Symbol requires a frame to compute its value")); - value = read_var_value (symbol, frame_info); + /* TODO: currently, we have no way to recover the block in which SYMBOL + was found, so we have no block to pass to read_var_value. This will + yield an incorrect value when symbol is not local to FRAME_INFO (this + can happen with nested functions). */ + value = read_var_value (symbol, NULL, frame_info); } CATCH (except, RETURN_MASK_ALL) { diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 82399a4..393ccb9 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1662,7 +1662,7 @@ finish_command_continuation (void *arg, int err) { struct value *func; - func = read_var_value (a->function, get_current_frame ()); + func = read_var_value (a->function, NULL, get_current_frame ()); TRY { /* print_return_value can throw an exception in some diff --git a/gdb/infrun.c b/gdb/infrun.c index 25036a4..1e224b1 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -7198,14 +7198,13 @@ insert_exception_resume_breakpoint (struct thread_info *tp, { TRY { - struct symbol *vsym; + struct block_symbol vsym; struct value *value; CORE_ADDR handler; struct breakpoint *bp; - vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, - NULL).symbol; - value = read_var_value (vsym, frame); + vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL); + value = read_var_value (vsym.symbol, vsym.block, frame); /* If the value was optimized out, revert to the old behavior. */ if (! value_optimized_out (value)) { diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y index 4999848..60b7d2e 100644 --- a/gdb/jv-exp.y +++ b/gdb/jv-exp.y @@ -1284,9 +1284,7 @@ push_variable (struct parser_state *par_state, struct stoken name) } write_exp_elt_opcode (par_state, OP_VAR_VALUE); - /* We want to use the selected frame, not another more inner frame - which happens to be in the same block. */ - write_exp_elt_block (par_state, NULL); + write_exp_elt_block (par_state, sym.block); write_exp_elt_sym (par_state, sym.symbol); write_exp_elt_opcode (par_state, OP_VAR_VALUE); return 1; diff --git a/gdb/language.h b/gdb/language.h index 2265afc..8b579a2 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -241,13 +241,19 @@ struct language_defn void (*la_value_print) (struct value *, struct ui_file *, const struct value_print_options *); - /* Given a symbol VAR, and a stack frame id FRAME, read the value - of the variable an return (pointer to a) struct value containing - the value. + /* Given a symbol VAR, the corresponding block VAR_BLOCK (if any) and a + stack frame id FRAME, read the value of the variable and return (pointer + to a) struct value containing the value. + + VAR_BLOCK is needed if there's a possibility for VAR to be outside + FRAME. This is what happens if FRAME correspond to a nested function + and VAR is defined in the outer function. If callers know that VAR is + located in FRAME or is global/static, NULL can be passed as VAR_BLOCK. Throw an error if the variable cannot be found. */ struct value *(*la_read_var_value) (struct symbol *var, + const struct block *var_block, struct frame_info *frame); /* PC is possibly an unknown languages trampoline. diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y index 633c354..360fdea 100644 --- a/gdb/m2-exp.y +++ b/gdb/m2-exp.y @@ -637,10 +637,7 @@ variable: NAME } write_exp_elt_opcode (pstate, OP_VAR_VALUE); - /* We want to use the selected frame, not - another more inner frame which happens to - be in the same block. */ - write_exp_elt_block (pstate, NULL); + write_exp_elt_block (pstate, sym.block); write_exp_elt_sym (pstate, sym.symbol); write_exp_elt_opcode (pstate, OP_VAR_VALUE); } diff --git a/gdb/objfiles.c b/gdb/objfiles.c index c6f9f00..93d8b7d 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -199,6 +199,92 @@ set_objfile_main_name (struct objfile *objfile, objfile->per_bfd->language_of_main = lang; } +/* Helper structure to map blocks to static link properties in hash tables. */ + +struct static_link_htab_entry +{ + const struct block *block; + const struct dynamic_prop *static_link; +}; + +/* Return a hash code for struct static_link_htab_entry *P. */ + +static hashval_t +static_link_htab_entry_hash (const void *p) +{ + const struct static_link_htab_entry *e + = (const struct static_link_htab_entry *) p; + + return htab_hash_pointer (e->block); +} + +/* Return whether P1 an P2 (pointers to struct static_link_htab_entry) are + mappings for the same block. */ + +static int +static_link_htab_entry_eq (const void *p1, const void *p2) +{ + const struct static_link_htab_entry *e1 + = (const struct static_link_htab_entry *) p1; + const struct static_link_htab_entry *e2 + = (const struct static_link_htab_entry *) p2; + + return e1->block == e2->block; +} + +/* Register STATIC_LINK as the static link for BLOCK, which is part of OBJFILE. + Must not be called more than once for each BLOCK. */ + +void +objfile_register_static_link (struct objfile *objfile, + const struct block *block, + const struct dynamic_prop *static_link) +{ + void **slot; + struct static_link_htab_entry lookup_entry; + struct static_link_htab_entry *entry; + + if (objfile->static_links == NULL) + objfile->static_links = htab_create_alloc + (1, &static_link_htab_entry_hash, static_link_htab_entry_eq, NULL, + xcalloc, xfree); + + /* Create a slot for the mapping, make sure it's the first mapping for this + block and then create the mapping itself. */ + lookup_entry.block = block; + slot = htab_find_slot (objfile->static_links, &lookup_entry, INSERT); + gdb_assert (*slot == NULL); + + entry = (struct static_link_htab_entry *) obstack_alloc + (&objfile->objfile_obstack, sizeof (*entry)); + entry->block = block; + entry->static_link = static_link; + *slot = (void *) entry; +} + +/* Look for a static link for BLOCK, which is part of OBJFILE. Return NULL if + none was found. */ + +const struct dynamic_prop * +objfile_lookup_static_link (struct objfile *objfile, + const struct block *block) +{ + struct static_link_htab_entry *entry; + struct static_link_htab_entry lookup_entry; + + if (objfile->static_links == NULL) + return NULL; + lookup_entry.block = block; + entry + = (struct static_link_htab_entry *) htab_find (objfile->static_links, + &lookup_entry); + if (entry == NULL) + return NULL; + + gdb_assert (entry->block == block); + return entry->static_link; +} + /* Called via bfd_map_over_sections to build up the section table that @@ -653,6 +739,11 @@ free_objfile (struct objfile *objfile) /* Rebuild section map next time we need it. */ get_objfile_pspace_data (objfile->pspace)->section_map_dirty = 1; + /* Free the map for static links. There's no need to free static link + themselves since they were allocated on the objstack. */ + if (objfile->static_links != NULL) + htab_delete (objfile->static_links); + /* The last thing we do is free the objfile struct itself. */ xfree (objfile); } diff --git a/gdb/objfiles.h b/gdb/objfiles.h index af70715..be2a5ef 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -20,6 +20,7 @@ #if !defined (OBJFILES_H) #define OBJFILES_H +#include "hashtab.h" #include "gdb_obstack.h" /* For obstack internals. */ #include "symfile.h" /* For struct psymbol_allocation_list. */ #include "progspace.h" @@ -428,6 +429,19 @@ struct objfile properly. */ struct symbol *template_symbols; + + /* Associate a static link (struct dynamic_prop *) to all blocks (struct + block *) that have one. + + In the context of nested functions (available in Pascal, Ada and GNU C, + for instance), a static link (as in DWARF's DW_AT_static_link attribute) + for a function is a way to get the frame corresponding to the enclosing + function. + + Very few blocks have a static link, so it's more memory efficient to + store these here rather than in struct block. Static links must be + allocated on the objfile's obstack. */ + htab_t static_links; }; /* Defines for the objfile flag word. */ @@ -735,4 +749,12 @@ extern const char *objfile_debug_name (const struct objfile *objfile); extern void set_objfile_main_name (struct objfile *objfile, const char *name, enum language lang); +extern void objfile_register_static_link + (struct objfile *objfile, + const struct block *block, + const struct dynamic_prop *static_link); + +extern const struct dynamic_prop *objfile_lookup_static_link + (struct objfile *objfile, const struct block *block); + #endif /* !defined (OBJFILES_H) */ diff --git a/gdb/p-exp.y b/gdb/p-exp.y index 191b3d3..c255a57 100644 --- a/gdb/p-exp.y +++ b/gdb/p-exp.y @@ -772,10 +772,7 @@ variable: name_not_typename } write_exp_elt_opcode (pstate, OP_VAR_VALUE); - /* We want to use the selected frame, not - another more inner frame which happens to - be in the same block. */ - write_exp_elt_block (pstate, NULL); + write_exp_elt_block (pstate, sym.block); write_exp_elt_sym (pstate, sym.symbol); write_exp_elt_opcode (pstate, OP_VAR_VALUE); current_type = sym.symbol->type; } diff --git a/gdb/printcmd.c b/gdb/printcmd.c index f51e25c..553cc71 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1988,7 +1988,11 @@ print_variable_and_value (const char *name, struct symbol *var, struct value *val; struct value_print_options opts; - val = read_var_value (var, frame); + /* READ_VAR_VALUE needs a block in order to deal with non-local + references (i.e. to handle nested functions). In this context, we + print variables that are local to this frame, so we can avoid passing + a block to it. */ + val = read_var_value (var, NULL, frame); get_user_print_options (&opts); opts.deref_ref = 1; common_val_print (val, stream, indent, &opts, current_language); diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c index e543bb3..351f68c 100644 --- a/gdb/python/py-finishbreakpoint.c +++ b/gdb/python/py-finishbreakpoint.c @@ -265,7 +265,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) /* Ignore Python errors at this stage. */ self_bpfinish->return_type = type_to_type_object (ret_type); PyErr_Clear (); - func_value = read_var_value (function, frame); + func_value = read_var_value (function, NULL, frame); self_bpfinish->function_value = value_to_value_object (func_value); PyErr_Clear (); diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 7e5dd17..b448686 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -504,6 +504,7 @@ frapy_read_var (PyObject *self, PyObject *args) struct frame_info *frame; PyObject *sym_obj, *block_obj = NULL; struct symbol *var = NULL; /* gcc-4.3.2 false warning. */ + const struct block *block = NULL; struct value *val = NULL; if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj)) @@ -514,7 +515,6 @@ frapy_read_var (PyObject *self, PyObject *args) else if (gdbpy_is_string (sym_obj)) { char *var_name; - const struct block *block = NULL; struct cleanup *cleanup; var_name = python_string_to_target_string (sym_obj); @@ -536,11 +536,14 @@ frapy_read_var (PyObject *self, PyObject *args) TRY { + struct block_symbol lookup_sym; FRAPY_REQUIRE_VALID (self, frame); if (!block) block = get_frame_block (frame, NULL); - var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL).symbol; + lookup_sym = lookup_symbol (var_name, block, VAR_DOMAIN, NULL); + var = lookup_sym.symbol; + block = lookup_sym.block; } CATCH (except, RETURN_MASK_ALL) { @@ -572,7 +575,7 @@ frapy_read_var (PyObject *self, PyObject *args) { FRAPY_REQUIRE_VALID (self, frame); - val = read_var_value (var, frame); + val = read_var_value (var, block, frame); } CATCH (except, RETURN_MASK_ALL) { diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index e3336b1..ac97723 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -43,16 +43,17 @@ enum mi_print_types NAME is a pass-through argument where the name of the symbol will be written. NAME is allocated in this function, but the caller is responsible for clean up. SYM is a pass-through argument where the - symbol will be written. In the case of the API returning a string, - this will be set to NULL. LANGUAGE is also a pass-through argument - denoting the language attributed to the Symbol. In the case of SYM - being NULL, this will be set to the current language. Returns - EXT_LANG_BT_ERROR on error with the appropriate Python exception set, and - EXT_LANG_BT_OK on success. */ + symbol will be written and SYM_BLOCK is a pass-through argument to + write the block where the symbol lies in. In the case of the API + returning a string, this will be set to NULL. LANGUAGE is also a + pass-through argument denoting the language attributed to the + Symbol. In the case of SYM being NULL, this will be set to the + current language. Returns EXT_LANG_BT_ERROR on error with the + appropriate Python exception set, and EXT_LANG_BT_OK on success. */ static enum ext_lang_bt_status extract_sym (PyObject *obj, char **name, struct symbol **sym, - const struct language_defn **language) + struct block **sym_block, const struct language_defn **language) { PyObject *result = PyObject_CallMethod (obj, "symbol", NULL); @@ -75,12 +76,18 @@ extract_sym (PyObject *obj, char **name, struct symbol **sym, python_language. */ *language = python_language; *sym = NULL; + *sym_block = NULL; } else { /* This type checks 'result' during the conversion so we just call it unconditionally and check the return. */ *sym = symbol_object_to_symbol (result); + /* TODO: currently, we have no way to recover the block in which SYMBOL + was found, so we have no block to return. Trying to evaluate SYMBOL + will yield an incorrect value when it's located in a FRAME and + evaluated from another frame (as permitted in nested functions). */ + *sym_block = NULL; Py_DECREF (result); @@ -537,10 +544,11 @@ enumerate_args (PyObject *iter, const struct language_defn *language; char *sym_name; struct symbol *sym; + struct block *sym_block; struct value *val; enum ext_lang_bt_status success = EXT_LANG_BT_ERROR; - success = extract_sym (item, &sym_name, &sym, &language); + success = extract_sym (item, &sym_name, &sym, &sym_block, &language); if (success == EXT_LANG_BT_ERROR) { Py_DECREF (item); @@ -736,12 +744,13 @@ enumerate_locals (PyObject *iter, struct value *val; enum ext_lang_bt_status success = EXT_LANG_BT_ERROR; struct symbol *sym; + struct block *sym_block; int local_indent = 8 + (8 * indent); struct cleanup *locals_cleanups; locals_cleanups = make_cleanup_py_decref (item); - success = extract_sym (item, &sym_name, &sym, &language); + success = extract_sym (item, &sym_name, &sym, &sym_block, &language); if (success == EXT_LANG_BT_ERROR) { do_cleanups (locals_cleanups); @@ -769,7 +778,7 @@ enumerate_locals (PyObject *iter, { TRY { - val = read_var_value (sym, frame); + val = read_var_value (sym, sym_block, frame); } CATCH (except, RETURN_MASK_ERROR) { diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c index f6466bd..3d2fa91 100644 --- a/gdb/python/py-symbol.c +++ b/gdb/python/py-symbol.c @@ -278,7 +278,11 @@ sympy_value (PyObject *self, PyObject *args) if (symbol_read_needs_frame (symbol) && frame_info == NULL) error (_("symbol requires a frame to compute its value")); - value = read_var_value (symbol, frame_info); + /* TODO: currently, we have no way to recover the block in which SYMBOL + was found, so we have no block to pass to read_var_value. This will + yield an incorrect value when symbol is not local to FRAME_INFO (this + can happen with nested functions). */ + value = read_var_value (symbol, NULL, frame_info); } CATCH (except, RETURN_MASK_ALL) { diff --git a/gdb/stack.c b/gdb/stack.c index ae53ec8..6d87f6f 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -318,7 +318,7 @@ read_frame_local (struct symbol *sym, struct frame_info *frame, TRY { - argp->val = read_var_value (sym, frame); + argp->val = read_var_value (sym, NULL, frame); } CATCH (except, RETURN_MASK_ERROR) { @@ -344,7 +344,7 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, { TRY { - val = read_var_value (sym, frame); + val = read_var_value (sym, NULL, frame); } CATCH (except, RETURN_MASK_ERROR) { @@ -471,7 +471,7 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, TRY { - val = read_var_value (sym, frame); + val = read_var_value (sym, NULL, frame); } CATCH (except, RETURN_MASK_ERROR) { @@ -2424,7 +2424,7 @@ return_command (char *retval_exp, int from_tty) value_fetch_lazy (return_value); if (thisfun != NULL) - function = read_var_value (thisfun, thisframe); + function = read_var_value (thisfun, NULL, thisframe); rv_conv = RETURN_VALUE_REGISTER_CONVENTION; if (TYPE_CODE (return_type) == TYPE_CODE_VOID) diff --git a/gdb/symtab.h b/gdb/symtab.h index e67151f..c6f26e7 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -686,6 +686,25 @@ struct symbol_block_ops uninitialized in such case. */ void (*find_frame_base_location) (struct symbol *framefunc, CORE_ADDR pc, const gdb_byte **start, size_t *length); + + /* Return the frame base address. FRAME is the frame for which we want to + compute the base address while FRAMEFUNC is the symbol for the + corresponding function. Return 0 on failure (FRAMEFUNC may not hold the + information we need). + + This method is designed to work with static links (nested functions + handling). Static links are function properties whose evaluation returns + the frame base address for the enclosing frame. However, there are + multiple definitions for "frame base": the content of the frame base + register, the CFA as defined by DWARF unwinding information, ... + + So this specific method is supposed to compute the frame base address such + as for nested fuctions, the static link computes the same address. For + instance, considering DWARF debugging information, the static link is + computed with DW_AT_static_link and this method must be used to compute + the corresponding DW_AT_frame_base attribute. */ + CORE_ADDR (*get_frame_base) (struct symbol *framefunc, + struct frame_info *frame); }; /* Functions used with LOC_REGISTER and LOC_REGPARM_ADDR. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index bf7f1eb..15ad42c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2015-08-25 Pierre-Marie de Rodat <derodat@adacore.com> + + * gdb.base/nested-subp1.exp: New file. + * gdb.base/nested-subp1.c: New file. + * gdb.base/nested-subp2.exp: New file. + * gdb.base/nested-subp2.c: New file. + * gdb.base/nested-subp3.exp: New file. + * gdb.base/nested-subp3.c: New file. + 2015-08-24 Pedro Alves <palves@redhat.com> * gdb.server/connect-without-multi-process.c: New file. diff --git a/gdb/testsuite/gdb.base/nested-subp1.c b/gdb/testsuite/gdb.base/nested-subp1.c new file mode 100644 index 0000000..967eb2f --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp1.c @@ -0,0 +1,37 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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 of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +int +foo (int i1) +{ + int + nested (int i2) + { + /* Here with i1 and i2, we can test that GDB can fetch both a local and a + non-local variable in the most simple nested function situation: the + parent block instance is accessible as the directly upper frame. */ + return i1 * i2; /* STOP */ + } + + return nested (i1 + 1); +} + +int +main () +{ + return !foo (1); +} diff --git a/gdb/testsuite/gdb.base/nested-subp1.exp b/gdb/testsuite/gdb.base/nested-subp1.exp new file mode 100644 index 0000000..9720f5b --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp1.exp @@ -0,0 +1,55 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 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 of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite. + +# +# Test nested functions related functionality. +# + +standard_testfile + + +set testcase "nested-subp1" + +if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \ + [standard_output_file "${testcase}"] \ + "${testcase}" \ + [list debug "additional_flags=-std=gnu99"]] != "" } { + return -1 +} + + +# Run until the variables we are interested in are visible. + +clean_restart "${testcase}" +if ![runto_main] { + perror "could not run to main" + continue +} + +set bp_location [gdb_get_line_number "STOP" "${testcase}.c"] +gdb_test "break ${testcase}.c:${bp_location}" \ + "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \ + "breakpoint to the STOP marker" +gdb_test "continue" \ + "Breakpoint \[0-9\]+, nested .*" \ + "continue to the STOP marker" + + +# Check we get correct values for both local and non-local variable references. + +gdb_test "print i1" "1" +gdb_test "print i2" "2" diff --git a/gdb/testsuite/gdb.base/nested-subp2.c b/gdb/testsuite/gdb.base/nested-subp2.c new file mode 100644 index 0000000..a6449e34 --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp2.c @@ -0,0 +1,48 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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 of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +void +iter_str (const char *str, void (*callback) (char c)) +{ + for (; *str != '\0'; ++str) + callback (*str); +} + +int +length_str (const char *str) +{ + int count = 0; + + void + increment (char c) + { + /* Here with COUNT, we can test that GDB can read a non-local variable even + though it's not directly in the upper stack frame. */ + count += 1; /* STOP */ + } + + iter_str (str, &increment); + return count; +} + +int +main () +{ + if (length_str ("foo") == 3) + return 0; + return 1; +} diff --git a/gdb/testsuite/gdb.base/nested-subp2.exp b/gdb/testsuite/gdb.base/nested-subp2.exp new file mode 100644 index 0000000..a107d1c --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp2.exp @@ -0,0 +1,64 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 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 of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite. + +# +# Test nested functions related functionality. +# + +standard_testfile + + +set testcase "nested-subp2" + +if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \ + [standard_output_file "${testcase}"] \ + "${testcase}" \ + [list debug "additional_flags=-std=gnu99"]] != "" } { + return -1 +} + + +# Run until the variables we are interested in are visible. + +clean_restart "${testcase}" +if ![runto_main] { + perror "could not run to main" + continue +} + +set bp_location [gdb_get_line_number "STOP" "${testcase}.c"] +gdb_test "break ${testcase}.c:${bp_location}" \ + "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \ + "breakpoint to the STOP marker" +gdb_test "continue" \ + "Breakpoint \[0-9\]+, increment .*" \ + "continue to the STOP marker" + + +# Check we get correct values for both local and non-local variable references. + +gdb_test "print c" "102 'f'" +gdb_test "print count" "0" + + +# Same but a little later: make sure we were looking at the proper places. + +gdb_test "continue" \ + "Breakpoint \[0-9\]+, increment .*" \ + "continue to the STOP marker" +gdb_test "print c" "111 'o'" +gdb_test "print count" "1" diff --git a/gdb/testsuite/gdb.base/nested-subp3.c b/gdb/testsuite/gdb.base/nested-subp3.c new file mode 100644 index 0000000..a51f417 --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp3.c @@ -0,0 +1,66 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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 of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> + +typedef void (*callback_t) (void); + +extern void process (callback_t cb); +extern void parent (int first, callback_t cb); + +void +ignore (int unused) +{ + (void) unused; +} + +void +process (callback_t cb) +{ + parent (0, cb); +} + +void +parent (int first, callback_t cb) +{ + void child (void) + { + /* When reaching this, there are two block instances for PARENT on the + stack: the one that is right in the upper frame is not the one actually + used for non-local references, so GDB has to follow the static link in + order to get the correct instance, and thus in order to read the proper + variables. + + As a simple check, we can verify that under GDB, the following is true: + parent_first == first (which should be one: see the IF block below). */ + const int parent_first = first; + ignore (parent_first); /* STOP */ + ignore (first); + } + + if (first) + process (&child); + else + cb (); +} + +int +main () +{ + parent (1, NULL); + return 0; +} diff --git a/gdb/testsuite/gdb.base/nested-subp3.exp b/gdb/testsuite/gdb.base/nested-subp3.exp new file mode 100644 index 0000000..8f9b522 --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp3.exp @@ -0,0 +1,55 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 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 of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite. + +# +# Test nested functions related functionality. +# + +standard_testfile + + +set testcase "nested-subp3" + +if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \ + [standard_output_file "${testcase}"] \ + "${testcase}" \ + [list debug "additional_flags=-std=gnu99"]] != "" } { + return -1 +} + + +# Run until the variables we are interested in are visible. + +clean_restart "${testcase}" +if ![runto_main] { + perror "could not run to main" + continue +} + +set bp_location [gdb_get_line_number "STOP" "${testcase}.c"] +gdb_test "break ${testcase}.c:${bp_location}" \ + "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \ + "breakpoint to the STOP marker" +gdb_test "continue" \ + "Breakpoint \[0-9\]+, child .*" \ + "continue to the STOP marker" + + +# Check we get correct values for both local and non-local variable references. + +gdb_test "print first" "1" +gdb_test "print parent_first" "1" diff --git a/gdb/valops.c b/gdb/valops.c index acaf027..26fdfa6 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1291,27 +1291,12 @@ value_repeat (struct value *arg1, int count) struct value * value_of_variable (struct symbol *var, const struct block *b) { - struct frame_info *frame; + struct frame_info *frame = NULL; - if (!symbol_read_needs_frame (var)) - frame = NULL; - else if (!b) + if (symbol_read_needs_frame (var)) frame = get_selected_frame (_("No frame selected.")); - else - { - frame = block_innermost_frame (b); - if (!frame) - { - if (BLOCK_FUNCTION (b) && !block_inlined_p (b) - && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))) - error (_("No frame is currently executing in block %s."), - SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))); - else - error (_("No frame is currently executing in specified block")); - } - } - return read_var_value (var, frame); + return read_var_value (var, b, frame); } struct value * @@ -3463,9 +3448,9 @@ value_struct_elt_for_reference (struct type *domain, int offset, return NULL; if (want_address) - return value_addr (read_var_value (s, 0)); + return value_addr (read_var_value (s, 0, 0)); else - return read_var_value (s, 0); + return read_var_value (s, 0, 0); } if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) @@ -3493,7 +3478,7 @@ value_struct_elt_for_reference (struct type *domain, int offset, if (s == NULL) return NULL; - v = read_var_value (s, 0); + v = read_var_value (s, 0, 0); if (!want_address) result = v; else @@ -3729,7 +3714,7 @@ value_full_object (struct value *argp, struct value * value_of_this (const struct language_defn *lang) { - struct symbol *sym; + struct block_symbol sym; const struct block *b; struct frame_info *frame; @@ -3740,12 +3725,12 @@ value_of_this (const struct language_defn *lang) b = get_frame_block (frame, NULL); - sym = lookup_language_this (lang, b).symbol; - if (sym == NULL) + sym = lookup_language_this (lang, b); + if (sym.symbol == NULL) error (_("current stack frame does not contain a variable named `%s'"), lang->la_name_of_this); - return read_var_value (sym, frame); + return read_var_value (sym.symbol, sym.block, frame); } /* Return the value of the local variable, if one exists. Return NULL diff --git a/gdb/value.h b/gdb/value.h index 82deaf2..0a4bc47 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -674,9 +674,11 @@ struct value *value_of_register_lazy (struct frame_info *frame, int regnum); extern int symbol_read_needs_frame (struct symbol *); extern struct value *read_var_value (struct symbol *var, + const struct block *var_block, struct frame_info *frame); extern struct value *default_read_var_value (struct symbol *var, + const struct block *var_block, struct frame_info *frame); extern struct value *allocate_value (struct type *type); diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c index 2edf8bd..7a0f074 100644 --- a/gdb/xcoffread.c +++ b/gdb/xcoffread.c @@ -1389,7 +1389,7 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst) } finish_block (newobj->name, &local_symbols, newobj->old_blocks, - newobj->start_addr, + NULL, newobj->start_addr, (fcn_cs_saved.c_value + fcn_aux_saved.x_sym.x_misc.x_fsize + ANOFFSET (objfile->section_offsets, @@ -1480,7 +1480,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst) if (local_symbols && context_stack_depth > 0) { /* Make a block for the local symbols within. */ - finish_block (newobj->name, &local_symbols, newobj->old_blocks, + finish_block (newobj->name, &local_symbols, + newobj->old_blocks, NULL, newobj->start_addr, (cs->c_value + ANOFFSET (objfile->section_offsets, |