mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 20:43:45 +08:00
63e43d3aed
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.
306 lines
8.4 KiB
C
306 lines
8.4 KiB
C
/* Build symbol tables in GDB's internal format.
|
||
Copyright (C) 1986-2015 Free Software Foundation, Inc.
|
||
|
||
This file is part of GDB.
|
||
|
||
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/>. */
|
||
|
||
#if !defined (BUILDSYM_H)
|
||
#define BUILDSYM_H 1
|
||
|
||
struct objfile;
|
||
struct symbol;
|
||
struct addrmap;
|
||
struct compunit_symtab;
|
||
|
||
/* This module provides definitions used for creating and adding to
|
||
the symbol table. These routines are called from various symbol-
|
||
file-reading routines.
|
||
|
||
They originated in dbxread.c of gdb-4.2, and were split out to
|
||
make xcoffread.c more maintainable by sharing code.
|
||
|
||
Variables declared in this file can be defined by #define-ing the
|
||
name EXTERN to null. It is used to declare variables that are
|
||
normally extern, but which get defined in a single module using
|
||
this technique. */
|
||
|
||
struct block;
|
||
struct pending_block;
|
||
|
||
struct dynamic_prop;
|
||
|
||
#ifndef EXTERN
|
||
#define EXTERN extern
|
||
#endif
|
||
|
||
#define HASHSIZE 127 /* Size of things hashed via
|
||
hashname(). */
|
||
|
||
/* Core address of start of text of current source file. This too
|
||
comes from the N_SO symbol. For Dwarf it typically comes from the
|
||
DW_AT_low_pc attribute of a DW_TAG_compile_unit DIE. */
|
||
|
||
EXTERN CORE_ADDR last_source_start_addr;
|
||
|
||
/* The list of sub-source-files within the current individual
|
||
compilation. Each file gets its own symtab with its own linetable
|
||
and associated info, but they all share one blockvector. */
|
||
|
||
struct subfile
|
||
{
|
||
struct subfile *next;
|
||
/* Space for this is malloc'd. */
|
||
char *name;
|
||
/* Space for this is malloc'd. */
|
||
struct linetable *line_vector;
|
||
int line_vector_length;
|
||
/* The "containing" compunit. */
|
||
struct buildsym_compunit *buildsym_compunit;
|
||
enum language language;
|
||
struct symtab *symtab;
|
||
};
|
||
|
||
EXTERN struct subfile *current_subfile;
|
||
|
||
/* Global variable which, when set, indicates that we are processing a
|
||
.o file compiled with gcc */
|
||
|
||
EXTERN unsigned char processing_gcc_compilation;
|
||
|
||
/* When set, we are processing a .o file compiled by sun acc. This is
|
||
misnamed; it refers to all stabs-in-elf implementations which use
|
||
N_UNDF the way Sun does, including Solaris gcc. Hopefully all
|
||
stabs-in-elf implementations ever invented will choose to be
|
||
compatible. */
|
||
|
||
EXTERN unsigned char processing_acc_compilation;
|
||
|
||
/* Count symbols as they are processed, for error messages. */
|
||
|
||
EXTERN unsigned int symnum;
|
||
|
||
/* Record the symbols defined for each context in a list. We don't
|
||
create a struct block for the context until we know how long to
|
||
make it. */
|
||
|
||
#define PENDINGSIZE 100
|
||
|
||
struct pending
|
||
{
|
||
struct pending *next;
|
||
int nsyms;
|
||
struct symbol *symbol[PENDINGSIZE];
|
||
};
|
||
|
||
/* Here are the three lists that symbols are put on. */
|
||
|
||
/* static at top level, and types */
|
||
|
||
EXTERN struct pending *file_symbols;
|
||
|
||
/* global functions and variables */
|
||
|
||
EXTERN struct pending *global_symbols;
|
||
|
||
/* everything local to lexical context */
|
||
|
||
EXTERN struct pending *local_symbols;
|
||
|
||
/* "using" directives local to lexical context. */
|
||
|
||
EXTERN struct using_direct *local_using_directives;
|
||
|
||
/* global "using" directives. */
|
||
|
||
EXTERN struct using_direct *global_using_directives;
|
||
|
||
/* Stack representing unclosed lexical contexts (that will become
|
||
blocks, eventually). */
|
||
|
||
struct context_stack
|
||
{
|
||
/* Outer locals at the time we entered */
|
||
|
||
struct pending *locals;
|
||
|
||
/* Pending using directives at the time we entered. */
|
||
|
||
struct using_direct *local_using_directives;
|
||
|
||
/* Pointer into blocklist as of entry */
|
||
|
||
struct pending_block *old_blocks;
|
||
|
||
/* Name of function, if any, defining context */
|
||
|
||
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;
|
||
|
||
/* Temp slot for exception handling. */
|
||
|
||
CORE_ADDR end_addr;
|
||
|
||
/* For error-checking matching push/pop */
|
||
|
||
int depth;
|
||
|
||
};
|
||
|
||
EXTERN struct context_stack *context_stack;
|
||
|
||
/* Index of first unused entry in context stack. */
|
||
|
||
EXTERN int context_stack_depth;
|
||
|
||
/* Currently allocated size of context stack. */
|
||
|
||
EXTERN int context_stack_size;
|
||
|
||
/* Non-zero if the context stack is empty. */
|
||
#define outermost_context_p() (context_stack_depth == 0)
|
||
|
||
/* Nonzero if within a function (so symbols should be local, if
|
||
nothing says specifically). */
|
||
|
||
EXTERN int within_function;
|
||
|
||
/* The type of the record_line function. */
|
||
typedef void (record_line_ftype) (struct subfile *subfile, int line,
|
||
CORE_ADDR pc);
|
||
|
||
|
||
|
||
#define next_symbol_text(objfile) (*next_symbol_text_func)(objfile)
|
||
|
||
/* Function to invoke get the next symbol. Return the symbol name. */
|
||
|
||
EXTERN char *(*next_symbol_text_func) (struct objfile *);
|
||
|
||
extern void add_symbol_to_list (struct symbol *symbol,
|
||
struct pending **listhead);
|
||
|
||
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,
|
||
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);
|
||
|
||
extern void really_free_pendings (void *dummy);
|
||
|
||
extern void start_subfile (const char *name);
|
||
|
||
extern void patch_subfile_names (struct subfile *subfile, char *name);
|
||
|
||
extern void push_subfile (void);
|
||
|
||
extern char *pop_subfile (void);
|
||
|
||
extern struct block *end_symtab_get_static_block (CORE_ADDR end_addr,
|
||
int expandable,
|
||
int required);
|
||
|
||
extern struct compunit_symtab *
|
||
end_symtab_from_static_block (struct block *static_block,
|
||
int section, int expandable);
|
||
|
||
extern struct compunit_symtab *end_symtab (CORE_ADDR end_addr, int section);
|
||
|
||
extern struct compunit_symtab *end_expandable_symtab (CORE_ADDR end_addr,
|
||
int section);
|
||
|
||
extern void augment_type_symtab (void);
|
||
|
||
/* Defined in stabsread.c. */
|
||
|
||
extern void scan_file_globals (struct objfile *objfile);
|
||
|
||
extern void buildsym_new_init (void);
|
||
|
||
extern void buildsym_init (void);
|
||
|
||
extern struct context_stack *push_context (int desc, CORE_ADDR valu);
|
||
|
||
extern struct context_stack *pop_context (void);
|
||
|
||
extern record_line_ftype record_line;
|
||
|
||
extern struct compunit_symtab *start_symtab (struct objfile *objfile,
|
||
const char *name,
|
||
const char *comp_dir,
|
||
CORE_ADDR start_addr);
|
||
|
||
extern void restart_symtab (struct compunit_symtab *cust,
|
||
const char *name, CORE_ADDR start_addr);
|
||
|
||
extern int hashname (const char *name);
|
||
|
||
extern void free_pending_blocks (void);
|
||
|
||
/* Record the name of the debug format in the current pending symbol
|
||
table. FORMAT must be a string with a lifetime at least as long as
|
||
the symtab's objfile. */
|
||
|
||
extern void record_debugformat (const char *format);
|
||
|
||
/* Record the name of the debuginfo producer (usually the compiler) in
|
||
the current pending symbol table. PRODUCER must be a string with a
|
||
lifetime at least as long as the symtab's objfile. */
|
||
|
||
extern void record_producer (const char *producer);
|
||
|
||
extern void merge_symbol_lists (struct pending **srclist,
|
||
struct pending **targetlist);
|
||
|
||
/* Set the name of the last source file. NAME is copied by this
|
||
function. */
|
||
|
||
extern void set_last_source_file (const char *name);
|
||
|
||
/* Fetch the name of the last source file. */
|
||
|
||
extern const char *get_last_source_file (void);
|
||
|
||
/* Return the compunit symtab object.
|
||
It is only valid to call this between calls to start_symtab and the
|
||
end_symtab* functions. */
|
||
|
||
extern struct compunit_symtab *buildsym_compunit_symtab (void);
|
||
|
||
/* Return the macro table.
|
||
Initialize it if this is the first use.
|
||
It is only valid to call this between calls to start_symtab and the
|
||
end_symtab* functions. */
|
||
|
||
extern struct macro_table *get_macro_table (void);
|
||
|
||
#undef EXTERN
|
||
|
||
#endif /* defined (BUILDSYM_H) */
|