DWARF: handle non-local references in nested functions
authorPierre-Marie de Rodat <derodat@adacore.com>
Thu, 5 Feb 2015 16:00:06 +0000 (17:00 +0100)
committerPierre-Marie de Rodat <derodat@adacore.com>
Tue, 25 Aug 2015 12:13:28 +0000 (08:13 -0400)
GDB's current behavior when dealing with non-local references in the
context of nested fuctions is approximative:

  - code using valops.c:value_of_variable read the first available stack
    frame that holds the corresponding variable (whereas there can be
    multiple candidates for this);

  - code directly relying on read_var_value will instead read non-local
    variables in frames where they are not even defined.

This change adds the necessary context to symbol reads (to get the block
they belong to) and to blocks (the static link property, if any) so that
GDB can make the proper decisions when dealing with non-local varibale
references.

gdb/ChangeLog:

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

gdb/testsuite/ChangeLog:

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

45 files changed:
gdb/ChangeLog
gdb/ada-lang.c
gdb/block.c
gdb/block.h
gdb/buildsym.c
gdb/buildsym.h
gdb/c-exp.y
gdb/coffread.c
gdb/compile/compile-c-symbols.c
gdb/compile/compile-loc2c.c
gdb/dbxread.c
gdb/dwarf2loc.c
gdb/dwarf2loc.h
gdb/dwarf2read.c
gdb/f-exp.y
gdb/findvar.c
gdb/gdbtypes.c
gdb/go-exp.y
gdb/guile/scm-frame.c
gdb/guile/scm-symbol.c
gdb/infcmd.c
gdb/infrun.c
gdb/jv-exp.y
gdb/language.h
gdb/m2-exp.y
gdb/objfiles.c
gdb/objfiles.h
gdb/p-exp.y
gdb/printcmd.c
gdb/python/py-finishbreakpoint.c
gdb/python/py-frame.c
gdb/python/py-framefilter.c
gdb/python/py-symbol.c
gdb/stack.c
gdb/symtab.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/nested-subp1.c [new file with mode: 0644]
gdb/testsuite/gdb.base/nested-subp1.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/nested-subp2.c [new file with mode: 0644]
gdb/testsuite/gdb.base/nested-subp2.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/nested-subp3.c [new file with mode: 0644]
gdb/testsuite/gdb.base/nested-subp3.exp [new file with mode: 0644]
gdb/valops.c
gdb/value.h
gdb/xcoffread.c

index 5dd90e7a4eaa6ed7dbb7a3a20acbbbddf183af19..8746f60668e2c4231dd9c877fd988f811f3e6c0a 100644 (file)
@@ -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 ...
index 1fa652448088689a45203a5cf06457743561f10b..4d7d22ec057113c4a2c3842adb243a7246396e07 100644 (file)
@@ -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 = {
index f7621aa6102e3684373bfda6da8ca134732762d3..f4b8e4f234e080544292611abe7ab9359b42c7f8 100644 (file)
@@ -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 *
index 3dbcbcbb2d7ed0f8c066c60415bc47c3b633288a..c15114b1e9503206f7321c8eb4cd019beb642488 100644 (file)
@@ -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.  */
index 92c42d5ae68465f5cf7721d12315e19088fa782c..36ec62fd5abea7060788ba05060733f41612cdbe 100644 (file)
@@ -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 ();
index 4c0ec15a3e0a71bb8870cc63bb942eaf60fb0c95..b1eda8cbc5fee0d3e51c5d51804b231943c4be32 100644 (file)
@@ -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);
index a8a4caf1125e8260db3156024bb30496bdaebb2f..351505e4fff9982a9d5f956593e389e8472dd631 100644 (file)
@@ -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);
                            }
index 7722cdbff7b1d6cd6a4651c452ee70f218a09587..c0f42670e72e9df24de996031a1f0e2f27f476a9 100644 (file)
@@ -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.  */
index 21ce655b4e9cfa3c7dbb5d179e3e2e3ffe2db2b8..355b06399ecd512dc87eadc643b3164eedfac0ac 100644 (file)
@@ -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
index b201d136314bb9979befca0c371087ef103c9d4c..8058cbd74fb342edbe4ef651d652d36b669d1d41 100644 (file)
@@ -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."),
index 1d0043259bbcd094829e68f8379d49870ac1b2d8..fdf4e0916e21d5a3af66e11bb78f2f8f86084d69 100644 (file)
@@ -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)
index d8e432ed930469f56e605f3c8f0a05111400da97..efe4357422fc57f128295df942437d7fb076a83f 100644 (file)
@@ -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;
index f3630ac0b273c6853115c8956a9240f4d3f5ec8d..2415656589ca7cba64091fc010022423e32da19e 100644 (file)
@@ -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);
 
