📄 dwarfread.c
字号:
/* DWARF debugging format support for GDB. Copyright (C) 1991, 1992 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. Portions based on dbxread.c, mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//*FIXME: Figure out how to get the frame pointer register number in theexecution environment of the target. Remove R_FP kludgeFIXME: Add generation of dependencies list to partial symtab code.FIXME: Resolve minor differences between what information we put in thepartial symbol table and what dbxread puts in. For example, we don't yetput enum constants there. And dbxread seems to invent a lot of typedefswe never see. Use the new printpsym command to see the partial symbol tablecontents.FIXME: Figure out a better way to tell gdb about the name of the functioncontain the user's entry point (I.E. main())FIXME: See other FIXME's and "ifdef 0" scattered throughout the code forother things to work on, if you get bored. :-)*/#include "defs.h"#include "bfd.h"#include "symtab.h"#include "gdbtypes.h"#include "symfile.h"#include "objfiles.h"#include "libbfd.h" /* FIXME Secret Internal BFD stuff (bfd_read) */#include "elf/dwarf.h"#include "buildsym.h"#include "demangle.h"#include <varargs.h>#include <fcntl.h>#include <string.h>#include <sys/types.h>#ifndef NO_SYS_FILE#include <sys/file.h>#endif/* FIXME -- convert this to SEEK_SET a la POSIX, move to config files. */#ifndef L_SET#define L_SET 0#endif#ifdef MAINTENANCE /* Define to 1 to compile in some maintenance stuff */#define SQUAWK(stuff) dwarfwarn stuff#else#define SQUAWK(stuff)#endif#ifndef R_FP /* FIXME */#define R_FP 14 /* Kludge to get frame pointer register number */#endiftypedef unsigned int DIE_REF; /* Reference to a DIE */#ifndef GCC_PRODUCER#define GCC_PRODUCER "GNU C "#endif#ifndef GPLUS_PRODUCER#define GPLUS_PRODUCER "GNU C++ "#endif#ifndef LCC_PRODUCER#define LCC_PRODUCER "NCR C/C++"#endif#ifndef CFRONT_PRODUCER#define CFRONT_PRODUCER "CFRONT " /* A wild a** guess... */#endif#define STREQ(a,b) (strcmp(a,b)==0)#define STREQN(a,b,n) (strncmp(a,b,n)==0)/* Flags to target_to_host() that tell whether or not the data object is expected to be signed. Used, for example, when fetching a signed integer in the target environment which is used as a signed integer in the host environment, and the two environments have different sized ints. In this case, *somebody* has to sign extend the smaller sized int. */#define GET_UNSIGNED 0 /* No sign extension required */#define GET_SIGNED 1 /* Sign extension required *//* Defines for things which are specified in the document "DWARF Debugging Information Format" published by UNIX International, Programming Languages SIG. These defines are based on revision 1.0.0, Jan 20, 1992. */#define SIZEOF_DIE_LENGTH 4#define SIZEOF_DIE_TAG 2#define SIZEOF_ATTRIBUTE 2#define SIZEOF_FORMAT_SPECIFIER 1#define SIZEOF_FMT_FT 2#define SIZEOF_LINETBL_LENGTH 4#define SIZEOF_LINETBL_LINENO 4#define SIZEOF_LINETBL_STMT 2#define SIZEOF_LINETBL_DELTA 4#define SIZEOF_LOC_ATOM_CODE 1#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified *//* Macros that return the sizes of various types of data in the target environment. FIXME: Currently these are just compile time constants (as they are in other parts of gdb as well). They need to be able to get the right size either from the bfd or possibly from the DWARF info. It would be nice if the DWARF producer inserted DIES that describe the fundamental types in the target environment into the DWARF info, similar to the way dbx stabs producers produce information about their fundamental types. */#define TARGET_FT_POINTER_SIZE(objfile) (TARGET_PTR_BIT / TARGET_CHAR_BIT)#define TARGET_FT_LONG_SIZE(objfile) (TARGET_LONG_BIT / TARGET_CHAR_BIT)/* The Amiga SVR4 header file <dwarf.h> defines AT_element_list as a FORM_BLOCK2, and this is the value emitted by the AT&T compiler. However, the Issue 2 DWARF specification from AT&T defines it as a FORM_BLOCK4, as does the latest specification from UI/PLSIG. For backwards compatibility with the AT&T compiler produced executables we define AT_short_element_list for this variant. */#define AT_short_element_list (0x00f0|FORM_BLOCK2)/* External variables referenced. */extern int info_verbose; /* From main.c; nonzero => verbose */extern char *warning_pre_print; /* From utils.c *//* The DWARF debugging information consists of two major pieces, one is a block of DWARF Information Entries (DIE's) and the other is a line number table. The "struct dieinfo" structure contains the information for a single DIE, the one currently being processed. In order to make it easier to randomly access the attribute fields of the current DIE, which are specifically unordered within the DIE, each DIE is scanned and an instance of the "struct dieinfo" structure is initialized. Initialization is done in two levels. The first, done by basicdieinfo(), just initializes those fields that are vital to deciding whether or not to use this DIE, how to skip past it, etc. The second, done by the function completedieinfo(), fills in the rest of the information. Attributes which have block forms are not interpreted at the time the DIE is scanned, instead we just save pointers to the start of their value fields. Some fields have a flag <name>_p that is set when the value of the field is valid (I.E. we found a matching attribute in the DIE). Since we may want to test for the presence of some attributes in the DIE, such as AT_low_pc, without restricting the values of the field, we need someway to note that we found such an attribute. */ typedef char BLOCK;struct dieinfo { char * die; /* Pointer to the raw DIE data */ unsigned long die_length; /* Length of the raw DIE data */ DIE_REF die_ref; /* Offset of this DIE */ unsigned short die_tag; /* Tag for this DIE */ unsigned long at_padding; unsigned long at_sibling; BLOCK * at_location; char * at_name; unsigned short at_fund_type; BLOCK * at_mod_fund_type; unsigned long at_user_def_type; BLOCK * at_mod_u_d_type; unsigned short at_ordering; BLOCK * at_subscr_data; unsigned long at_byte_size; unsigned short at_bit_offset; unsigned long at_bit_size; BLOCK * at_element_list; unsigned long at_stmt_list; unsigned long at_low_pc; unsigned long at_high_pc; unsigned long at_language; unsigned long at_member; unsigned long at_discr; BLOCK * at_discr_value; BLOCK * at_string_length; char * at_comp_dir; char * at_producer; unsigned long at_start_scope; unsigned long at_stride_size; unsigned long at_src_info; char * at_prototyped; unsigned int has_at_low_pc:1; unsigned int has_at_stmt_list:1; unsigned int has_at_byte_size:1; unsigned int short_element_list:1;};static int diecount; /* Approximate count of dies for compilation unit */static struct dieinfo *curdie; /* For warnings and such */static char *dbbase; /* Base pointer to dwarf info */static int dbsize; /* Size of dwarf info in bytes */static int dbroff; /* Relative offset from start of .debug section */static char *lnbase; /* Base pointer to line section */static int isreg; /* Kludge to identify register variables */static int offreg; /* Kludge to identify basereg references *//* This value is added to each symbol value. FIXME: Generalize to the section_offsets structure used by dbxread. */static CORE_ADDR baseaddr; /* Add to each symbol value *//* The section offsets used in the current psymtab or symtab. FIXME, only used to pass one value (baseaddr) at the moment. */static struct section_offsets *base_section_offsets;/* Each partial symbol table entry contains a pointer to private data for the read_symtab() function to use when expanding a partial symbol table entry to a full symbol table entry. For DWARF debugging info, this data is contained in the following structure and macros are provided for easy access to the members given a pointer to a partial symbol table entry. dbfoff Always the absolute file offset to the start of the ".debug" section for the file containing the DIE's being accessed. dbroff Relative offset from the start of the ".debug" access to the first DIE to be accessed. When building the partial symbol table, this value will be zero since we are accessing the entire ".debug" section. When expanding a partial symbol table entry, this value will be the offset to the first DIE for the compilation unit containing the symbol that triggers the expansion. dblength The size of the chunk of DIE's being examined, in bytes. lnfoff The absolute file offset to the line table fragment. Ignored when building partial symbol tables, but used when expanding them, and contains the absolute file offset to the fragment of the ".line" section containing the line numbers for the current compilation unit. */struct dwfinfo { file_ptr dbfoff; /* Absolute file offset to start of .debug section */ int dbroff; /* Relative offset from start of .debug section */ int dblength; /* Size of the chunk of DIE's being examined */ file_ptr lnfoff; /* Absolute file offset to line table fragment */};#define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)#define DBROFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbroff)#define DBLENGTH(p) (((struct dwfinfo *)((p)->read_symtab_private))->dblength)#define LNFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->lnfoff)/* The generic symbol table building routines have separate lists for file scope symbols and all all other scopes (local scopes). So we need to select the right one to pass to add_symbol_to_list(). We do it by keeping a pointer to the correct list in list_in_scope. FIXME: The original dwarf code just treated the file scope as the first local scope, and all other local scopes as nested local scopes, and worked fine. Check to see if we really need to distinguish these in buildsym.c */struct pending **list_in_scope = &file_symbols;/* DIES which have user defined types or modified user defined types refer to other DIES for the type information. Thus we need to associate the offset of a DIE for a user defined type with a pointer to the type information. Originally this was done using a simple but expensive algorithm, with an array of unsorted structures, each containing an offset/type-pointer pair. This array was scanned linearly each time a lookup was done. The result was that gdb was spending over half it's startup time munging through this array of pointers looking for a structure that had the right offset member. The second attempt used the same array of structures, but the array was sorted using qsort each time a new offset/type was recorded, and a binary search was used to find the type pointer for a given DIE offset. This was even slower, due to the overhead of sorting the array each time a new offset/type pair was entered. The third attempt uses a fixed size array of type pointers, indexed by a value derived from the DIE offset. Since the minimum DIE size is 4 bytes, we can divide any DIE offset by 4 to obtain a unique index into this fixed size array. Since each element is a 4 byte pointer, it takes exactly as much memory to hold this array as to hold the DWARF info for a given compilation unit. But it gets freed as soon as we are done with it. */static struct type **utypes; /* Pointer to array of user type pointers */static int numutypes; /* Max number of user type pointers *//* Record the language for the compilation unit which is currently being processed. We know it once we have seen the TAG_compile_unit DIE, and we need it while processing the DIE's for that compilation unit. It is eventually saved in the symtab structure, but we don't finalize the symtab struct until we have processed all the DIE's for the compilation unit. */static enum language cu_language;/* Forward declarations of static functions so we don't have to worry about ordering within this file. */static intattribute_size PARAMS ((unsigned int));static unsigned longtarget_to_host PARAMS ((char *, int, int, struct objfile *));static voidadd_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));static voidhandle_producer PARAMS ((char *));static voidread_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));static voidread_func_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));static voidread_lexical_block_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));static voiddwarfwarn ();static voidscan_partial_symbols PARAMS ((char *, char *, struct objfile *));static voidscan_compilation_units PARAMS ((char *, char *, file_ptr, file_ptr, struct objfile *));static voidadd_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));static voidinit_psymbol_list PARAMS ((struct objfile *, int));static voidbasicdieinfo PARAMS ((struct dieinfo *, char *, struct objfile *));static voidcompletedieinfo PARAMS ((struct dieinfo *, struct objfile *));static voiddwarf_psymtab_to_symtab PARAMS ((struct partial_symtab *));static voidpsymtab_to_symtab_1 PARAMS ((struct partial_symtab *));static struct symtab *read_ofile_symtab PARAMS ((struct partial_symtab *));static voidprocess_dies PARAMS ((char *, char *, struct objfile *));static voidread_structure_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));static struct type *decode_array_element_type PARAMS ((char *));static struct type *decode_subscr_data PARAMS ((char *, char *));static voiddwarf_read_array_type PARAMS ((struct dieinfo *));static voidread_tag_pointer_type PARAMS ((struct dieinfo *dip));static voidread_subroutine_type PARAMS ((struct dieinfo *, char *, char *));static voidread_enumeration PARAMS ((struct dieinfo *, char *, char *, struct objfile *));static struct type *struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *));static struct type *enum_type PARAMS ((struct dieinfo *, struct objfile *));static voiddecode_line_numbers PARAMS ((char *));static struct type *decode_die_type PARAMS ((struct dieinfo *));static struct type *decode_mod_fund_type PARAMS ((char *));static struct type *decode_mod_u_d_type PARAMS ((char *));static struct type *decode_modified_type PARAMS ((char *, unsigned int, int));static struct type *decode_fund_type PARAMS ((unsigned int));static char *create_name PARAMS ((char *, struct obstack *));static struct type *lookup_utype PARAMS ((DIE_REF));static struct type *alloc_utype PARAMS ((DIE_REF, struct type *));static struct symbol *new_symbol PARAMS ((struct dieinfo *, struct objfile *));static voidsynthesize_typedef PARAMS ((struct dieinfo *, struct objfile *, struct type *));static intlocval PARAMS ((char *));static voidrecord_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type, struct objfile *));static voidset_cu_language PARAMS ((struct dieinfo *));/*LOCAL FUNCTION set_cu_language -- set local copy of language for compilation unitSYNOPSIS void set_cu_language (struct dieinfo *dip)DESCRIPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -