From: Peter Schauer Date: Sun, 1 Dec 1996 08:33:39 +0000 (+0000) Subject: Add support for Irix 6.2 native O32 and N32 ABI. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0db3fe94c3a498329fc165e3c0f61c25d8572a7c;p=binutils-gdb.git Add support for Irix 6.2 native O32 and N32 ABI. * config.in, configure.in, configure: Check for . * configure.tgt: Handle mips*-sgi-irix6* like irix5 for now. * cp-valprint.c (cp_print_value_fields): Use SYMBOL_VALUE_ADDRESS instead of SYMBOL_BLOCK_VALUE to get the address of a static member. * dwarf2read.c: Turn warnings and recoverable errors into complaints, add new complaints where appropriate. gcc -Wall cleanup. (struct line_head): Change line_base from char to int to avoid problems with compilers whose plain char is represented by an unsigned char. (struct partial_die_info): Add is_declaration field. (dwarf2_tmp_obstack): New obstack for allocating temporary storage used during symbol reading. (cu_header_offset): New variable for resolving relative reference dies. (optimized_out, basereg, islocal, frame_base_reg, frame_base_offset): New interface variables for decode_locdesc. (struct dwarf2_pinfo): New structure for communication between psymtab and symtab reading, passed via pst->read_symtab_private. (dwarf2_has_info, dwarf2_build_psymtabs): Accept objects files without line number sections. (dwarf2_build_psymtabs_hard): Initialize temporary obstack for symbol reading. Allocate and initialize pst->read_symtab_private. Relocate pst->textlow and pst->texthigh with baseaddr. (scan_partial_symbols): Do not add DW_AT_declaration symbols to the partial symbol table. Add file scope enumerator symbols to the partial symbol table. Fix typo in highpc computation. If we didn't find a lowpc, set it to highpc to avoid complaints from `maint check. (add_partial_symbol): Relocate symbol values with baseaddr. Add static DW_TAG_subprogram and DW_TAG_variable symbols to the minimal symbol table. Obtain symbol values for DW_TAG_variable symbols from the location descriptor, skip symbols with missing location desciptors. Skip symbols for aggregate types without children. Handle enumerator symbols. (dwarf2_psymtab_to_symtab): Issue symbol reading message if verbose. (psymtab_to_symtab_1): Set local variables from pst->read_symtab_private, set cu_header_offset and baseaddr. Initialize temporary obstack for symbol reading, initialize buildsym and add a cleanup to really_free_pendings. Relocate highpc with baseaddr when calling end_symtab. If the compilation is from a C file generated by language preprocessors, do not set the symtab language if it was already deduced by start_subfile. Removed verbose sorting symbol table message. (process_die): Handle DW_TAG_ptr_to_member_type and DW_TAG_reference_type. Use read_subroutine_type to get the function type for DW_TAG_subprogram before calling read_func_scope. (read_file_scope): Initialize file name to , start_subfile expects a non-NULL name. If we didn't find a lowpc, set it to highpc to avoid complaints from finish_symbol. Relocate lowpc and highpc with baseaddr. Get rid of Irix6.2 native cc compile machine prefix in comp_dir. Zero out ftypes for each new compilation unit (may be different language or different objfile). Accept compilation units without line number information, pass comp_dir to decode_lines. (read_func_scope): Initialize function name to to avoid core dumps when DW_AT_name is missing. Relocate lowpc and highpc with baseaddr. Handle DW_AT_frame_base, keep result for DW_OP_fbreg operations. Pass function type to new_symbol. (read_lexical_block_scope): Relocate lowpc and highpc with baseaddr. (read_structure_scope): Set TYPE_TAG_NAME, not TYPE_NAME. Handle DW_TAG_class_type. Copy fields to type_obstack, release temporary storage for fields. Don't add symbol if die is a stub die and has no children. Handle C++ static member fields. (read_enumeration): Set TYPE_TAG_NAME, not TYPE_NAME. Copy fields to type_obstack, release temporary storage for fields. Let new_symbol handle the symbol creation for enumerators instead of handcrafting a symbol. Determine signedness of enum type from enumerators. (dwarf_read_array_type): Handle variable length arrays. Use lookup_pointer_type instead of handcrafting a type. Create array type only if a DW_TAG_subrange_type was found. (read_tag_pointer_type, read_tag_reference_type): Use lookup_pointer_type and lookup_reference_type instead of handcrafting a type. (read_tag_ptr_to_member_type): New function to handle DW_TAG_ptr_to_member_type. (read_subroutine_type): Handle parameter dies. Use lookup_function_type instead of handcrafting a type. (read_typedef): Allocate a TYPE_CODE_TYPEDEF type for the typedef. (read_base_type): If the type has a name, use init_type to create a new type instead of second guessing a fundamental type. (read_comp_unit): Reset die reference table before building a new one. (dwarf2_read_section): Read section contents into psymbol_obstack. (dwarf2_read_abbrevs): Handle unterminated abbreviations for a compile unit gracefully. (read_partial_die): Zero partial die before reading its info. Handle DW_AT_declaration. Fix typo in handling of DW_FORM_block4. (read_full_die): Fix typo in handling of DW_FORM_block4. (read_1_signed_byte, read_2_signed_bytes, read_4_signed_bytes): New routines to get signed values from a buffer. (read_n_bytes, read_string): Allocate storage from the temporary obstack. If the host char size permits it, return pointer to buffer instead of allocating storage. (set_cu_language): Handle DW_LANG_Mips_Assembler. (dwarf_attr): Return NULL if reference die for DW_AT_specification or DW_AT_abstract_origin die is not found. (record_minimal_symbol): Removed, replaced with a direct call to prim_record_minimal_symbol, it now handles saving the string itself. (convert_locdesc): Removed, partial symtab reading now uses decode_locdesc. (dwarf_attr): Use dwarf2_get_ref_die_offset to get the absolute offset for the die reference. (dwarf_decode_lines): Complain if the line section info is missing. Use read_1_signed_byte to extract lh.line_base to avoid problems with compilers whose plain char is represented by an unsigned char. Add cleanups for allocated temporary storage. Start a subfile for the first file in the state machine. Fix off by one problem with dirs.dirs access. Use comp_dir when directory index is 0. Support multiple sequences (from Jason Merrill ). (dwarf2_start_subfile): Try to keep line numbers from identical absolute and relative file names in a common subfile. (new_symbol): Allocate symbol and symbol name on the symbol_obstack. Set SYMBOL_LINE from DW_AT_decl_line if present. Set SYMBOL_TYPE from passed type if not NULL. Change DW_TAG_variable symbol types with missing type entries to a sensible type. Handle optimized_out, offreg and islocal storage classes. Add external symbols with type information whose address isn't known as LOC_UNRESOLVED symbols. Synthesize typedefs for C++ classes, structs, unions and enumerations. Handle DW_TAG_enumerator symbols, complain for unrecognized symbol tags. (die_type): A missing DW_AT_type represents a void type. Use dwarf2_get_ref_die_offset to get the absolute offset for the die reference. (die_containing_type): New function to build type from DW_AT_containing_type attribut. (read_type_die): Handle DW_TAG_ptr_to_member_type. Treat DW_TAG_subprogram like DW_TAG_subroutine_type. (dwarf_base_type): Fix typo with creation of FT_UNSIGNED_SHORT fundamental type. (create_name): Removed, symbol name allocation is now done in new_symbol. (dump_die): Use print_address_numeric to print a CORE_ADDR. (dwarf2_empty_die_ref_table): New function to clear the die reference table. (dwarf2_get_ref_die_offset): New function to get the absolute die offset from a die reference attribute. (decode_locdesc): Complete rewrite using a stack, code mostly borrowed from dwarfread.c:locval. (dwarf_alloc_type): Removed, replaced by direct calls to alloc_type. (dwarf_alloc_block): Allocate block on temporary obstack. * elfread.c (elf_symtab_read): When handling Irix dynamic symbols, skip section name symbols and relocate all others. (elf_symfile_read): Build dwarf2 psymtab even if offset is non-zero. * irix5-nat.c (fetch_core_registers): Handle core_reg_sect from N32 executables. Call registers_fetched after extracting the registers. (obj_list_variant, struct link_map, LM_OFFSET, LM_ADDR): New definitions to enable support of O32 and N32 format objlists. (struct so_list): New members offset, so_name and lmstart to eliminate dependencies from the objlist format used. (solib_map_sections, symbol_add_stub, solib_add, info_sharedlibrary_command, solib_address, clear_solib): Use so_name and LM_OFFSET. (first_link_map_member): Rewrite to enable support of O32 and N32 format objlists. (next_link_map_member, xfer_link_map_member): New functions to support O32 and N32 format objlists. (find_solib): Use first_link_map_member, next_link_map_member and xfer_link_map_member. (solib_create_inferior_hook): Use TARGET_SIGNAL_* instead of host signal numbers. * mdebugread.c (parse_partial_symbols, handle_psymbol_enumerators): Pass CORE_ADDR variant to add_psymbol_to_list. * mips-tdep.c (heuristic_proc_desc): Stop examining the prologue if we encounter a positive stack adjustment. Handle `move $30,$sp'. Handle `sd reg,offset($sp)' for 32 bit ABIs. * symmisc.c (dump_msymbols, print_partial_symbols): Use print_address_numeric to print a SYMBOL_VALUE_ADDRESS. (dump_symtab): Print compilation directory if it is not NULL. * valops.c (search_struct_field, value_struct_elt_for_reference): Use SYMBOL_VALUE_ADDRESS instead of SYMBOL_BLOCK_VALUE to get the address of a static member. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1df7d8ece16..b29fed2d872 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,204 @@ +Sun Dec 1 00:18:59 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + Add support for Irix 6.2 native O32 and N32 ABI. + + * config.in, configure.in, configure: Check for . + * configure.tgt: Handle mips*-sgi-irix6* like irix5 for now. + + * cp-valprint.c (cp_print_value_fields): Use SYMBOL_VALUE_ADDRESS + instead of SYMBOL_BLOCK_VALUE to get the address of a static member. + + * dwarf2read.c: Turn warnings and recoverable errors into complaints, + add new complaints where appropriate. + gcc -Wall cleanup. + (struct line_head): Change line_base from char to int to avoid + problems with compilers whose plain char is represented by an + unsigned char. + (struct partial_die_info): Add is_declaration field. + (dwarf2_tmp_obstack): New obstack for allocating temporary storage + used during symbol reading. + (cu_header_offset): New variable for resolving relative reference + dies. + (optimized_out, basereg, islocal, frame_base_reg, frame_base_offset): + New interface variables for decode_locdesc. + (struct dwarf2_pinfo): New structure for communication between + psymtab and symtab reading, passed via pst->read_symtab_private. + (dwarf2_has_info, dwarf2_build_psymtabs): Accept objects files + without line number sections. + (dwarf2_build_psymtabs_hard): Initialize temporary obstack + for symbol reading. + Allocate and initialize pst->read_symtab_private. + Relocate pst->textlow and pst->texthigh with baseaddr. + (scan_partial_symbols): Do not add DW_AT_declaration symbols + to the partial symbol table. + Add file scope enumerator symbols to the partial symbol table. + Fix typo in highpc computation. + If we didn't find a lowpc, set it to highpc to avoid complaints + from `maint check. + (add_partial_symbol): Relocate symbol values with baseaddr. + Add static DW_TAG_subprogram and DW_TAG_variable symbols to the + minimal symbol table. + Obtain symbol values for DW_TAG_variable symbols from the location + descriptor, skip symbols with missing location desciptors. + Skip symbols for aggregate types without children. + Handle enumerator symbols. + (dwarf2_psymtab_to_symtab): Issue symbol reading message if verbose. + (psymtab_to_symtab_1): Set local variables from + pst->read_symtab_private, set cu_header_offset and baseaddr. + Initialize temporary obstack for symbol reading, initialize + buildsym and add a cleanup to really_free_pendings. + Relocate highpc with baseaddr when calling end_symtab. + If the compilation is from a C file generated by language + preprocessors, do not set the symtab language if it was already + deduced by start_subfile. + Removed verbose sorting symbol table message. + (process_die): Handle DW_TAG_ptr_to_member_type and + DW_TAG_reference_type. + Use read_subroutine_type to get the function type for + DW_TAG_subprogram before calling read_func_scope. + (read_file_scope): Initialize file name to , start_subfile + expects a non-NULL name. + If we didn't find a lowpc, set it to highpc to avoid complaints + from finish_symbol. + Relocate lowpc and highpc with baseaddr. + Get rid of Irix6.2 native cc compile machine prefix in comp_dir. + Zero out ftypes for each new compilation unit (may be different + language or different objfile). + Accept compilation units without line number information, pass + comp_dir to decode_lines. + (read_func_scope): Initialize function name to to avoid + core dumps when DW_AT_name is missing. + Relocate lowpc and highpc with baseaddr. + Handle DW_AT_frame_base, keep result for DW_OP_fbreg operations. + Pass function type to new_symbol. + (read_lexical_block_scope): Relocate lowpc and highpc with baseaddr. + (read_structure_scope): Set TYPE_TAG_NAME, not TYPE_NAME. + Handle DW_TAG_class_type. + Copy fields to type_obstack, release temporary storage for fields. + Don't add symbol if die is a stub die and has no children. + Handle C++ static member fields. + (read_enumeration): Set TYPE_TAG_NAME, not TYPE_NAME. + Copy fields to type_obstack, release temporary storage for fields. + Let new_symbol handle the symbol creation for enumerators + instead of handcrafting a symbol. + Determine signedness of enum type from enumerators. + (dwarf_read_array_type): Handle variable length arrays. + Use lookup_pointer_type instead of handcrafting a type. + Create array type only if a DW_TAG_subrange_type was found. + (read_tag_pointer_type, read_tag_reference_type): + Use lookup_pointer_type and lookup_reference_type instead + of handcrafting a type. + (read_tag_ptr_to_member_type): New function to handle + DW_TAG_ptr_to_member_type. + (read_subroutine_type): Handle parameter dies. + Use lookup_function_type instead of handcrafting a type. + (read_typedef): Allocate a TYPE_CODE_TYPEDEF type for the typedef. + (read_base_type): If the type has a name, use init_type to create + a new type instead of second guessing a fundamental type. + (read_comp_unit): Reset die reference table before building + a new one. + (dwarf2_read_section): Read section contents into psymbol_obstack. + (dwarf2_read_abbrevs): Handle unterminated abbreviations + for a compile unit gracefully. + (read_partial_die): Zero partial die before reading its info. + Handle DW_AT_declaration. + Fix typo in handling of DW_FORM_block4. + (read_full_die): Fix typo in handling of DW_FORM_block4. + (read_1_signed_byte, read_2_signed_bytes, read_4_signed_bytes): + New routines to get signed values from a buffer. + (read_n_bytes, read_string): Allocate storage from the temporary + obstack. If the host char size permits it, return pointer + to buffer instead of allocating storage. + (set_cu_language): Handle DW_LANG_Mips_Assembler. + (dwarf_attr): Return NULL if reference die for DW_AT_specification + or DW_AT_abstract_origin die is not found. + (record_minimal_symbol): Removed, replaced with a direct call to + prim_record_minimal_symbol, it now handles saving the string itself. + (convert_locdesc): Removed, partial symtab reading now uses + decode_locdesc. + (dwarf_attr): Use dwarf2_get_ref_die_offset to get the absolute + offset for the die reference. + (dwarf_decode_lines): Complain if the line section info is missing. + Use read_1_signed_byte to extract lh.line_base to avoid + problems with compilers whose plain char is represented by an + unsigned char. + Add cleanups for allocated temporary storage. + Start a subfile for the first file in the state machine. + Fix off by one problem with dirs.dirs access. + Use comp_dir when directory index is 0. + Support multiple sequences (from Jason Merrill ). + (dwarf2_start_subfile): Try to keep line numbers from identical + absolute and relative file names in a common subfile. + (new_symbol): Allocate symbol and symbol name on the symbol_obstack. + Set SYMBOL_LINE from DW_AT_decl_line if present. + Set SYMBOL_TYPE from passed type if not NULL. + Change DW_TAG_variable symbol types with missing type entries + to a sensible type. + Handle optimized_out, offreg and islocal storage classes. + Add external symbols with type information whose address isn't + known as LOC_UNRESOLVED symbols. + Synthesize typedefs for C++ classes, structs, unions and enumerations. + Handle DW_TAG_enumerator symbols, complain for unrecognized + symbol tags. + (die_type): A missing DW_AT_type represents a void type. + Use dwarf2_get_ref_die_offset to get the absolute offset for + the die reference. + (die_containing_type): New function to build type from + DW_AT_containing_type attribut. + (read_type_die): Handle DW_TAG_ptr_to_member_type. + Treat DW_TAG_subprogram like DW_TAG_subroutine_type. + (dwarf_base_type): Fix typo with creation of FT_UNSIGNED_SHORT + fundamental type. + (create_name): Removed, symbol name allocation is now done + in new_symbol. + (dump_die): Use print_address_numeric to print a CORE_ADDR. + (dwarf2_empty_die_ref_table): New function to clear the die + reference table. + (dwarf2_get_ref_die_offset): New function to get the absolute + die offset from a die reference attribute. + (decode_locdesc): Complete rewrite using a stack, code mostly + borrowed from dwarfread.c:locval. + (dwarf_alloc_type): Removed, replaced by direct calls to alloc_type. + (dwarf_alloc_block): Allocate block on temporary obstack. + + * elfread.c (elf_symtab_read): When handling Irix dynamic symbols, + skip section name symbols and relocate all others. + (elf_symfile_read): Build dwarf2 psymtab even if offset is non-zero. + + * irix5-nat.c (fetch_core_registers): Handle core_reg_sect + from N32 executables. Call registers_fetched after extracting + the registers. + (obj_list_variant, struct link_map, LM_OFFSET, LM_ADDR): New + definitions to enable support of O32 and N32 format objlists. + (struct so_list): New members offset, so_name and lmstart to + eliminate dependencies from the objlist format used. + (solib_map_sections, symbol_add_stub, solib_add, + info_sharedlibrary_command, solib_address, clear_solib): Use + so_name and LM_OFFSET. + (first_link_map_member): Rewrite to enable support of O32 and N32 + format objlists. + (next_link_map_member, xfer_link_map_member): New functions to + support O32 and N32 format objlists. + (find_solib): Use first_link_map_member, next_link_map_member and + xfer_link_map_member. + (solib_create_inferior_hook): Use TARGET_SIGNAL_* instead of + host signal numbers. + + * mdebugread.c (parse_partial_symbols, handle_psymbol_enumerators): + Pass CORE_ADDR variant to add_psymbol_to_list. + + * mips-tdep.c (heuristic_proc_desc): Stop examining the prologue + if we encounter a positive stack adjustment. Handle `move $30,$sp'. + Handle `sd reg,offset($sp)' for 32 bit ABIs. + + * symmisc.c (dump_msymbols, print_partial_symbols): Use + print_address_numeric to print a SYMBOL_VALUE_ADDRESS. + (dump_symtab): Print compilation directory if it is not NULL. + + * valops.c (search_struct_field, value_struct_elt_for_reference): + Use SYMBOL_VALUE_ADDRESS instead of SYMBOL_BLOCK_VALUE to get the + address of a static member. + Thu Nov 28 00:46:24 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) * vax-tdep.c (vax_print_insn): Made static, modified to take diff --git a/gdb/config.in b/gdb/config.in index a719fb0ec82..cd240799203 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -110,6 +110,9 @@ /* Define if you have the header file. */ #undef HAVE_UNISTD_H +/* Define if you have the header file. */ +#undef HAVE_OBJLIST_H + /* Define if you have the select function. */ #undef HAVE_SELECT diff --git a/gdb/configure b/gdb/configure index 61af5e200df..88337788fe9 100755 --- a/gdb/configure +++ b/gdb/configure @@ -1346,7 +1346,7 @@ EOF fi -for ac_hdr in limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h +for ac_hdr in limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h objlist.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 diff --git a/gdb/configure.in b/gdb/configure.in index cacdff6e180..7c65340747d 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -40,7 +40,7 @@ AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..) AC_ARG_PROGRAM AC_HEADER_STDC -AC_CHECK_HEADERS(limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h) +AC_CHECK_HEADERS(limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h objlist.h) AC_HEADER_STAT AC_C_CONST diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 847a6ab9700..84f2f9b1e10 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -175,6 +175,7 @@ mips*el-*-elf*) gdb_target=embedl ;; mips*-*-elf*) gdb_target=embed ;; mips*-little-*) gdb_target=littlemips ;; mips*-sgi-irix5*) gdb_target=irix5 ;; +mips*-sgi-irix6*) gdb_target=irix5 ;; mips*-sgi-*) gdb_target=irix3 ;; mips*-sony-*) gdb_target=bigmips ;; mips*-*-mach3*) gdb_target=mach3 ;; diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index a4027eacf42..dc689c9c640 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -342,7 +342,7 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, else { v = value_at (TYPE_FIELD_TYPE (type, i), - (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); + SYMBOL_VALUE_ADDRESS (sym)); cp_print_static_field (TYPE_FIELD_TYPE (type, i), v, stream, format, recurse + 1, pretty); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 1dfcfe3656d..5338a3f7dcf 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "demangle.h" #include "expression.h" #include "language.h" +#include "complaints.h" #include #include "gdb_string.h" @@ -168,7 +169,7 @@ struct line_head unsigned int prologue_length; unsigned char minimum_instruction_length; unsigned char default_is_stmt; - char line_base; + int line_base; unsigned char line_range; unsigned char opcode_base; unsigned char *standard_opcode_lengths; @@ -181,6 +182,7 @@ struct partial_die_info unsigned short tag; unsigned char has_children; unsigned char is_external; + unsigned char is_declaration; unsigned int offset; unsigned int abbrev; char *name; @@ -254,12 +256,6 @@ struct dwarf_block #define ATTR_ALLOC_CHUNK 4 #endif -/* FIXME: do away with this */ - -#ifndef DWARF2_MAX_STRING_SIZE -#define DWARF2_MAX_STRING_SIZE 1024 -#endif - static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; /* A hash table of die offsets for following references. */ @@ -269,6 +265,13 @@ static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; static struct die_info *die_ref_table[REF_HASH_SIZE]; +/* Obstack for allocating temporary storage used during symbol reading. */ +static struct obstack dwarf2_tmp_obstack; + +/* Offset to the first byte of the current compilation unit header, + for resolving relative reference dies. */ +static unsigned int cu_header_offset; + /* Allocate fields for structs, unions and enums in this size. */ #ifndef DW_FIELD_ALLOC_CHUNK #define DW_FIELD_ALLOC_CHUNK 4 @@ -283,9 +286,8 @@ static char *dwarf_info_buffer; static char *dwarf_abbrev_buffer; static char *dwarf_line_buffer; -/* A zeroed version of several structures for initialization purposes. */ +/* A zeroed version of a partial die for initialization purposes. */ static struct partial_die_info zeroed_partial_die; -static struct die_info zeroed_die; /* The generic symbol table building routines have separate lists for file scope symbols and all all other scopes (local scopes). So @@ -297,16 +299,67 @@ static struct die_info zeroed_die; fine. Check to see if we really need to distinguish these in buildsym.c. */ static struct pending **list_in_scope = &file_symbols; -static int isreg; /* Kludge to identify register - variables */ -static int offreg; /* Kludge to identify basereg - references */ + +/* FIXME: The following variables pass additional information from + decode_locdesc to the caller. */ +static int optimized_out; /* Kludge to identify optimized out variables */ +static int isreg; /* Kludge to identify register variables */ +static int offreg; /* Kludge to identify basereg references */ +static int basereg; /* Which base register is it relative to? */ +static int islocal; /* Kludge to identify local variables */ + +/* DW_AT_frame_base values for the current function. + frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it + contains the register number for the frame register. + frame_base_offset is the offset from the frame register to the + virtual stack frame. */ +static int frame_base_reg; +static CORE_ADDR frame_base_offset; /* This value is added to each symbol value. FIXME: Generalize to the section_offsets structure used by dbxread (once this is done, pass the appropriate section number to end_symtab). */ static CORE_ADDR baseaddr; /* Add to each symbol value */ +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. + The complete dwarf information for an objfile is kept in the + psymbol_obstack, so that absolute die references can be handled. + Most of the information in this structure is related to an entire + object file and could be passed via the sym_private field of the objfile. + It is however conceivable that dwarf2 might not be the only type + of symbols read from an object file. */ + +struct dwarf2_pinfo +{ + /* Pointer to start of dwarf info buffer for the objfile. */ + + char *dwarf_info_buffer; + + /* Offset in dwarf_info_buffer for this compilation unit. */ + + unsigned long dwarf_info_offset; + + /* Pointer to start of dwarf abbreviation buffer for the objfile. */ + + char *dwarf_abbrev_buffer; + + /* Size of dwarf abbreviation section for the objfile. */ + + unsigned int dwarf_abbrev_size; + + /* Pointer to start of dwarf line buffer for the objfile. */ + + char *dwarf_line_buffer; +}; + +#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) +#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer) +#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset) +#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer) +#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size) +#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer) + /* Maintain an array of referenced fundamental types for the current compilation unit being read. For DWARF version 1, we have to construct the fundamental types on the fly, since no information about the @@ -321,16 +374,56 @@ static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */ /* FIXME - set from bfd function */ static int bits_per_byte = 8; -/* Keep track of whether we have given a warning about not - handling DW_TAG_const_type dies. */ -static int tag_const_warning_given = 0; +/* Various complaints about symbol reading that don't abort the process */ -/* Keep track of whether we have given a warning about not - handling DW_TAG_volatile_type dies. */ -static int tag_volatile_warning_given = 0; - -/* Keep track of constant array bound warning. */ -static int array_bound_warning_given = 0; +static struct complaint dwarf2_const_ignored = +{ + "type qualifier 'const' ignored", 0, 0 +}; +static struct complaint dwarf2_volatile_ignored = +{ + "type qualifier 'volatile' ignored", 0, 0 +}; +static struct complaint dwarf2_non_const_array_bound_ignored = +{ + "non-constant array bounds form %s ignored", 0, 0 +}; +static struct complaint dwarf2_missing_line_number_section = +{ + "missing .debug_line section", 0, 0 +}; +static struct complaint dwarf2_mangled_line_number_section = +{ + "mangled .debug_line section", 0, 0 +}; +static struct complaint dwarf2_unsupported_die_ref_attr = +{ + "unsupported die ref attribute form: %s", 0, 0 +}; +static struct complaint dwarf2_unsupported_stack_op = +{ + "unsupported stack op: '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_tag = +{ + "unsupported tag: '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_at_encoding = +{ + "unsupported DW_AT_encoding: '%s'", 0, 0 +}; +static struct complaint dwarf2_unsupported_at_frame_base = +{ + "unsupported DW_AT_frame_base for function '%s'", 0, 0 +}; +static struct complaint dwarf2_missing_at_frame_base = +{ + "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0 +}; +static struct complaint dwarf2_bad_static_member_name = +{ + "unrecognized static data member name %s", 0, 0 +}; /* Remember the addr_size read from the dwarf. If a target expects to link compilation units with differing address @@ -345,9 +438,12 @@ extern int info_verbose; /* From main.c; nonzero => verbose */ static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR)); +#if 0 static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *, struct section_offsets *, int)); +#endif + static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *, struct section_offsets *, int)); @@ -362,13 +458,12 @@ static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *)); static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *)); -static void add_die_to_symtab PARAMS ((struct die_info *, struct objfile *)); - -static char *dwarf2_read_section PARAMS ((bfd *, file_ptr, unsigned int)); +static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr, + unsigned int)); static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int)); -static void dwarf2_empty_abbrev_table PARAMS ((void)); +static void dwarf2_empty_abbrev_table PARAMS ((PTR)); static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int)); @@ -379,6 +474,8 @@ static char *read_full_die PARAMS ((struct die_info **, bfd *, char *)); static unsigned int read_1_byte PARAMS ((bfd *, char *)); +static int read_1_signed_byte PARAMS ((bfd *, char *)); + static unsigned int read_2_bytes PARAMS ((bfd *, char *)); static unsigned int read_4_bytes PARAMS ((bfd *, char *)); @@ -398,113 +495,125 @@ static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *)); static void set_cu_language PARAMS ((unsigned int)); -static void record_minimal_symbol PARAMS ((char *, CORE_ADDR, - enum minimal_symbol_type, - struct objfile *)); - -static int convert_locdesc PARAMS ((struct dwarf_block *)); - static struct attribute *dwarf_attr PARAMS ((struct die_info *, unsigned int)); -static void dwarf_decode_lines PARAMS ((unsigned int, bfd *)); +static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *)); + +static void dwarf2_start_subfile PARAMS ((char *, char *)); -static struct symbol *new_symbol PARAMS ((struct die_info * die, struct objfile * objfile)); +static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *, + struct objfile *)); -static struct type *die_type PARAMS ((struct die_info * die, struct objfile * objfile)); +static struct type *die_type PARAMS ((struct die_info *, struct objfile *)); -static struct type *type_at_offset PARAMS ((unsigned int offset, struct objfile * objfile)); +static struct type *die_containing_type PARAMS ((struct die_info *, + struct objfile *)); + +#if 0 +static struct type *type_at_offset PARAMS ((unsigned int, struct objfile *)); +#endif -static struct type *tag_type_to_type PARAMS ((struct die_info * die, struct objfile * objfile)); +static struct type *tag_type_to_type PARAMS ((struct die_info *, + struct objfile *)); -static void read_type_die PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_type_die PARAMS ((struct die_info *, struct objfile *)); -static void read_typedef PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_typedef PARAMS ((struct die_info *, struct objfile *)); -static void read_base_type PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_base_type PARAMS ((struct die_info *, struct objfile *)); -static void read_file_scope PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_file_scope PARAMS ((struct die_info *, struct objfile *)); -static void read_func_scope PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_func_scope PARAMS ((struct die_info *, struct objfile *)); -static void read_lexical_block_scope PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_lexical_block_scope PARAMS ((struct die_info *, + struct objfile *)); -static void read_structure_scope PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_structure_scope PARAMS ((struct die_info *, struct objfile *)); -static void read_common_block PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_common_block PARAMS ((struct die_info *, struct objfile *)); -static void read_enumeration PARAMS ((struct die_info * die, struct objfile * objfile)); +static void read_enumeration PARAMS ((struct die_info *, struct objfile *)); -static struct type * dwarf_base_type PARAMS ((int encoding, int size)); +static struct type * dwarf_base_type PARAMS ((int, int)); static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *, struct objfile *)); -static char *create_name PARAMS ((char *, struct obstack *)); +static void dwarf_read_array_type PARAMS ((struct die_info *, + struct objfile *)); -static void dwarf_read_array_type PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_tag_pointer_type PARAMS ((struct die_info *, + struct objfile *)); -static void read_tag_pointer_type PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_tag_ptr_to_member_type PARAMS ((struct die_info *, + struct objfile *)); -static void read_tag_const_type PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_tag_reference_type PARAMS ((struct die_info *, + struct objfile *)); -static void read_tag_volatile_type PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_tag_const_type PARAMS ((struct die_info *, struct objfile *)); -static void read_tag_string_type PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_tag_volatile_type PARAMS ((struct die_info *, + struct objfile *)); -static void read_subroutine_type PARAMS ((struct die_info * die, - struct objfile * objfile)); +static void read_tag_string_type PARAMS ((struct die_info *, + struct objfile *)); -struct die_info *read_comp_unit PARAMS ((char *info_ptr, bfd * abfd)); +static void read_subroutine_type PARAMS ((struct die_info *, + struct objfile *)); -static void free_die_list PARAMS ((struct die_info * dies)); +struct die_info *read_comp_unit PARAMS ((char *, bfd *)); + +static void free_die_list PARAMS ((struct die_info *)); static void process_die PARAMS ((struct die_info *, struct objfile *)); -static char *dwarf_tag_name PARAMS ((unsigned tag)); +static char *dwarf_tag_name PARAMS ((unsigned int)); -static char *dwarf_attr_name PARAMS ((unsigned attr)); +static char *dwarf_attr_name PARAMS ((unsigned int)); -static char *dwarf_form_name PARAMS ((unsigned form)); +static char *dwarf_form_name PARAMS ((unsigned int)); -static char *dwarf_stack_op_name PARAMS ((unsigned op)); +static char *dwarf_stack_op_name PARAMS ((unsigned int)); -static char *dwarf_bool_name PARAMS ((unsigned bool)); +static char *dwarf_bool_name PARAMS ((unsigned int)); -static char *dwarf_bool_name PARAMS ((unsigned tag)); +static char *dwarf_bool_name PARAMS ((unsigned int)); -static char *dwarf_type_encoding_name PARAMS ((unsigned enc)); +static char *dwarf_type_encoding_name PARAMS ((unsigned int)); -static char *dwarf_cfi_name PARAMS ((unsigned cfi_opc)); +#if 0 +static char *dwarf_cfi_name PARAMS ((unsigned int)); -struct die_info *copy_die PARAMS ((struct die_info *old_die)); +struct die_info *copy_die PARAMS ((struct die_info *)); +#endif -struct die_info *sibling_die PARAMS ((struct die_info *die)); +struct die_info *sibling_die PARAMS ((struct die_info *)); -void dump_die PARAMS ((struct die_info *die)); +void dump_die PARAMS ((struct die_info *)); -void dump_die_list PARAMS ((struct die_info *dies)); +void dump_die_list PARAMS ((struct die_info *)); void store_in_ref_table PARAMS ((unsigned int, struct die_info *)); -struct die_info *follow_die_ref PARAMS ((unsigned int offset)); +static void dwarf2_empty_die_ref_table PARAMS ((void)); + +static unsigned int dwarf2_get_ref_die_offset PARAMS ((struct attribute *)); + +struct die_info *follow_die_ref PARAMS ((unsigned int)); static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int)); /* memory allocation interface */ -static struct type *dwarf_alloc_type PARAMS ((struct objfile *)); - -static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void)); +static void dwarf2_free_tmp_obstack PARAMS ((PTR)); static struct dwarf_block *dwarf_alloc_block PARAMS ((void)); +static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void)); + static struct die_info *dwarf_alloc_die PARAMS ((void)); /* Try to locate the sections we need for DWARF 2 debugging @@ -516,7 +625,7 @@ dwarf2_has_info (abfd) { dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0; bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); - if (dwarf_info_offset && dwarf_abbrev_offset && dwarf_line_offset) + if (dwarf_info_offset && dwarf_abbrev_offset) { return 1; } @@ -586,18 +695,16 @@ dwarf2_build_psymtabs (objfile, section_offsets, mainline) struct section_offsets *section_offsets; int mainline; { - bfd *abfd = objfile->obfd; - /* We definitely need the .debug_info, .debug_abbrev, and .debug_line - sections */ + /* We definitely need the .debug_info and .debug_abbrev sections */ - dwarf_info_buffer = dwarf2_read_section (abfd, + dwarf_info_buffer = dwarf2_read_section (objfile, dwarf_info_offset, dwarf_info_size); - dwarf_abbrev_buffer = dwarf2_read_section (abfd, + dwarf_abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_offset, dwarf_abbrev_size); - dwarf_line_buffer = dwarf2_read_section (abfd, + dwarf_line_buffer = dwarf2_read_section (objfile, dwarf_line_offset, dwarf_line_size); @@ -624,6 +731,7 @@ dwarf2_build_psymtabs (objfile, section_offsets, mainline) } } +#if 0 /* Build the partial symbol table from the information in the .debug_pubnames and .debug_aranges sections. */ @@ -638,7 +746,7 @@ dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline) char *aranges_ptr, *pubnames_ptr; unsigned int entry_length, version, info_offset, info_size; - pubnames_buffer = dwarf2_read_section (abfd, + pubnames_buffer = dwarf2_read_section (objfile, dwarf_pubnames_offset, dwarf_pubnames_size); pubnames_ptr = pubnames_buffer; @@ -654,11 +762,12 @@ dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline) pubnames_ptr += 4; } - aranges_buffer = dwarf2_read_section (abfd, + aranges_buffer = dwarf2_read_section (objfile, dwarf_aranges_offset, dwarf_aranges_size); } +#endif /* Build the partial symbol table by doing a quick pass through the .debug_info and .debug_abbrev sections. */ @@ -673,20 +782,21 @@ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline) mmap() on architectures that support it. (FIXME) */ bfd *abfd = objfile->obfd; char *info_ptr, *abbrev_ptr; - char *beg_of_comp_unit, *comp_unit_die_offset; + char *beg_of_comp_unit; struct comp_unit_head cu_header; struct partial_die_info comp_unit_die; struct partial_symtab *pst; struct cleanup *back_to; int comp_unit_has_pc_info; - int has_pc_info; CORE_ADDR lowpc, highpc; - comp_unit_die = zeroed_partial_die; info_ptr = dwarf_info_buffer; abbrev_ptr = dwarf_abbrev_buffer; - while ((info_ptr - dwarf_info_buffer) + obstack_init (&dwarf2_tmp_obstack); + back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL); + + while ((unsigned int) (info_ptr - dwarf_info_buffer) + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size) { beg_of_comp_unit = info_ptr; @@ -708,7 +818,7 @@ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline) /* Read the abbrevs for this compilation unit into a table */ dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); - back_to = make_cleanup (dwarf2_empty_abbrev_table, NULL); + make_cleanup (dwarf2_empty_abbrev_table, NULL); /* Read the compilation unit die */ info_ptr = read_partial_die (&comp_unit_die, abfd, @@ -724,9 +834,14 @@ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline) objfile->global_psymbols.next, objfile->static_psymbols.next); - /* Store offset in the .debug_info section of the comp_unit_die. */ pst->read_symtab_private = (char *) - (beg_of_comp_unit - dwarf_info_buffer); + obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo)); + DWARF_INFO_BUFFER(pst) = dwarf_info_buffer; + DWARF_INFO_OFFSET(pst) = beg_of_comp_unit - dwarf_info_buffer; + DWARF_ABBREV_BUFFER(pst) = dwarf_abbrev_buffer; + DWARF_ABBREV_SIZE(pst) = dwarf_abbrev_size; + DWARF_LINE_BUFFER(pst) = dwarf_line_buffer; + baseaddr = ANOFFSET (section_offsets, 0); /* Store the function that reads in the rest of the symbol table */ pst->read_symtab = dwarf2_psymtab_to_symtab; @@ -741,8 +856,8 @@ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline) comp_unit_die.lowpc = lowpc; comp_unit_die.highpc = highpc; } - pst->textlow = comp_unit_die.lowpc; - pst->texthigh = comp_unit_die.highpc; + pst->textlow = comp_unit_die.lowpc + baseaddr; + pst->texthigh = comp_unit_die.highpc + baseaddr; pst->n_global_syms = objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset); @@ -769,15 +884,11 @@ scan_partial_symbols (info_ptr, objfile, lowpc, highpc) CORE_ADDR *lowpc; CORE_ADDR *highpc; { - /* FIXME: This should free the attributes of the partial die structure - when it is done with them (is there a more efficient way - to do this). */ bfd *abfd = objfile->obfd; struct partial_die_info pdi; int nesting_level = 1; /* we've already read in comp_unit_die */ int has_pc_info; - pdi = zeroed_partial_die; *lowpc = ((CORE_ADDR) -1); *highpc = ((CORE_ADDR) 0); do @@ -791,9 +902,10 @@ scan_partial_symbols (info_ptr, objfile, lowpc, highpc) case DW_TAG_class_type: case DW_TAG_structure_type: case DW_TAG_union_type: + case DW_TAG_enumeration_type: if (pdi.is_external || nesting_level == 1) { - if (pdi.name) + if (pdi.name && !pdi.is_declaration) { add_partial_symbol (&pdi, objfile); } @@ -804,11 +916,17 @@ scan_partial_symbols (info_ptr, objfile, lowpc, highpc) { *lowpc = pdi.lowpc; } - if (pdi.highpc > *lowpc) + if (pdi.highpc > *highpc) { *highpc = pdi.highpc; } } + break; + case DW_TAG_enumerator: + /* File scope enumerators are added to the partial symbol table. */ + if (pdi.name && nesting_level == 2) + add_partial_symbol (&pdi, objfile); + break; } if (pdi.has_children) { @@ -820,6 +938,11 @@ scan_partial_symbols (info_ptr, objfile, lowpc, highpc) } } while (nesting_level); + + /* If we didn't find a lowpc, set it to highpc to avoid complaints + from `maint check. */ + if (*lowpc == ((CORE_ADDR) -1)) + *lowpc = *highpc; return info_ptr; } @@ -833,62 +956,85 @@ add_partial_symbol (pdi, objfile) case DW_TAG_subprogram: if (pdi->is_external) { - record_minimal_symbol (pdi->name, pdi->lowpc, - mst_text, objfile); + prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, + mst_text, objfile); add_psymbol_to_list (pdi->name, strlen (pdi->name), VAR_NAMESPACE, LOC_BLOCK, &objfile->global_psymbols, - 0, pdi->lowpc, cu_language, objfile); + 0, pdi->lowpc + baseaddr, cu_language, objfile); } else { + prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, + mst_file_text, objfile); add_psymbol_to_list (pdi->name, strlen (pdi->name), VAR_NAMESPACE, LOC_BLOCK, &objfile->static_psymbols, - 0, pdi->lowpc, cu_language, objfile); + 0, pdi->lowpc + baseaddr, cu_language, objfile); } break; case DW_TAG_variable: + /* Skip symbols without location desciptors, these are external + references. */ + if (pdi->locdesc == NULL) + return; if (pdi->is_external) { - record_minimal_symbol (pdi->name, convert_locdesc (pdi->locdesc), - mst_data, objfile); + prim_record_minimal_symbol (pdi->name, + decode_locdesc (pdi->locdesc, objfile) + + baseaddr, + mst_data, objfile); add_psymbol_to_list (pdi->name, strlen (pdi->name), VAR_NAMESPACE, LOC_STATIC, &objfile->global_psymbols, - 0, 0, cu_language, objfile); + 0, (CORE_ADDR) 0, cu_language, objfile); } else { + prim_record_minimal_symbol (pdi->name, + decode_locdesc (pdi->locdesc, objfile) + + baseaddr, + mst_file_data, objfile); add_psymbol_to_list (pdi->name, strlen (pdi->name), VAR_NAMESPACE, LOC_STATIC, &objfile->static_psymbols, - 0, 0, cu_language, objfile); + 0, (CORE_ADDR) 0, cu_language, objfile); } break; case DW_TAG_typedef: add_psymbol_to_list (pdi->name, strlen (pdi->name), VAR_NAMESPACE, LOC_TYPEDEF, &objfile->static_psymbols, - 0, 0, cu_language, objfile); + 0, (CORE_ADDR) 0, cu_language, objfile); break; case DW_TAG_class_type: case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_enumeration_type: + /* Skip aggregate types without children, these are external + references. */ + if (pdi->has_children == 0) + return; add_psymbol_to_list (pdi->name, strlen (pdi->name), STRUCT_NAMESPACE, LOC_TYPEDEF, &objfile->static_psymbols, - 0, 0, cu_language, objfile); + 0, (CORE_ADDR) 0, cu_language, objfile); + if (cu_language == language_cplus) { /* For C++, these implicitly act as typedefs as well. */ add_psymbol_to_list (pdi->name, strlen (pdi->name), VAR_NAMESPACE, LOC_TYPEDEF, &objfile->static_psymbols, - 0, 0, cu_language, objfile); + 0, (CORE_ADDR) 0, cu_language, objfile); } break; + case DW_TAG_enumerator: + add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_NAMESPACE, LOC_CONST, + &objfile->static_psymbols, + 0, (CORE_ADDR) 0, cu_language, objfile); + break; } } @@ -907,7 +1053,17 @@ dwarf2_psymtab_to_symtab (pst) } else { + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + gdb_flush (gdb_stdout); + } + psymtab_to_symtab_1 (pst); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); } } } @@ -922,19 +1078,29 @@ psymtab_to_symtab_1 (pst) struct die_info *dies; struct attribute *attr; unsigned long offset; - unsigned long int nesting_level; CORE_ADDR highpc; struct attribute *high_pc_attr; struct die_info *child_die; char *info_ptr; - struct context_stack *context; struct symtab *symtab; - struct cleanup *abbrev_cleanup, *die_cleanup; + struct cleanup *back_to; - /* Get the offset of this compilation units debug info */ - offset = (unsigned long) pst->read_symtab_private; + /* Set local variables from the partial symbol table info. */ + offset = DWARF_INFO_OFFSET(pst); + dwarf_info_buffer = DWARF_INFO_BUFFER(pst); + dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER(pst); + dwarf_abbrev_size = DWARF_ABBREV_SIZE(pst); + dwarf_line_buffer = DWARF_LINE_BUFFER(pst); + baseaddr = ANOFFSET (pst->section_offsets, 0); + cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; + obstack_init (&dwarf2_tmp_obstack); + back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL); + + buildsym_init (); + make_cleanup (really_free_pendings, NULL); + /* read in the comp_unit header */ cu_header.length = read_4_bytes (abfd, info_ptr); info_ptr += 4; @@ -947,11 +1113,11 @@ psymtab_to_symtab_1 (pst) /* Read the abbrevs for this compilation unit */ dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); - abbrev_cleanup = make_cleanup (dwarf2_empty_abbrev_table, NULL); + make_cleanup (dwarf2_empty_abbrev_table, NULL); dies = read_comp_unit (info_ptr, abfd); - die_cleanup = make_cleanup (free_die_list, dies); + make_cleanup (free_die_list, dies); /* Do line number decoding in read_file_scope () */ process_die (dies, objfile); @@ -984,22 +1150,21 @@ psymtab_to_symtab_1 (pst) } } } + symtab = end_symtab (highpc + baseaddr, objfile, 0); - symtab = end_symtab (highpc, objfile, 0); - if (symtab != NULL) + /* Set symtab language to language from DW_AT_language. + If the compilation is from a C file generated by language preprocessors, + do not set the language if it was already deduced by start_subfile. */ + if (symtab != NULL + && !(cu_language == language_c && symtab->language != language_c)) { symtab->language = cu_language; } pst->symtab = symtab; pst->readin = 1; - if (info_verbose) - { - printf_filtered ("Sorting symbol table..."); - wrap_here (""); - fflush (stdout); - } sort_symtab_syms (pst->symtab); - do_cleanups (abbrev_cleanup); + + do_cleanups (back_to); } /* Process a die and its children. */ @@ -1017,6 +1182,7 @@ process_die (die, objfile) read_file_scope (die, objfile); break; case DW_TAG_subprogram: + read_subroutine_type (die, objfile); if (dwarf_attr (die, DW_AT_low_pc)) { read_func_scope (die, objfile); @@ -1042,6 +1208,12 @@ process_die (die, objfile) case DW_TAG_pointer_type: read_tag_pointer_type (die, objfile); break; + case DW_TAG_ptr_to_member_type: + read_tag_ptr_to_member_type (die, objfile); + break; + case DW_TAG_reference_type: + read_tag_reference_type (die, objfile); + break; case DW_TAG_string_type: read_tag_string_type (die, objfile); break; @@ -1054,7 +1226,7 @@ process_die (die, objfile) case DW_TAG_common_inclusion: break; default: - new_symbol (die, objfile); + new_symbol (die, NULL, objfile); break; } } @@ -1068,7 +1240,7 @@ read_file_scope (die, objfile) CORE_ADDR lowpc = ((CORE_ADDR) -1); CORE_ADDR highpc = ((CORE_ADDR) 0); struct attribute *attr, *low_pc_attr, *high_pc_attr; - char *name = NULL; + char *name = ""; char *comp_dir = NULL; struct die_info *child_die; bfd *abfd = objfile->obfd; @@ -1108,6 +1280,13 @@ read_file_scope (die, objfile) } } + /* If we didn't find a lowpc, set it to highpc to avoid complaints + from finish_block. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + lowpc += baseaddr; + highpc += baseaddr; + attr = dwarf_attr (die, DW_AT_name); if (attr) { @@ -1117,6 +1296,15 @@ read_file_scope (die, objfile) if (attr) { comp_dir = DW_STRING (attr); + if (comp_dir) + { + /* Irix 6.2 native cc prepends .: to the compilation + directory, get rid of it. */ + char *cp = strchr (comp_dir, ':'); + + if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/') + comp_dir = cp + 1; + } } if (objfile->ei.entry_point >= lowpc && @@ -1140,18 +1328,19 @@ read_file_scope (die, objfile) } #endif + /* The compilation unit may be in a different language or objfile, + zero out all remembered fundamental types. */ + memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *)); + start_symtab (name, comp_dir, lowpc); - /* Decode line number information. */ + /* Decode line number information if present. */ attr = dwarf_attr (die, DW_AT_stmt_list); - if (!attr) + if (attr) { - error ( - "Dwarf Error: No line number information for compilation unit: %s.", - name); + line_offset = DW_UNSND (attr); + dwarf_decode_lines (line_offset, comp_dir, abfd); } - line_offset = DW_UNSND (attr); - dwarf_decode_lines (line_offset, abfd); /* Process all dies in compilation unit. */ if (die->has_children) @@ -1175,8 +1364,7 @@ read_func_scope (die, objfile) CORE_ADDR highpc = 0; struct die_info *child_die; struct attribute *attr; - struct minimal_symbol *min_sym; - char *name = NULL; + char *name = ""; attr = dwarf_attr (die, DW_AT_name); if (attr) @@ -1195,6 +1383,8 @@ read_func_scope (die, objfile) { highpc = DW_ADDR (attr); } + lowpc += baseaddr; + highpc += baseaddr; if (objfile->ei.entry_point >= lowpc && objfile->ei.entry_point < highpc) @@ -1208,8 +1398,28 @@ read_func_scope (die, objfile) objfile->ei.main_func_lowpc = lowpc; objfile->ei.main_func_highpc = highpc; } + + /* Decode DW_AT_frame_base location descriptor if present, keep result + for DW_OP_fbreg operands in decode_locdesc. */ + frame_base_reg = -1; + frame_base_offset = 0; + attr = dwarf_attr (die, DW_AT_frame_base); + if (attr) + { + CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile); + if (isreg) + frame_base_reg = addr; + else if (offreg) + { + frame_base_reg = basereg; + frame_base_offset = addr; + } + else + complain (&dwarf2_unsupported_at_frame_base, name); + } + new = push_context (0, lowpc); - new->name = new_symbol (die, objfile); + new->name = new_symbol (die, die->type, objfile); list_in_scope = &local_symbols; if (die->has_children) @@ -1252,6 +1462,8 @@ read_lexical_block_scope (die, objfile) { highpc = DW_ADDR (attr); } + lowpc += baseaddr; + highpc += baseaddr; push_context (0, lowpc); if (die->has_children) @@ -1294,36 +1506,37 @@ read_structure_scope (die, objfile) struct die_info *die; struct objfile *objfile; { - struct type *type, *member_type; + struct type *type; struct field *fields; struct die_info *child_die; struct attribute *attr; struct symbol *sym; int num_fields; - type = dwarf_alloc_type (objfile); + type = alloc_type (objfile); INIT_CPLUS_SPECIFIC (type); attr = dwarf_attr (die, DW_AT_name); + if (attr) + { + TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->type_obstack); + } if (die->tag == DW_TAG_structure_type) { TYPE_CODE (type) = TYPE_CODE_STRUCT; - if (attr) - { - TYPE_NAME (type) = obconcat (&objfile->type_obstack, - "struct", " ", DW_STRING (attr)); - } } - else + else if (die->tag == DW_TAG_union_type) { - /* die->tag == DW_TAG_union_type */ TYPE_CODE (type) = TYPE_CODE_UNION; - if (attr) - { - TYPE_NAME (type) = obconcat (&objfile->type_obstack, - "union", " ", DW_STRING (attr)); - } + } + else + { + /* FIXME: This should be changed to TYPE_CODE_CLASS when the rest + of GDB knows how to handle it. */ + TYPE_CODE (type) = TYPE_CODE_STRUCT; } attr = dwarf_attr (die, DW_AT_byte_size); @@ -1348,11 +1561,7 @@ read_structure_scope (die, objfile) child_die = die->next; while (child_die && child_die->tag) { - if (child_die->tag != DW_TAG_member) - { - process_die (child_die, objfile); - } - else + if (child_die->tag == DW_TAG_member) { if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) { @@ -1391,26 +1600,91 @@ read_structure_scope (die, objfile) } /* Get type of member. */ - member_type = die_type (child_die, objfile); - fields[num_fields].type = member_type; + fields[num_fields].type = die_type (child_die, objfile); /* Get name of member. */ attr = dwarf_attr (child_die, DW_AT_name); if (attr) { - fields[num_fields].name = obsavestring (DW_STRING (attr), - strlen (DW_STRING (attr)), - &objfile->type_obstack); -#if 0 - fields[num_fields].name = strdup (DW_STRING (attr)); -#endif + fields[num_fields].name = + obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->type_obstack); } num_fields++; } + else if (child_die->tag == DW_TAG_variable) + { + char *physname = NULL; + char *fieldname = NULL; + + /* C++ static member. + Get physical name, extract field name from physical name. */ + attr = dwarf_attr (child_die, DW_AT_name); + if (attr) + { + char *cp; + + physname = DW_STRING (attr); + + cp = physname; + while (*cp && !is_cplus_marker (*cp)) + cp++; + if (*cp) + fieldname = cp + 1; + } + + if (physname && fieldname) + { + if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) + { + fields = (struct field *) + xrealloc (fields, + (num_fields + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct field)); + } + fields[num_fields].bitpos = -1; + fields[num_fields].bitsize = (long) + obsavestring (physname, strlen (physname), + &objfile->type_obstack); + fields[num_fields].type = die_type (child_die, objfile); + fields[num_fields].name = + obsavestring (fieldname, strlen (fieldname), + &objfile->type_obstack); + num_fields++; + } + else + { + complain (&dwarf2_bad_static_member_name, + physname ? physname : ""); + } + } + else if (child_die->tag == DW_TAG_subprogram) + { + /* FIXME: C++ member function. */ + process_die (child_die, objfile); + } + else if (child_die->tag == DW_TAG_inheritance) + { + /* FIXME: C++ inheritance information. */ + } + else + { + process_die (child_die, objfile); + } child_die = sibling_die (child_die); } - type->nfields = num_fields; - type->fields = fields; + if (num_fields) + { + TYPE_NFIELDS (type) = num_fields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * num_fields); + memcpy (TYPE_FIELDS (type), fields, + sizeof (struct field) * num_fields); + free (fields); + } + + sym = new_symbol (die, type, objfile); } else { @@ -1419,11 +1693,6 @@ read_structure_scope (die, objfile) } die->type = type; - sym = new_symbol (die, objfile); - if (sym != NULL) - { - SYMBOL_TYPE (sym) = type; - } } /* Given a pointer to a die which begins an enumeration, process all @@ -1445,18 +1714,18 @@ read_enumeration (die, objfile) struct field *fields; struct attribute *attr; struct symbol *sym; - struct dwarf_block *blk; int num_fields; - unsigned int size, bytes_read, i; + int unsigned_enum = 1; - type = dwarf_alloc_type (objfile); + type = alloc_type (objfile); TYPE_CODE (type) = TYPE_CODE_ENUM; attr = dwarf_attr (die, DW_AT_name); if (attr) { - TYPE_NAME (type) = obconcat (&objfile->type_obstack, - "enum ", " ", DW_STRING (attr)); + TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->type_obstack); } attr = dwarf_attr (die, DW_AT_byte_size); @@ -1482,58 +1751,47 @@ read_enumeration (die, objfile) } else { - if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) - { - fields = (struct field *) - xrealloc (fields, - (num_fields + DW_FIELD_ALLOC_CHUNK) - * sizeof (struct field)); - } - - /* Handcraft a new symbol for this enum member. */ - sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, - sizeof (struct symbol)); - memset (sym, 0, sizeof (struct symbol)); - - fields[num_fields].type = NULL; - fields[num_fields].bitsize = 0; attr = dwarf_attr (child_die, DW_AT_name); if (attr) { - fields[num_fields].name = strdup (DW_STRING (attr)); - SYMBOL_NAME (sym) = strdup (fields[num_fields].name); - } - attr = dwarf_attr (child_die, DW_AT_const_value); - if (attr) - { - fields[num_fields].bitpos = DW_UNSND (attr); - SYMBOL_VALUE (sym) = DW_UNSND (attr); - } + sym = new_symbol (child_die, type, objfile); + if (SYMBOL_VALUE (sym) < 0) + unsigned_enum = 0; -#if 0 - SYMBOL_NAME (sym) = create_name (elist->str, - &objfile->symbol_obstack); -#endif - SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language); - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_CLASS (sym) = LOC_CONST; - SYMBOL_TYPE (sym) = type; - add_symbol_to_list (sym, list_in_scope); + if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) + { + fields = (struct field *) + xrealloc (fields, + (num_fields + DW_FIELD_ALLOC_CHUNK) + * sizeof (struct field)); + } - num_fields++; + fields[num_fields].name = SYMBOL_NAME (sym); + fields[num_fields].type = NULL; + fields[num_fields].bitpos = SYMBOL_VALUE (sym); + fields[num_fields].bitsize = 0; + + num_fields++; + } } child_die = sibling_die (child_die); } - type->fields = fields; - type->nfields = num_fields; + + if (num_fields) + { + TYPE_NFIELDS (type) = num_fields; + TYPE_FIELDS (type) = (struct field *) + TYPE_ALLOC (type, sizeof (struct field) * num_fields); + memcpy (TYPE_FIELDS (type), fields, + sizeof (struct field) * num_fields); + free (fields); + } + if (unsigned_enum) + TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; } die->type = type; - sym = new_symbol (die, objfile); - if (sym != NULL) - { - SYMBOL_TYPE (sym) = type; - } + sym = new_symbol (die, type, objfile); } /* Extract all information from a DW_TAG_array_type DIE and put it in @@ -1546,11 +1804,9 @@ dwarf_read_array_type (die, objfile) struct objfile *objfile; { struct die_info *child_die; - struct type *type, *element_type, *range_type, *index_type; + struct type *type = NULL; + struct type *element_type, *range_type, *index_type; struct attribute *attr; - struct dwarf_block *blk; - unsigned int size, i, type_form, bytes_read; - unsigned int index_spec, lo_spec, hi_spec, type_ref; unsigned int low, high; /* Return if we've already decoded this type. */ @@ -1561,6 +1817,16 @@ dwarf_read_array_type (die, objfile) element_type = die_type (die, objfile); + /* Irix 6.2 native cc creates array types without children for + variable length arrays. */ + if (die->has_children == 0) + { + index_type = dwarf2_fundamental_type (objfile, FT_INTEGER); + range_type = create_range_type (NULL, index_type, 0, -1); + die->type = create_array_type (NULL, element_type, range_type); + return; + } + low = 0; high = 1; if (cu_language == DW_LANG_Fortran77 || cu_language == DW_LANG_Fortran90) @@ -1591,20 +1857,11 @@ dwarf_read_array_type (die, objfile) } else { - if (!array_bound_warning_given) - { - warning ("Non-constant array bounds ignored."); - array_bound_warning_given = 1; - } + complain (&dwarf2_non_const_array_bound_ignored, + dwarf_form_name (attr->form)); #ifdef FORTRAN_HACK - type = dwarf_alloc_type (objfile); - TYPE_TARGET_TYPE (type) = element_type; - TYPE_OBJFILE (type) = objfile; - TYPE_LENGTH (type) = 4; - TYPE_CODE (type) = TYPE_CODE_PTR; - TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; - TYPE_POINTER_TYPE (element_type) = type; - goto done; + die->type = lookup_pointer_type (element_type); + return; #else low = 0; #endif @@ -1624,34 +1881,33 @@ dwarf_read_array_type (die, objfile) { high = DW_UNSND (attr); } + else if (attr->form == DW_FORM_block1) + { + /* GCC encodes arrays with unspecified or dynamic length + with a DW_FORM_block1 attribute. + FIXME: GDB does not yet know how to handle dynamic + arrays properly, treat them as arrays with unspecified + length for now. */ + high = -1; + } else { - if (!array_bound_warning_given) - { - warning ("Non-constant array bounds ignored."); - array_bound_warning_given = 1; - } + complain (&dwarf2_non_const_array_bound_ignored, + dwarf_form_name (attr->form)); #ifdef FORTRAN_HACK - type = dwarf_alloc_type (objfile); - TYPE_TARGET_TYPE (type) = element_type; - TYPE_OBJFILE (type) = objfile; - TYPE_LENGTH (type) = 4; - TYPE_CODE (type) = TYPE_CODE_PTR; - TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; - TYPE_POINTER_TYPE (element_type) = type; - goto done; + die->type = lookup_pointer_type (element_type); + return; #else high = 1; #endif } } + range_type = create_range_type (NULL, index_type, low, high); + type = create_array_type (NULL, element_type, range_type); + element_type = type; } - range_type = create_range_type (NULL, index_type, low, high); - type = create_array_type (NULL, element_type, range_type); - element_type = type; child_die = sibling_die (child_die); } -done: /* Install the type in the die. */ die->type = type; } @@ -1666,7 +1922,7 @@ read_common_block (die, objfile) struct die_info *child_die; struct attribute *attr; struct symbol *sym; - CORE_ADDR base; + CORE_ADDR base = (CORE_ADDR) 0; attr = dwarf_attr (die, DW_AT_location); if (attr) @@ -1678,7 +1934,7 @@ read_common_block (die, objfile) child_die = die->next; while (child_die && child_die->tag) { - sym = new_symbol (child_die, objfile); + sym = new_symbol (child_die, NULL, objfile); attr = dwarf_attr (child_die, DW_AT_data_member_location); if (attr) { @@ -1699,7 +1955,7 @@ read_tag_pointer_type (die, objfile) struct die_info *die; struct objfile *objfile; { - struct type *type, *pointed_to_type; + struct type *type; struct attribute *attr; if (die->type) @@ -1707,11 +1963,7 @@ read_tag_pointer_type (die, objfile) return; } - pointed_to_type = die_type (die, objfile); - - type = dwarf_alloc_type (objfile); - TYPE_TARGET_TYPE (type) = pointed_to_type; - TYPE_OBJFILE (type) = objfile; + type = lookup_pointer_type (die_type (die, objfile)); attr = dwarf_attr (die, DW_AT_byte_size); if (attr) { @@ -1721,10 +1973,31 @@ read_tag_pointer_type (die, objfile) { TYPE_LENGTH (type) = address_size; } - TYPE_CODE (type) = TYPE_CODE_PTR; - TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; + die->type = type; +} + +/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to + the user defined type vector. */ + +static void +read_tag_ptr_to_member_type (die, objfile) + struct die_info *die; + struct objfile *objfile; +{ + struct type *type; + struct type *to_type; + struct type *domain; + + if (die->type) + { + return; + } + + type = alloc_type (objfile); + to_type = die_type (die, objfile); + domain = die_containing_type (die, objfile); + smash_to_member_type (type, domain, to_type); - TYPE_POINTER_TYPE (pointed_to_type) = type; die->type = type; } @@ -1736,7 +2009,7 @@ read_tag_reference_type (die, objfile) struct die_info *die; struct objfile *objfile; { - struct type *type, *pointed_to_type; + struct type *type; struct attribute *attr; if (die->type) @@ -1744,11 +2017,7 @@ read_tag_reference_type (die, objfile) return; } - pointed_to_type = die_type (die, objfile); - - type = dwarf_alloc_type (objfile); - TYPE_TARGET_TYPE (type) = pointed_to_type; - TYPE_OBJFILE (type) = objfile; + type = lookup_reference_type (die_type (die, objfile)); attr = dwarf_attr (die, DW_AT_byte_size); if (attr) { @@ -1758,10 +2027,6 @@ read_tag_reference_type (die, objfile) { TYPE_LENGTH (type) = address_size; } - TYPE_CODE (type) = TYPE_CODE_REF; - TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; - - TYPE_REFERENCE_TYPE (pointed_to_type) = type; die->type = type; } @@ -1775,12 +2040,7 @@ read_tag_const_type (die, objfile) return; } - if (!tag_const_warning_given) - { - warning ("gdb ignores `const' qualifiers."); - tag_const_warning_given = 1; - } - + complain (&dwarf2_const_ignored); die->type = die_type (die, objfile); } @@ -1794,12 +2054,7 @@ read_tag_volatile_type (die, objfile) return; } - if (!tag_volatile_warning_given) - { - warning ("gdb ignores `volatile' qualifiers."); - tag_volatile_warning_given = 1; - } - + complain (&dwarf2_volatile_ignored); die->type = die_type (die, objfile); } @@ -1847,10 +2102,7 @@ read_tag_string_type (die, objfile) }; ('funcp' generates a DW_TAG_subroutine_type DIE) - - NOTE: parameter DIES are currently ignored. See if gdb has a way to - include this info in it's type system, and decode them if so. Is - this what the type structure's "arg_types" field is for? (FIXME) */ +*/ static void read_subroutine_type (die, objfile) @@ -1868,12 +2120,41 @@ read_subroutine_type (die, objfile) type = die_type (die, objfile); ftype = lookup_function_type (type); - TYPE_TARGET_TYPE (ftype) = type; - TYPE_LENGTH (ftype) = 1; - TYPE_CODE (ftype) = TYPE_CODE_FUNC; - TYPE_OBJFILE (ftype) = objfile; + if (die->has_children) + { + struct die_info *child_die; + int nparams = 0; + int iparams = 0; - die->type = type; + /* Count the number of parameters. + FIXME: GDB currently has no way to deal with ellipsis, + represented by DW_TAG_unspecified_parameters. */ + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_formal_parameter) + nparams++; + child_die = sibling_die (child_die); + } + + /* Allocate storage for parameters and fill them in. */ + TYPE_NFIELDS (ftype) = nparams; + TYPE_FIELDS (ftype) = (struct field *) + TYPE_ALLOC (ftype, nparams * sizeof (struct field)); + + child_die = die->next; + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_formal_parameter) + { + TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile); + iparams++; + } + child_die = sibling_die (child_die); + } + } + + die->type = ftype; } static void @@ -1885,7 +2166,21 @@ read_typedef (die, objfile) if (!die->type) { - type = die_type (die, objfile); + struct attribute *attr; + struct type *xtype; + + xtype = die_type (die, objfile); + + type = alloc_type (objfile); + TYPE_CODE (type) = TYPE_CODE_TYPEDEF; + TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB; + TYPE_TARGET_TYPE (type) = xtype; + attr = dwarf_attr (die, DW_AT_name); + if (attr) + TYPE_NAME (type) = obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->type_obstack); + die->type = type; } } @@ -1918,7 +2213,48 @@ read_base_type (die, objfile) { size = DW_UNSND (attr); } - type = dwarf_base_type (encoding, size); + attr = dwarf_attr (die, DW_AT_name); + if (attr) + { + enum type_code code = TYPE_CODE_INT; + int is_unsigned = 0; + + switch (encoding) + { + case DW_ATE_address: + /* Turn DW_ATE_address into a void * pointer. */ + code = TYPE_CODE_PTR; + is_unsigned = 1; + break; + case DW_ATE_boolean: + code = TYPE_CODE_BOOL; + break; + case DW_ATE_complex_float: + code = TYPE_CODE_COMPLEX; + break; + case DW_ATE_float: + code = TYPE_CODE_FLT; + break; + case DW_ATE_signed: + case DW_ATE_signed_char: + break; + case DW_ATE_unsigned: + case DW_ATE_unsigned_char: + is_unsigned = 1; + break; + default: + complain (&dwarf2_unsupported_at_encoding, + dwarf_type_encoding_name (encoding)); + break; + } + type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile); + if (encoding == DW_ATE_address) + TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID); + } + else + { + type = dwarf_base_type (encoding, size); + } die->type = type; } @@ -1933,6 +2269,9 @@ read_comp_unit (info_ptr, abfd) char *cur_ptr; int nesting_level; + /* Reset die reference table, we are building a new one now. */ + dwarf2_empty_die_ref_table (); + cur_ptr = info_ptr; nesting_level = 0; first_die = last_die = NULL; @@ -1985,22 +2324,25 @@ free_die_list (dies) } } -/* Read the contents of the section at OFFSET and of size SIZE in the - object file specified by ABFD into a buffer of bytes and return it. */ +/* Read the contents of the section at OFFSET and of size SIZE from the + object file specified by OBJFILE into the psymbol_obstack and return it. */ static char * -dwarf2_read_section (abfd, offset, size) - bfd * abfd; +dwarf2_read_section (objfile, offset, size) + struct objfile *objfile; file_ptr offset; unsigned int size; { + bfd *abfd = objfile->obfd; char *buf; - buf = xmalloc (size); + if (size == 0) + return NULL; + + buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size); if ((bfd_seek (abfd, offset, SEEK_SET) != 0) || (bfd_read (buf, size, 1, abfd) != size)) { - free (buf); buf = NULL; error ("Dwarf Error: Can't read DWARF data from '%s'", bfd_get_filename (abfd)); @@ -2024,7 +2366,7 @@ dwarf2_read_abbrevs (abfd, offset) unsigned int abbrev_form, hash_number; /* empty the table */ - dwarf2_empty_abbrev_table (); + dwarf2_empty_abbrev_table (NULL); abbrev_ptr = dwarf_abbrev_buffer + offset; abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); @@ -2051,9 +2393,10 @@ dwarf2_read_abbrevs (abfd, offset) { if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0) { - cur_abbrev->attrs = xrealloc (cur_abbrev->attrs, - (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK) - * sizeof (struct attr_abbrev)); + cur_abbrev->attrs = (struct attr_abbrev *) + xrealloc (cur_abbrev->attrs, + (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK) + * sizeof (struct attr_abbrev)); } cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name; cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form; @@ -2067,16 +2410,29 @@ dwarf2_read_abbrevs (abfd, offset) cur_abbrev->next = dwarf2_abbrevs[hash_number]; dwarf2_abbrevs[hash_number] = cur_abbrev; - /* get next abbrev */ + /* Get next abbreviation. + Under Irix6 the abbreviations for a compilation unit are not + always properly terminated with an abbrev number of 0. + Exit loop if we encounter an abbreviation which we have + already read (which means we are about to read the abbreviations + for the next compile unit) or if the end of the abbreviation + table is reached. */ + if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer) + >= dwarf_abbrev_size) + break; abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); abbrev_ptr += bytes_read; + if (dwarf2_lookup_abbrev (abbrev_number) != NULL) + break; } } /* Empty the abbrev table for a new compilation unit. */ +/* ARGSUSED */ static void -dwarf2_empty_abbrev_table () +dwarf2_empty_abbrev_table (ignore) + PTR ignore; { int i; struct abbrev_info *abbrev, *next; @@ -2133,16 +2489,12 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) int has_low_pc_attr = 0; int has_high_pc_attr = 0; + *part_die = zeroed_partial_die; *has_pc_info = 0; abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; if (!abbrev_number) - { - part_die->tag = 0; - part_die->has_children = 0; - part_die->abbrev = abbrev_number; - return info_ptr; - } + return info_ptr; abbrev = dwarf2_lookup_abbrev (abbrev_number); if (!abbrev) @@ -2152,7 +2504,6 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) part_die->offset = info_ptr - dwarf_info_buffer; part_die->tag = abbrev->tag; part_die->has_children = abbrev->has_children; - part_die->is_external = 0; part_die->abbrev = abbrev_number; { @@ -2185,7 +2536,7 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) case DW_FORM_block4: blk = dwarf_alloc_block (); blk->size = read_4_bytes (abfd, info_ptr); - info_ptr += 2; + info_ptr += 4; blk->data = read_n_bytes (abfd, info_ptr, blk->size); info_ptr += blk->size; break; @@ -2282,6 +2633,10 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) break; case DW_AT_external: part_die->is_external = unsnd; + break; + case DW_AT_declaration: + part_die->is_declaration = unsnd; + break; } } } @@ -2329,14 +2684,11 @@ read_full_die (diep, abfd, info_ptr) die->type = NULL; die->num_attrs = abbrev->num_attrs; - die->attrs = xmalloc (die->num_attrs * sizeof (struct attribute)); + die->attrs = (struct attribute *) + xmalloc (die->num_attrs * sizeof (struct attribute)); { - char *str; struct dwarf_block *blk; - unsigned long addr; - unsigned int unsnd; - int snd; for (i = 0; i < abbrev->num_attrs; ++i) { @@ -2363,7 +2715,7 @@ read_full_die (diep, abfd, info_ptr) case DW_FORM_block4: blk = dwarf_alloc_block (); blk->size = read_4_bytes (abfd, info_ptr); - info_ptr += 2; + info_ptr += 4; blk->data = read_n_bytes (abfd, info_ptr, blk->size); info_ptr += blk->size; die->attrs[i].u.blk = blk; @@ -2462,6 +2814,14 @@ read_1_byte (abfd, buf) return bfd_get_8 (abfd, (bfd_byte *) buf); } +static int +read_1_signed_byte (abfd, buf) + bfd *abfd; + char *buf; +{ + return bfd_get_signed_8 (abfd, (bfd_byte *) buf); +} + static unsigned int read_2_bytes (abfd, buf) bfd *abfd; @@ -2470,6 +2830,14 @@ read_2_bytes (abfd, buf) return bfd_get_16 (abfd, (bfd_byte *) buf); } +static int +read_2_signed_bytes (abfd, buf) + bfd *abfd; + char *buf; +{ + return bfd_get_signed_16 (abfd, (bfd_byte *) buf); +} + static unsigned int read_4_bytes (abfd, buf) bfd *abfd; @@ -2478,6 +2846,14 @@ read_4_bytes (abfd, buf) return bfd_get_32 (abfd, (bfd_byte *) buf); } +static int +read_4_signed_bytes (abfd, buf) + bfd *abfd; + char *buf; +{ + return bfd_get_signed_32 (abfd, (bfd_byte *) buf); +} + static unsigned int read_8_bytes (abfd, buf) bfd *abfd; @@ -2508,46 +2884,61 @@ read_n_bytes (abfd, buf, size) char *buf; unsigned int size; { + /* If the size of a host char is 8 bits, we can return a pointer + to the buffer, otherwise we have to copy the data to a buffer + allocated on the temporary obstack. */ +#if HOST_CHAR_BIT == 8 + return buf; +#else char *ret; unsigned int i; - ret = xmalloc (size); + ret = obstack_alloc (&dwarf2_tmp_obstack, size); for (i = 0; i < size; ++i) { ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf); buf++; } return ret; +#endif } -/* FIXME : hardwired string size limit */ - static char * read_string (abfd, buf, bytes_read_ptr) bfd *abfd; char *buf; unsigned int *bytes_read_ptr; { - char ret_buf[DWARF2_MAX_STRING_SIZE], *ret, byte; - unsigned int i; + /* If the size of a host char is 8 bits, we can return a pointer + to the string, otherwise we have to copy the string to a buffer + allocated on the temporary obstack. */ +#if HOST_CHAR_BIT == 8 + if (*buf == '\0') + { + *bytes_read_ptr = 1; + return NULL; + } + *bytes_read_ptr = strlen (buf) + 1; + return buf; +#else + int byte; + unsigned int i = 0; - i = 0; - do + while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0) { - byte = bfd_get_8 (abfd, (bfd_byte *) buf); + obstack_1grow (&dwarf2_tmp_obstack, byte); + i++; buf++; - ret_buf[i++] = byte; } - while (byte); - if (i == 1) + if (i == 0) { *bytes_read_ptr = 1; return NULL; } - ret = xmalloc (i); - strncpy (ret, ret_buf, i); - *bytes_read_ptr = i; - return ret; + obstack_1grow (&dwarf2_tmp_obstack, '\0'); + *bytes_read_ptr = i + 1; + return obstack_finish (&dwarf2_tmp_obstack); +#endif } static unsigned int @@ -2629,6 +3020,9 @@ set_cu_language (lang) case DW_LANG_C_plus_plus: cu_language = language_cplus; break; + case DW_LANG_Mips_Assembler: + cu_language = language_asm; + break; case DW_LANG_Ada83: case DW_LANG_Cobol74: case DW_LANG_Cobol85: @@ -2645,27 +3039,6 @@ set_cu_language (lang) cu_language_defn = language_def (cu_language); } -static void -record_minimal_symbol (name, address, ms_type, objfile) - char *name; - CORE_ADDR address; - enum minimal_symbol_type ms_type; - struct objfile *objfile; -{ - name = obsavestring (name, strlen (name), &objfile->symbol_obstack); - prim_record_minimal_symbol (name, address, ms_type, objfile); -} - -/* Converts a location description into gdb form. */ - -static int -convert_locdesc (blk) - struct dwarf_block *blk; -{ - /* FIXME : this is only a stub! */ - return 0; -} - /* Return the named attribute or NULL if not there. */ static struct attribute * @@ -2687,17 +3060,24 @@ dwarf_attr (die, name) spec = &die->attrs[i]; } if (spec) - return dwarf_attr (follow_die_ref (DW_UNSND (spec)), name); + { + struct die_info *ref_die = + follow_die_ref (dwarf2_get_ref_die_offset (spec)); + + if (ref_die) + return dwarf_attr (ref_die, name); + } return NULL; } /* Decode the line number information for the compilation unit whose - line number info is at OFFSET in the .debug_line section. */ + line number info is at OFFSET in the .debug_line section. + The compilation directory of the file is passed in COMP_DIR. */ struct filenames { - int num_files; + unsigned int num_files; struct fileinfo { char *name; @@ -2710,16 +3090,18 @@ struct filenames struct directories { - int num_dirs; + unsigned int num_dirs; char **dirs; }; static void -dwarf_decode_lines (offset, abfd) +dwarf_decode_lines (offset, comp_dir, abfd) unsigned int offset; + char *comp_dir; bfd *abfd; { char *line_ptr; + char *line_end; struct line_head lh; struct cleanup *back_to; unsigned int i, bytes_read; @@ -2732,15 +3114,11 @@ dwarf_decode_lines (offset, abfd) struct filenames files; struct directories dirs; - /* state machine registers */ - unsigned int address = 0; - unsigned int file = 1; - unsigned int line = 1; - unsigned int column = 0; - int is_stmt; /* initialized below */ - int basic_block = 0; - int beg_of_comp_unit = 0; /* is this right? */ - int end_sequence = 0; + if (dwarf_line_buffer == NULL) + { + complain (&dwarf2_missing_line_number_section); + return; + } files.num_files = 0; files.files = NULL; @@ -2753,6 +3131,7 @@ dwarf_decode_lines (offset, abfd) /* read in the prologue */ lh.total_length = read_4_bytes (abfd, line_ptr); line_ptr += 4; + line_end = line_ptr + lh.total_length; lh.version = read_2_bytes (abfd, line_ptr); line_ptr += 2; lh.prologue_length = read_4_bytes (abfd, line_ptr); @@ -2760,9 +3139,8 @@ dwarf_decode_lines (offset, abfd) lh.minimum_instruction_length = read_1_byte (abfd, line_ptr); line_ptr += 1; lh.default_is_stmt = read_1_byte (abfd, line_ptr); - is_stmt = lh.default_is_stmt; line_ptr += 1; - lh.line_base = read_1_byte (abfd, line_ptr); + lh.line_base = read_1_signed_byte (abfd, line_ptr); line_ptr += 1; lh.line_range = read_1_byte (abfd, line_ptr); line_ptr += 1; @@ -2770,7 +3148,7 @@ dwarf_decode_lines (offset, abfd) line_ptr += 1; lh.standard_opcode_lengths = (unsigned char *) xmalloc (lh.opcode_base * sizeof (unsigned char)); - back_to = make_cleanup (free, lh.standard_opcode_lengths); + back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths); lh.standard_opcode_lengths[0] = 1; for (i = 1; i < lh.opcode_base; ++i) @@ -2780,150 +3158,235 @@ dwarf_decode_lines (offset, abfd) } /* Read directory table */ - while (cur_dir = read_string (abfd, line_ptr, &bytes_read)) + while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL) { line_ptr += bytes_read; if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0) { - dirs.dirs = xrealloc (dirs.dirs, - (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *)); + dirs.dirs = (char **) + xrealloc (dirs.dirs, + (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *)); + if (dirs.num_dirs == 0) + make_cleanup (free_current_contents, &dirs.dirs); } dirs.dirs[dirs.num_dirs++] = cur_dir; } line_ptr += bytes_read; /* Read file name table */ - while (cur_file = read_string (abfd, line_ptr, &bytes_read)) + while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL) { line_ptr += bytes_read; if ((files.num_files % FILE_ALLOC_CHUNK) == 0) { - files.files = xrealloc (files.files, - (files.num_files + FILE_ALLOC_CHUNK) * sizeof (struct fileinfo)); + files.files = (struct fileinfo *) + xrealloc (files.files, + (files.num_files + FILE_ALLOC_CHUNK) + * sizeof (struct fileinfo)); + if (files.num_files == 0) + make_cleanup (free_current_contents, &files.files); } files.files[files.num_files].name = cur_file; - files.files[files.num_files].dir = read_unsigned_leb128 (abfd, - line_ptr, &bytes_read); + files.files[files.num_files].dir = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - files.files[files.num_files].time = read_unsigned_leb128 (abfd, - line_ptr, &bytes_read); + files.files[files.num_files].time = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - files.files[files.num_files].size = read_unsigned_leb128 (abfd, - line_ptr, &bytes_read); + files.files[files.num_files].size = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; files.num_files++; } line_ptr += bytes_read; - /* Decode the table. */ - if (lh.total_length - (lh.prologue_length + 4 + 2) >= 4) - do - { - op_code = read_1_byte (abfd, line_ptr); - line_ptr += 1; - switch (op_code) - { - case DW_LNS_extended_op: - line_ptr += 1; /* ignore length */ - extended_op = read_1_byte (abfd, line_ptr); - line_ptr += 1; - switch (extended_op) - { - case DW_LNE_end_sequence: - end_sequence = 1; - record_line (current_subfile, line, address); - return; /* return! */ - break; - case DW_LNE_set_address: - address = read_address (abfd, line_ptr); - line_ptr += address_size; - break; - case DW_LNE_define_file: - cur_file = read_string (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - if ((files.num_files % FILE_ALLOC_CHUNK) == 0) - { - files.files = xrealloc (files.files, - (files.num_files + FILE_ALLOC_CHUNK) - * sizeof (struct fileinfo)); - } - files.files[files.num_files].name = cur_file; - files.files[files.num_files].dir = read_unsigned_leb128 ( - abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - files.files[files.num_files].time = read_unsigned_leb128 (abfd, - line_ptr, &bytes_read); - line_ptr += bytes_read; - files.files[files.num_files].size = read_unsigned_leb128 (abfd, - line_ptr, &bytes_read); - line_ptr += bytes_read; - break; - default: - error ("Dwarf Error: Mangled .debug_line section."); - return; - } - break; - case DW_LNS_copy: - record_line (current_subfile, line, address); - basic_block = 0; - break; - case DW_LNS_advance_pc: - address += lh.minimum_instruction_length - * read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - break; - case DW_LNS_advance_line: - line += read_signed_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - break; - case DW_LNS_set_file: - /* The file table is 0 based and the references are 1 - based, thus the subtraction of `1' at the end of the - next line */ - file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read) - 1; - start_subfile (files.files[file].name, - (files.files[file].dir ? - dirs.dirs[files.files[file].dir] : 0)); - line_ptr += bytes_read; - break; - case DW_LNS_set_column: - column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - break; - case DW_LNS_negate_stmt: - is_stmt = (!is_stmt); - break; - case DW_LNS_set_basic_block: - basic_block = 1; - break; - case DW_LNS_const_add_pc: - address += (255 - lh.opcode_base) / lh.line_range; - break; - case DW_LNS_fixed_advance_pc: - address += read_2_bytes (abfd, line_ptr); - line_ptr += 2; - break; - default: /* special operand */ - adj_opcode = op_code - lh.opcode_base; - address += (adj_opcode / lh.line_range) - * lh.minimum_instruction_length; - line += lh.line_base + (adj_opcode % lh.line_range); - /* append row to matrix using current values */ - record_line (current_subfile, line, address); - basic_block = 1; - } - } - while (1); + /* Read the statement sequences until there's nothing left. */ + while (line_ptr < line_end) + { + /* state machine registers */ + unsigned int address = 0; + unsigned int file = 1; + unsigned int line = 1; + unsigned int column = 0; + int is_stmt = lh.default_is_stmt; + int basic_block = 0; + int end_sequence = 0; + + /* Start a subfile for the current file of the state machine. */ + if (files.num_files >= file) + { + /* The file and directory tables are 0 based, the references + are 1 based. */ + dwarf2_start_subfile (files.files[file - 1].name, + (files.files[file - 1].dir + ? dirs.dirs[files.files[file - 1].dir - 1] + : comp_dir)); + } + + /* Decode the table. */ + while (! end_sequence) + { + op_code = read_1_byte (abfd, line_ptr); + line_ptr += 1; + switch (op_code) + { + case DW_LNS_extended_op: + line_ptr += 1; /* ignore length */ + extended_op = read_1_byte (abfd, line_ptr); + line_ptr += 1; + switch (extended_op) + { + case DW_LNE_end_sequence: + end_sequence = 1; + record_line (current_subfile, line, address); + break; + case DW_LNE_set_address: + address = read_address (abfd, line_ptr) + baseaddr; + line_ptr += address_size; + break; + case DW_LNE_define_file: + cur_file = read_string (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + if ((files.num_files % FILE_ALLOC_CHUNK) == 0) + { + files.files = (struct fileinfo *) + xrealloc (files.files, + (files.num_files + FILE_ALLOC_CHUNK) + * sizeof (struct fileinfo)); + if (files.num_files == 0) + make_cleanup (free_current_contents, &files.files); + } + files.files[files.num_files].name = cur_file; + files.files[files.num_files].dir = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + files.files[files.num_files].time = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + files.files[files.num_files].size = + read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + files.num_files++; + break; + default: + complain (&dwarf2_mangled_line_number_section); + goto done; + } + break; + case DW_LNS_copy: + record_line (current_subfile, line, address); + basic_block = 0; + break; + case DW_LNS_advance_pc: + address += lh.minimum_instruction_length + * read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_advance_line: + line += read_signed_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_set_file: + /* The file and directory tables are 0 based, the references + are 1 based. */ + file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + dwarf2_start_subfile + (files.files[file - 1].name, + (files.files[file - 1].dir + ? dirs.dirs[files.files[file - 1].dir - 1] + : comp_dir)); + break; + case DW_LNS_set_column: + column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + break; + case DW_LNS_negate_stmt: + is_stmt = (!is_stmt); + break; + case DW_LNS_set_basic_block: + basic_block = 1; + break; + case DW_LNS_const_add_pc: + address += (255 - lh.opcode_base) / lh.line_range; + break; + case DW_LNS_fixed_advance_pc: + address += read_2_bytes (abfd, line_ptr); + line_ptr += 2; + break; + default: /* special operand */ + adj_opcode = op_code - lh.opcode_base; + address += (adj_opcode / lh.line_range) + * lh.minimum_instruction_length; + line += lh.line_base + (adj_opcode % lh.line_range); + /* append row to matrix using current values */ + record_line (current_subfile, line, address); + basic_block = 1; + } + } + } +done: do_cleanups (back_to); } +/* Start a subfile for DWARF. FILENAME is the name of the file and + DIRNAME the name of the source directory which contains FILENAME + or NULL if not known. + This routine tries to keep line numbers from identical absolute and + relative file names in a common subfile. + + Using the `list' example from the GDB testsuite, which resides in + /srcdir and compiling it with Irix6.2 cc in /compdir using a filename + of /srcdir/list0.c yields the following debugging information for list0.c: + + DW_AT_name: /srcdir/list0.c + DW_AT_comp_dir: /compdir + files.files[0].name: list0.h + files.files[0].dir: /srcdir + files.files[1].name: list0.c + files.files[1].dir: /srcdir + + The line number information for list0.c has to end up in a single + subfile, so that `break /srcdir/list0.c:1' works as expected. */ + +static void +dwarf2_start_subfile (filename, dirname) + char *filename; + char *dirname; +{ + /* If the filename isn't absolute, try to match an existing subfile + with the full pathname. */ + + if (*filename != '/' && dirname != NULL) + { + struct subfile *subfile; + char *fullname = concat (dirname, "/", filename, NULL); + + for (subfile = subfiles; subfile; subfile = subfile->next) + { + if (STREQ (subfile->name, fullname)) + { + current_subfile = subfile; + free (fullname); + return; + } + } + free (fullname); + } + start_subfile (filename, dirname); +} + /* Given a pointer to a DWARF information entry, figure out if we need to make a symbol table entry for it, and if so, create a new entry - and return a pointer to it. */ + and return a pointer to it. + If TYPE is NULL, determine symbol type from the die, otherwise + used the passed type. + */ static struct symbol * -new_symbol (die, objfile) +new_symbol (die, type, objfile) struct die_info *die; + struct type *type; struct objfile *objfile; { struct symbol *sym = NULL; @@ -2934,21 +3397,27 @@ new_symbol (die, objfile) attr = dwarf_attr (die, DW_AT_name); if (attr) { -#if 0 sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); -#endif - sym = (struct symbol *) xmalloc (sizeof (struct symbol)); + OBJSTAT (objfile, n_syms++); memset (sym, 0, sizeof (struct symbol)); -#if 0 - SYMBOL_NAME (sym) = create_name (DW_STRING (attr), - &objfile->symbol_obstack); -#endif - SYMBOL_NAME (sym) = strdup (DW_STRING (attr)); - /* default assumptions */ + SYMBOL_NAME (sym) = obsavestring (DW_STRING (attr), + strlen (DW_STRING (attr)), + &objfile->symbol_obstack); + + /* Default assumptions. + Use the passed type or decode it from the die. */ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_TYPE (sym) = die_type (die, objfile); + if (type != NULL) + SYMBOL_TYPE (sym) = type; + else + SYMBOL_TYPE (sym) = die_type (die, objfile); + attr = dwarf_attr (die, DW_AT_decl_line); + if (attr) + { + SYMBOL_LINE (sym) = DW_UNSND (attr); + } /* If this symbol is from a C++ compilation, then attempt to cache the demangled form for future reference. This is a @@ -2974,8 +3443,6 @@ new_symbol (die, objfile) { SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr); } - SYMBOL_TYPE (sym) = make_function_type (die_type (die, objfile), - NULL); SYMBOL_CLASS (sym) = LOC_BLOCK; attr2 = dwarf_attr (die, DW_AT_external); if (attr2 && (DW_UNSND (attr2) != 0)) @@ -2988,6 +3455,14 @@ new_symbol (die, objfile) } break; case DW_TAG_variable: + /* Compilation with minimal debug info may result in variables + with missing type entries. Change the misleading `void' type + to something sensible. */ + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID) + SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / HOST_CHAR_BIT, 0, + "", + objfile); attr = dwarf_attr (die, DW_AT_location); if (attr) { @@ -3005,11 +3480,20 @@ new_symbol (die, objfile) SYMBOL_VALUE (sym) = addr = decode_locdesc (DW_BLOCK (attr), objfile); add_symbol_to_list (sym, list_in_scope); - if (isreg) + if (optimized_out) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + else if (isreg) { SYMBOL_CLASS (sym) = LOC_REGISTER; } else if (offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG; + SYMBOL_BASEREG (sym) = basereg; + } + else if (islocal) { SYMBOL_CLASS (sym) = LOC_LOCAL; } @@ -3020,6 +3504,22 @@ new_symbol (die, objfile) } } } + else + { + /* We do not know the address of this symbol. + If it is an external symbol and we have type information + it, enter the symbol as a LOC_UNRESOLVED symbol. + The address of the variable will then be determined from + the minimal symbol table whenever the variable is + referenced. */ + attr2 = dwarf_attr (die, DW_AT_external); + if (attr2 && (DW_UNSND (attr2) != 0) + && dwarf_attr (die, DW_AT_type) != NULL) + { + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; + add_symbol_to_list (sym, &global_symbols); + } + } break; case DW_TAG_formal_parameter: attr = dwarf_attr (die, DW_AT_location); @@ -3032,6 +3532,11 @@ new_symbol (die, objfile) { SYMBOL_CLASS (sym) = LOC_REGPARM; } + else if (offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG_ARG; + SYMBOL_BASEREG (sym) = basereg; + } else { SYMBOL_CLASS (sym) = LOC_ARG; @@ -3049,17 +3554,45 @@ new_symbol (die, objfile) SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; add_symbol_to_list (sym, list_in_scope); + + /* The semantics of C++ state that "struct foo { ... }" also + defines a typedef for "foo". Synthesize a typedef symbol so + that "ptype foo" works as expected. */ + if (cu_language == language_cplus) + { + struct symbol *typedef_sym = (struct symbol *) + obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + *typedef_sym = *sym; + SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE; + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) = + obsavestring (SYMBOL_NAME (sym), + strlen (SYMBOL_NAME (sym)), + &objfile->type_obstack); + add_symbol_to_list (typedef_sym, list_in_scope); + } break; case DW_TAG_typedef: SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; add_symbol_to_list (sym, list_in_scope); break; + case DW_TAG_enumerator: + SYMBOL_CLASS (sym) = LOC_CONST; + attr = dwarf_attr (die, DW_AT_const_value); + if (attr) + { + SYMBOL_VALUE (sym) = DW_UNSND (attr); + } + add_symbol_to_list (sym, list_in_scope); + break; default: /* Not a tag we recognize. Hopefully we aren't processing trash data, but since we must specifically ignore things we don't recognize, there is nothing else we should do at this point. */ + complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag)); break; } } @@ -3074,19 +3607,19 @@ die_type (die, objfile) struct objfile *objfile; { struct type *type; - struct attribute *attr, *type_attr; + struct attribute *type_attr; struct die_info *type_die; - unsigned int size = 0, encoding = 0, ref; + unsigned int ref; type_attr = dwarf_attr (die, DW_AT_type); if (!type_attr) { - type = dwarf_base_type (0, 0); - return type; + /* A missing DW_AT_type represents a void type. */ + return dwarf2_fundamental_type (objfile, FT_VOID); } else { - ref = DW_UNSND (type_attr); + ref = dwarf2_get_ref_die_offset (type_attr); type_die = follow_die_ref (ref); if (!type_die) { @@ -3097,12 +3630,47 @@ die_type (die, objfile) type = tag_type_to_type (type_die, objfile); if (!type) { - error ("Dwarf Error: Problem turning type die at offset into gdb type:"); dump_die (type_die); + error ("Dwarf Error: Problem turning type die at offset into gdb type."); + } + return type; +} + +/* Return the containing type of the die in question using its + DW_AT_containing_type attribute. */ + +static struct type * +die_containing_type (die, objfile) + struct die_info *die; + struct objfile *objfile; +{ + struct type *type = NULL; + struct attribute *type_attr; + struct die_info *type_die = NULL; + unsigned int ref; + + type_attr = dwarf_attr (die, DW_AT_containing_type); + if (type_attr) + { + ref = dwarf2_get_ref_die_offset (type_attr); + type_die = follow_die_ref (ref); + if (!type_die) + { + error ("Dwarf Error: Cannot find referent at offset %d.", ref); + return NULL; + } + type = tag_type_to_type (type_die, objfile); + } + if (!type) + { + if (type_die) + dump_die (type_die); + error ("Dwarf Error: Problem turning containing type into gdb type."); } return type; } +#if 0 static struct type * type_at_offset (offset, objfile) unsigned int offset; @@ -3120,6 +3688,7 @@ type_at_offset (offset, objfile) type = tag_type_to_type (die, objfile); return type; } +#endif static struct type * tag_type_to_type (die, objfile) @@ -3136,7 +3705,7 @@ tag_type_to_type (die, objfile) if (!die->type) { dump_die (die); - error ("Dwarf Error: Cannot find type of die:"); + error ("Dwarf Error: Cannot find type of die."); } return die->type; } @@ -3157,6 +3726,7 @@ read_type_die (die, objfile) case DW_TAG_enumeration_type: read_enumeration (die, objfile); break; + case DW_TAG_subprogram: case DW_TAG_subroutine_type: read_subroutine_type (die, objfile); break; @@ -3166,6 +3736,9 @@ read_type_die (die, objfile) case DW_TAG_pointer_type: read_tag_pointer_type (die, objfile); break; + case DW_TAG_ptr_to_member_type: + read_tag_ptr_to_member_type (die, objfile); + break; case DW_TAG_reference_type: read_tag_reference_type (die, objfile); break; @@ -3186,7 +3759,6 @@ read_type_die (die, objfile) break; case DW_TAG_padding: case DW_TAG_compile_unit: - case DW_TAG_subprogram: case DW_TAG_lexical_block: default: break; @@ -3254,7 +3826,7 @@ dwarf_base_type (encoding, size) type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_CHAR); break; case 2: - type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_SHORT); + type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_SHORT); break; default: case 4: @@ -3271,23 +3843,7 @@ dwarf_base_type (encoding, size) } } -/* Given a pointer to a string and a pointer to an obstack, allocates - a fresh copy of the string on the specified obstack. */ - -static char * -create_name (name, obstackp) - char *name; - struct obstack *obstackp; -{ - int length; - char *newname; - - length = strlen (name) + 1; - newname = (char *) obstack_alloc (obstackp, length); - strcpy (newname, name); - return (newname); -} - +#if 0 struct die_info * copy_die (old_die) struct die_info *old_die; @@ -3319,6 +3875,7 @@ copy_die (old_die) new_die->next = NULL; return new_die; } +#endif /* Return sibling of die, NULL if no sibling. */ @@ -3326,7 +3883,6 @@ struct die_info * sibling_die (die) struct die_info *die; { - struct die_info *new; int nesting_level = 0; if (!die->has_children) @@ -4049,6 +4605,7 @@ dwarf_type_encoding_name (enc) /* Convert a DWARF call frame info operation to its string name. */ +#if 0 static char * dwarf_cfi_name (cfi_opc) register unsigned cfi_opc; @@ -4098,12 +4655,13 @@ dwarf_cfi_name (cfi_opc) return "DW_CFA_"; } } +#endif void dump_die (die) struct die_info *die; { - int i; + unsigned int i; fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n", dwarf_tag_name (die->tag), die->abbrev, die->offset); @@ -4120,9 +4678,8 @@ dump_die (die) { case DW_FORM_ref_addr: case DW_FORM_addr: - fprintf (stderr, sizeof (CORE_ADDR) > sizeof (long) ? - "address: 0x%LLx" : "address: 0x%x", - die->attrs[i].u.addr); + fprintf (stderr, "address: "); + print_address_numeric (die->attrs[i].u.addr, 1, stderr); break; case DW_FORM_block2: case DW_FORM_block4: @@ -4154,8 +4711,9 @@ dump_die (die) section yet */ case DW_FORM_indirect: /* we do not handle indirect yet */ case DW_FORM_data8: /* we do not have 64 bit quantities */ - error ("Dwarf Error: Unsupported attribute form: %d.", - die->attrs[i].form); + default: + fprintf (stderr, "unsupported attribute form: %d.", + die->attrs[i].form); } fprintf (stderr, "\n"); } @@ -4186,6 +4744,36 @@ store_in_ref_table (offset, die) die_ref_table[h] = die; } + +static void +dwarf2_empty_die_ref_table () +{ + memset (die_ref_table, 0, sizeof (die_ref_table)); +} + +static unsigned int +dwarf2_get_ref_die_offset (attr) + struct attribute *attr; +{ + unsigned int result = 0; + + switch (attr->form) + { + case DW_FORM_ref_addr: + result = DW_ADDR (attr); + break; + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref_udata: + result = cu_header_offset + DW_UNSND (attr); + break; + default: + complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form)); + } + return result; +} + struct die_info * follow_die_ref (offset) unsigned int offset; @@ -4230,135 +4818,95 @@ dwarf2_fundamental_type (objfile, typeid) } /* Decode simple location descriptions. - There are three cases: - An address: return the address. - An address relative to frame pointer: return the offset. - A register: return register number and set isreg to true. - A constant followed by plus: return the constant. */ + Given a pointer to a dwarf block that defines a location, compute + the location and return the value. + + FIXME: This is a kludge until we figure out a better + way to handle the location descriptions. + Gdb's design does not mesh well with the DWARF2 notion of a location + computing interpreter, which is a shame because the flexibility goes unused. + FIXME: Implement more operations as necessary. + + A location description containing no operations indicates that the + object is optimized out. The global optimized_out flag is set for + those, the return value is meaningless. + + When the result is a register number, the global isreg flag is set, + otherwise it is cleared. + + When the result is a base register offset, the global offreg flag is set + and the register number is returned in basereg, otherwise it is cleared. + + When the DW_OP_fbreg operation is encountered without a corresponding + DW_AT_frame_base attribute, the global islocal flag is set. + Hopefully the machine dependent code knows how to set up a virtual + frame pointer for the local references. + + Note that stack[0] is unused except as a default error return. + Note that stack overflow is not yet handled. */ static CORE_ADDR decode_locdesc (blk, objfile) struct dwarf_block *blk; struct objfile *objfile; { - int i, snd; + int i; int size = blk->size; char *data = blk->data; + CORE_ADDR stack[64]; + int stacki; unsigned int bytes_read, unsnd; unsigned char op; - union - { - CORE_ADDR addr; - char bytes[sizeof (CORE_ADDR)]; - } - u; i = 0; + stacki = 0; + stack[stacki] = 0; isreg = 0; offreg = 0; + islocal = 0; + optimized_out = 1; - /* FIXME: handle more general forms of location descriptors. */ while (i < size) { + optimized_out = 0; op = data[i++]; switch (op) { case DW_OP_reg0: - isreg = 1; - return 0; case DW_OP_reg1: - isreg = 1; - return 1; case DW_OP_reg2: - isreg = 1; - return 2; case DW_OP_reg3: - isreg = 1; - return 3; case DW_OP_reg4: - isreg = 1; - return 4; case DW_OP_reg5: - isreg = 1; - return 5; case DW_OP_reg6: - isreg = 1; - return 6; case DW_OP_reg7: - isreg = 1; - return 7; case DW_OP_reg8: - isreg = 1; - return 8; case DW_OP_reg9: - isreg = 1; - return 9; case DW_OP_reg10: - isreg = 1; - return 10; case DW_OP_reg11: - isreg = 1; - return 11; case DW_OP_reg12: - isreg = 1; - return 12; case DW_OP_reg13: - isreg = 1; - return 13; case DW_OP_reg14: - isreg = 1; - return 14; case DW_OP_reg15: - isreg = 1; - return 15; case DW_OP_reg16: - isreg = 1; - return 16; case DW_OP_reg17: - isreg = 1; - return 17; case DW_OP_reg18: - isreg = 1; - return 18; case DW_OP_reg19: - isreg = 1; - return 19; case DW_OP_reg20: - isreg = 1; - return 20; case DW_OP_reg21: - isreg = 1; - return 21; case DW_OP_reg22: - isreg = 1; - return 22; case DW_OP_reg23: - isreg = 1; - return 23; case DW_OP_reg24: - isreg = 1; - return 24; case DW_OP_reg25: - isreg = 1; - return 25; case DW_OP_reg26: - isreg = 1; - return 26; case DW_OP_reg27: - isreg = 1; - return 27; case DW_OP_reg28: - isreg = 1; - return 28; case DW_OP_reg29: - isreg = 1; - return 29; case DW_OP_reg30: - isreg = 1; - return 30; case DW_OP_reg31: isreg = 1; - return 31; + stack[++stacki] = op - DW_OP_reg0; + break; case DW_OP_regx: isreg = 1; @@ -4368,51 +4916,147 @@ decode_locdesc (blk, objfile) /* The Harris 88110 gdb ports have long kept their special reg numbers between their gp-regs and their x-regs. This is not how our dwarf is generated. Punt. */ - return unsnd + 6; -#else - return unsnd; + unsnd += 6; #endif + stack[++stacki] = unsnd; + break; - case DW_OP_fbreg: + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: case DW_OP_breg31: offreg = 1; - snd = read_signed_leb128 (NULL, (data + i), &bytes_read); + basereg = op - DW_OP_breg0; + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); + i += bytes_read; + break; + + case DW_OP_fbreg: + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); i += bytes_read; - return snd; + if (frame_base_reg >= 0) + { + offreg = 1; + basereg = frame_base_reg; + stack[stacki] += frame_base_offset; + } + else + { + complain (&dwarf2_missing_at_frame_base); + islocal = 1; + } + break; case DW_OP_addr: - isreg = 0; - return read_address (objfile->obfd, &data[i]); + stack[++stacki] = read_address (objfile->obfd, &data[i]); + i += address_size; + break; + + case DW_OP_const1u: + stack[++stacki] = read_1_byte (objfile->obfd, &data[i]); + i += 1; + break; + + case DW_OP_const1s: + stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]); + i += 1; + break; + + case DW_OP_const2u: + stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]); + i += 2; + break; + + case DW_OP_const2s: + stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]); + i += 2; + break; + + case DW_OP_const4u: + stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]); + i += 4; + break; + + case DW_OP_const4s: + stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]); + i += 4; + break; case DW_OP_constu: - unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read); + stack[++stacki] = read_unsigned_leb128 (NULL, (data + i), + &bytes_read); + i += bytes_read; + break; + + case DW_OP_consts: + stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read); i += bytes_read; break; case DW_OP_plus: - return unsnd; + stack[stacki - 1] += stack[stacki]; + stacki--; + break; + + case DW_OP_minus: + stack[stacki - 1] = stack[stacki] - stack[stacki - 1]; + stacki--; + break; + default: + complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name(op)); + return (stack[stacki]); } } - return 0; + return (stack[stacki]); } /* memory allocation interface */ -static struct type * -dwarf_alloc_type (objfile) - struct objfile *objfile; +/* ARGSUSED */ +static void +dwarf2_free_tmp_obstack (ignore) + PTR ignore; { - struct type *type; - - type = (struct type *) xmalloc (sizeof (struct type)); - memset (type, 0, sizeof (struct type)); + obstack_free (&dwarf2_tmp_obstack, NULL); +} -#if 0 - type = alloc_type (objfile); -#endif +static struct dwarf_block * +dwarf_alloc_block () +{ + struct dwarf_block *blk; - return (type); + blk = (struct dwarf_block *) + obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block)); + return (blk); } static struct abbrev_info * @@ -4420,20 +5064,11 @@ dwarf_alloc_abbrev () { struct abbrev_info *abbrev; - abbrev = xmalloc (sizeof (struct abbrev_info)); + abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info)); memset (abbrev, 0, sizeof (struct abbrev_info)); return (abbrev); } -static struct dwarf_block * -dwarf_alloc_block () -{ - struct dwarf_block *blk; - - blk = (struct dwarf_block *) xmalloc (sizeof (struct dwarf_block)); - return (blk); -} - static struct die_info * dwarf_alloc_die () { diff --git a/gdb/elfread.c b/gdb/elfread.c index 107bdafa37e..524df4a2d72 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -389,6 +389,15 @@ elf_symtab_read (abfd, addr, objfile, dynamic) default: ms_type = mst_abs; } + + /* If it is an Irix dynamic symbol, skip section name + symbols, relocate all others. */ + if (ms_type != mst_abs) + { + if (sym->name[0] == '.') + continue; + symaddr += addr; + } } else if (sym -> section -> flags & SEC_CODE) { @@ -603,7 +612,7 @@ elf_symfile_read (objfile, section_offsets, mainline) special ELF sections. We first have to find them... */ bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei); - if (dwarf2_has_info (abfd) && !offset) + if (dwarf2_has_info (abfd)) { /* DWARF 2 sections */ dwarf2_build_psymtabs (objfile, section_offsets, mainline); diff --git a/gdb/irix5-nat.c b/gdb/irix5-nat.c index 7bba96da8b8..992c46d72cb 100644 --- a/gdb/irix5-nat.c +++ b/gdb/irix5-nat.c @@ -169,17 +169,53 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) int which; /* Unused */ CORE_ADDR reg_addr; /* Unused */ { - if (core_reg_size != REGISTER_BYTES) + if (core_reg_size == REGISTER_BYTES) + { + memcpy ((char *)registers, core_reg_sect, core_reg_size); + } + else if (core_reg_size == (2 * REGISTER_BYTES) && MIPS_REGSIZE == 4) + { + /* This is a core file from a N32 executable, 64 bits are saved + for all registers. */ + char *srcp = core_reg_sect; + char *dstp = registers; + int regno; + + for (regno = 0; regno < NUM_REGS; regno++) + { + if (regno >= FP0_REGNUM && regno < (FP0_REGNUM + 32)) + { + /* FIXME, this is wrong, N32 has 64 bit FP regs, but GDB + currently assumes that they are 32 bit. */ + *dstp++ = *srcp++; + *dstp++ = *srcp++; + *dstp++ = *srcp++; + *dstp++ = *srcp++; + srcp += 4; + } + else + { + srcp += 4; + *dstp++ = *srcp++; + *dstp++ = *srcp++; + *dstp++ = *srcp++; + *dstp++ = *srcp++; + } + } + } + else { warning ("wrong size gregset struct in core file"); return; } - memcpy ((char *)registers, core_reg_sect, core_reg_size); + registers_fetched (); } /* Irix 5 uses what appears to be a unique form of shared library support. This is a copy of solib.c modified for Irix 5. */ +/* FIXME: Most of this code could be merged with osfsolib.c and solib.c + by using next_link_map_member and xfer_link_map_member in solib.c. */ #include #include @@ -192,6 +228,13 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) #define __SYM_H__ #define __SYMCONST_H__ #include +#ifdef HAVE_OBJLIST_H +#include +#endif + +#ifdef NEW_OBJ_INFO_MAGIC +#define HANDLE_NEW_OBJ_LIST +#endif #include "symtab.h" #include "bfd.h" @@ -207,16 +250,43 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) /* The symbol which starts off the list of shared libraries. */ #define DEBUG_BASE "__rld_obj_head" -/* How to get the loaded address of a shared library. */ -#define LM_ADDR(so) ((so)->lm.o_praw) +/* Irix 6.x introduces a new variant of object lists. + To be able to debug O32 executables under Irix 6, we have to handle both + variants. */ + +typedef enum +{ + OBJ_LIST_OLD, /* Pre Irix 6.x object list. */ + OBJ_LIST_32, /* 32 Bit Elf32_Obj_Info. */ + OBJ_LIST_64 /* 64 Bit Elf64_Obj_Info, FIXME not yet implemented. */ +} obj_list_variant; + +/* Define our own link_map structure. + This will help to share code with osfsolib.c and solib.c. */ + +struct link_map { + obj_list_variant l_variant; /* which variant of object list */ + CORE_ADDR l_lladdr; /* addr in inferior list was read from */ + CORE_ADDR l_next; /* address of next object list entry */ +}; + +/* Irix 5 shared objects are pre-linked to particular addresses + although the dynamic linker may have to relocate them if the + address ranges of the libraries used by the main program clash. + The offset is the difference between the address where the object + is mapped and the binding address of the shared library. */ +#define LM_OFFSET(so) ((so) -> offset) +/* Loaded address of shared library. */ +#define LM_ADDR(so) ((so) -> lmstart) char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */ struct so_list { struct so_list *next; /* next structure in linked list */ - struct obj_list ll; - struct obj lm; /* copy of link map from inferior */ - struct obj_list *lladdr; /* addr in inferior lm was read from */ + struct link_map lm; + CORE_ADDR offset; /* prelink to load address offset */ + char *so_name; /* shared object lib name */ + CORE_ADDR lmstart; /* lower addr bound of mapped object */ CORE_ADDR lmend; /* upper addr bound of mapped object */ char symbols_loaded; /* flag: symbols read in yet? */ char from_tty; /* flag: print msgs? */ @@ -251,9 +321,15 @@ symbol_add_stub PARAMS ((char *)); static struct so_list * find_solib PARAMS ((struct so_list *)); -static struct obj_list * +static struct link_map * first_link_map_member PARAMS ((void)); +static struct link_map * +next_link_map_member PARAMS ((struct so_list *)); + +static void +xfer_link_map_member PARAMS ((struct so_list *, struct link_map *)); + static CORE_ADDR locate_base PARAMS ((void)); @@ -297,9 +373,8 @@ solib_map_sections (so) struct section_table *p; struct cleanup *old_chain; bfd *abfd; - CORE_ADDR offset; - filename = tilde_expand (so -> lm.o_path); + filename = tilde_expand (so -> so_name); old_chain = make_cleanup (free, filename); scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, @@ -337,20 +412,13 @@ solib_map_sections (so) bfd_get_filename (exec_bfd), bfd_errmsg (bfd_get_error ())); } - /* Irix 5 shared objects are pre-linked to particular addresses - although the dynamic linker may have to relocate them if the - address ranges of the libraries used by the main program clash. - The offset is the difference between the address where the object - is mapped and the binding address of the shared library. */ - offset = (CORE_ADDR) LM_ADDR (so) - so -> lm.o_base_address; - for (p = so -> sections; p < so -> sections_end; p++) { /* Relocate the section binding addresses as recorded in the shared object's file by the offset to get the address to which the object was actually mapped. */ - p -> addr += offset; - p -> endaddr += offset; + p -> addr += LM_OFFSET (so); + p -> endaddr += LM_OFFSET (so); so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend); if (STREQ (p -> the_bfd_section -> name, ".text")) { @@ -437,27 +505,196 @@ DESCRIPTION Read in a copy of the first member in the inferior's dynamic link map from the inferior's dynamic linker structures, and return - a pointer to the copy in our address space. + a pointer to the link map descriptor. */ -static struct obj_list * +static struct link_map * first_link_map_member () { - struct obj_list *lm; - struct obj_list s; + struct obj_list *listp; + struct obj_list list_old; + struct link_map *lm; + static struct link_map first_lm; + CORE_ADDR lladdr; + CORE_ADDR next_lladdr; + + /* We have not already read in the dynamic linking structures + from the inferior, lookup the address of the base structure. */ + debug_base = locate_base (); + if (debug_base == 0) + return NULL; - read_memory (debug_base, (char *) &lm, sizeof (struct obj_list *)); + /* Get address of first list entry. */ + read_memory (debug_base, (char *) &listp, sizeof (struct obj_list *)); - if (lm == NULL) + if (listp == NULL) return NULL; + /* Get first list entry. */ + lladdr = (CORE_ADDR) listp; + read_memory (lladdr, (char *) &list_old, sizeof (struct obj_list)); + /* The first entry in the list is the object file we are debugging, so skip it. */ - read_memory ((CORE_ADDR) lm, (char *) &s, sizeof (struct obj_list)); + next_lladdr = (CORE_ADDR) list_old.next; + +#ifdef HANDLE_NEW_OBJ_LIST + if (list_old.data == NEW_OBJ_INFO_MAGIC) + { + Elf32_Obj_Info list_32; + + read_memory (lladdr, (char *) &list_32, sizeof (Elf32_Obj_Info)); + if (list_32.oi_size != sizeof (Elf32_Obj_Info)) + return NULL; + next_lladdr = (CORE_ADDR) list_32.oi_next; + } +#endif + + if (next_lladdr == 0) + return NULL; + + first_lm.l_lladdr = next_lladdr; + lm = &first_lm; + return lm; +} + +/* + +LOCAL FUNCTION + + next_link_map_member -- locate next member in dynamic linker's map + +SYNOPSIS + + static struct link_map *next_link_map_member (so_list_ptr) + +DESCRIPTION + + Read in a copy of the next member in the inferior's dynamic + link map from the inferior's dynamic linker structures, and return + a pointer to the link map descriptor. +*/ + +static struct link_map * +next_link_map_member (so_list_ptr) + struct so_list *so_list_ptr; +{ + struct link_map *lm = &so_list_ptr -> lm; + CORE_ADDR next_lladdr = lm -> l_next; + static struct link_map next_lm; + + if (next_lladdr == 0) + { + /* We have hit the end of the list, so check to see if any were + added, but be quiet if we can't read from the target any more. */ + int status = 0; + + if (lm -> l_variant == OBJ_LIST_OLD) + { + struct obj_list list_old; + + status = target_read_memory (lm -> l_lladdr, + (char *) &list_old, + sizeof (struct obj_list)); + next_lladdr = (CORE_ADDR) list_old.next; + } +#ifdef HANDLE_NEW_OBJ_LIST + else if (lm -> l_variant == OBJ_LIST_32) + { + Elf32_Obj_Info list_32; + status = target_read_memory (lm -> l_lladdr, + (char *) &list_32, + sizeof (Elf32_Obj_Info)); + next_lladdr = (CORE_ADDR) list_32.oi_next; + } +#endif + + if (status != 0 || next_lladdr == 0) + return NULL; + } - return s.next; + next_lm.l_lladdr = next_lladdr; + lm = &next_lm; + return lm; } +/* + +LOCAL FUNCTION + + xfer_link_map_member -- set local variables from dynamic linker's map + +SYNOPSIS + + static void xfer_link_map_member (so_list_ptr, lm) + +DESCRIPTION + + Read in a copy of the requested member in the inferior's dynamic + link map from the inferior's dynamic linker structures, and fill + in the necessary so_list_ptr elements. +*/ + +static void +xfer_link_map_member (so_list_ptr, lm) + struct so_list *so_list_ptr; + struct link_map *lm; +{ + struct obj_list list_old; + CORE_ADDR lladdr = lm -> l_lladdr; + struct link_map *new_lm = &so_list_ptr -> lm; + int errcode; + + read_memory (lladdr, (char *) &list_old, sizeof (struct obj_list)); + + new_lm -> l_variant = OBJ_LIST_OLD; + new_lm -> l_lladdr = lladdr; + new_lm -> l_next = (CORE_ADDR) list_old.next; + +#ifdef HANDLE_NEW_OBJ_LIST + if (list_old.data == NEW_OBJ_INFO_MAGIC) + { + Elf32_Obj_Info list_32; + + read_memory (lladdr, (char *) &list_32, sizeof (Elf32_Obj_Info)); + if (list_32.oi_size != sizeof (Elf32_Obj_Info)) + return; + new_lm -> l_variant = OBJ_LIST_32; + new_lm -> l_next = (CORE_ADDR) list_32.oi_next; + + target_read_string ((CORE_ADDR) list_32.oi_pathname, + &so_list_ptr -> so_name, + list_32.oi_pathname_len + 1, &errcode); + if (errcode != 0) + memory_error (errcode, (CORE_ADDR) list_32.oi_pathname); + + LM_ADDR (so_list_ptr) = (CORE_ADDR) list_32.oi_ehdr; + LM_OFFSET (so_list_ptr) + = (CORE_ADDR) list_32.oi_ehdr - (CORE_ADDR) list_32.oi_orig_ehdr; + } + else +#endif + { + struct obj obj_old; + + read_memory ((CORE_ADDR) list_old.data, (char *) &obj_old, + sizeof (struct obj)); + + target_read_string ((CORE_ADDR) obj_old.o_path, + &so_list_ptr -> so_name, + INT_MAX, &errcode); + if (errcode != 0) + memory_error (errcode, (CORE_ADDR) obj_old.o_path); + + LM_ADDR (so_list_ptr) = (CORE_ADDR) obj_old.o_praw; + LM_OFFSET (so_list_ptr) + = (CORE_ADDR) obj_old.o_praw - obj_old.o_base_address; + } + + solib_map_sections (so_list_ptr); +} + + /* LOCAL FUNCTION @@ -483,7 +720,7 @@ find_solib (so_list_ptr) struct so_list *so_list_ptr; /* Last lm or NULL for first one */ { struct so_list *so_list_next = NULL; - struct obj_list *lm = NULL; + struct link_map *lm = NULL; struct so_list *new; if (so_list_ptr == NULL) @@ -491,49 +728,21 @@ find_solib (so_list_ptr) /* We are setting up for a new scan through the loaded images. */ if ((so_list_next = so_list_head) == NULL) { - /* We have not already read in the dynamic linking structures - from the inferior, lookup the address of the base structure. */ - debug_base = locate_base (); - if (debug_base != 0) - { - /* Read the base structure in and find the address of the first - link map list member. */ - lm = first_link_map_member (); - } + /* Find the first link map list member. */ + lm = first_link_map_member (); } } else { /* We have been called before, and are in the process of walking the shared library list. Advance to the next shared object. */ - if ((lm = so_list_ptr->ll.next) == NULL) - { - /* We have hit the end of the list, so check to see if any were - added, but be quiet if we can't read from the target any more. */ - int status = target_read_memory ((CORE_ADDR) so_list_ptr -> lladdr, - (char *) &(so_list_ptr -> ll), - sizeof (struct obj_list)); - if (status == 0) - { - lm = so_list_ptr->ll.next; - } - else - { - lm = NULL; - } - } + lm = next_link_map_member (so_list_ptr); so_list_next = so_list_ptr -> next; } if ((so_list_next == NULL) && (lm != NULL)) { - int errcode; - char *buffer; - - /* Get next link map structure from inferior image and build a local - abbreviated load_map structure */ new = (struct so_list *) xmalloc (sizeof (struct so_list)); memset ((char *) new, 0, sizeof (struct so_list)); - new -> lladdr = lm; /* Add the new node as the next node in the list, or as the root node if this is the first one. */ if (so_list_ptr != NULL) @@ -545,16 +754,7 @@ find_solib (so_list_ptr) so_list_head = new; } so_list_next = new; - read_memory ((CORE_ADDR) lm, (char *) &(new -> ll), - sizeof (struct obj_list)); - read_memory ((CORE_ADDR) new->ll.data, (char *) &(new -> lm), - sizeof (struct obj)); - target_read_string ((CORE_ADDR)new->lm.o_path, &buffer, - INT_MAX, &errcode); - if (errcode != 0) - memory_error (errcode, (CORE_ADDR)new->lm.o_path); - new->lm.o_path = buffer; - solib_map_sections (new); + xfer_link_map_member (new, lm); } return (so_list_next); } @@ -582,11 +782,10 @@ symbol_add_stub (arg) bfd_map_over_sections (so -> abfd, find_lowest_section, (PTR) &lowest_sect); if (lowest_sect) - text_addr = bfd_section_vma (so -> abfd, lowest_sect) - + (CORE_ADDR) LM_ADDR (so) - so -> lm.o_base_address; + text_addr = bfd_section_vma (so -> abfd, lowest_sect) + LM_OFFSET (so); } - so -> objfile = symbol_file_add (so -> lm.o_path, so -> from_tty, + so -> objfile = symbol_file_add (so -> so_name, so -> from_tty, text_addr, 0, 0, 0); return (1); @@ -636,7 +835,7 @@ solib_add (arg_string, from_tty, target) count = 0; while ((so = find_solib (so)) != NULL) { - if (so -> lm.o_path[0]) + if (so -> so_name[0]) { count += so -> sections_end - so -> sections; } @@ -678,7 +877,7 @@ solib_add (arg_string, from_tty, target) /* Add these section table entries to the target's table. */ while ((so = find_solib (so)) != NULL) { - if (so -> lm.o_path[0]) + if (so -> so_name[0]) { count = so -> sections_end - so -> sections; memcpy ((char *) (target -> to_sections + old), @@ -693,14 +892,14 @@ solib_add (arg_string, from_tty, target) /* Now add the symbol files. */ while ((so = find_solib (so)) != NULL) { - if (so -> lm.o_path[0] && re_exec (so -> lm.o_path)) + if (so -> so_name[0] && re_exec (so -> so_name)) { so -> from_tty = from_tty; if (so -> symbols_loaded) { if (from_tty) { - printf_unfiltered ("Symbols already loaded for %s\n", so -> lm.o_path); + printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name); } } else if (catch_errors @@ -751,7 +950,7 @@ info_sharedlibrary_command (ignore, from_tty) } while ((so = find_solib (so)) != NULL) { - if (so -> lm.o_path[0]) + if (so -> so_name[0]) { if (!header_done) { @@ -766,7 +965,7 @@ info_sharedlibrary_command (ignore, from_tty) local_hex_string_custom ((unsigned long) so -> lmend, "08l")); printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No"); - printf_unfiltered ("%s\n", so -> lm.o_path); + printf_unfiltered ("%s\n", so -> so_name); } } if (so_list_head == NULL) @@ -807,11 +1006,11 @@ solib_address (address) while ((so = find_solib (so)) != NULL) { - if (so -> lm.o_path[0]) + if (so -> so_name[0]) { if ((address >= (CORE_ADDR) LM_ADDR (so)) && (address < (CORE_ADDR) so -> lmend)) - return (so->lm.o_path); + return (so->so_name); } } return (0); @@ -845,7 +1044,7 @@ clear_solib() next = so_list_head -> next; if (bfd_filename) free ((PTR)bfd_filename); - free (so_list_head->lm.o_path); + free (so_list_head->so_name); free ((PTR)so_list_head); so_list_head = next; } @@ -993,13 +1192,13 @@ solib_create_inferior_hook() clear_proceed_status (); stop_soon_quietly = 1; - stop_signal = 0; + stop_signal = TARGET_SIGNAL_0; do { target_resume (-1, 0, stop_signal); wait_for_inferior (); } - while (stop_signal != SIGTRAP); + while (stop_signal != TARGET_SIGNAL_TRAP); /* We are now either at the "mapping complete" breakpoint (or somewhere else, a condition we aren't prepared to deal with anyway), so adjust diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c index e0d4625c810..17e02c6185f 100644 --- a/gdb/mdebugread.c +++ b/gdb/mdebugread.c @@ -254,8 +254,8 @@ static int cur_sdx; /* Note how much "debuggable" this image is. We would like to see at least one FDR with full symbols */ -static max_gdbinfo; -static max_glevel; +static int max_gdbinfo; +static int max_glevel; /* When examining .o files, report on undefined symbols */ @@ -2745,12 +2745,12 @@ parse_partial_symbols (objfile, section_offsets) add_psymbol_to_list (name, strlen (name), VAR_NAMESPACE, LOC_BLOCK, &objfile->global_psymbols, - sh.value, 0, psymtab_language, objfile); + 0, sh.value, psymtab_language, objfile); else add_psymbol_to_list (name, strlen (name), VAR_NAMESPACE, LOC_BLOCK, &objfile->static_psymbols, - sh.value, 0, psymtab_language, objfile); + 0, sh.value, psymtab_language, objfile); /* Skip over procedure to next one. */ if (sh.index >= hdr->iauxMax) @@ -2841,7 +2841,7 @@ parse_partial_symbols (objfile, section_offsets) add_psymbol_to_list (name, strlen (name), STRUCT_NAMESPACE, LOC_TYPEDEF, &objfile->static_psymbols, - sh.value, 0, + 0, (CORE_ADDR) 0, psymtab_language, objfile); } handle_psymbol_enumerators (objfile, fh, sh.st, sh.value); @@ -2879,8 +2879,8 @@ parse_partial_symbols (objfile, section_offsets) /* Use this gdb symbol */ add_psymbol_to_list (name, strlen (name), VAR_NAMESPACE, class, - &objfile->static_psymbols, sh.value, - 0, psymtab_language, objfile); + &objfile->static_psymbols, + 0, sh.value, psymtab_language, objfile); skip: cur_sdx++; /* Go to next file symbol */ } @@ -3127,7 +3127,7 @@ handle_psymbol_enumerators (objfile, fh, stype, svalue) add_psymbol_to_list (name, strlen (name), VAR_NAMESPACE, LOC_CONST, &objfile->static_psymbols, 0, - 0, psymtab_language, objfile); + (CORE_ADDR) 0, psymtab_language, objfile); ext_sym += external_sym_size; } }