/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
based on Fred Fish's (Cygnus Support) implementation of DWARF 1
support in dwarfread.c
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "bfd.h"
-#include "elf-bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "symfile.h"
#include "buildsym.h"
#include "demangle.h"
#include "expression.h"
+#include "filenames.h" /* for DOSish file names */
+#include "macrotab.h"
+
#include "language.h"
#include "complaints.h"
-
+#include "bcache.h"
#include <fcntl.h>
#include "gdb_string.h"
+#include "gdb_assert.h"
#include <sys/types.h>
-/* .debug_info header for a compilation unit
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
+#if 0
+/* .debug_info header for a compilation unit
Because of alignment constraints, this structure has padding and cannot
be mapped directly onto the beginning of the .debug_info section. */
typedef struct comp_unit_header
}
_COMP_UNIT_HEADER;
#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
+#endif
/* .debug_pubnames header
Because of alignment constraints, this structure has padding and cannot
static file_ptr dwarf_loc_offset;
static file_ptr dwarf_macinfo_offset;
static file_ptr dwarf_str_offset;
+file_ptr dwarf_frame_offset;
+file_ptr dwarf_eh_frame_offset;
static unsigned int dwarf_info_size;
static unsigned int dwarf_abbrev_size;
static unsigned int dwarf_loc_size;
static unsigned int dwarf_macinfo_size;
static unsigned int dwarf_str_size;
+unsigned int dwarf_frame_size;
+unsigned int dwarf_eh_frame_size;
/* names of the debugging sections */
#define LOC_SECTION ".debug_loc"
#define MACINFO_SECTION ".debug_macinfo"
#define STR_SECTION ".debug_str"
+#define FRAME_SECTION ".debug_frame"
+#define EH_FRAME_SECTION ".eh_frame"
/* local data types */
-/* The data in a compilation unit header looks like this. */
+/* The data in a compilation unit header, after target2host
+ translation, looks like this. */
struct comp_unit_head
{
- unsigned int length;
+ unsigned long length;
short version;
unsigned int abbrev_offset;
unsigned char addr_size;
+ unsigned char signed_addr_p;
+ unsigned int offset_size; /* size of file offsets; either 4 or 8 */
+ unsigned int initial_length_size; /* size of the length field; either
+ 4 or 12 */
};
-/* The data in the .debug_line statement prologue looks like this. */
-struct line_head
+/* The line number information for a compilation unit (found in the
+ .debug_line section) begins with a "statement program header",
+ which contains the following information. */
+struct line_header
+{
+ unsigned int total_length;
+ unsigned short version;
+ unsigned int header_length;
+ unsigned char minimum_instruction_length;
+ unsigned char default_is_stmt;
+ int line_base;
+ unsigned char line_range;
+ unsigned char opcode_base;
+
+ /* standard_opcode_lengths[i] is the number of operands for the
+ standard opcode whose value is i. This means that
+ standard_opcode_lengths[0] is unused, and the last meaningful
+ element is standard_opcode_lengths[opcode_base - 1]. */
+ unsigned char *standard_opcode_lengths;
+
+ /* The include_directories table. NOTE! These strings are not
+ allocated with xmalloc; instead, they are pointers into
+ debug_line_buffer. If you try to free them, `free' will get
+ indigestion. */
+ unsigned int num_include_dirs, include_dirs_size;
+ char **include_dirs;
+
+ /* The file_names table. NOTE! These strings are not allocated
+ with xmalloc; instead, they are pointers into debug_line_buffer.
+ Don't try to free them directly. */
+ unsigned int num_file_names, file_names_size;
+ struct file_entry
{
- unsigned int total_length;
- unsigned short version;
- unsigned int prologue_length;
- unsigned char minimum_instruction_length;
- unsigned char default_is_stmt;
- int line_base;
- unsigned char line_range;
- unsigned char opcode_base;
- unsigned char *standard_opcode_lengths;
- };
+ char *name;
+ unsigned int dir_index;
+ unsigned int mod_time;
+ unsigned int length;
+ } *file_names;
+
+ /* The start and end of the statement program following this
+ header. These point into dwarf_line_buffer. */
+ char *statement_program_start, *statement_program_end;
+};
/* When we construct a partial symbol table entry we only
need this much information. */
unsigned int offset;
unsigned int abbrev;
char *name;
+ int has_pc_info;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct dwarf_block *locdesc;
/* This data structure holds a complete die structure. */
struct die_info
{
- enum dwarf_tag tag; /* Tag indicating type of die */
- unsigned short has_children; /* Does the die have children */
- unsigned int abbrev; /* Abbrev number */
- unsigned int offset; /* Offset in .debug_info section */
- unsigned int num_attrs; /* Number of attributes */
- struct attribute *attrs; /* An array of attributes */
- struct die_info *next_ref; /* Next die in ref hash table */
- struct die_info *next; /* Next die in linked list */
- struct type *type; /* Cached type information */
+ enum dwarf_tag tag; /* Tag indicating type of die */
+ unsigned short has_children; /* Does the die have children */
+ unsigned int abbrev; /* Abbrev number */
+ unsigned int offset; /* Offset in .debug_info section */
+ unsigned int num_attrs; /* Number of attributes */
+ struct attribute *attrs; /* An array of attributes */
+ struct die_info *next_ref; /* Next die in ref hash table */
+ struct die_info *next; /* Next die in linked list */
+ struct type *type; /* Cached type information */
};
/* Attributes have a name and a value */
{
char *str;
struct dwarf_block *blk;
- unsigned int unsnd;
- int snd;
+ unsigned long unsnd;
+ long int snd;
CORE_ADDR addr;
}
u;
};
+struct function_range
+{
+ const char *name;
+ CORE_ADDR lowpc, highpc;
+ int seen_line;
+ struct function_range *next;
+};
+
+static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn;
+
/* Get at parts of an attribute structure */
#define DW_STRING(attr) ((attr)->u.str)
static char *dwarf_info_buffer;
static char *dwarf_abbrev_buffer;
static char *dwarf_line_buffer;
+static char *dwarf_str_buffer;
+static char *dwarf_macinfo_buffer;
/* A zeroed version of a partial die for initialization purposes. */
static struct partial_die_info zeroed_partial_die;
in buildsym.c. */
static struct pending **list_in_scope = &file_symbols;
-/* 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 */
+/* FIXME: decode_locdesc sets these variables to describe the location
+ to the caller. These ought to be a structure or something. If
+ none of the flags are set, the object lives at the address returned
+ by decode_locdesc. */
+
+static int optimized_out; /* No ops in location in expression,
+ so object was optimized out. */
+static int isreg; /* Object lives in register.
+ decode_locdesc's return value is
+ the register number. */
+static int offreg; /* Object's address is the sum of the
+ register specified by basereg, plus
+ the offset returned. */
+static int basereg; /* See `offreg'. */
+static int isderef; /* Value described by flags above is
+ the address of a pointer to the object. */
+static int islocal; /* Variable is at the returned offset
+ from the frame start, but there's
+ no identified frame pointer for
+ this function, so we can't say
+ which register it's relative to;
+ use LOC_LOCAL. */
/* DW_AT_frame_base values for the current function.
frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
static int frame_base_reg;
static CORE_ADDR frame_base_offset;
-/* This value is added to each symbol value. FIXME: Generalize to
+/* 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 */
of symbols read from an object file. */
struct dwarf2_pinfo
-{
- /* Pointer to start of dwarf info buffer for the objfile. */
+ {
+ /* Pointer to start of dwarf info buffer for the objfile. */
- char *dwarf_info_buffer;
+ char *dwarf_info_buffer;
- /* Offset in dwarf_info_buffer for this compilation unit. */
+ /* Offset in dwarf_info_buffer for this compilation unit. */
- unsigned long dwarf_info_offset;
+ unsigned long dwarf_info_offset;
- /* Pointer to start of dwarf abbreviation buffer for the objfile. */
+ /* Pointer to start of dwarf abbreviation buffer for the objfile. */
- char *dwarf_abbrev_buffer;
+ char *dwarf_abbrev_buffer;
- /* Size of dwarf abbreviation section for the objfile. */
+ /* Size of dwarf abbreviation section for the objfile. */
- unsigned int dwarf_abbrev_size;
+ unsigned int dwarf_abbrev_size;
- /* Pointer to start of dwarf line buffer for the objfile. */
+ /* Pointer to start of dwarf line buffer for the objfile. */
- char *dwarf_line_buffer;
-};
+ char *dwarf_line_buffer;
+
+ /* Size of dwarf_line_buffer, in bytes. */
+
+ unsigned int dwarf_line_size;
+
+ /* Pointer to start of dwarf string buffer for the objfile. */
+
+ char *dwarf_str_buffer;
+
+ /* Size of dwarf string section for the objfile. */
+
+ unsigned int dwarf_str_size;
+
+ /* Pointer to start of dwarf macro buffer for the objfile. */
+
+ char *dwarf_macinfo_buffer;
+
+ /* Size of dwarf macinfo section for the objfile. */
+
+ unsigned int dwarf_macinfo_size;
+
+ };
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
#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)
+#define DWARF_LINE_SIZE(p) (PST_PRIVATE(p)->dwarf_line_size)
+#define DWARF_STR_BUFFER(p) (PST_PRIVATE(p)->dwarf_str_buffer)
+#define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size)
+#define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
+#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size)
/* Maintain an array of referenced fundamental types for the current
compilation unit being read. For DWARF version 1, we have to construct
pass lists of data member fields and lists of member function fields
in an instance of a field_info structure, as defined below. */
struct field_info
-{
- /* List of data member and baseclasses fields. */
- struct nextfield
- {
- struct nextfield *next;
- int accessibility;
- int virtuality;
- struct field field;
- } *fields;
-
- /* Number of fields. */
- int nfields;
-
- /* Number of baseclasses. */
- int nbaseclasses;
+ {
+ /* List of data member and baseclasses fields. */
+ struct nextfield
+ {
+ struct nextfield *next;
+ int accessibility;
+ int virtuality;
+ struct field field;
+ }
+ *fields;
- /* Set if the accesibility of one of the fields is not public. */
- int non_public_fields;
+ /* Number of fields. */
+ int nfields;
- /* Member function fields array, entries are allocated in the order they
- are encountered in the object file. */
- struct nextfnfield
- {
- struct nextfnfield *next;
- struct fn_field fnfield;
- } *fnfields;
+ /* Number of baseclasses. */
+ int nbaseclasses;
- /* Member function fieldlist array, contains name of possibly overloaded
- member function, number of overloaded member functions and a pointer
- to the head of the member function field chain. */
- struct fnfieldlist
- {
- char *name;
- int length;
- struct nextfnfield *head;
- } *fnfieldlists;
+ /* Set if the accesibility of one of the fields is not public. */
+ int non_public_fields;
- /* Number of entries in the fnfieldlists array. */
- int nfnfields;
-};
+ /* Member function fields array, entries are allocated in the order they
+ are encountered in the object file. */
+ struct nextfnfield
+ {
+ struct nextfnfield *next;
+ struct fn_field fnfield;
+ }
+ *fnfields;
-/* FIXME: Kludge to mark a varargs function type for C++ member function
- argument processing. */
-#define TYPE_FLAG_VARARGS (1 << 10)
+ /* Member function fieldlist array, contains name of possibly overloaded
+ member function, number of overloaded member functions and a pointer
+ to the head of the member function field chain. */
+ struct fnfieldlist
+ {
+ char *name;
+ int length;
+ struct nextfnfield *head;
+ }
+ *fnfieldlists;
-/* Dwarf2 has no clean way to discern C++ static and non-static member
- functions. G++ helps GDB by marking the first parameter for non-static
- member functions (which is the this pointer) as artificial.
- We pass this information between dwarf2_add_member_fn and
- read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
-#define TYPE_FIELD_ARTIFICIAL TYPE_FIELD_BITPOS
+ /* Number of entries in the fnfieldlists array. */
+ int nfnfields;
+ };
/* Various complaints about symbol reading that don't abort the process */
{
"missing .debug_line section", 0, 0
};
+static struct complaint dwarf2_statement_list_fits_in_line_number_section =
+{
+ "statement list doesn't fit in .debug_line section", 0, 0
+};
static struct complaint dwarf2_mangled_line_number_section =
{
"mangled .debug_line section", 0, 0
{
"unsupported stack op: '%s'", 0, 0
};
+static struct complaint dwarf2_complex_location_expr =
+{
+ "location expression too complex", 0, 0
+};
static struct complaint dwarf2_unsupported_tag =
{
"unsupported tag: '%s'", 0, 0
{
"unsupported const value attribute form: '%s'", 0, 0
};
-
-/* Remember the addr_size read from the dwarf.
- If a target expects to link compilation units with differing address
- sizes, gdb needs to be sure that the appropriate size is here for
- whatever scope is currently getting read. */
-static int address_size;
-
-/* Some elf32 object file formats while linked for a 32 bit address
- space contain debug information that has assumed 64 bit
- addresses. Eg 64 bit MIPS target produced by GCC/GAS/LD where the
- symbol table contains 32bit address values while its .debug_info
- section contains 64 bit address values.
- ADDRESS_SIGNIFICANT_SIZE specifies the number significant bits in
- the ADDRESS_SIZE bytes read from the file */
-static int address_significant_size;
-
-/* Externals references. */
-extern int info_verbose; /* From main.c; nonzero => verbose */
+static struct complaint dwarf2_misplaced_line_number =
+{
+ "misplaced first line number at 0x%lx for '%s'", 0, 0
+};
+static struct complaint dwarf2_line_header_too_long =
+{
+ "line number info header doesn't fit in `.debug_line' section", 0, 0
+};
+static struct complaint dwarf2_missing_macinfo_section =
+{
+ "missing .debug_macinfo section", 0, 0
+};
+static struct complaint dwarf2_macros_too_long =
+{
+ "macro info runs off end of `.debug_macinfo' section", 0, 0
+};
+static struct complaint dwarf2_macros_not_terminated =
+{
+ "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0
+};
+static struct complaint dwarf2_macro_outside_file =
+{
+ "debug info gives macro %s outside of any file: %s", 0, 0
+};
+static struct complaint dwarf2_macro_unmatched_end_file =
+{
+ "macro debug info has an unmatched `close_file' directive", 0, 0
+};
+static struct complaint dwarf2_macro_malformed_definition =
+{
+ "macro debug info contains a malformed macro definition:\n`%s'", 0, 0
+};
+static struct complaint dwarf2_macro_spaces_in_definition =
+{
+ "macro definition contains spaces in formal argument list:\n`%s'", 0, 0
+};
/* local function prototypes */
-static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
+static void dwarf2_locate_sections (bfd *, asection *, PTR);
#if 0
-static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *,
- struct section_offsets *,
- int));
+static void dwarf2_build_psymtabs_easy (struct objfile *, int);
#endif
-static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *,
- struct section_offsets *,
- int));
+static void dwarf2_build_psymtabs_hard (struct objfile *, int);
+
+static char *scan_partial_symbols (char *, struct objfile *,
+ CORE_ADDR *, CORE_ADDR *,
+ const struct comp_unit_head *);
+
+static void add_partial_symbol (struct partial_die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
+
+static void psymtab_to_symtab_1 (struct partial_symtab *);
+
+char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
-static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
- CORE_ADDR *, CORE_ADDR *));
+static void dwarf2_read_abbrevs (bfd *, unsigned int);
-static void add_partial_symbol PARAMS ((struct partial_die_info *,
- struct objfile *));
+static void dwarf2_empty_abbrev_table (PTR);
-static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
-static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+static char *read_partial_die (struct partial_die_info *,
+ bfd *, char *,
+ const struct comp_unit_head *);
-static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr,
- unsigned int));
+static char *read_full_die (struct die_info **, bfd *, char *,
+ const struct comp_unit_head *);
-static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
+static char *read_attribute (struct attribute *, struct attr_abbrev *,
+ bfd *, char *, const struct comp_unit_head *);
-static void dwarf2_empty_abbrev_table PARAMS ((PTR));
+static char *read_attribute_value (struct attribute *, unsigned,
+ bfd *, char *, const struct comp_unit_head *);
-static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
+static unsigned int read_1_byte (bfd *, char *);
-static char *read_partial_die PARAMS ((struct partial_die_info *,
- bfd *, char *, int *));
+static int read_1_signed_byte (bfd *, char *);
-static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
+static unsigned int read_2_bytes (bfd *, char *);
-static char *read_attribute PARAMS ((struct attribute *, struct attr_abbrev *,
- bfd *, char *));
+static unsigned int read_4_bytes (bfd *, char *);
-static unsigned int read_1_byte PARAMS ((bfd *, char *));
+static unsigned long read_8_bytes (bfd *, char *);
-static int read_1_signed_byte PARAMS ((bfd *, char *));
+static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
+ int *bytes_read);
-static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+static LONGEST read_initial_length (bfd *, char *,
+ struct comp_unit_head *, int *bytes_read);
-static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
+ int *bytes_read);
-static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+static char *read_n_bytes (bfd *, char *, unsigned int);
-static CORE_ADDR read_address PARAMS ((bfd *, char *));
+static char *read_string (bfd *, char *, unsigned int *);
-static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *,
+ unsigned int *);
-static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
-static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
- unsigned int *));
+static long read_signed_leb128 (bfd *, char *, unsigned int *);
-static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
+static void set_cu_language (unsigned int);
-static void set_cu_language PARAMS ((unsigned int));
+static struct attribute *dwarf_attr (struct die_info *, unsigned int);
-static struct attribute *dwarf_attr PARAMS ((struct die_info *,
- unsigned int));
+static int die_is_declaration (struct die_info *);
-static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *));
+static void free_line_header (struct line_header *lh);
-static void dwarf2_start_subfile PARAMS ((char *, char *));
+static struct line_header *(dwarf_decode_line_header
+ (unsigned int offset,
+ bfd *abfd,
+ const struct comp_unit_head *cu_header));
-static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *,
- struct objfile *));
+static void dwarf_decode_lines (struct line_header *, char *, bfd *,
+ const struct comp_unit_head *);
-static void dwarf2_const_value PARAMS ((struct attribute *, struct symbol *,
- struct objfile *));
+static void dwarf2_start_subfile (char *, char *);
-static struct type *die_type PARAMS ((struct die_info *, struct objfile *));
+static struct symbol *new_symbol (struct die_info *, struct type *,
+ struct objfile *, const struct comp_unit_head *);
-static struct type *die_containing_type PARAMS ((struct die_info *,
- struct objfile *));
+static void dwarf2_const_value (struct attribute *, struct symbol *,
+ struct objfile *, const struct comp_unit_head *);
+
+static void dwarf2_const_value_data (struct attribute *attr,
+ struct symbol *sym,
+ int bits);
+
+static struct type *die_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static struct type *die_containing_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
#if 0
-static struct type *type_at_offset PARAMS ((unsigned int, struct objfile *));
+static struct type *type_at_offset (unsigned int, struct objfile *);
#endif
-static struct type *tag_type_to_type PARAMS ((struct die_info *,
- struct objfile *));
+static struct type *tag_type_to_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_type_die PARAMS ((struct die_info *, struct objfile *));
+static void read_type_die (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_typedef PARAMS ((struct die_info *, struct objfile *));
+static void read_typedef (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_base_type PARAMS ((struct die_info *, struct objfile *));
+static void read_base_type (struct die_info *, struct objfile *);
-static void read_file_scope PARAMS ((struct die_info *, struct objfile *));
+static void read_file_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_func_scope PARAMS ((struct die_info *, struct objfile *));
+static void read_func_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_lexical_block_scope PARAMS ((struct die_info *,
- struct objfile *));
+static void read_lexical_block_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static int dwarf2_get_pc_bounds PARAMS ((struct die_info *,
- CORE_ADDR *, CORE_ADDR *,
- struct objfile *));
+static int dwarf2_get_pc_bounds (struct die_info *,
+ CORE_ADDR *, CORE_ADDR *, struct objfile *);
-static void dwarf2_add_field PARAMS ((struct field_info *, struct die_info *,
- struct objfile *));
+static void dwarf2_add_field (struct field_info *, struct die_info *,
+ struct objfile *, const struct comp_unit_head *);
-static void dwarf2_attach_fields_to_type PARAMS ((struct field_info *,
- struct type *,
- struct objfile *));
+static void dwarf2_attach_fields_to_type (struct field_info *,
+ struct type *, struct objfile *);
-static char *skip_member_fn_name PARAMS ((char *));
+static void dwarf2_add_member_fn (struct field_info *,
+ struct die_info *, struct objfile *objfile,
+ const struct comp_unit_head *);
-static void dwarf2_add_member_fn PARAMS ((struct field_info *,
- struct die_info *, struct type *,
- struct objfile *objfile));
+static void dwarf2_attach_fn_fields_to_type (struct field_info *,
+ struct type *, struct objfile *);
-static void dwarf2_attach_fn_fields_to_type PARAMS ((struct field_info *,
- struct type *,
- struct objfile *));
+static void read_structure_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_structure_scope PARAMS ((struct die_info *, struct objfile *));
+static void read_common_block (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_common_block PARAMS ((struct die_info *, struct objfile *));
+static void read_enumeration (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_enumeration PARAMS ((struct die_info *, struct objfile *));
+static struct type *dwarf_base_type (int, int, struct objfile *);
-static struct type *dwarf_base_type PARAMS ((int, int, struct objfile *));
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *,
+ const struct comp_unit_head *);
-static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
- struct objfile *));
+static void read_array_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_array_type PARAMS ((struct die_info *, struct objfile *));
+static void read_tag_pointer_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_pointer_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_ptr_to_member_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_reference_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_reference_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_const_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_const_type PARAMS ((struct die_info *, struct objfile *));
+static void read_tag_volatile_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_volatile_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_string_type (struct die_info *, struct objfile *);
-static void read_tag_string_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_subroutine_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_subroutine_type PARAMS ((struct die_info *,
- struct objfile *));
+static struct die_info *read_comp_unit (char *, bfd *,
+ const struct comp_unit_head *);
-struct die_info *read_comp_unit PARAMS ((char *, bfd *));
+static void free_die_list (struct die_info *);
-static void free_die_list PARAMS ((struct die_info *));
+static struct cleanup *make_cleanup_free_die_list (struct die_info *);
-static void process_die PARAMS ((struct die_info *, struct objfile *));
+static void process_die (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static char *dwarf2_linkage_name PARAMS ((struct die_info *));
+static char *dwarf2_linkage_name (struct die_info *);
-static char *dwarf_tag_name PARAMS ((unsigned int));
+static char *dwarf_tag_name (unsigned int);
-static char *dwarf_attr_name PARAMS ((unsigned int));
+static char *dwarf_attr_name (unsigned int);
-static char *dwarf_form_name PARAMS ((unsigned int));
+static char *dwarf_form_name (unsigned int);
-static char *dwarf_stack_op_name PARAMS ((unsigned int));
+static char *dwarf_stack_op_name (unsigned int);
-static char *dwarf_bool_name PARAMS ((unsigned int));
+static char *dwarf_bool_name (unsigned int);
-static char *dwarf_type_encoding_name PARAMS ((unsigned int));
+static char *dwarf_type_encoding_name (unsigned int);
#if 0
-static char *dwarf_cfi_name PARAMS ((unsigned int));
+static char *dwarf_cfi_name (unsigned int);
-struct die_info *copy_die PARAMS ((struct die_info *));
+struct die_info *copy_die (struct die_info *);
#endif
-struct die_info *sibling_die PARAMS ((struct die_info *));
+static struct die_info *sibling_die (struct die_info *);
-void dump_die PARAMS ((struct die_info *));
+static void dump_die (struct die_info *);
-void dump_die_list PARAMS ((struct die_info *));
+static void dump_die_list (struct die_info *);
-void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
+static void store_in_ref_table (unsigned int, struct die_info *);
-static void dwarf2_empty_die_ref_table PARAMS ((void));
+static void dwarf2_empty_hash_tables (void);
-static unsigned int dwarf2_get_ref_die_offset PARAMS ((struct attribute *));
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
-struct die_info *follow_die_ref PARAMS ((unsigned int));
+static struct die_info *follow_die_ref (unsigned int);
-static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int));
+static struct type *dwarf2_fundamental_type (struct objfile *, int);
/* memory allocation interface */
-static void dwarf2_free_tmp_obstack PARAMS ((PTR));
+static void dwarf2_free_tmp_obstack (PTR);
+
+static struct dwarf_block *dwarf_alloc_block (void);
-static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
+static struct abbrev_info *dwarf_alloc_abbrev (void);
-static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
+static struct die_info *dwarf_alloc_die (void);
-static struct die_info *dwarf_alloc_die PARAMS ((void));
+static void initialize_cu_func_list (void);
+
+static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
+
+static void dwarf_decode_macros (struct line_header *, unsigned int,
+ char *, bfd *, const struct comp_unit_head *,
+ struct objfile *);
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
int
-dwarf2_has_info (abfd)
- bfd *abfd;
+dwarf2_has_info (bfd *abfd)
{
- dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
+ dwarf_info_offset = 0;
+ dwarf_abbrev_offset = 0;
+ dwarf_line_offset = 0;
+ dwarf_str_offset = 0;
+ dwarf_macinfo_offset = 0;
+ dwarf_frame_offset = 0;
+ dwarf_eh_frame_offset = 0;
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
if (dwarf_info_offset && dwarf_abbrev_offset)
{
in. */
static void
-dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
- bfd *ignore_abfd;
- asection *sectp;
- PTR ignore_ptr;
+dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr)
{
if (STREQ (sectp->name, INFO_SECTION))
{
dwarf_str_offset = sectp->filepos;
dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
}
+ else if (STREQ (sectp->name, FRAME_SECTION))
+ {
+ dwarf_frame_offset = sectp->filepos;
+ dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, EH_FRAME_SECTION))
+ {
+ dwarf_eh_frame_offset = sectp->filepos;
+ dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ }
}
/* Build a partial symbol table. */
void
-dwarf2_build_psymtabs (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
+dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
{
/* We definitely need the .debug_info and .debug_abbrev sections */
dwarf_line_offset,
dwarf_line_size);
- if (mainline || objfile->global_psymbols.size == 0 ||
- objfile->static_psymbols.size == 0)
+ if (dwarf_str_offset)
+ dwarf_str_buffer = dwarf2_read_section (objfile,
+ dwarf_str_offset,
+ dwarf_str_size);
+ else
+ dwarf_str_buffer = NULL;
+
+ if (dwarf_macinfo_offset)
+ dwarf_macinfo_buffer = dwarf2_read_section (objfile,
+ dwarf_macinfo_offset,
+ dwarf_macinfo_size);
+ else
+ dwarf_macinfo_buffer = NULL;
+
+ if (mainline
+ || (objfile->global_psymbols.size == 0
+ && objfile->static_psymbols.size == 0))
{
init_psymbol_list (objfile, 1024);
}
#if 0
if (dwarf_aranges_offset && dwarf_pubnames_offset)
{
- /* Things are significanlty easier if we have .debug_aranges and
+ /* Things are significantly easier if we have .debug_aranges and
.debug_pubnames sections */
- dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline);
+ dwarf2_build_psymtabs_easy (objfile, mainline);
}
else
#endif
/* only test this case for now */
- {
+ {
/* In this case we have to work a bit harder */
- dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline);
+ dwarf2_build_psymtabs_hard (objfile, mainline);
}
}
.debug_pubnames and .debug_aranges sections. */
static void
-dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
+dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
{
bfd *abfd = objfile->obfd;
char *aranges_buffer, *pubnames_buffer;
pubnames_ptr = pubnames_buffer;
while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
{
- entry_length = read_4_bytes (abfd, pubnames_ptr);
- pubnames_ptr += 4;
+ struct comp_unit_head cu_header;
+ int bytes_read;
+
+ entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
+ &bytes_read);
+ pubnames_ptr += bytes_read;
version = read_1_byte (abfd, pubnames_ptr);
pubnames_ptr += 1;
info_offset = read_4_bytes (abfd, pubnames_ptr);
}
#endif
+/* Read in the comp unit header information from the debug_info at
+ info_ptr. */
+
+static char *
+read_comp_unit_head (struct comp_unit_head *cu_header,
+ char *info_ptr, bfd *abfd)
+{
+ int signed_addr;
+ int bytes_read;
+ cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
+ cu_header->version = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
+ cu_header->addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ signed_addr = bfd_get_sign_extend_vma (abfd);
+ if (signed_addr < 0)
+ internal_error (__FILE__, __LINE__,
+ "read_comp_unit_head: dwarf from non elf file");
+ cu_header->signed_addr_p = signed_addr;
+ return info_ptr;
+}
+
/* Build the partial symbol table by doing a quick pass through the
.debug_info and .debug_abbrev sections. */
static void
-dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
+dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
{
/* Instead of reading this into a big buffer, we should probably use
mmap() on architectures that support it. (FIXME) */
bfd *abfd = objfile->obfd;
char *info_ptr, *abbrev_ptr;
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;
CORE_ADDR lowpc, highpc;
- /* Number of bytes of any addresses that are signficant */
- address_significant_size = get_elf_backend_data (abfd)->s->arch_size / 8;
-
info_ptr = dwarf_info_buffer;
abbrev_ptr = dwarf_abbrev_buffer;
+ /* We use dwarf2_tmp_obstack for objects that don't need to survive
+ the partial symbol scan, like attribute values.
+
+ We could reduce our peak memory consumption during partial symbol
+ table construction by freeing stuff from this obstack more often
+ --- say, after processing each compilation unit, or each die ---
+ but it turns out that this saves almost nothing. For an
+ executable with 11Mb of Dwarf 2 data, I found about 64k allocated
+ on dwarf2_tmp_obstack. Some investigation showed:
+
+ 1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
+ DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*. These are
+ all fixed-length values not requiring dynamic allocation.
+
+ 2) 30% of the attributes used the form DW_FORM_string. For
+ DW_FORM_string, read_attribute simply hands back a pointer to
+ the null-terminated string in dwarf_info_buffer, so no dynamic
+ allocation is needed there either.
+
+ 3) The remaining 1% of the attributes all used DW_FORM_block1.
+ 75% of those were DW_AT_frame_base location lists for
+ functions; the rest were DW_AT_location attributes, probably
+ for the global variables.
+
+ Anyway, what this all means is that the memory the dwarf2
+ reader uses as temporary space reading partial symbols is about
+ 0.5% as much as we use for dwarf_*_buffer. That's noise. */
+
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)
+ /* Since the objects we're extracting from dwarf_info_buffer vary in
+ length, only the individual functions to extract them (like
+ read_comp_unit_head and read_partial_die) can really know whether
+ the buffer is large enough to hold another complete object.
+
+ At the moment, they don't actually check that. If
+ dwarf_info_buffer holds just one extra byte after the last
+ compilation unit's dies, then read_comp_unit_head will happily
+ read off the end of the buffer. read_partial_die is similarly
+ casual. Those functions should be fixed.
+
+ For this loop condition, simply checking whether there's any data
+ left at all should be sufficient. */
+ while (info_ptr < dwarf_info_buffer + dwarf_info_size)
{
+ struct comp_unit_head cu_header;
beg_of_comp_unit = info_ptr;
- cu_header.length = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.version = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- address_size = cu_header.addr_size;
+ info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
if (cu_header.version != 2)
{
(long) (beg_of_comp_unit - dwarf_info_buffer));
return;
}
- if (beg_of_comp_unit + cu_header.length + 4
+ if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
> dwarf_info_buffer + dwarf_info_size)
{
error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
(long) (beg_of_comp_unit - dwarf_info_buffer));
return;
}
- if (address_size < address_significant_size)
- {
- error ("Dwarf Error: bad address size (%ld) in compilation unit header (offset 0x%lx + 11).",
- (long) cu_header.addr_size,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
- }
-
/* Read the abbrevs for this compilation unit into a table */
dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
make_cleanup (dwarf2_empty_abbrev_table, NULL);
/* Read the compilation unit die */
- info_ptr = read_partial_die (&comp_unit_die, abfd,
- info_ptr, &comp_unit_has_pc_info);
+ info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
+ &cu_header);
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language);
/* Allocate a new partial symbol table structure */
- pst = start_psymtab_common (objfile, section_offsets,
- comp_unit_die.name ? comp_unit_die.name : "",
+ pst = start_psymtab_common (objfile, objfile->section_offsets,
+ comp_unit_die.name ? comp_unit_die.name : "",
comp_unit_die.lowpc,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
pst->read_symtab_private = (char *)
obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
- 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);
+ 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;
+ DWARF_LINE_SIZE (pst) = dwarf_line_size;
+ DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
+ DWARF_STR_SIZE (pst) = dwarf_str_size;
+ DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
+ DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
pst->read_symtab = dwarf2_psymtab_to_symtab;
If not, there's no more debug_info for this comp unit. */
if (comp_unit_die.has_children)
{
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
+ info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
+ &cu_header);
/* If the compilation unit didn't have an explicit address range,
then use the information extracted from its child dies. */
- if (!comp_unit_has_pc_info)
+ if (! comp_unit_die.has_pc_info)
{
- comp_unit_die.lowpc = lowpc;
+ comp_unit_die.lowpc = lowpc;
comp_unit_die.highpc = highpc;
}
}
- pst->textlow = comp_unit_die.lowpc + baseaddr;
+ pst->textlow = comp_unit_die.lowpc + baseaddr;
pst->texthigh = comp_unit_die.highpc + baseaddr;
pst->n_global_syms = objfile->global_psymbols.next -
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
- info_ptr = beg_of_comp_unit + cu_header.length + 4;
+ info_ptr = beg_of_comp_unit + cu_header.length
+ + cu_header.initial_length_size;
}
do_cleanups (back_to);
}
/* Read in all interesting dies to the end of the compilation unit. */
static char *
-scan_partial_symbols (info_ptr, objfile, lowpc, highpc)
- char *info_ptr;
- struct objfile *objfile;
- CORE_ADDR *lowpc;
- CORE_ADDR *highpc;
+scan_partial_symbols (char *info_ptr, struct objfile *objfile,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ const struct comp_unit_head *cu_header)
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
back to that level. */
int nesting_level = 1;
- int has_pc_info;
-
- *lowpc = ((CORE_ADDR) -1);
+
+ *lowpc = ((CORE_ADDR) -1);
*highpc = ((CORE_ADDR) 0);
while (nesting_level)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
if (pdi.name)
{
switch (pdi.tag)
{
case DW_TAG_subprogram:
- if (has_pc_info)
+ if (pdi.has_pc_info)
{
if (pdi.lowpc < *lowpc)
{
if ((pdi.is_external || nesting_level == 1)
&& !pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile);
+ add_partial_symbol (&pdi, objfile, cu_header);
}
}
break;
if ((pdi.is_external || nesting_level == 1)
&& !pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile);
+ add_partial_symbol (&pdi, objfile, cu_header);
}
break;
case DW_TAG_enumerator:
/* File scope enumerators are added to the partial symbol
- table. */
+ table. */
if (nesting_level == 2)
- add_partial_symbol (&pdi, objfile);
+ add_partial_symbol (&pdi, objfile, cu_header);
break;
case DW_TAG_base_type:
/* File scope base type definitions are added to the partial
- symbol table. */
+ symbol table. */
if (nesting_level == 1)
- add_partial_symbol (&pdi, objfile);
+ add_partial_symbol (&pdi, objfile, cu_header);
break;
default:
break;
}
/* If the die has a sibling, skip to the sibling.
- Do not skip enumeration types, we want to record their
- enumerators. */
+ Do not skip enumeration types, we want to record their
+ enumerators. */
if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type)
{
info_ptr = pdi.sibling;
}
static void
-add_partial_symbol (pdi, objfile)
- struct partial_die_info *pdi;
- struct objfile *objfile;
+add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
CORE_ADDR addr = 0;
if (pdi->is_external)
{
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
- mst_text, objfile);*/
+ mst_text, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_BLOCK,
&objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ 0, pdi->lowpc + baseaddr, cu_language, objfile);
}
else
{
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
- mst_file_text, objfile);*/
+ mst_file_text, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_BLOCK,
&objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ 0, pdi->lowpc + baseaddr, cu_language, objfile);
}
break;
case DW_TAG_variable:
table building. */
if (pdi->locdesc)
- addr = decode_locdesc (pdi->locdesc, objfile);
+ addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
if (pdi->locdesc || pdi->has_type)
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_STATIC,
/* Static Variable. Skip symbols without location descriptors. */
if (pdi->locdesc == NULL)
return;
- addr = decode_locdesc (pdi->locdesc, objfile);
+ addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
/*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
- mst_file_data, objfile);*/
+ mst_file_data, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_STATIC,
&objfile->static_psymbols,
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
/* Skip aggregate types without children, these are external
- references. */
+ references. */
if (pdi->has_children == 0)
return;
add_psymbol_to_list (pdi->name, strlen (pdi->name),
/* Expand this partial symbol table into a full symbol table. */
static void
-dwarf2_psymtab_to_symtab (pst)
- struct partial_symtab *pst;
+dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
{
/* FIXME: This is barely more than a stub. */
if (pst != NULL)
}
static void
-psymtab_to_symtab_1 (pst)
- struct partial_symtab *pst;
+psymtab_to_symtab_1 (struct partial_symtab *pst)
{
struct objfile *objfile = pst->objfile;
bfd *abfd = objfile->obfd;
struct cleanup *back_to;
/* 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);
+ 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);
+ dwarf_line_size = DWARF_LINE_SIZE (pst);
+ dwarf_str_buffer = DWARF_STR_BUFFER (pst);
+ dwarf_str_size = DWARF_STR_SIZE (pst);
+ dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
+ dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
+ baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
cu_header_offset = offset;
info_ptr = dwarf_info_buffer + offset;
make_cleanup (really_free_pendings, NULL);
/* read in the comp_unit header */
- cu_header.length = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.version = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
+ info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
/* Read the abbrevs for this compilation unit */
dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
make_cleanup (dwarf2_empty_abbrev_table, NULL);
- dies = read_comp_unit (info_ptr, abfd);
+ dies = read_comp_unit (info_ptr, abfd, &cu_header);
- make_cleanup (free_die_list, dies);
+ make_cleanup_free_die_list (dies);
/* Do line number decoding in read_file_scope () */
- process_die (dies, objfile);
+ process_die (dies, objfile, &cu_header);
if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
{
/* Some compilers don't define a DW_AT_high_pc attribute for
- the compilation unit. If the DW_AT_high_pc is missing,
- synthesize it, by scanning the DIE's below the compilation unit. */
+ the compilation unit. If the DW_AT_high_pc is missing,
+ synthesize it, by scanning the DIE's below the compilation unit. */
highpc = 0;
if (dies->has_children)
{
}
}
}
- symtab = end_symtab (highpc + baseaddr, objfile, 0);
+ symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
/* Set symtab language to language from DW_AT_language.
If the compilation is from a C file generated by language preprocessors,
/* Process a die and its children. */
static void
-process_die (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+process_die (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
switch (die->tag)
{
case DW_TAG_padding:
break;
case DW_TAG_compile_unit:
- read_file_scope (die, objfile);
+ read_file_scope (die, objfile, cu_header);
break;
case DW_TAG_subprogram:
- read_subroutine_type (die, objfile);
- read_func_scope (die, objfile);
+ read_subroutine_type (die, objfile, cu_header);
+ read_func_scope (die, objfile, cu_header);
break;
case DW_TAG_inlined_subroutine:
/* FIXME: These are ignored for now.
- They could be used to set breakpoints on all inlined instances
- of a function and make GDB `next' properly over inlined functions. */
+ They could be used to set breakpoints on all inlined instances
+ of a function and make GDB `next' properly over inlined functions. */
break;
case DW_TAG_lexical_block:
- read_lexical_block_scope (die, objfile);
+ read_lexical_block_scope (die, objfile, cu_header);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile);
+ read_structure_scope (die, objfile, cu_header);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile);
+ read_enumeration (die, objfile, cu_header);
break;
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile);
+ read_subroutine_type (die, objfile, cu_header);
break;
case DW_TAG_array_type:
- read_array_type (die, objfile);
+ read_array_type (die, objfile, cu_header);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile);
+ read_tag_pointer_type (die, objfile, cu_header);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile);
+ read_tag_ptr_to_member_type (die, objfile, cu_header);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile);
+ read_tag_reference_type (die, objfile, cu_header);
break;
case DW_TAG_string_type:
read_tag_string_type (die, objfile);
if (dwarf_attr (die, DW_AT_name))
{
/* Add a typedef symbol for the base type definition. */
- new_symbol (die, die->type, objfile);
+ new_symbol (die, die->type, objfile, cu_header);
}
break;
case DW_TAG_common_block:
- read_common_block (die, objfile);
+ read_common_block (die, objfile, cu_header);
break;
case DW_TAG_common_inclusion:
break;
default:
- new_symbol (die, NULL, objfile);
+ new_symbol (die, NULL, objfile, cu_header);
break;
}
}
static void
-read_file_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+initialize_cu_func_list (void)
+{
+ cu_first_fn = cu_last_fn = cu_cached_fn = NULL;
+}
+
+static void
+read_file_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
- unsigned int line_offset = 0;
- CORE_ADDR lowpc = ((CORE_ADDR) -1);
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+ CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
struct attribute *attr;
char *name = "<unknown>";
char *comp_dir = NULL;
struct die_info *child_die;
bfd *abfd = objfile->obfd;
+ struct line_header *line_header = 0;
if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
{
/* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
#if 0
- /* FIXME:Do something here. */
- if (dip->at_producer != NULL)
+ /* FIXME:Do something here. */
+ if (dip->at_producer != NULL)
{
handle_producer (dip->at_producer);
}
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
- /* Decode line number information if present. */
- attr = dwarf_attr (die, DW_AT_stmt_list);
- if (attr)
- {
- line_offset = DW_UNSND (attr);
- dwarf_decode_lines (line_offset, comp_dir, abfd);
- }
+ initialize_cu_func_list ();
/* Process all dies in compilation unit. */
if (die->has_children)
child_die = die->next;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
child_die = sibling_die (child_die);
}
}
+
+ /* Decode line number information if present. */
+ attr = dwarf_attr (die, DW_AT_stmt_list);
+ if (attr)
+ {
+ unsigned int line_offset = DW_UNSND (attr);
+ line_header = dwarf_decode_line_header (line_offset,
+ abfd, cu_header);
+ if (line_header)
+ {
+ make_cleanup ((make_cleanup_ftype *) free_line_header,
+ (void *) line_header);
+ dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+ }
+ }
+
+ /* Decode macro information, if present. Dwarf 2 macro information
+ refers to information in the line number info statement program
+ header, so we can only read it if we've read the header
+ successfully. */
+ attr = dwarf_attr (die, DW_AT_macro_info);
+ if (attr)
+ {
+ unsigned int macro_offset = DW_UNSND (attr);
+ dwarf_decode_macros (line_header, macro_offset,
+ comp_dir, abfd, cu_header, objfile);
+ }
+ do_cleanups (back_to);
+}
+
+static void
+add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc)
+{
+ struct function_range *thisfn;
+
+ thisfn = (struct function_range *)
+ obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range));
+ thisfn->name = name;
+ thisfn->lowpc = lowpc;
+ thisfn->highpc = highpc;
+ thisfn->seen_line = 0;
+ thisfn->next = NULL;
+
+ if (cu_last_fn == NULL)
+ cu_first_fn = thisfn;
+ else
+ cu_last_fn->next = thisfn;
+
+ cu_last_fn = thisfn;
}
static void
-read_func_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_func_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
register struct context_stack *new;
CORE_ADDR lowpc;
lowpc += baseaddr;
highpc += baseaddr;
+ /* Record the function range for dwarf_decode_lines. */
+ add_to_cu_func_list (name, lowpc, highpc);
+
if (objfile->ei.entry_point >= lowpc &&
objfile->ei.entry_point < highpc)
{
objfile->ei.entry_func_highpc = highpc;
}
- if (STREQ (name, "main")) /* FIXME: hardwired name */
- {
- 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;
attr = dwarf_attr (die, DW_AT_frame_base);
if (attr)
{
- CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
- if (isreg)
+ CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ if (isderef)
+ complain (&dwarf2_unsupported_at_frame_base, name);
+ else if (isreg)
frame_base_reg = addr;
else if (offreg)
{
}
new = push_context (0, lowpc);
- new->name = new_symbol (die, die->type, objfile);
+ new->name = new_symbol (die, die->type, objfile, cu_header);
list_in_scope = &local_symbols;
if (die->has_children)
child_die = die->next;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
child_die = sibling_die (child_die);
}
}
a new scope, process the dies, and then close the scope. */
static void
-read_lexical_block_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
register struct context_stack *new;
CORE_ADDR lowpc, highpc;
child_die = die->next;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
child_die = sibling_die (child_die);
}
}
Return 1 if the attributes are present and valid, otherwise, return 0. */
static int
-dwarf2_get_pc_bounds (die, lowpc, highpc, objfile)
- struct die_info *die;
- CORE_ADDR *lowpc;
- CORE_ADDR *highpc;
- struct objfile *objfile;
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct objfile *objfile)
{
struct attribute *attr;
CORE_ADDR low;
/* Add an aggregate field to the field list. */
static void
-dwarf2_add_field (fip, die, objfile)
- struct field_info *fip;
- struct die_info *die;
- struct objfile *objfile;
+dwarf2_add_field (struct field_info *fip, struct die_info *die,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct nextfield *new_field;
struct attribute *attr;
/* Allocate a new field list entry and link it in. */
new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
- make_cleanup (free, new_field);
+ make_cleanup (xfree, new_field);
memset (new_field, 0, sizeof (struct nextfield));
new_field->next = fip->fields;
fip->fields = new_field;
if (die->tag == DW_TAG_member)
{
/* Get type of field. */
- fp->type = die_type (die, objfile);
+ fp->type = die_type (die, objfile, cu_header);
/* Get bit size of field (zero if none). */
attr = dwarf_attr (die, DW_AT_bit_size);
if (attr)
{
FIELD_BITPOS (*fp) =
- decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
}
else
FIELD_BITPOS (*fp) = 0;
if (BITS_BIG_ENDIAN)
{
/* For big endian bits, the DW_AT_bit_offset gives the
- additional bit offset from the MSB of the containing
- anonymous object to the MSB of the field. We don't
- have to do anything special since we don't need to
- know the size of the anonymous object. */
+ additional bit offset from the MSB of the containing
+ anonymous object to the MSB of the field. We don't
+ have to do anything special since we don't need to
+ know the size of the anonymous object. */
FIELD_BITPOS (*fp) += DW_UNSND (attr);
}
else
{
/* For little endian bits, compute the bit offset to the
- MSB of the anonymous object, subtract off the number of
- bits from the MSB of the field to the MSB of the
- object, and then subtract off the number of bits of
- the field itself. The result is the bit offset of
- the LSB of the field. */
+ MSB of the anonymous object, subtract off the number of
+ bits from the MSB of the field to the MSB of the
+ object, and then subtract off the number of bits of
+ the field itself. The result is the bit offset of
+ the LSB of the field. */
int anonymous_size;
int bit_offset = DW_UNSND (attr);
&objfile->type_obstack);
/* Change accessibility for artificial fields (e.g. virtual table
- pointer or virtual base class pointer) to private. */
+ pointer or virtual base class pointer) to private. */
if (dwarf_attr (die, DW_AT_artificial))
{
new_field->accessibility = DW_ACCESS_private;
else if (die->tag == DW_TAG_variable)
{
char *physname;
- char *cp;
/* C++ static member.
- Get physical name, extract field name from physical name. */
- physname = dwarf2_linkage_name (die);
- if (physname == NULL)
+ Get name of field. */
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ fieldname = DW_STRING (attr);
+ else
return;
- cp = physname;
- while (*cp && !is_cplus_marker (*cp))
- cp++;
- if (*cp)
- fieldname = cp + 1;
- if (*fieldname == '\0')
- {
- complain (&dwarf2_bad_static_member_name, physname);
- }
+ /* Get physical name. */
+ physname = dwarf2_linkage_name (die);
SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
- &objfile->type_obstack));
- FIELD_TYPE (*fp) = die_type (die, objfile);
+ &objfile->type_obstack));
+ FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
- &objfile->type_obstack);
+ &objfile->type_obstack);
}
else if (die->tag == DW_TAG_inheritance)
{
/* C++ base class field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
- FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
+ * bits_per_byte);
FIELD_BITSIZE (*fp) = 0;
- FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
fip->nbaseclasses++;
}
/* Create the vector of fields, and attach it to the type. */
static void
-dwarf2_attach_fields_to_type (fip, type, objfile)
- struct field_info *fip;
- struct type *type;
- struct objfile *objfile;
+dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
+ struct objfile *objfile)
{
int nfields = fip->nfields;
TYPE_FIELD (type, nfields) = fip->fields->field;
switch (fip->fields->accessibility)
{
- case DW_ACCESS_private:
- SET_TYPE_FIELD_PRIVATE (type, nfields);
- break;
+ case DW_ACCESS_private:
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+ break;
- case DW_ACCESS_protected:
- SET_TYPE_FIELD_PROTECTED (type, nfields);
- break;
+ case DW_ACCESS_protected:
+ SET_TYPE_FIELD_PROTECTED (type, nfields);
+ break;
- case DW_ACCESS_public:
- break;
+ case DW_ACCESS_public:
+ break;
- default:
- /* Unknown accessibility. Complain and treat it as public. */
- {
- complain (&dwarf2_unsupported_accessibility,
- fip->fields->accessibility);
- }
- break;
+ default:
+ /* Unknown accessibility. Complain and treat it as public. */
+ {
+ complain (&dwarf2_unsupported_accessibility,
+ fip->fields->accessibility);
+ }
+ break;
}
if (nfields < fip->nbaseclasses)
{
switch (fip->fields->virtuality)
{
- case DW_VIRTUALITY_virtual:
- case DW_VIRTUALITY_pure_virtual:
- SET_TYPE_FIELD_VIRTUAL (type, nfields);
- break;
+ case DW_VIRTUALITY_virtual:
+ case DW_VIRTUALITY_pure_virtual:
+ SET_TYPE_FIELD_VIRTUAL (type, nfields);
+ break;
}
}
fip->fields = fip->fields->next;
}
}
-/* Skip to the end of a member function name in a mangled name. */
-
-static char *
-skip_member_fn_name (physname)
- char *physname;
-{
- char *endname = physname;
-
- /* Skip over leading underscores. */
- while (*endname == '_')
- endname++;
-
- /* Find two succesive underscores. */
- do
- endname = strchr (endname, '_');
- while (endname != NULL && *++endname != '_');
-
- if (endname == NULL)
- {
- complain (&dwarf2_bad_member_name_complaint, physname);
- endname = physname;
- }
- else
- {
- /* Take care of trailing underscores. */
- if (endname[1] != '_')
- endname--;
- }
- return endname;
-}
-
/* Add a member function to the proper fieldlist. */
static void
-dwarf2_add_member_fn (fip, die, type, objfile)
- struct field_info *fip;
- struct die_info *die;
- struct type *type;
- struct objfile *objfile;
+dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct attribute *attr;
struct fnfieldlist *flp;
char *physname;
struct nextfnfield *new_fnfield;
- /* Extract member function name from mangled name. */
- physname = dwarf2_linkage_name (die);
- if (physname == NULL)
- return;
- if ((physname[0] == '_' && physname[1] == '_'
- && strchr ("0123456789Qt", physname[2]))
- || DESTRUCTOR_PREFIX_P (physname))
- {
- /* Constructor and destructor field names are set to the name
- of the class, but without template parameter lists.
- The name might be missing for anonymous aggregates. */
- if (TYPE_TAG_NAME (type))
- {
- char *p = strchr (TYPE_TAG_NAME (type), '<');
-
- if (p == NULL)
- fieldname = TYPE_TAG_NAME (type);
- else
- fieldname = obsavestring (TYPE_TAG_NAME (type),
- p - TYPE_TAG_NAME (type),
- &objfile->type_obstack);
- }
- else
- {
- char *anon_name = "";
- fieldname = obsavestring (anon_name, strlen (anon_name),
- &objfile->type_obstack);
- }
- }
+ /* Get name of member function. */
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ fieldname = DW_STRING (attr);
else
- {
- char *endname = skip_member_fn_name (physname);
+ return;
- /* Ignore member function if we were unable not extract the member
- function name. */
- if (endname == physname)
- return;
- fieldname = obsavestring (physname, endname - physname,
- &objfile->type_obstack);
- }
+ /* Get the mangled name. */
+ physname = dwarf2_linkage_name (die);
/* Look up member function name in fieldlist. */
for (i = 0; i < fip->nfnfields; i++)
fip->fnfieldlists = (struct fnfieldlist *)
xrealloc (fip->fnfieldlists,
(fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct fnfieldlist));
+ * sizeof (struct fnfieldlist));
if (fip->nfnfields == 0)
make_cleanup (free_current_contents, &fip->fnfieldlists);
}
/* Create a new member function field and chain it to the field list
entry. */
new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
- make_cleanup (free, new_fnfield);
+ make_cleanup (xfree, new_fnfield);
memset (new_fnfield, 0, sizeof (struct nextfnfield));
new_fnfield->next = flp->head;
flp->head = new_fnfield;
if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
{
struct type *return_type = TYPE_TARGET_TYPE (die->type);
- struct type **arg_types;
int nparams = TYPE_NFIELDS (die->type);
- int iparams;
-
- /* Copy argument types from the subroutine type. */
- arg_types = (struct type **)
- TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
- for (iparams = 0; iparams < nparams; iparams++)
- arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
- /* Set last entry in argument type vector. */
- if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
- arg_types[nparams] = NULL;
- else
- arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
-
- smash_to_method_type (fnp->type, type, return_type, arg_types);
+ smash_to_method_type (fnp->type, die->type,
+ TYPE_TARGET_TYPE (die->type),
+ TYPE_FIELDS (die->type),
+ TYPE_NFIELDS (die->type),
+ TYPE_VARARGS (die->type));
/* Handle static member functions.
- Dwarf2 has no clean way to discern C++ static and non-static
- member functions. G++ helps GDB by marking the first
- parameter for non-static member functions (which is the
- this pointer) as artificial. We obtain this information
- from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
+ Dwarf2 has no clean way to discern C++ static and non-static
+ member functions. G++ helps GDB by marking the first
+ parameter for non-static member functions (which is the
+ this pointer) as artificial. We obtain this information
+ from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
fnp->voffset = VOFFSET_STATIC;
}
/* Get fcontext from DW_AT_containing_type if present. */
if (dwarf_attr (die, DW_AT_containing_type) != NULL)
- fnp->fcontext = die_containing_type (die, objfile);
+ fnp->fcontext = die_containing_type (die, objfile, cu_header);
/* dwarf2 doesn't have stubbed physical names, so the setting of is_const
and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */
{
switch (DW_UNSND (attr))
{
- case DW_ACCESS_private:
- fnp->is_private = 1;
- break;
- case DW_ACCESS_protected:
- fnp->is_protected = 1;
- break;
+ case DW_ACCESS_private:
+ fnp->is_private = 1;
+ break;
+ case DW_ACCESS_protected:
+ fnp->is_protected = 1;
+ break;
}
}
+ /* Check for artificial methods. */
+ attr = dwarf_attr (die, DW_AT_artificial);
+ if (attr && DW_UNSND (attr) != 0)
+ fnp->is_artificial = 1;
+
/* Get index in virtual function table if it is a virtual member function. */
attr = dwarf_attr (die, DW_AT_vtable_elem_location);
if (attr)
- fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile) + 2;
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
}
/* Create the vector of member function fields, and attach it to the type. */
static void
-dwarf2_attach_fn_fields_to_type (fip, type, objfile)
- struct field_info *fip;
- struct type *type;
- struct objfile *objfile;
+dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
+ struct objfile *objfile)
{
struct fnfieldlist *flp;
int total_length = 0;
fn_flp->fn_fields = (struct fn_field *)
TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
for (k = flp->length; (k--, nfp); nfp = nfp->next)
- fn_flp->fn_fields[k] = nfp->fnfield;
+ fn_flp->fn_fields[k] = nfp->fnfield;
total_length += flp->length;
}
suppresses creating a symbol table entry itself). */
static void
-read_structure_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_structure_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *attr;
else
{
/* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT
- in gdbtypes.h. */
+ in gdbtypes.h. */
TYPE_CODE (type) = TYPE_CODE_CLASS;
}
type within the structure itself. */
die->type = type;
- if (die->has_children)
+ if (die->has_children && ! die_is_declaration (die))
{
struct field_info fi;
struct die_info *child_die;
{
if (child_die->tag == DW_TAG_member)
{
- dwarf2_add_field (&fi, child_die, objfile);
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_variable)
{
/* C++ static member. */
- dwarf2_add_field (&fi, child_die, objfile);
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_subprogram)
{
/* C++ member function. */
- process_die (child_die, objfile);
- dwarf2_add_member_fn (&fi, child_die, type, objfile);
+ process_die (child_die, objfile, cu_header);
+ dwarf2_add_member_fn (&fi, child_die, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_inheritance)
{
/* C++ base class field. */
- dwarf2_add_field (&fi, child_die, objfile);
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
}
child_die = sibling_die (child_die);
}
{
dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
- /* Get the type which refers to the base class (possibly this
+ /* Get the type which refers to the base class (possibly this
class itself) which contains the vtable pointer for the current
class from the DW_AT_containing_type attribute. */
if (dwarf_attr (die, DW_AT_containing_type) != NULL)
{
- struct type *t = die_containing_type (die, objfile);
+ struct type *t = die_containing_type (die, objfile, cu_header);
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
{
- static const char vptr_name[] = { '_','v','p','t','r','\0' };
+ static const char vptr_name[] =
+ {'_', 'v', 'p', 't', 'r', '\0'};
int i;
/* Our own class provides vtbl ptr. */
/* Complain if virtual function table field not found. */
if (i < TYPE_N_BASECLASSES (t))
complain (&dwarf2_vtbl_not_found_complaint,
- TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
+ TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
}
else
{
}
}
- new_symbol (die, type, objfile);
+ new_symbol (die, type, objfile, cu_header);
do_cleanups (back_to);
}
/* No children, must be stub. */
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
}
-
- die->type = type;
}
/* Given a pointer to a die which begins an enumeration, process all
NOTE: We reverse the order of the element list. */
static void
-read_enumeration (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_enumeration (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct die_info *child_die;
struct type *type;
{
if (child_die->tag != DW_TAG_enumerator)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
}
else
{
attr = dwarf_attr (child_die, DW_AT_name);
if (attr)
{
- sym = new_symbol (child_die, type, objfile);
+ sym = new_symbol (child_die, type, objfile, cu_header);
if (SYMBOL_VALUE (sym) < 0)
unsigned_enum = 0;
fields = (struct field *)
xrealloc (fields,
(num_fields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct field));
+ * sizeof (struct field));
}
FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
TYPE_ALLOC (type, sizeof (struct field) * num_fields);
memcpy (TYPE_FIELDS (type), fields,
sizeof (struct field) * num_fields);
- free (fields);
+ xfree (fields);
}
if (unsigned_enum)
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
}
die->type = type;
- new_symbol (die, type, objfile);
+ new_symbol (die, type, objfile, cu_header);
}
/* Extract all information from a DW_TAG_array_type DIE and put it in
arrays. */
static void
-read_array_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_array_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct die_info *child_die;
struct type *type = NULL;
return;
}
- element_type = die_type (die, objfile);
+ element_type = die_type (die, objfile, cu_header);
/* Irix 6.2 native cc creates array types without children for
arrays with unspecified length. */
low = 1;
}
- index_type = die_type (child_die, objfile);
+ index_type = die_type (child_die, objfile, cu_header);
attr = dwarf_attr (child_die, DW_AT_lower_bound);
if (attr)
{
low = DW_SND (attr);
}
else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4)
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
{
low = DW_UNSND (attr);
}
high = DW_SND (attr);
}
else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4)
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
{
high = DW_UNSND (attr);
}
{
range_types = (struct type **)
xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct type *));
+ * sizeof (struct type *));
if (ndim == 0)
make_cleanup (free_current_contents, &range_types);
}
while (ndim-- > 0)
type = create_array_type (NULL, type, range_types[ndim]);
+ /* Understand Dwarf2 support for vector types (like they occur on
+ the PowerPC w/ AltiVec). Gcc just adds another attribute to the
+ array type. This is not part of the Dwarf2/3 standard yet, but a
+ custom vendor extension. The main difference between a regular
+ array and the vector variant is that vectors are passed by value
+ to functions. */
+ attr = dwarf_attr (die, DW_AT_GNU_vector);
+ if (attr)
+ TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+
do_cleanups (back_to);
/* Install the type in the die. */
/* First cut: install each common block member as a global variable. */
static void
-read_common_block (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_common_block (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct die_info *child_die;
struct attribute *attr;
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- base = decode_locdesc (DW_BLOCK (attr), objfile);
+ base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
}
if (die->has_children)
{
child_die = die->next;
while (child_die && child_die->tag)
{
- sym = new_symbol (child_die, NULL, objfile);
+ sym = new_symbol (child_die, NULL, objfile, cu_header);
attr = dwarf_attr (child_die, DW_AT_data_member_location);
if (attr)
{
SYMBOL_VALUE_ADDRESS (sym) =
- base + decode_locdesc (DW_BLOCK (attr), objfile);
+ base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
add_symbol_to_list (sym, &global_symbols);
}
child_die = sibling_die (child_die);
the user defined type vector. */
static void
-read_tag_pointer_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *attr;
return;
}
- type = lookup_pointer_type (die_type (die, objfile));
+ type = lookup_pointer_type (die_type (die, objfile, cu_header));
attr = dwarf_attr (die, DW_AT_byte_size);
if (attr)
{
}
else
{
- TYPE_LENGTH (type) = address_size;
+ TYPE_LENGTH (type) = cu_header->addr_size;
}
die->type = type;
}
the user defined type vector. */
static void
-read_tag_ptr_to_member_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct type *to_type;
}
type = alloc_type (objfile);
- to_type = die_type (die, objfile);
- domain = die_containing_type (die, objfile);
+ to_type = die_type (die, objfile, cu_header);
+ domain = die_containing_type (die, objfile, cu_header);
smash_to_member_type (type, domain, to_type);
die->type = type;
the user defined type vector. */
static void
-read_tag_reference_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_reference_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *attr;
return;
}
- type = lookup_reference_type (die_type (die, objfile));
+ type = lookup_reference_type (die_type (die, objfile, cu_header));
attr = dwarf_attr (die, DW_AT_byte_size);
if (attr)
{
}
else
{
- TYPE_LENGTH (type) = address_size;
+ TYPE_LENGTH (type) = cu_header->addr_size;
}
die->type = type;
}
static void
-read_tag_const_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_const_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
+ struct type *base_type;
+
if (die->type)
{
return;
}
- complain (&dwarf2_const_ignored);
- die->type = die_type (die, objfile);
+ base_type = die_type (die, objfile, cu_header);
+ die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
}
static void
-read_tag_volatile_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
+ struct type *base_type;
+
if (die->type)
{
return;
}
- complain (&dwarf2_volatile_ignored);
- die->type = die_type (die, objfile);
+ base_type = die_type (die, objfile, cu_header);
+ die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
}
/* Extract all information from a DW_TAG_string_type DIE and add to
attribute to reference it. */
static void
-read_tag_string_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_string_type (struct die_info *die, struct objfile *objfile)
{
struct type *type, *range_type, *index_type, *char_type;
struct attribute *attr;
}
else
{
- length = 1;
+ /* check for the DW_AT_byte_size attribute */
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ length = DW_UNSND (attr);
+ }
+ else
+ {
+ length = 1;
+ }
}
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
range_type = create_range_type (NULL, index_type, 1, length);
- char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
- type = create_string_type (char_type, range_type);
+ if (cu_language == language_fortran)
+ {
+ /* Need to create a unique string type for bounds
+ information */
+ type = create_string_type (0, range_type);
+ }
+ else
+ {
+ char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+ type = create_string_type (char_type, range_type);
+ }
die->type = type;
}
/* Handle DIES due to C code like:
struct foo
- {
- int (*funcp)(int a, long l);
- int b;
- };
+ {
+ int (*funcp)(int a, long l);
+ int b;
+ };
('funcp' generates a DW_TAG_subroutine_type DIE)
-*/
+ */
static void
-read_subroutine_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_subroutine_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type; /* Type that this function returns */
struct type *ftype; /* Function that returns above type */
{
return;
}
- type = die_type (die, objfile);
+ type = die_type (die, objfile, cu_header);
ftype = lookup_function_type (type);
/* All functions in C++ have prototypes. */
if (child_die->tag == DW_TAG_formal_parameter)
{
/* Dwarf2 has no clean way to discern C++ static and non-static
- member functions. G++ helps GDB by marking the first
- parameter for non-static member functions (which is the
- this pointer) as artificial. We pass this information
- to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */
+ member functions. G++ helps GDB by marking the first
+ parameter for non-static member functions (which is the
+ this pointer) as artificial. We pass this information
+ to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */
attr = dwarf_attr (child_die, DW_AT_artificial);
if (attr)
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
else
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
- TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile);
+ TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile,
+ cu_header);
iparams++;
}
child_die = sibling_die (child_die);
}
static void
-read_typedef (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_typedef (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
- struct type *type;
+ struct attribute *attr;
+ char *name = NULL;
if (!die->type)
{
- 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 && DW_STRING (attr))
- TYPE_NAME (type) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
- &objfile->type_obstack);
-
- die->type = type;
+ {
+ name = DW_STRING (attr);
+ }
+ die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
+ TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header);
}
}
it in the TYPE field of the die. */
static void
-read_base_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_base_type (struct die_info *die, struct objfile *objfile)
{
struct type *type;
struct attribute *attr;
if (attr && DW_STRING (attr))
{
enum type_code code = TYPE_CODE_INT;
- int is_unsigned = 0;
+ int type_flags = 0;
switch (encoding)
{
case DW_ATE_address:
/* Turn DW_ATE_address into a void * pointer. */
code = TYPE_CODE_PTR;
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_boolean:
code = TYPE_CODE_BOOL;
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
break;
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
default:
complain (&dwarf2_unsupported_at_encoding,
dwarf_type_encoding_name (encoding));
break;
}
- type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
+ type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
if (encoding == DW_ATE_address)
TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+ else if (encoding == DW_ATE_complex_float)
+ {
+ if (size == 32)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+ else if (size == 16)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ else if (size == 8)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_FLOAT);
+ }
}
else
{
/* Read a whole compilation unit into a linked list of dies. */
-struct die_info *
-read_comp_unit (info_ptr, abfd)
- char *info_ptr;
- bfd *abfd;
+static struct die_info *
+read_comp_unit (char *info_ptr, bfd *abfd,
+ const struct comp_unit_head *cu_header)
{
struct die_info *first_die, *last_die, *die;
char *cur_ptr;
int nesting_level;
- /* Reset die reference table, we are building a new one now. */
- dwarf2_empty_die_ref_table ();
+ /* Reset die reference table; we are
+ building new ones now. */
+ dwarf2_empty_hash_tables ();
cur_ptr = info_ptr;
nesting_level = 0;
first_die = last_die = NULL;
do
{
- cur_ptr = read_full_die (&die, abfd, cur_ptr);
+ cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
if (die->has_children)
{
nesting_level++;
/* Free a linked list of dies. */
static void
-free_die_list (dies)
- struct die_info *dies;
+free_die_list (struct die_info *dies)
{
struct die_info *die, *next;
while (die)
{
next = die->next;
- free (die->attrs);
- free (die);
+ xfree (die->attrs);
+ xfree (die);
die = next;
}
}
+static void
+do_free_die_list_cleanup (void *dies)
+{
+ free_die_list (dies);
+}
+
+static struct cleanup *
+make_cleanup_free_die_list (struct die_info *dies)
+{
+ return make_cleanup (do_free_die_list_cleanup, dies);
+}
+
+
/* 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 (objfile, offset, size)
- struct objfile *objfile;
- file_ptr offset;
- unsigned int size;
+char *
+dwarf2_read_section (struct objfile *objfile, file_ptr offset,
+ unsigned int size)
{
bfd *abfd = objfile->obfd;
char *buf;
buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
- (bfd_read (buf, size, 1, abfd) != size))
+ (bfd_bread (buf, size, abfd) != size))
{
buf = NULL;
error ("Dwarf Error: Can't read DWARF data from '%s'",
- bfd_get_filename (abfd));
+ bfd_get_filename (abfd));
}
return buf;
}
in a hash table. */
static void
-dwarf2_read_abbrevs (abfd, offset)
- bfd * abfd;
- unsigned int offset;
+dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
{
char *abbrev_ptr;
struct abbrev_info *cur_abbrev;
cur_abbrev->attrs = (struct attr_abbrev *)
xrealloc (cur_abbrev->attrs,
(cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
- * sizeof (struct attr_abbrev));
+ * sizeof (struct attr_abbrev));
}
cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
/* 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. */
+ 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)
+ >= dwarf_abbrev_size)
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
/* ARGSUSED */
static void
-dwarf2_empty_abbrev_table (ignore)
- PTR ignore;
+dwarf2_empty_abbrev_table (PTR ignore)
{
int i;
struct abbrev_info *abbrev, *next;
while (abbrev)
{
next = abbrev->next;
- free (abbrev->attrs);
- free (abbrev);
+ xfree (abbrev->attrs);
+ xfree (abbrev);
abbrev = next;
}
dwarf2_abbrevs[i] = NULL;
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info *
-dwarf2_lookup_abbrev (number)
- unsigned int number;
+dwarf2_lookup_abbrev (unsigned int number)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
/* Read a minimal amount of information into the minimal die structure. */
static char *
-read_partial_die (part_die, abfd, info_ptr, has_pc_info)
- struct partial_die_info *part_die;
- bfd * abfd;
- char *info_ptr;
- int *has_pc_info;
+read_partial_die (struct partial_die_info *part_die, bfd *abfd,
+ char *info_ptr, const struct comp_unit_head *cu_header)
{
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
struct attribute attr;
struct attribute spec_attr;
int found_spec_attr = 0;
- int has_low_pc_attr = 0;
+ 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)
for (i = 0; i < abbrev->num_attrs; ++i)
{
- info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr);
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
+ info_ptr, cu_header);
/* Store the data if it is of an attribute we want to keep in a
- partial symbol table. */
+ partial symbol table. */
switch (attr.name)
{
case DW_AT_name:
/* Ignore absolute siblings, they might point outside of
the current compile unit. */
if (attr.form == DW_FORM_ref_addr)
- complain(&dwarf2_absolute_sibling_complaint);
+ complain (&dwarf2_absolute_sibling_complaint);
else
part_die->sibling =
dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
int dummy;
spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
- read_partial_die (&spec_die, abfd, spec_ptr, &dummy);
+ read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
if (spec_die.name)
{
part_die->name = spec_die.name;
&& part_die->lowpc < part_die->highpc
&& (part_die->lowpc != 0
|| (bfd_get_file_flags (abfd) & HAS_RELOC)))
- *has_pc_info = 1;
+ part_die->has_pc_info = 1;
return info_ptr;
}
point to a newly allocated die with its information. */
static char *
-read_full_die (diep, abfd, info_ptr)
- struct die_info **diep;
- bfd *abfd;
- char *info_ptr;
+read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info *abbrev;
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
- abfd, info_ptr);
+ abfd, info_ptr, cu_header);
}
*diep = die;
return info_ptr;
}
-/* Read an attribute described by an abbreviated attribute. */
+/* Read an attribute value described by an attribute form. */
static char *
-read_attribute (attr, abbrev, abfd, info_ptr)
- struct attribute *attr;
- struct attr_abbrev *abbrev;
- bfd *abfd;
- char *info_ptr;
+read_attribute_value (struct attribute *attr, unsigned form,
+ bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
{
unsigned int bytes_read;
struct dwarf_block *blk;
- attr->name = abbrev->name;
- attr->form = abbrev->form;
- switch (abbrev->form)
+ attr->form = form;
+ switch (form)
{
case DW_FORM_addr:
case DW_FORM_ref_addr:
- DW_ADDR (attr) = read_address (abfd, info_ptr);
- info_ptr += address_size;
+ DW_ADDR (attr) = read_address (abfd, info_ptr, cu_header, &bytes_read);
+ info_ptr += bytes_read;
break;
case DW_FORM_block2:
blk = dwarf_alloc_block ();
DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
+ case DW_FORM_strp:
+ DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
+ break;
case DW_FORM_block:
blk = dwarf_alloc_block ();
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
info_ptr += 4;
break;
- case DW_FORM_ref_udata:
- DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ case DW_FORM_ref8:
+ DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+ info_ptr += 8;
+ break;
+ case DW_FORM_ref_udata:
+ DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
- case DW_FORM_strp:
case DW_FORM_indirect:
+ form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header);
+ break;
default:
error ("Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (abbrev->form));
+ dwarf_form_name (form));
}
return info_ptr;
}
+/* Read an attribute described by an abbreviated attribute. */
+
+static char *
+read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+ bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
+{
+ attr->name = abbrev->name;
+ return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header);
+}
+
/* read dwarf information from a buffer */
static unsigned int
-read_1_byte (abfd, buf)
- bfd *abfd;
- char *buf;
+read_1_byte (bfd *abfd, char *buf)
{
return bfd_get_8 (abfd, (bfd_byte *) buf);
}
static int
-read_1_signed_byte (abfd, buf)
- bfd *abfd;
- char *buf;
+read_1_signed_byte (bfd *abfd, char *buf)
{
return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
}
static unsigned int
-read_2_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_2_bytes (bfd *abfd, char *buf)
{
return bfd_get_16 (abfd, (bfd_byte *) buf);
}
static int
-read_2_signed_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_2_signed_bytes (bfd *abfd, char *buf)
{
return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
}
static unsigned int
-read_4_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_4_bytes (bfd *abfd, char *buf)
{
return bfd_get_32 (abfd, (bfd_byte *) buf);
}
static int
-read_4_signed_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_4_signed_bytes (bfd *abfd, char *buf)
{
return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
}
-static unsigned int
-read_8_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+static unsigned long
+read_8_bytes (bfd *abfd, char *buf)
{
return bfd_get_64 (abfd, (bfd_byte *) buf);
}
static CORE_ADDR
-read_address (abfd, buf)
- bfd *abfd;
- char *buf;
+read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
{
CORE_ADDR retval = 0;
- switch (address_size)
+ if (cu_header->signed_addr_p)
+ {
+ switch (cu_header->addr_size)
+ {
+ case 2:
+ retval = bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+ break;
+ case 4:
+ retval = bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+ break;
+ case 8:
+ retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ "read_address: bad switch, signed");
+ }
+ }
+ else
+ {
+ switch (cu_header->addr_size)
+ {
+ case 2:
+ retval = bfd_get_16 (abfd, (bfd_byte *) buf);
+ break;
+ case 4:
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ break;
+ case 8:
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ "read_address: bad switch, unsigned");
+ }
+ }
+
+ *bytes_read = cu_header->addr_size;
+ return retval;
+}
+
+/* Reads the initial length from a section. The (draft) DWARF 2.1
+ specification allows the initial length to take up either 4 bytes
+ or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8
+ bytes describe the length and all offsets will be 8 bytes in length
+ instead of 4.
+
+ The value returned via bytes_read should be used to increment
+ the relevant pointer after calling read_initial_length().
+
+ As a side effect, this function sets the fields initial_length_size
+ and offset_size in cu_header to the values appropriate for the
+ length field. (The format of the initial length field determines
+ the width of file offsets to be fetched later with fetch_offset().)
+
+ [ Note: read_initial_length() and read_offset() are based on the
+ document entitled "DWARF Debugging Information Format", revision
+ 2.1, draft 4, dated July 20, 2000. This document was obtained
+ from:
+
+ http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+
+ This document is only a draft and is subject to change. (So beware.)
+
+ - Kevin, Aug 4, 2000
+ ] */
+
+static LONGEST
+read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ LONGEST retval = 0;
+
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+
+ if (retval == 0xffffffff)
+ {
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+ *bytes_read = 12;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 12;
+ cu_header->offset_size = 8;
+ }
+ }
+ else
+ {
+ *bytes_read = 4;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 4;
+ cu_header->offset_size = 4;
+ }
+ }
+
+ return retval;
+}
+
+/* Read an offset from the data stream. The size of the offset is
+ given by cu_header->offset_size. */
+
+static LONGEST
+read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ LONGEST retval = 0;
+
+ switch (cu_header->offset_size)
{
case 4:
retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ *bytes_read = 4;
break;
case 8:
retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ *bytes_read = 8;
break;
default:
- /* *THE* alternative is 8, right? */
- abort ();
+ internal_error (__FILE__, __LINE__,
+ "read_offset: bad switch");
}
- /* If the address being read is larger than the address that is
- applicable for the object file format then mask it down to the
- correct size. Take care to avoid unnecessary shift or shift
- overflow */
- if (address_size > address_significant_size
- && address_significant_size < sizeof (CORE_ADDR))
- {
- CORE_ADDR mask = ((CORE_ADDR) 0) - 1;
- retval &= ~(mask << (address_significant_size * 8));
- }
- return retval;
+
+ return retval;
}
static char *
-read_n_bytes (abfd, buf, size)
- bfd * abfd;
- char *buf;
- unsigned int size;
+read_n_bytes (bfd *abfd, 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
+ gdb_assert (HOST_CHAR_BIT == 8);
return buf;
-#else
- char *ret;
- unsigned int i;
-
- 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
}
static char *
-read_string (abfd, buf, bytes_read_ptr)
- bfd *abfd;
- char *buf;
- unsigned int *bytes_read_ptr;
+read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
/* 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
+ gdb_assert (HOST_CHAR_BIT == 8);
if (*buf == '\0')
{
*bytes_read_ptr = 1;
}
*bytes_read_ptr = strlen (buf) + 1;
return buf;
-#else
- int byte;
- unsigned int i = 0;
+}
- while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
+static char *
+read_indirect_string (bfd *abfd, char *buf,
+ const struct comp_unit_head *cu_header,
+ unsigned int *bytes_read_ptr)
+{
+ LONGEST str_offset = read_offset (abfd, buf, cu_header,
+ (int *) bytes_read_ptr);
+
+ if (dwarf_str_buffer == NULL)
{
- obstack_1grow (&dwarf2_tmp_obstack, byte);
- i++;
- buf++;
+ error ("DW_FORM_strp used without .debug_str section");
+ return NULL;
}
- if (i == 0)
+ if (str_offset >= dwarf_str_size)
{
- *bytes_read_ptr = 1;
+ error ("DW_FORM_strp pointing outside of .debug_str section");
return NULL;
}
- obstack_1grow (&dwarf2_tmp_obstack, '\0');
- *bytes_read_ptr = i + 1;
- return obstack_finish (&dwarf2_tmp_obstack);
-#endif
+ gdb_assert (HOST_CHAR_BIT == 8);
+ if (dwarf_str_buffer[str_offset] == '\0')
+ return NULL;
+ return dwarf_str_buffer + str_offset;
}
-static unsigned int
-read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
- bfd *abfd;
- char *buf;
- unsigned int *bytes_read_ptr;
+static unsigned long
+read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
- unsigned int result, num_read;
+ unsigned long result;
+ unsigned int num_read;
int i, shift;
unsigned char byte;
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
num_read++;
- result |= ((byte & 127) << shift);
+ result |= ((unsigned long)(byte & 127) << shift);
if ((byte & 128) == 0)
{
break;
return result;
}
-static int
-read_signed_leb128 (abfd, buf, bytes_read_ptr)
- bfd *abfd;
- char *buf;
- unsigned int *bytes_read_ptr;
+static long
+read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
- int result;
+ long result;
int i, shift, size, num_read;
unsigned char byte;
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
num_read++;
- result |= ((byte & 127) << shift);
+ result |= ((long)(byte & 127) << shift);
shift += 7;
if ((byte & 128) == 0)
{
}
static void
-set_cu_language (lang)
- unsigned int lang;
+set_cu_language (unsigned int lang)
{
switch (lang)
{
break;
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
+ case DW_LANG_Fortran95:
cu_language = language_fortran;
break;
case DW_LANG_Mips_Assembler:
cu_language = language_asm;
break;
+ case DW_LANG_Java:
+ cu_language = language_java;
+ break;
case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
/* Return the named attribute or NULL if not there. */
static struct attribute *
-dwarf_attr (die, name)
- struct die_info *die;
- unsigned int name;
+dwarf_attr (struct die_info *die, unsigned int name)
{
unsigned int i;
struct attribute *spec = NULL;
if (spec)
{
struct die_info *ref_die =
- follow_die_ref (dwarf2_get_ref_die_offset (spec));
+ 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.
- The compilation directory of the file is passed in COMP_DIR. */
+static int
+die_is_declaration (struct die_info *die)
+{
+ return (dwarf_attr (die, DW_AT_declaration)
+ && ! dwarf_attr (die, DW_AT_specification));
+}
-struct filenames
+
+/* Free the line_header structure *LH, and any arrays and strings it
+ refers to. */
+static void
+free_line_header (struct line_header *lh)
{
- unsigned int num_files;
- struct fileinfo
- {
- char *name;
- unsigned int dir;
- unsigned int time;
- unsigned int size;
- }
- *files;
-};
+ if (lh->standard_opcode_lengths)
+ xfree (lh->standard_opcode_lengths);
-struct directories
+ /* Remember that all the lh->file_names[i].name pointers are
+ pointers into debug_line_buffer, and don't need to be freed. */
+ if (lh->file_names)
+ xfree (lh->file_names);
+
+ /* Similarly for the include directory names. */
+ if (lh->include_dirs)
+ xfree (lh->include_dirs);
+
+ xfree (lh);
+}
+
+
+/* Add an entry to LH's include directory table. */
+static void
+add_include_dir (struct line_header *lh, char *include_dir)
{
- unsigned int num_dirs;
- char **dirs;
-};
+ /* Grow the array if necessary. */
+ if (lh->include_dirs_size == 0)
+ {
+ lh->include_dirs_size = 1; /* for testing */
+ lh->include_dirs = xmalloc (lh->include_dirs_size
+ * sizeof (*lh->include_dirs));
+ }
+ else if (lh->num_include_dirs >= lh->include_dirs_size)
+ {
+ lh->include_dirs_size *= 2;
+ lh->include_dirs = xrealloc (lh->include_dirs,
+ (lh->include_dirs_size
+ * sizeof (*lh->include_dirs)));
+ }
+ lh->include_dirs[lh->num_include_dirs++] = include_dir;
+}
+
+
+/* Add an entry to LH's file name table. */
static void
-dwarf_decode_lines (offset, comp_dir, abfd)
- unsigned int offset;
- char *comp_dir;
- bfd *abfd;
+add_file_name (struct line_header *lh,
+ char *name,
+ unsigned int dir_index,
+ unsigned int mod_time,
+ unsigned int length)
{
- char *line_ptr;
- char *line_end;
- struct line_head lh;
- struct cleanup *back_to;
- unsigned int i, bytes_read;
- char *cur_file, *cur_dir;
- unsigned char op_code, extended_op, adj_opcode;
+ struct file_entry *fe;
-#define FILE_ALLOC_CHUNK 5
-#define DIR_ALLOC_CHUNK 5
+ /* Grow the array if necessary. */
+ if (lh->file_names_size == 0)
+ {
+ lh->file_names_size = 1; /* for testing */
+ lh->file_names = xmalloc (lh->file_names_size
+ * sizeof (*lh->file_names));
+ }
+ else if (lh->num_file_names >= lh->file_names_size)
+ {
+ lh->file_names_size *= 2;
+ lh->file_names = xrealloc (lh->file_names,
+ (lh->file_names_size
+ * sizeof (*lh->file_names)));
+ }
+
+ fe = &lh->file_names[lh->num_file_names++];
+ fe->name = name;
+ fe->dir_index = dir_index;
+ fe->mod_time = mod_time;
+ fe->length = length;
+}
+
+
+/* Read the statement program header starting at OFFSET in
+ dwarf_line_buffer, according to the endianness of ABFD. Return a
+ pointer to a struct line_header, allocated using xmalloc.
- struct filenames files;
- struct directories dirs;
+ NOTE: the strings in the include directory and file name tables of
+ the returned object point into debug_line_buffer, and must not be
+ freed. */
+static struct line_header *
+dwarf_decode_line_header (unsigned int offset, bfd *abfd,
+ const struct comp_unit_head *cu_header)
+{
+ struct cleanup *back_to;
+ struct line_header *lh;
+ char *line_ptr;
+ int bytes_read;
+ int i;
+ char *cur_dir, *cur_file;
if (dwarf_line_buffer == NULL)
{
complain (&dwarf2_missing_line_number_section);
- return;
+ return 0;
}
- files.num_files = 0;
- files.files = NULL;
+ /* Make sure that at least there's room for the total_length field. That
+ could be 12 bytes long, but we're just going to fudge that. */
+ if (offset + 4 >= dwarf_line_size)
+ {
+ complain (&dwarf2_statement_list_fits_in_line_number_section);
+ return 0;
+ }
- dirs.num_dirs = 0;
- dirs.dirs = NULL;
+ lh = xmalloc (sizeof (*lh));
+ memset (lh, 0, sizeof (*lh));
+ back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
+ (void *) lh);
line_ptr = dwarf_line_buffer + offset;
- /* 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);
+ /* read in the header */
+ lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+ line_ptr += bytes_read;
+ if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+ {
+ complain (&dwarf2_statement_list_fits_in_line_number_section);
+ return 0;
+ }
+ lh->statement_program_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);
- line_ptr += 4;
- lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
+ lh->header_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+ line_ptr += bytes_read;
+ lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.default_is_stmt = read_1_byte (abfd, line_ptr);
+ lh->default_is_stmt = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.line_base = read_1_signed_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);
+ lh->line_range = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.opcode_base = read_1_byte (abfd, line_ptr);
+ lh->opcode_base = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.standard_opcode_lengths = (unsigned char *)
- xmalloc (lh.opcode_base * sizeof (unsigned char));
- back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths);
+ lh->standard_opcode_lengths
+ = (unsigned char *) xmalloc (lh->opcode_base * sizeof (unsigned char));
- lh.standard_opcode_lengths[0] = 1;
- for (i = 1; i < lh.opcode_base; ++i)
+ lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */
+ for (i = 1; i < lh->opcode_base; ++i)
{
- lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+ lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
line_ptr += 1;
}
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 = (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;
+ add_include_dir (lh, cur_dir);
}
line_ptr += bytes_read;
/* Read file name table */
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
+ unsigned int dir_index, mod_time, length;
+
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);
+ dir_index = 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);
+ mod_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);
+ length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
- files.num_files++;
+
+ add_file_name (lh, cur_file, dir_index, mod_time, length);
}
line_ptr += bytes_read;
+ lh->statement_program_start = line_ptr;
+
+ if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+ complain (&dwarf2_line_header_too_long);
+
+ discard_cleanups (back_to);
+ return lh;
+}
+
+/* This function exists to work around a bug in certain compilers
+ (particularly GCC 2.95), in which the first line number marker of a
+ function does not show up until after the prologue, right before
+ the second line number marker. This function shifts ADDRESS down
+ to the beginning of the function if necessary, and is called on
+ addresses passed to record_line. */
+
+static CORE_ADDR
+check_cu_functions (CORE_ADDR address)
+{
+ struct function_range *fn;
+
+ /* Find the function_range containing address. */
+ if (!cu_first_fn)
+ return address;
+
+ if (!cu_cached_fn)
+ cu_cached_fn = cu_first_fn;
+
+ fn = cu_cached_fn;
+ while (fn)
+ if (fn->lowpc <= address && fn->highpc > address)
+ goto found;
+ else
+ fn = fn->next;
+
+ fn = cu_first_fn;
+ while (fn && fn != cu_cached_fn)
+ if (fn->lowpc <= address && fn->highpc > address)
+ goto found;
+ else
+ fn = fn->next;
+
+ return address;
+
+ found:
+ if (fn->seen_line)
+ return address;
+ if (address != fn->lowpc)
+ complain (&dwarf2_misplaced_line_number,
+ (unsigned long) address, fn->name);
+ fn->seen_line = 1;
+ return fn->lowpc;
+}
+
+/* Decode the line number information for the compilation unit whose
+ line number info is at OFFSET in the .debug_line section.
+ The compilation directory of the file is passed in COMP_DIR. */
+
+static void
+dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
+ const struct comp_unit_head *cu_header)
+{
+ char *line_ptr;
+ char *line_end;
+ unsigned int i, bytes_read;
+ char *cur_dir;
+ unsigned char op_code, extended_op, adj_opcode;
+
+ line_ptr = lh->statement_program_start;
+ line_end = lh->statement_program_end;
/* Read the statement sequences until there's nothing left. */
while (line_ptr < line_end)
unsigned int file = 1;
unsigned int line = 1;
unsigned int column = 0;
- int is_stmt = lh.default_is_stmt;
+ 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)
+ if (lh->num_file_names >= 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));
+ /* lh->include_dirs and lh->file_names are 0-based, but the
+ directory and file name numbers in the statement program
+ are 1-based. */
+ struct file_entry *fe = &lh->file_names[file - 1];
+ char *dir;
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+ dwarf2_start_subfile (fe->name, dir);
}
/* Decode the table. */
- while (! end_sequence)
+ while (!end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- switch (op_code)
+
+ if (op_code >= lh->opcode_base)
+ { /* 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 */
+ address = check_cu_functions (address);
+ record_line (current_subfile, line, address);
+ basic_block = 1;
+ }
+ else switch (op_code)
{
case DW_LNS_extended_op:
line_ptr += 1; /* ignore length */
{
case DW_LNE_end_sequence:
end_sequence = 1;
- record_line (current_subfile, line, address);
+ record_line (current_subfile, 0, address);
break;
case DW_LNE_set_address:
- address = read_address (abfd, line_ptr) + baseaddr;
- line_ptr += address_size;
+ address = read_address (abfd, line_ptr, cu_header, &bytes_read);
+ line_ptr += bytes_read;
+ address += baseaddr;
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++;
+ {
+ char *cur_file;
+ unsigned int dir_index, mod_time, length;
+
+ cur_file = read_string (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ dir_index =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ mod_time =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ length =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ add_file_name (lh, cur_file, dir_index, mod_time, length);
+ }
break;
default:
complain (&dwarf2_mangled_line_number_section);
- goto done;
+ return;
}
break;
case DW_LNS_copy:
+ address = check_cu_functions (address);
record_line (current_subfile, line, address);
basic_block = 0;
break;
case DW_LNS_advance_pc:
- address += lh.minimum_instruction_length
+ address += lh->minimum_instruction_length
* read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
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));
+ {
+ /* lh->include_dirs and lh->file_names are 0-based,
+ but the directory and file name numbers in the
+ statement program are 1-based. */
+ struct file_entry *fe;
+ char *dir;
+ file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ fe = &lh->file_names[file - 1];
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+ dwarf2_start_subfile (fe->name, dir);
+ }
break;
case DW_LNS_set_column:
column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
case DW_LNS_set_basic_block:
basic_block = 1;
break;
+ /* Add to the address register of the state machine the
+ address increment value corresponding to special opcode
+ 255. Ie, this value is scaled by the minimum instruction
+ length since special opcode 255 would have scaled the
+ the increment. */
case DW_LNS_const_add_pc:
- address += (255 - lh.opcode_base) / lh.line_range;
+ address += (lh->minimum_instruction_length
+ * ((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;
+ default:
+ { /* Unknown standard opcode, ignore it. */
+ int i;
+ for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
+ {
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ }
+ }
}
}
}
-done:
- do_cleanups (back_to);
}
/* Start a subfile for DWARF. FILENAME is the name of the file and
/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
+ 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;
+dwarf2_start_subfile (char *filename, char *dirname)
{
/* If the filename isn't absolute, try to match an existing subfile
with the full pathname. */
- if (*filename != '/' && dirname != NULL)
+ if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
{
struct subfile *subfile;
char *fullname = concat (dirname, "/", filename, NULL);
for (subfile = subfiles; subfile; subfile = subfile->next)
{
- if (STREQ (subfile->name, fullname))
+ if (FILENAME_CMP (subfile->name, fullname) == 0)
{
current_subfile = subfile;
- free (fullname);
+ xfree (fullname);
return;
}
}
- free (fullname);
+ xfree (fullname);
}
start_subfile (filename, dirname);
}
to make a symbol table entry for it, and if so, create a new entry
and return a pointer to it.
If TYPE is NULL, determine symbol type from the die, otherwise
- used the passed type.
- */
+ used the passed type. */
static struct symbol *
-new_symbol (die, type, objfile)
- struct die_info *die;
- struct type *type;
- struct objfile *objfile;
+new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct symbol *sym = NULL;
char *name;
&objfile->symbol_obstack);
/* Default assumptions.
- Use the passed type or decode it from the die. */
+ Use the passed type or decode it from the die. */
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_CLASS (sym) = LOC_STATIC;
if (type != NULL)
SYMBOL_TYPE (sym) = type;
else
- SYMBOL_TYPE (sym) = die_type (die, objfile);
+ SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header);
attr = dwarf_attr (die, DW_AT_decl_line);
if (attr)
{
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile);
+ dwarf2_const_value (attr, sym, objfile, cu_header);
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
add_symbol_to_list (sym, &global_symbols);
if (attr2 && (DW_UNSND (attr2) != 0))
{
SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile);
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
add_symbol_to_list (sym, &global_symbols);
- /* In shared libraries the address of the variable
+ /* In shared libraries the address of the variable
in the location descriptor might still be relocatable,
so its value could be zero.
Enter the symbol as a LOC_UNRESOLVED symbol, if its
the variable is referenced. */
if (SYMBOL_VALUE_ADDRESS (sym))
{
- SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
}
else
else
{
SYMBOL_VALUE (sym) = addr =
- decode_locdesc (DW_BLOCK (attr), objfile);
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
add_symbol_to_list (sym, list_in_scope);
if (optimized_out)
{
else if (isreg)
{
SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) =
+ DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
}
else if (offreg)
{
SYMBOL_CLASS (sym) = LOC_BASEREG;
- SYMBOL_BASEREG (sym) = basereg;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
}
else if (islocal)
{
}
else
{
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) =
+ addr + ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
- SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
}
}
}
else
{
/* We do not know the address of this symbol.
- If it is an external symbol and we have type information
- for 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. */
+ If it is an external symbol and we have type information
+ for 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)
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
+ SYMBOL_VALUE (sym) =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
if (isreg)
{
SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) =
+ DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
}
else if (offreg)
{
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = basereg;
+ if (isderef)
+ {
+ if (basereg != frame_base_reg)
+ complain (&dwarf2_complex_location_expr);
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+ }
}
else
{
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile);
+ dwarf2_const_value (attr, sym, objfile, cu_header);
}
add_symbol_to_list (sym, list_in_scope);
break;
if (cu_language == language_cplus)
{
struct symbol *typedef_sym = (struct symbol *)
- obstack_alloc (&objfile->symbol_obstack,
- sizeof (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)
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile);
+ dwarf2_const_value (attr, sym, objfile, cu_header);
}
add_symbol_to_list (sym, list_in_scope);
break;
/* Copy constant value from an attribute to a symbol. */
static void
-dwarf2_const_value (attr, sym, objfile)
- struct attribute *attr;
- struct symbol *sym;
- struct objfile *objfile;
+dwarf2_const_value (struct attribute *attr, struct symbol *sym,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct dwarf_block *blk;
switch (attr->form)
{
case DW_FORM_addr:
- if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != (unsigned int) address_size)
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
- address_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ cu_header->addr_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
- obstack_alloc (&objfile->symbol_obstack, address_size);
- store_address (SYMBOL_VALUE_BYTES (sym), address_size, DW_ADDR (attr));
+ obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size);
+ store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
+ DW_ADDR (attr));
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
case DW_FORM_block1:
memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
+
+ /* The DW_AT_const_value attributes are supposed to carry the
+ symbol's value "represented as it would be on the target
+ architecture." By the time we get here, it's already been
+ converted to host endianness, so we just need to sign- or
+ zero-extend it as appropriate. */
+ case DW_FORM_data1:
+ dwarf2_const_value_data (attr, sym, 8);
+ break;
case DW_FORM_data2:
+ dwarf2_const_value_data (attr, sym, 16);
+ break;
case DW_FORM_data4:
+ dwarf2_const_value_data (attr, sym, 32);
+ break;
case DW_FORM_data8:
- case DW_FORM_data1:
+ dwarf2_const_value_data (attr, sym, 64);
+ break;
+
case DW_FORM_sdata:
+ SYMBOL_VALUE (sym) = DW_SND (attr);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ break;
+
case DW_FORM_udata:
SYMBOL_VALUE (sym) = DW_UNSND (attr);
SYMBOL_CLASS (sym) = LOC_CONST;
break;
+
default:
complain (&dwarf2_unsupported_const_value_attr,
dwarf_form_name (attr->form));
}
}
+
+/* Given an attr with a DW_FORM_dataN value in host byte order, sign-
+ or zero-extend it as appropriate for the symbol's type. */
+static void
+dwarf2_const_value_data (struct attribute *attr,
+ struct symbol *sym,
+ int bits)
+{
+ LONGEST l = DW_UNSND (attr);
+
+ if (bits < sizeof (l) * 8)
+ {
+ if (TYPE_UNSIGNED (SYMBOL_TYPE (sym)))
+ l &= ((LONGEST) 1 << bits) - 1;
+ else
+ l = (l << (sizeof (l) * 8 - bits)) >> (sizeof (l) * 8 - bits);
+ }
+
+ SYMBOL_VALUE (sym) = l;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+}
+
+
/* Return the type of the die in question using its DW_AT_type attribute. */
static struct type *
-die_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+die_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *type_attr;
return NULL;
}
}
- type = tag_type_to_type (type_die, objfile);
+ type = tag_type_to_type (type_die, objfile, cu_header);
if (!type)
{
dump_die (type_die);
DW_AT_containing_type attribute. */
static struct type *
-die_containing_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+die_containing_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type = NULL;
struct attribute *type_attr;
error ("Dwarf Error: Cannot find referent at offset %d.", ref);
return NULL;
}
- type = tag_type_to_type (type_die, objfile);
+ type = tag_type_to_type (type_die, objfile, cu_header);
}
if (!type)
{
#if 0
static struct type *
-type_at_offset (offset, objfile)
- unsigned int offset;
- struct objfile *objfile;
+type_at_offset (unsigned int offset, struct objfile *objfile)
{
struct die_info *die;
struct type *type;
#endif
static struct type *
-tag_type_to_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+tag_type_to_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
if (die->type)
{
}
else
{
- read_type_die (die, objfile);
+ read_type_die (die, objfile, cu_header);
if (!die->type)
{
dump_die (die);
}
static void
-read_type_die (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_type_die (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
switch (die->tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile);
+ read_structure_scope (die, objfile, cu_header);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile);
+ read_enumeration (die, objfile, cu_header);
break;
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile);
+ read_subroutine_type (die, objfile, cu_header);
break;
case DW_TAG_array_type:
- read_array_type (die, objfile);
+ read_array_type (die, objfile, cu_header);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile);
+ read_tag_pointer_type (die, objfile, cu_header);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile);
+ read_tag_ptr_to_member_type (die, objfile, cu_header);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile);
+ read_tag_reference_type (die, objfile, cu_header);
break;
case DW_TAG_const_type:
- read_tag_const_type (die, objfile);
+ read_tag_const_type (die, objfile, cu_header);
break;
case DW_TAG_volatile_type:
- read_tag_volatile_type (die, objfile);
+ read_tag_volatile_type (die, objfile, cu_header);
break;
case DW_TAG_string_type:
read_tag_string_type (die, objfile);
break;
case DW_TAG_typedef:
- read_typedef (die, objfile);
+ read_typedef (die, objfile, cu_header);
break;
case DW_TAG_base_type:
read_base_type (die, objfile);
}
static struct type *
-dwarf_base_type (encoding, size, objfile)
- int encoding;
- int size;
- struct objfile *objfile;
+dwarf_base_type (int encoding, int size, struct objfile *objfile)
{
/* FIXME - this should not produce a new (struct type *)
every time. It should cache base types. */
#if 0
struct die_info *
-copy_die (old_die)
- struct die_info *old_die;
+copy_die (struct die_info *old_die)
{
struct die_info *new_die;
int i, num_attrs;
/* Return sibling of die, NULL if no sibling. */
-struct die_info *
-sibling_die (die)
- struct die_info *die;
+static struct die_info *
+sibling_die (struct die_info *die)
{
int nesting_level = 0;
/* Get linkage name of a die, return NULL if not found. */
static char *
-dwarf2_linkage_name (die)
- struct die_info *die;
+dwarf2_linkage_name (struct die_info *die)
{
struct attribute *attr;
/* Convert a DIE tag into its string name. */
static char *
-dwarf_tag_name (tag)
- register unsigned tag;
+dwarf_tag_name (register unsigned tag)
{
switch (tag)
{
/* Convert a DWARF attribute code into its string name. */
static char *
-dwarf_attr_name (attr)
- register unsigned attr;
+dwarf_attr_name (register unsigned attr)
{
switch (attr)
{
return "DW_AT_body_begin";
case DW_AT_body_end:
return "DW_AT_body_end";
+ case DW_AT_GNU_vector:
+ return "DW_AT_GNU_vector";
default:
return "DW_AT_<unknown>";
}
/* Convert a DWARF value form code into its string name. */
static char *
-dwarf_form_name (form)
- register unsigned form;
+dwarf_form_name (register unsigned form)
{
switch (form)
{
/* Convert a DWARF stack opcode into its string name. */
static char *
-dwarf_stack_op_name (op)
- register unsigned op;
+dwarf_stack_op_name (register unsigned op)
{
switch (op)
{
}
static char *
-dwarf_bool_name (bool)
- unsigned bool;
+dwarf_bool_name (unsigned mybool)
{
- if (bool)
+ if (mybool)
return "TRUE";
else
return "FALSE";
/* Convert a DWARF type code into its string name. */
static char *
-dwarf_type_encoding_name (enc)
- register unsigned enc;
+dwarf_type_encoding_name (register unsigned enc)
{
switch (enc)
{
#if 0
static char *
-dwarf_cfi_name (cfi_opc)
- register unsigned cfi_opc;
+dwarf_cfi_name (register unsigned cfi_opc)
{
switch (cfi_opc)
{
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+
+ /* DWARF 3 */
+ case DW_CFA_def_cfa_expression:
+ return "DW_CFA_def_cfa_expression";
+ case DW_CFA_expression:
+ return "DW_CFA_expression";
+ case DW_CFA_offset_extended_sf:
+ return "DW_CFA_offset_extended_sf";
+ case DW_CFA_def_cfa_sf:
+ return "DW_CFA_def_cfa_sf";
+ case DW_CFA_def_cfa_offset_sf:
+ return "DW_CFA_def_cfa_offset_sf";
+
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
+
+ /* GNU extensions */
+ case DW_CFA_GNU_window_save:
+ return "DW_CFA_GNU_window_save";
+ case DW_CFA_GNU_args_size:
+ return "DW_CFA_GNU_args_size";
+ case DW_CFA_GNU_negative_offset_extended:
+ return "DW_CFA_GNU_negative_offset_extended";
+
default:
return "DW_CFA_<unknown>";
}
}
#endif
-void
-dump_die (die)
- struct die_info *die;
+static void
+dump_die (struct die_info *die)
{
unsigned int i;
- fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
+ fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
- fprintf (stderr, "\thas children: %s\n",
+ fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
dwarf_bool_name (die->has_children));
- fprintf (stderr, "\tattributes:\n");
+ fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
for (i = 0; i < die->num_attrs; ++i)
{
- fprintf (stderr, "\t\t%s (%s) ",
+ fprintf_unfiltered (gdb_stderr, "\t\t%s (%s) ",
dwarf_attr_name (die->attrs[i].name),
dwarf_form_name (die->attrs[i].form));
switch (die->attrs[i].form)
{
case DW_FORM_ref_addr:
case DW_FORM_addr:
- fprintf (stderr, "address: ");
- print_address_numeric (DW_ADDR (&die->attrs[i]), 1, stderr);
+ fprintf_unfiltered (gdb_stderr, "address: ");
+ print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
+ fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
+ case DW_FORM_data8:
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_udata:
case DW_FORM_sdata:
- fprintf (stderr, "constant: %d", DW_UNSND (&die->attrs[i]));
+ fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
case DW_FORM_string:
- fprintf (stderr, "string: \"%s\"",
+ case DW_FORM_strp:
+ fprintf_unfiltered (gdb_stderr, "string: \"%s\"",
DW_STRING (&die->attrs[i])
- ? DW_STRING (&die->attrs[i]) : "");
+ ? DW_STRING (&die->attrs[i]) : "");
break;
case DW_FORM_flag:
if (DW_UNSND (&die->attrs[i]))
- fprintf (stderr, "flag: TRUE");
+ fprintf_unfiltered (gdb_stderr, "flag: TRUE");
else
- fprintf (stderr, "flag: FALSE");
+ fprintf_unfiltered (gdb_stderr, "flag: FALSE");
+ break;
+ case DW_FORM_indirect:
+ /* the reader will have reduced the indirect form to
+ the "base form" so this form should not occur */
+ fprintf_unfiltered (gdb_stderr, "unexpected attribute form: DW_FORM_indirect");
break;
- case DW_FORM_strp: /* we do not support separate string
- section yet */
- case DW_FORM_indirect: /* we do not handle indirect yet */
- case DW_FORM_data8: /* we do not have 64 bit quantities */
default:
- fprintf (stderr, "unsupported attribute form: %d.",
- die->attrs[i].form);
+ fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.",
+ die->attrs[i].form);
}
- fprintf (stderr, "\n");
+ fprintf_unfiltered (gdb_stderr, "\n");
}
}
-void
-dump_die_list (die)
- struct die_info *die;
+static void
+dump_die_list (struct die_info *die)
{
while (die)
{
}
}
-void
-store_in_ref_table (offset, die)
- unsigned int offset;
- struct die_info *die;
+static void
+store_in_ref_table (unsigned int offset, struct die_info *die)
{
int h;
struct die_info *old;
static void
-dwarf2_empty_die_ref_table ()
+dwarf2_empty_hash_tables (void)
{
memset (die_ref_table, 0, sizeof (die_ref_table));
}
static unsigned int
-dwarf2_get_ref_die_offset (attr)
- struct attribute *attr;
+dwarf2_get_ref_die_offset (struct attribute *attr)
{
unsigned int result = 0;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
+ case DW_FORM_ref8:
case DW_FORM_ref_udata:
result = cu_header_offset + DW_UNSND (attr);
break;
return result;
}
-struct die_info *
-follow_die_ref (offset)
- unsigned int offset;
+static struct die_info *
+follow_die_ref (unsigned int offset)
{
struct die_info *die;
int h;
}
static struct type *
-dwarf2_fundamental_type (objfile, typeid)
- struct objfile *objfile;
- int typeid;
+dwarf2_fundamental_type (struct objfile *objfile, int typeid)
{
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
{
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;
+decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
int i;
int size = blk->size;
stack[stacki] = 0;
isreg = 0;
offreg = 0;
+ isderef = 0;
islocal = 0;
optimized_out = 1;
op = data[i++];
switch (op)
{
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ stack[++stacki] = op - DW_OP_lit0;
+ break;
+
case DW_OP_reg0:
case DW_OP_reg1:
case DW_OP_reg2:
i += bytes_read;
break;
+ case DW_OP_bregx:
+ offreg = 1;
+ basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ 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;
break;
case DW_OP_addr:
- stack[++stacki] = read_address (objfile->obfd, &data[i]);
- i += address_size;
+ stack[++stacki] = read_address (objfile->obfd, &data[i],
+ cu_header, &bytes_read);
+ i += bytes_read;
break;
case DW_OP_const1u:
case DW_OP_constu:
stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
- &bytes_read);
+ &bytes_read);
i += bytes_read;
break;
i += bytes_read;
break;
+ case DW_OP_dup:
+ stack[stacki + 1] = stack[stacki];
+ stacki++;
+ break;
+
case DW_OP_plus:
stack[stacki - 1] += stack[stacki];
stacki--;
break;
case DW_OP_minus:
- stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
+ stack[stacki - 1] -= stack[stacki];
stacki--;
break;
+ case DW_OP_deref:
+ isderef = 1;
+ /* If we're not the last op, then we definitely can't encode
+ this using GDB's address_class enum. */
+ if (i < size)
+ complain (&dwarf2_complex_location_expr);
+ break;
+
default:
- complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name(op));
+ complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
return (stack[stacki]);
}
}
/* ARGSUSED */
static void
-dwarf2_free_tmp_obstack (ignore)
- PTR ignore;
+dwarf2_free_tmp_obstack (PTR ignore)
{
obstack_free (&dwarf2_tmp_obstack, NULL);
}
static struct dwarf_block *
-dwarf_alloc_block ()
+dwarf_alloc_block (void)
{
struct dwarf_block *blk;
}
static struct abbrev_info *
-dwarf_alloc_abbrev ()
+dwarf_alloc_abbrev (void)
{
struct abbrev_info *abbrev;
}
static struct die_info *
-dwarf_alloc_die ()
+dwarf_alloc_die (void)
{
struct die_info *die;
memset (die, 0, sizeof (struct die_info));
return (die);
}
+
+\f
+/* Macro support. */
+
+
+/* Return the full name of file number I in *LH's file name table.
+ Use COMP_DIR as the name of the current directory of the
+ compilation. The result is allocated using xmalloc; the caller is
+ responsible for freeing it. */
+static char *
+file_full_name (int file, struct line_header *lh, const char *comp_dir)
+{
+ struct file_entry *fe = &lh->file_names[file - 1];
+
+ if (IS_ABSOLUTE_PATH (fe->name))
+ return xstrdup (fe->name);
+ else
+ {
+ const char *dir;
+ int dir_len;
+ char *full_name;
+
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+
+ if (dir)
+ {
+ dir_len = strlen (dir);
+ full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
+ strcpy (full_name, dir);
+ full_name[dir_len] = '/';
+ strcpy (full_name + dir_len + 1, fe->name);
+ return full_name;
+ }
+ else
+ return xstrdup (fe->name);
+ }
+}
+
+
+static struct macro_source_file *
+macro_start_file (int file, int line,
+ struct macro_source_file *current_file,
+ const char *comp_dir,
+ struct line_header *lh, struct objfile *objfile)
+{
+ /* The full name of this source file. */
+ char *full_name = file_full_name (file, lh, comp_dir);
+
+ /* We don't create a macro table for this compilation unit
+ at all until we actually get a filename. */
+ if (! pending_macros)
+ pending_macros = new_macro_table (&objfile->symbol_obstack,
+ &objfile->macro_cache);
+
+ if (! current_file)
+ /* If we have no current file, then this must be the start_file
+ directive for the compilation unit's main source file. */
+ current_file = macro_set_main (pending_macros, full_name);
+ else
+ current_file = macro_include (current_file, line, full_name);
+
+ xfree (full_name);
+
+ return current_file;
+}
+
+
+/* Copy the LEN characters at BUF to a xmalloc'ed block of memory,
+ followed by a null byte. */
+static char *
+copy_string (const char *buf, int len)
+{
+ char *s = xmalloc (len + 1);
+ memcpy (s, buf, len);
+ s[len] = '\0';
+
+ return s;
+}
+
+
+static const char *
+consume_improper_spaces (const char *p, const char *body)
+{
+ if (*p == ' ')
+ {
+ complain (&dwarf2_macro_spaces_in_definition, body);
+
+ while (*p == ' ')
+ p++;
+ }
+
+ return p;
+}
+
+
+static void
+parse_macro_definition (struct macro_source_file *file, int line,
+ const char *body)
+{
+ const char *p;
+
+ /* The body string takes one of two forms. For object-like macro
+ definitions, it should be:
+
+ <macro name> " " <definition>
+
+ For function-like macro definitions, it should be:
+
+ <macro name> "() " <definition>
+ or
+ <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
+
+ Spaces may appear only where explicitly indicated, and in the
+ <definition>.
+
+ The Dwarf 2 spec says that an object-like macro's name is always
+ followed by a space, but versions of GCC around March 2002 omit
+ the space when the macro's definition is the empty string.
+
+ The Dwarf 2 spec says that there should be no spaces between the
+ formal arguments in a function-like macro's formal argument list,
+ but versions of GCC around March 2002 include spaces after the
+ commas. */
+
+
+ /* Find the extent of the macro name. The macro name is terminated
+ by either a space or null character (for an object-like macro) or
+ an opening paren (for a function-like macro). */
+ for (p = body; *p; p++)
+ if (*p == ' ' || *p == '(')
+ break;
+
+ if (*p == ' ' || *p == '\0')
+ {
+ /* It's an object-like macro. */
+ int name_len = p - body;
+ char *name = copy_string (body, name_len);
+ const char *replacement;
+
+ if (*p == ' ')
+ replacement = body + name_len + 1;
+ else
+ {
+ complain (&dwarf2_macro_malformed_definition, body);
+ replacement = body + name_len;
+ }
+
+ macro_define_object (file, line, name, replacement);
+
+ xfree (name);
+ }
+ else if (*p == '(')
+ {
+ /* It's a function-like macro. */
+ char *name = copy_string (body, p - body);
+ int argc = 0;
+ int argv_size = 1;
+ char **argv = xmalloc (argv_size * sizeof (*argv));
+
+ p++;
+
+ p = consume_improper_spaces (p, body);
+
+ /* Parse the formal argument list. */
+ while (*p && *p != ')')
+ {
+ /* Find the extent of the current argument name. */
+ const char *arg_start = p;
+
+ while (*p && *p != ',' && *p != ')' && *p != ' ')
+ p++;
+
+ if (! *p || p == arg_start)
+ complain (&dwarf2_macro_malformed_definition,
+ body);
+ else
+ {
+ /* Make sure argv has room for the new argument. */
+ if (argc >= argv_size)
+ {
+ argv_size *= 2;
+ argv = xrealloc (argv, argv_size * sizeof (*argv));
+ }
+
+ argv[argc++] = copy_string (arg_start, p - arg_start);
+ }
+
+ p = consume_improper_spaces (p, body);
+
+ /* Consume the comma, if present. */
+ if (*p == ',')
+ {
+ p++;
+
+ p = consume_improper_spaces (p, body);
+ }
+ }
+
+ if (*p == ')')
+ {
+ p++;
+
+ if (*p == ' ')
+ /* Perfectly formed definition, no complaints. */
+ macro_define_function (file, line, name,
+ argc, (const char **) argv,
+ p + 1);
+ else if (*p == '\0')
+ {
+ /* Complain, but do define it. */
+ complain (&dwarf2_macro_malformed_definition, body);
+ macro_define_function (file, line, name,
+ argc, (const char **) argv,
+ p);
+ }
+ else
+ /* Just complain. */
+ complain (&dwarf2_macro_malformed_definition, body);
+ }
+ else
+ /* Just complain. */
+ complain (&dwarf2_macro_malformed_definition, body);
+
+ xfree (name);
+ {
+ int i;
+
+ for (i = 0; i < argc; i++)
+ xfree (argv[i]);
+ }
+ xfree (argv);
+ }
+ else
+ complain (&dwarf2_macro_malformed_definition, body);
+}
+
+
+static void
+dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+ char *comp_dir, bfd *abfd,
+ const struct comp_unit_head *cu_header,
+ struct objfile *objfile)
+{
+ char *mac_ptr, *mac_end;
+ struct macro_source_file *current_file = 0;
+
+ if (dwarf_macinfo_buffer == NULL)
+ {
+ complain (&dwarf2_missing_macinfo_section);
+ return;
+ }
+
+ mac_ptr = dwarf_macinfo_buffer + offset;
+ mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+
+ for (;;)
+ {
+ enum dwarf_macinfo_record_type macinfo_type;
+
+ /* Do we at least have room for a macinfo type byte? */
+ if (mac_ptr >= mac_end)
+ {
+ complain (&dwarf2_macros_too_long);
+ return;
+ }
+
+ macinfo_type = read_1_byte (abfd, mac_ptr);
+ mac_ptr++;
+
+ switch (macinfo_type)
+ {
+ /* A zero macinfo type indicates the end of the macro
+ information. */
+ case 0:
+ return;
+
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ {
+ int bytes_read;
+ int line;
+ char *body;
+
+ line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+ body = read_string (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+
+ if (! current_file)
+ complain (&dwarf2_macro_outside_file,
+ macinfo_type == DW_MACINFO_define ? "definition" :
+ macinfo_type == DW_MACINFO_undef ? "undefinition" :
+ "something-or-other",
+ body);
+ else
+ {
+ if (macinfo_type == DW_MACINFO_define)
+ parse_macro_definition (current_file, line, body);
+ else if (macinfo_type == DW_MACINFO_undef)
+ macro_undef (current_file, line, body);
+ }
+ }
+ break;
+
+ case DW_MACINFO_start_file:
+ {
+ int bytes_read;
+ int line, file;
+
+ line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+ file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+
+ current_file = macro_start_file (file, line,
+ current_file, comp_dir,
+ lh, objfile);
+ }
+ break;
+
+ case DW_MACINFO_end_file:
+ if (! current_file)
+ complain (&dwarf2_macro_unmatched_end_file);
+ else
+ {
+ current_file = current_file->included_by;
+ if (! current_file)
+ {
+ enum dwarf_macinfo_record_type next_type;
+
+ /* GCC circa March 2002 doesn't produce the zero
+ type byte marking the end of the compilation
+ unit. Complain if it's not there, but exit no
+ matter what. */
+
+ /* Do we at least have room for a macinfo type byte? */
+ if (mac_ptr >= mac_end)
+ {
+ complain (&dwarf2_macros_too_long);
+ return;
+ }
+
+ /* We don't increment mac_ptr here, so this is just
+ a look-ahead. */
+ next_type = read_1_byte (abfd, mac_ptr);
+ if (next_type != 0)
+ complain (&dwarf2_macros_not_terminated);
+
+ return;
+ }
+ }
+ break;
+
+ case DW_MACINFO_vendor_ext:
+ {
+ int bytes_read;
+ int constant;
+ char *string;
+
+ constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+ string = read_string (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+
+ /* We don't recognize any vendor extensions. */
+ }
+ break;
+ }
+ }
+}