index 67b4a6d713009c52af277be539fc377f47e2f08e..77d37ddf83284ff77a51a1db8c0aa93d4ed1d937 100644 (file)
@@ -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
index 3c486ef1f4dd180ef23e7a24acb51bb91d316067..56629dc40c0d25c84836e88c3ca114d499a293e6 100644 (file)
@@ -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;
index 83b4fca500af32c3f43847a8828d50f5c30d6f3f..1c077f71690c5a72ec879c6ffd2eff765e562d22 100644 (file)
@@ -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.  */
index 125af016adc8347d7f722f7449b939ba3719829c..301c6fcfc9be6cde2a54c1ae504da478b1282583 100644 (file)
@@ -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;
index c1ddfa9bfd81a5585de8662fb93c1f8f3ecef263..4e017fe3dce52b6929e491431f7603993825f28d 100644 (file)
@@ -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);
                            }
index 64ac0c0275397fcc5f912cebd065bbc21faf3db5..de77c21845018217006dd07527429d1d2a7b86a0 100644 (file)
@@ -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)
     {
index 01c9eb13f3cbaf2a8325663a3b4e51bc12592536..0970a72bdccb87bdbfce6cd457c5356eb54b5b7c 100644 (file)
@@ -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)
     {
index 82399a4f949f7698054e0bce1a13a016e9ee2d38..393ccb9a079975ba7c38476c89f25a177407fced 100644 (file)
@@ -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
index 25036a466d19e450f16a79b54d759044fe5fde90..1e224b1785b9dd2653c009c0a1a101baf06b2576 100644 (file)
@@ -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))
        {
index 49998487eb8dd58cc01cd1406eba3596ef779a39..60b7d2e4e0aa830290e95ad8e4d16b958c150050 100644 (file)
@@ -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;
index 2265afcbfc20fae5c93b6db3266564356828b3a4..8b579a2198f51b05dbe49a09bd5ffcbadd4a923c 100644 (file)
@@ -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.
index 633c354869153f02a7ba56e910450ef72eb858fa..360fdea1aa24bc9ad2cfddfdcfcccd0c4980571d 100644 (file)
@@ -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);
                            }
index c6f9f001a3c687658b711eb751344e2f22719996..93d8b7dea89b483050586bafdde01890490f40e7 100644 (file)
@@ -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;
+}
+
 \f
 
 /* 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);
 }
index af707154229c5b147041c608588ec51bc3556141..be2a5ef0f3129c4b160f6cce5ddcce8b6b7ca54b 100644 (file)
@@ -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) */
index 191b3d37f276e989e7c4e24a72ff3e2324511aa4..c255a57d0b6a175405a45278bac1a8b09a5c29cb 100644 (file)
@@ -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; }
index f51e25cbbb949e4e787e908629bc408157406257..553cc71bf916a4c3838bf18e86eaae7d641ce35b 100644 (file)
@@ -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);
index e543bb32dd1fd769b8d9e4b4dc909aaeefc8335b..351f68cdf95e864b0ebabeb63f90df18467e8066 100644 (file)
@@ -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 ();
index 7e5dd17b339dcdbe74b5ce4616e56414c23012e0..b4486869f70a1e307d1c41184828335cc00ed628 100644 (file)
@@ -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)
     {
index e3336b14bb40e336c106f1171149f5c428734e44..ac97723976b541766890a6694b39350bef755f0d 100644 (file)
@@ -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)
            {
index f6466bd1c154175ca594d28c5a56357b3c911fd8..3d2fa91567898daa5db27a6bda4b7180b8ad96fa 100644 (file)
@@ -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)
     {
index ae53ec8b3f3c6aa46fd84ece3591d53fdeff0b30..6d87f6fe6c779413a46d1cdc90f5b9a6ff7bd2ad 100644 (file)
@@ -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)
index e67151f739d6a58a675a9d345e772e470175c381..c6f26e772d2d61daf4a6bcf72ac4af1cec0e414d 100644 (file)
@@ -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.  */
index bf7f1eb2ffdae6e4bb49e3cdd8f6ea97e5bde4dc..15ad42c4cb0c2a316510d0c67efa773cc27f91c7 100644 (file)
@@ -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 (file)
index 0000000..967eb2f
--- /dev/null
@@ -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 (file)
index 0000000..9720f5b
--- /dev/null
@@ -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 (file)
index 0000000..a6449e3
--- /dev/null
@@ -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 (file)
index 0000000..a107d1c
--- /dev/null
@@ -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 (file)
index 0000000..a51f417
--- /dev/null
@@ -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 (file)
index 0000000..8f9b522
--- /dev/null
@@ -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"
index acaf027d9d2fa893bfd7a3d2c6bfbe073f8910db..26fdfa666f7f4c11e5815b164b72253d5249d757 100644 (file)
@@ -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
index 82deaf21688749ddc816f276e693b55850d80c36..0a4bc473f4cf6fe66b52b32da3244f559d146d40 100644 (file)
@@ -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);
index 2edf8bd57f883739fb6f6698f72ff3ab186728b3..7a0f0742cdd5c8cadd15cbef10ba23b0fe452f5b 100644 (file)
@@ -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,