#include "defs.h"
#include "bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "objfiles.h"
#include "elf/dwarf2.h"
#include "buildsym.h"
#include "demangle.h"
#include "expression.h"
#include "filenames.h"
#include "macrotab.h"
#include "language.h"
#include "complaints.h"
#include "bcache.h"
#include "dwarf2expr.h"
#include "dwarf2loc.h"
#include "cp-support.h"
#include "hashtab.h"
#include "command.h"
#include "gdbcmd.h"
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_assert.h"
#include <sys/types.h>
#include "db-access-functions.h"
#include "symfile.h"
#ifndef DWARF2_REG_TO_REGNUM
#define DWARF2_REG_TO_REGNUM(REG) (REG)
#endif
#if 0
typedef struct comp_unit_header
{
unsigned int length;
unsigned short version;
unsigned int abbrev_offset;
unsigned char addr_size;
}
_COMP_UNIT_HEADER;
#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
#endif
typedef struct pubnames_header
{
unsigned int length;
unsigned char version;
unsigned int info_offset;
unsigned int info_size;
}
_PUBNAMES_HEADER;
#define _ACTUAL_PUBNAMES_HEADER_SIZE 13
typedef struct aranges_header
{
unsigned int length;
unsigned short version;
unsigned int info_offset;
unsigned char addr_size;
unsigned char seg_size;
}
_ARANGES_HEADER;
#define _ACTUAL_ARANGES_HEADER_SIZE 12
typedef struct statement_prologue
{
unsigned int total_length;
unsigned short version;
unsigned int prologue_length;
unsigned char minimum_instruction_length;
unsigned char default_is_stmt;
char line_base;
unsigned char line_range;
unsigned char opcode_base;
unsigned char *standard_opcode_lengths;
}
_STATEMENT_PROLOGUE;
static const struct objfile_data *dwarf2_objfile_data_key;
struct dwarf2_per_objfile
{
unsigned int info_size;
unsigned int abbrev_size;
unsigned int line_size;
unsigned int pubnames_size;
unsigned int aranges_size;
unsigned int loc_size;
unsigned int macinfo_size;
unsigned int str_size;
unsigned int ranges_size;
unsigned int frame_size;
unsigned int eh_frame_size;
char *info_buffer;
char *abbrev_buffer;
char *line_buffer;
char *str_buffer;
char *macinfo_buffer;
char *ranges_buffer;
char *loc_buffer;
struct dwarf2_per_cu_data **all_comp_units;
int n_comp_units;
struct dwarf2_per_cu_data *read_in_chain;
};
struct oso_final_addr_tuple {
char *name;
CORE_ADDR oso_low_addr;
CORE_ADDR oso_high_addr;
CORE_ADDR final_addr;
int present_in_final;
};
struct oso_to_final_addr_map {
int entries;
struct oso_final_addr_tuple *tuples;
int common_entries;
struct oso_final_addr_tuple *common_pairs;
};
static struct dwarf2_per_objfile *dwarf2_per_objfile;
static asection *dwarf_info_section;
static asection *dwarf_abbrev_section;
static asection *dwarf_line_section;
static asection *dwarf_pubnames_section;
static asection *dwarf_aranges_section;
static asection *dwarf_loc_section;
static asection *dwarf_macinfo_section;
static asection *dwarf_str_section;
static asection *dwarf_ranges_section;
asection *dwarf_frame_section;
asection *dwarf_eh_frame_section;
#define INFO_SECTION "LC_SEGMENT.__DWARF.__debug_info"
#define ABBREV_SECTION "LC_SEGMENT.__DWARF.__debug_abbrev"
#define LINE_SECTION "LC_SEGMENT.__DWARF.__debug_line"
#define PUBNAMES_SECTION "LC_SEGMENT.__DWARF.__debug_pubnames"
#define ARANGES_SECTION "LC_SEGMENT.__DWARF.__debug_aranges"
#define LOC_SECTION "LC_SEGMENT.__DWARF.__debug_loc"
#define MACINFO_SECTION "LC_SEGMENT.__DWARF.__debug_macinfo"
#define STR_SECTION "LC_SEGMENT.__DWARF.__debug_str"
#define FRAME_SECTION "LC_SEGMENT.__DWARF.__debug_frame"
#define RANGES_SECTION "LC_SEGMENT.__DWARF.__debug_ranges"
#define EH_FRAME_SECTION ".eh_frame"
#ifndef ABBREV_HASH_SIZE
#define ABBREV_HASH_SIZE 121
#endif
struct comp_unit_head
{
unsigned long length;
short version;
unsigned int abbrev_offset;
unsigned char addr_size;
unsigned char signed_addr_p;
unsigned int offset_size;
unsigned int initial_length_size;
unsigned int offset;
char *cu_head_ptr;
char *first_die_ptr;
struct comp_unit_head *next;
CORE_ADDR base_address;
int base_known;
};
#ifndef REF_HASH_SIZE
#define REF_HASH_SIZE 1021
#endif
struct dwarf2_cu
{
struct objfile *objfile;
struct comp_unit_head header;
struct function_range *first_fn, *last_fn, *cached_fn;
enum language language;
const struct language_defn *language_defn;
const char *producer;
char *comp_dir;
struct pending **list_in_scope;
struct type *ftypes[FT_NUM_MEMBERS];
struct abbrev_info **dwarf2_abbrevs;
struct obstack abbrev_obstack;
htab_t partial_dies;
struct obstack comp_unit_obstack;
struct dwarf2_per_cu_data *read_in_chain;
struct dwarf2_per_cu_data *per_cu;
int last_used;
struct die_info *die_ref_table[REF_HASH_SIZE];
struct die_info *dies;
htab_t dependencies;
unsigned int mark : 1;
unsigned int has_form_ref_addr : 1;
unsigned int has_namespace_info : 1;
sqlite3 *repository;
char *repository_name;
struct oso_to_final_addr_map *addr_map;
};
struct dwarf2_per_cu_data
{
unsigned long offset;
unsigned long length : 31;
unsigned long queued : 1;
struct dwarf2_cu *cu;
htab_t type_hash;
struct partial_symtab *psymtab;
};
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;
unsigned char *standard_opcode_lengths;
unsigned int num_include_dirs, include_dirs_size;
char **include_dirs;
unsigned int num_file_names, file_names_size;
struct file_entry
{
char *name;
unsigned int dir_index;
unsigned int mod_time;
unsigned int length;
int included_p;
} *file_names;
char *statement_program_start, *statement_program_end;
};
struct partial_die_info
{
unsigned int offset;
ENUM_BITFIELD(dwarf_tag) tag : 16;
unsigned int language : 8;
unsigned int has_children : 1;
unsigned int is_external : 1;
unsigned int is_declaration : 1;
unsigned int has_type : 1;
unsigned int has_specification : 1;
unsigned int has_stmt_list : 1;
unsigned int has_pc_info : 1;
unsigned int has_repo_specification : 1;
unsigned int has_repository : 1;
unsigned int has_repository_type : 1;
unsigned int scope_set : 1;
char *name;
char *dirname;
char *scope;
struct dwarf_block *locdesc;
CORE_ADDR lowpc;
CORE_ADDR highpc;
char *sibling;
unsigned int spec_offset;
unsigned int repo_spec_id;
char *repo_name;
unsigned int line_offset;
struct partial_die_info *die_parent, *die_child, *die_sibling;
};
struct abbrev_info
{
unsigned int number;
enum dwarf_tag tag;
unsigned short has_children;
unsigned short num_attrs;
struct attr_abbrev *attrs;
struct abbrev_info *next;
};
struct attr_abbrev
{
enum dwarf_attribute name;
enum dwarf_form form;
};
struct die_info
{
enum dwarf_tag tag;
unsigned int abbrev;
unsigned int offset;
unsigned int repository_id;
unsigned int num_attrs;
struct attribute *attrs;
struct die_info *next_ref;
struct die_info *child;
struct die_info *sibling;
struct die_info *parent;
struct type *type;
};
struct attribute
{
enum dwarf_attribute name;
enum dwarf_form form;
union
{
char *str;
struct dwarf_block *blk;
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;
};
#define DW_STRING(attr) ((attr)->u.str)
#define DW_UNSND(attr) ((attr)->u.unsnd)
#define DW_BLOCK(attr) ((attr)->u.blk)
#define DW_SND(attr) ((attr)->u.snd)
#define DW_ADDR(attr) ((attr)->u.addr)
struct dwarf_block
{
unsigned int size;
char *data;
};
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4
#endif
#ifndef DW_FIELD_ALLOC_CHUNK
#define DW_FIELD_ALLOC_CHUNK 4
#endif
static int isreg;
static int bits_per_byte = 8;
struct field_info
{
struct nextfield
{
struct nextfield *next;
int accessibility;
int virtuality;
struct field field;
}
*fields;
int nfields;
int nbaseclasses;
int non_public_fields;
struct nextfnfield
{
struct nextfnfield *next;
struct fn_field fnfield;
}
*fnfields;
struct fnfieldlist
{
char *name;
int length;
struct nextfnfield *head;
}
*fnfieldlists;
int nfnfields;
};
struct dwarf2_queue_item
{
struct dwarf2_per_cu_data *per_cu;
struct dwarf2_queue_item *next;
};
static struct dwarf2_queue_item *dwarf2_queue, *dwarf2_queue_tail;
static int dwarf2_max_cache_age = 5;
static void
show_dwarf2_max_cache_age (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
The upper bound on the age of cached dwarf2 compilation units is %s.\n"),
value);
}
static int debug_debugmap = 0;
static void
show_debug_debugmap (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("DWARF debugmap debugging is %s.\n"), value);
}
static void
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
{
complaint (&symfile_complaints,
_("statement list doesn't fit in .debug_line section"));
}
static void
dwarf2_complex_location_expr_complaint (void)
{
complaint (&symfile_complaints, _("location expression too complex"));
}
static void
dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
int arg3)
{
complaint (&symfile_complaints,
_("const value length mismatch for '%s', got %d, expected %d"), arg1,
arg2, arg3);
}
static void
dwarf2_macros_too_long_complaint (void)
{
complaint (&symfile_complaints,
_("macro info runs off end of `.debug_macinfo' section"));
}
static void
dwarf2_macro_malformed_definition_complaint (const char *arg1)
{
complaint (&symfile_complaints,
_("macro debug info contains a malformed macro definition:\n`%s'"),
arg1);
}
static void
dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
{
complaint (&symfile_complaints,
_("invalid attribute class or form for '%s' in '%s'"), arg1, arg2);
}
static void dwarf2_locate_sections (bfd *, asection *, void *);
#if 0
static void dwarf2_build_psymtabs_easy (struct objfile *, int);
#endif
static void dwarf2_create_include_psymtab (char *, struct partial_symtab *,
struct objfile *);
static void dwarf2_build_include_psymtabs (struct dwarf2_cu *,
struct partial_die_info *,
struct partial_symtab *);
static void dwarf2_build_psymtabs_hard (struct objfile *, int);
static void scan_partial_symbols (struct partial_die_info *,
CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *);
static void add_partial_symbol (struct partial_die_info *,
struct dwarf2_cu *);
static int pdi_needs_namespace (enum dwarf_tag tag);
static void add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
struct dwarf2_cu *cu);
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
struct dwarf2_cu *cu);
static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
char *info_ptr,
bfd *abfd,
struct dwarf2_cu *cu);
static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
static void psymtab_to_symtab_1 (struct partial_symtab *);
char *dwarf2_read_section (struct objfile *, bfd *, asection *);
static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
static void dwarf2_free_abbrev_table (void *);
static struct abbrev_info *peek_die_abbrev (char *, int *, struct dwarf2_cu *);
static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
struct dwarf2_cu *);
static struct partial_die_info *load_partial_dies (bfd *, char *, int,
struct dwarf2_cu *);
static char *read_partial_die (struct partial_die_info *,
struct abbrev_info *abbrev, unsigned int,
bfd *, char *, struct dwarf2_cu *);
static struct partial_die_info *find_partial_die (unsigned long,
struct dwarf2_cu *);
static void fixup_partial_die (struct partial_die_info *,
struct dwarf2_cu *);
static char *read_full_die (struct die_info **, bfd *, char *,
struct dwarf2_cu *, int *);
static char *read_attribute (struct attribute *, struct attr_abbrev *,
bfd *, char *, struct dwarf2_cu *);
static char *read_attribute_value (struct attribute *, unsigned,
bfd *, char *, struct dwarf2_cu *);
static unsigned int read_1_byte (bfd *, char *);
static int read_1_signed_byte (bfd *, char *);
static unsigned int read_2_bytes (bfd *, char *);
static unsigned int read_4_bytes (bfd *, char *);
static unsigned long read_8_bytes (bfd *, char *);
static CORE_ADDR read_address (bfd *, char *ptr, struct dwarf2_cu *,
int *bytes_read);
static LONGEST read_initial_length (bfd *, char *,
struct comp_unit_head *, int *bytes_read);
static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
int *bytes_read);
static char *read_n_bytes (bfd *, char *, unsigned int);
static char *read_string (bfd *, char *, unsigned int *);
static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *,
unsigned int *);
static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
static long read_signed_leb128 (bfd *, char *, unsigned int *);
static char *skip_leb128 (bfd *, char *);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
struct dwarf2_cu *);
static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
struct dwarf2_cu *cu);
static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
static struct die_info *die_specification (struct die_info *die,
struct dwarf2_cu *);
static void free_line_header (struct line_header *lh);
static void add_file_name (struct line_header *, char *, unsigned int,
unsigned int, unsigned int);
static struct line_header *(dwarf_decode_line_header
(unsigned int offset,
bfd *abfd, struct dwarf2_cu *cu));
static void dwarf_decode_lines (struct line_header *, char *, bfd *,
struct dwarf2_cu *, struct partial_symtab *);
static void dwarf2_start_subfile (char *, char *, char *);
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *);
static void dwarf2_const_value (struct attribute *, struct symbol *,
struct dwarf2_cu *);
static void dwarf2_const_value_data (struct attribute *attr,
struct symbol *sym,
int bits);
static struct type *die_type (struct die_info *, struct dwarf2_cu *);
static struct type *die_containing_type (struct die_info *,
struct dwarf2_cu *);
static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *);
static void read_type_die (struct die_info *, struct dwarf2_cu *);
static char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
static char *typename_concat (struct obstack *, const char *prefix, const char *suffix,
struct dwarf2_cu *);
static void read_typedef (struct die_info *, struct dwarf2_cu *);
static void read_base_type (struct die_info *, struct dwarf2_cu *);
static void read_subrange_type (struct die_info *die, struct dwarf2_cu *cu);
static void read_file_scope (struct die_info *, struct dwarf2_cu *);
static void read_func_scope (struct die_info *, struct dwarf2_cu *);
static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
static int dwarf2_get_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *);
static void get_scope_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *);
static void dwarf2_add_field (struct field_info *, struct die_info *,
struct dwarf2_cu *);
static void dwarf2_attach_fields_to_type (struct field_info *,
struct type *, struct dwarf2_cu *);
static void dwarf2_add_member_fn (struct field_info *,
struct die_info *, struct type *,
struct dwarf2_cu *);
static void dwarf2_attach_fn_fields_to_type (struct field_info *,
struct type *, struct dwarf2_cu *);
static void read_structure_type (struct die_info *, struct dwarf2_cu *);
static void process_structure_scope (struct die_info *, struct dwarf2_cu *);
static char *determine_class_name (struct die_info *die, struct dwarf2_cu *cu);
static void read_common_block (struct die_info *, struct dwarf2_cu *);
static void read_namespace (struct die_info *die, struct dwarf2_cu *);
static const char *namespace_name (struct die_info *die,
int *is_anonymous, struct dwarf2_cu *);
static void read_enumeration_type (struct die_info *, struct dwarf2_cu *);
static void process_enumeration_scope (struct die_info *, struct dwarf2_cu *);
static struct type *dwarf_base_type (int, int, struct dwarf2_cu *);
static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *);
static void read_array_type (struct die_info *, struct dwarf2_cu *);
static enum dwarf_array_dim_ordering read_array_order (struct die_info *,
struct dwarf2_cu *);
static void read_tag_pointer_type (struct die_info *, struct dwarf2_cu *);
static void read_tag_ptr_to_member_type (struct die_info *,
struct dwarf2_cu *);
static void read_tag_reference_type (struct die_info *, struct dwarf2_cu *);
static void read_tag_const_type (struct die_info *, struct dwarf2_cu *);
static void read_tag_volatile_type (struct die_info *, struct dwarf2_cu *);
static void read_tag_string_type (struct die_info *, struct dwarf2_cu *);
static void read_subroutine_type (struct die_info *, struct dwarf2_cu *);
static struct die_info *read_comp_unit (char *, bfd *, struct dwarf2_cu *);
static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd,
struct dwarf2_cu *,
char **new_info_ptr,
struct die_info *parent);
static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd,
struct dwarf2_cu *,
char **new_info_ptr,
struct die_info *parent);
static void free_die_list (struct die_info *);
static void process_die (struct die_info *, struct dwarf2_cu *);
static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
static struct die_info *dwarf2_extension (struct die_info *die,
struct dwarf2_cu *);
static char *dwarf_tag_name (unsigned int);
static char *dwarf_attr_name (unsigned int);
static char *dwarf_form_name (unsigned int);
static char *dwarf_stack_op_name (unsigned int);
static char *dwarf_bool_name (unsigned int);
static char *dwarf_type_encoding_name (unsigned int);
#if 0
static char *dwarf_cfi_name (unsigned int);
struct die_info *copy_die (struct die_info *);
#endif
static struct die_info *sibling_die (struct die_info *);
static void dump_die (struct die_info *);
static void dump_die_list (struct die_info *);
static void store_in_ref_table (unsigned int, struct die_info *,
struct dwarf2_cu *);
static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
struct dwarf2_cu *);
static int dwarf2_get_attr_constant_value (struct attribute *, int);
static struct die_info *follow_die_ref (struct die_info *,
struct attribute *,
struct dwarf2_cu *);
static struct type *dwarf2_fundamental_type (struct objfile *, int,
struct dwarf2_cu *);
static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
static struct abbrev_info *dwarf_alloc_abbrev (struct dwarf2_cu *);
static struct die_info *dwarf_alloc_die (void);
static void initialize_cu_func_list (struct dwarf2_cu *);
static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR,
struct dwarf2_cu *);
static void dwarf_decode_macros (struct line_header *, unsigned int,
char *, bfd *, struct dwarf2_cu *);
static int attr_form_is_block (struct attribute *);
static void
dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu);
static char *skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
struct dwarf2_cu *cu);
static void free_stack_comp_unit (void *);
static void *hashtab_obstack_allocate (void *data, size_t size, size_t count);
static void dummy_obstack_deallocate (void *object, void *data);
static hashval_t partial_die_hash (const void *item);
static int partial_die_eq (const void *item_lhs, const void *item_rhs);
static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
(unsigned long offset, struct objfile *objfile);
static struct dwarf2_per_cu_data *dwarf2_find_comp_unit
(unsigned long offset, struct objfile *objfile);
static void free_one_comp_unit (void *);
static void free_cached_comp_units (void *);
static void age_cached_comp_units (void);
static void free_one_cached_comp_unit (void *);
static void set_die_type (struct die_info *, struct type *,
struct dwarf2_cu *);
static void reset_die_and_siblings_types (struct die_info *,
struct dwarf2_cu *);
static void create_all_comp_units (struct objfile *);
static struct dwarf2_cu *load_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
struct oso_to_final_addr_map *addr_map);
static void process_full_comp_unit (struct dwarf2_per_cu_data *);
static void dwarf2_add_dependence (struct dwarf2_cu *,
struct dwarf2_per_cu_data *);
static void dwarf2_mark (struct dwarf2_cu *);
static void dwarf2_clear_marks (struct dwarf2_per_cu_data *);
static int translate_debug_map_address (struct dwarf2_cu *, CORE_ADDR,
CORE_ADDR *, int);
static int
dwarf2_has_info_1 (struct objfile *objfile, bfd *abfd)
{
struct dwarf2_per_objfile *data;
data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
memset (data, 0, sizeof (*data));
set_objfile_data (objfile, dwarf2_objfile_data_key, data);
dwarf2_per_objfile = data;
dwarf_info_section = 0;
dwarf_abbrev_section = 0;
dwarf_line_section = 0;
dwarf_str_section = 0;
dwarf_macinfo_section = 0;
dwarf_frame_section = 0;
dwarf_eh_frame_section = 0;
dwarf_ranges_section = 0;
dwarf_loc_section = 0;
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL);
}
int
dwarf2_has_info (struct objfile *objfile)
{
return dwarf2_has_info_1 (objfile, objfile->obfd);
}
static void
dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, void *ignore_ptr)
{
if (strcmp (sectp->name, INFO_SECTION) == 0)
{
dwarf2_per_objfile->info_size = bfd_get_section_size (sectp);
dwarf_info_section = sectp;
}
else if (strcmp (sectp->name, ABBREV_SECTION) == 0)
{
dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp);
dwarf_abbrev_section = sectp;
}
else if (strcmp (sectp->name, LINE_SECTION) == 0)
{
dwarf2_per_objfile->line_size = bfd_get_section_size (sectp);
dwarf_line_section = sectp;
}
else if (strcmp (sectp->name, PUBNAMES_SECTION) == 0)
{
dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp);
dwarf_pubnames_section = sectp;
}
else if (strcmp (sectp->name, ARANGES_SECTION) == 0)
{
dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp);
dwarf_aranges_section = sectp;
}
else if (strcmp (sectp->name, LOC_SECTION) == 0)
{
dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp);
dwarf_loc_section = sectp;
}
else if (strcmp (sectp->name, MACINFO_SECTION) == 0)
{
dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp);
dwarf_macinfo_section = sectp;
}
else if (strcmp (sectp->name, STR_SECTION) == 0)
{
dwarf2_per_objfile->str_size = bfd_get_section_size (sectp);
dwarf_str_section = sectp;
}
else if (strcmp (sectp->name, FRAME_SECTION) == 0)
{
dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp);
dwarf_frame_section = sectp;
}
else if (strcmp (sectp->name, EH_FRAME_SECTION) == 0)
{
flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
if (aflag & SEC_HAS_CONTENTS)
{
dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp);
dwarf_eh_frame_section = sectp;
}
}
else if (strcmp (sectp->name, RANGES_SECTION) == 0)
{
dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp);
dwarf_ranges_section = sectp;
}
}
static void
dwarf2_copy_dwarf_from_file (struct objfile *objfile, bfd *abfd)
{
dwarf2_per_objfile->info_buffer = dwarf2_read_section (objfile, abfd,
dwarf_info_section);
dwarf2_per_objfile->abbrev_buffer = dwarf2_read_section (objfile, abfd,
dwarf_abbrev_section);
if (dwarf_line_section)
dwarf2_per_objfile->line_buffer = dwarf2_read_section (objfile, abfd,
dwarf_line_section);
else
dwarf2_per_objfile->line_buffer = NULL;
if (dwarf_str_section)
dwarf2_per_objfile->str_buffer = dwarf2_read_section (objfile, abfd,
dwarf_str_section);
else
dwarf2_per_objfile->str_buffer = NULL;
if (dwarf_macinfo_section)
dwarf2_per_objfile->macinfo_buffer = dwarf2_read_section (objfile,
abfd, dwarf_macinfo_section);
else
dwarf2_per_objfile->macinfo_buffer = NULL;
if (dwarf_ranges_section)
dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, abfd,
dwarf_ranges_section);
else
dwarf2_per_objfile->ranges_buffer = NULL;
if (dwarf_loc_section)
dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, abfd,
dwarf_loc_section);
else
dwarf2_per_objfile->loc_buffer = NULL;
}
void
dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
{
dwarf2_copy_dwarf_from_file (objfile, objfile->obfd);
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)
{
dwarf2_build_psymtabs_easy (objfile, mainline);
}
else
#endif
{
dwarf2_build_psymtabs_hard (objfile, mainline);
}
}
#if 0
static void
dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
{
bfd *abfd = objfile->obfd;
char *aranges_buffer, *pubnames_buffer;
char *aranges_ptr, *pubnames_ptr;
unsigned int entry_length, version, info_offset, info_size;
pubnames_buffer = dwarf2_read_section (objfile, objfile->ofd,
dwarf_pubnames_section);
pubnames_ptr = pubnames_buffer;
while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size)
{
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);
pubnames_ptr += 4;
info_size = read_4_bytes (abfd, pubnames_ptr);
pubnames_ptr += 4;
}
aranges_buffer = dwarf2_read_section (objfile, objfile->ofd,
dwarf_aranges_section);
}
#endif
static char *
read_comp_unit_head (struct comp_unit_head *cu_header,
char *info_ptr, bfd *abfd)
{
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;
cu_header->signed_addr_p = 0;
return info_ptr;
}
static char *
partial_read_comp_unit_head (struct comp_unit_head *header, char *info_ptr,
bfd *abfd)
{
char *beg_of_comp_unit = info_ptr;
info_ptr = read_comp_unit_head (header, info_ptr, abfd);
if (header->version != 2)
error (_("Dwarf Error: wrong version in compilation unit header "
"(is %d, should be %d) [in module %s]"), header->version,
2, bfd_get_filename (abfd));
if (header->abbrev_offset >= dwarf2_per_objfile->abbrev_size)
error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
"(offset 0x%lx + 6) [in module %s]"),
(long) header->abbrev_offset,
(long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
bfd_get_filename (abfd));
if (beg_of_comp_unit + header->length + header->initial_length_size
> dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
"(offset 0x%lx + 0) [in module %s]"),
(long) header->length,
(long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
bfd_get_filename (abfd));
return info_ptr;
}
static void
dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst,
struct objfile *objfile)
{
struct partial_symtab *subpst = allocate_psymtab (name, objfile);
subpst->section_offsets = pst->section_offsets;
subpst->textlow = 0;
subpst->texthigh = 0;
subpst->dependencies = (struct partial_symtab **)
obstack_alloc (&objfile->objfile_obstack,
sizeof (struct partial_symtab *));
subpst->dependencies[0] = pst;
subpst->number_of_dependencies = 1;
subpst->globals_offset = 0;
subpst->n_global_syms = 0;
subpst->statics_offset = 0;
subpst->n_static_syms = 0;
subpst->symtab = NULL;
subpst->read_symtab = pst->read_symtab;
subpst->readin = 0;
subpst->read_symtab_private = NULL;
}
static void
dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
struct partial_die_info *pdi,
struct partial_symtab *pst)
{
struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
struct line_header *lh;
lh = dwarf_decode_line_header (pdi->line_offset, abfd, cu);
if (lh == NULL)
return;
dwarf_decode_lines (lh, NULL, abfd, cu, pst);
free_line_header (lh);
}
static int open_dwarf_repository (char *, char *, struct objfile *,
struct dwarf2_cu *);
static void dwarf2_read_repository_abbrevs (struct dwarf2_cu *);
static struct dwarf2_cu *build_dummy_cu (struct objfile *, struct dwarf2_cu *);
static struct objfile *build_dummy_objfile (struct objfile *);
static void read_in_db_abbrev_table (struct abbrev_info **, sqlite3 *);
static void db_error (char *, char *, sqlite3 *);
static struct die_info *db_lookup_type (int , sqlite3 *, struct abbrev_info *);
static void fill_in_die_info (struct die_info *, int, uint8_t *, uint8_t *,
struct abbrev_info *, sqlite3 *);
static uint32_t get_uleb128 (uint8_t **);
static uint8_t *db_read_attribute_value (struct attribute *, unsigned,
uint8_t **);
static struct die_info *follow_db_ref (struct die_info *, struct attribute *,
struct dwarf2_cu *);
static void set_repository_cu_language (unsigned int, struct dwarf2_cu *);
static struct attribute *get_repository_name (struct attribute *,
struct dwarf2_cu *);
static int finalize_stmts (sqlite3 *);
static struct database_info *find_open_repository (sqlite3 *);
enum db_status { DB_UNKNOWN, DB_OPEN, DB_ABBREVS_LOADED, DB_CLOSED };
struct objfile_list_node {
struct objfile *ofile;
struct objfile_list_node *next;
};
struct database_info {
char *fullname;
struct abbrev_info *abbrev_table;
enum db_status current_status;
struct rb_tree_node *db_types;
struct objfile_list_node *num_uses;
struct dwarf2_cu *dummy_cu;
struct objfile *dummy_objfile;
sqlite3 *db;
};
static void increment_use_count (struct database_info *, struct objfile *);
static void decrement_use_count (struct database_info *, struct objfile *);
static int byte_swap_p;
static void
dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
{
bfd *abfd = objfile->obfd;
char *info_ptr;
char *beg_of_comp_unit;
struct partial_die_info comp_unit_die;
struct partial_symtab *pst;
struct cleanup *back_to;
CORE_ADDR lowpc, highpc, baseaddr;
if (bfd_big_endian (abfd) == BFD_ENDIAN_BIG)
byte_swap_p = 0;
else
byte_swap_p = 1;
info_ptr = dwarf2_per_objfile->info_buffer;
back_to = make_cleanup (free_cached_comp_units, NULL);
create_all_comp_units (objfile);
while (info_ptr < (dwarf2_per_objfile->info_buffer
+ dwarf2_per_objfile->info_size))
{
struct cleanup *back_to_inner;
struct dwarf2_cu cu;
struct abbrev_info *abbrev;
unsigned int bytes_read;
struct dwarf2_per_cu_data *this_cu;
beg_of_comp_unit = info_ptr;
memset (&cu, 0, sizeof (cu));
obstack_init (&cu.comp_unit_obstack);
back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
cu.objfile = objfile;
info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd);
cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
cu.header.first_die_ptr = info_ptr;
cu.header.cu_head_ptr = beg_of_comp_unit;
cu.list_in_scope = &file_symbols;
dwarf2_read_abbrevs (abfd, &cu);
make_cleanup (dwarf2_free_abbrev_table, &cu);
this_cu = dwarf2_find_comp_unit (cu.header.offset, objfile);
abbrev = peek_die_abbrev (info_ptr, (int *) &bytes_read, &cu);
info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
abfd, info_ptr, &cu);
if (comp_unit_die.has_repository)
{
dwarf2_read_repository_abbrevs (&cu);
set_repository_cu_language (comp_unit_die.language, &cu);
}
set_cu_language (comp_unit_die.language, &cu);
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);
if (comp_unit_die.dirname)
pst->dirname = xstrdup (comp_unit_die.dirname);
pst->read_symtab_private = (char *) this_cu;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
pst->read_symtab = dwarf2_psymtab_to_symtab;
if (this_cu->cu != NULL)
free_one_cached_comp_unit (this_cu->cu);
cu.per_cu = this_cu;
this_cu->cu = &cu;
this_cu->psymtab = pst;
if (comp_unit_die.has_children)
{
struct partial_die_info *first_die;
lowpc = ((CORE_ADDR) -1);
highpc = ((CORE_ADDR) 0);
first_die = load_partial_dies (abfd, info_ptr, 1, &cu);
scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
if (lowpc == ((CORE_ADDR) -1))
lowpc = highpc;
if (! comp_unit_die.has_pc_info)
{
comp_unit_die.lowpc = lowpc;
comp_unit_die.highpc = highpc;
}
}
pst->textlow = comp_unit_die.lowpc + baseaddr;
pst->texthigh = comp_unit_die.highpc + baseaddr;
pst->n_global_syms = objfile->global_psymbols.next -
(objfile->global_psymbols.list + pst->globals_offset);
pst->n_static_syms = objfile->static_psymbols.next -
(objfile->static_psymbols.list + pst->statics_offset);
sort_pst_symbols (pst);
free_named_symtabs (pst->filename);
info_ptr = beg_of_comp_unit + cu.header.length
+ cu.header.initial_length_size;
if (comp_unit_die.has_stmt_list)
{
dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst);
}
do_cleanups (back_to_inner);
}
do_cleanups (back_to);
}
static void
load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile)
{
bfd *abfd = objfile->obfd;
char *info_ptr, *beg_of_comp_unit;
struct partial_die_info comp_unit_die;
struct dwarf2_cu *cu;
struct abbrev_info *abbrev;
unsigned int bytes_read;
struct cleanup *back_to;
info_ptr = dwarf2_per_objfile->info_buffer + this_cu->offset;
beg_of_comp_unit = info_ptr;
cu = xmalloc (sizeof (struct dwarf2_cu));
memset (cu, 0, sizeof (struct dwarf2_cu));
obstack_init (&cu->comp_unit_obstack);
cu->objfile = objfile;
info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, abfd);
cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
cu->header.first_die_ptr = info_ptr;
cu->header.cu_head_ptr = beg_of_comp_unit;
dwarf2_read_abbrevs (abfd, cu);
back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
abbrev = peek_die_abbrev (info_ptr, (int *) &bytes_read, cu);
info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
abfd, info_ptr, cu);
set_cu_language (comp_unit_die.language, cu);
this_cu->cu = cu;
cu->per_cu = this_cu;
if (comp_unit_die.has_children)
load_partial_dies (abfd, info_ptr, 0, cu);
do_cleanups (back_to);
}
static void
create_all_comp_units (struct objfile *objfile)
{
int n_allocated;
int n_comp_units;
struct dwarf2_per_cu_data **all_comp_units;
char *info_ptr = dwarf2_per_objfile->info_buffer;
n_comp_units = 0;
n_allocated = 10;
all_comp_units = xmalloc (n_allocated
* sizeof (struct dwarf2_per_cu_data *));
while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
{
struct comp_unit_head cu_header;
struct dwarf2_per_cu_data *this_cu;
unsigned long offset;
int bytes_read;
offset = info_ptr - dwarf2_per_objfile->info_buffer;
cu_header.initial_length_size = 0;
cu_header.length = read_initial_length (objfile->obfd, info_ptr,
&cu_header, &bytes_read);
this_cu = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_per_cu_data));
memset (this_cu, 0, sizeof (*this_cu));
this_cu->offset = offset;
this_cu->length = cu_header.length + cu_header.initial_length_size;
if (n_comp_units == n_allocated)
{
n_allocated *= 2;
all_comp_units = xrealloc (all_comp_units,
n_allocated
* sizeof (struct dwarf2_per_cu_data *));
}
all_comp_units[n_comp_units++] = this_cu;
info_ptr = info_ptr + this_cu->length;
}
dwarf2_per_objfile->all_comp_units
= obstack_alloc (&objfile->objfile_obstack,
n_comp_units * sizeof (struct dwarf2_per_cu_data *));
memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units,
n_comp_units * sizeof (struct dwarf2_per_cu_data *));
xfree (all_comp_units);
dwarf2_per_objfile->n_comp_units = n_comp_units;
}
static void
scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
CORE_ADDR *highpc, struct dwarf2_cu *cu)
{
struct partial_die_info *pdi;
pdi = first_die;
while (pdi != NULL)
{
fixup_partial_die (pdi, cu);
if (pdi->name != NULL || pdi->tag == DW_TAG_namespace
|| pdi->tag == DW_TAG_enumeration_type)
{
switch (pdi->tag)
{
case DW_TAG_subprogram:
if (pdi->has_pc_info)
{
if (pdi->lowpc < *lowpc)
{
*lowpc = pdi->lowpc;
}
if (pdi->highpc > *highpc)
{
*highpc = pdi->highpc;
}
if (!pdi->is_declaration)
{
add_partial_symbol (pdi, cu);
}
}
break;
case DW_TAG_variable:
case DW_TAG_typedef:
case DW_TAG_union_type:
if (!pdi->is_declaration)
{
add_partial_symbol (pdi, cu);
}
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
if (!pdi->is_declaration)
{
add_partial_symbol (pdi, cu);
}
break;
case DW_TAG_enumeration_type:
if (!pdi->is_declaration)
add_partial_enumeration (pdi, cu);
break;
case DW_TAG_base_type:
case DW_TAG_subrange_type:
add_partial_symbol (pdi, cu);
break;
case DW_TAG_namespace:
add_partial_namespace (pdi, lowpc, highpc, cu);
break;
default:
break;
}
}
pdi = pdi->die_sibling;
}
}
static char *
partial_die_parent_scope (struct partial_die_info *pdi,
struct dwarf2_cu *cu)
{
char *grandparent_scope;
struct partial_die_info *parent, *real_pdi;
real_pdi = pdi;
while (real_pdi->has_specification)
real_pdi = find_partial_die (real_pdi->spec_offset, cu);
parent = real_pdi->die_parent;
if (parent == NULL)
return NULL;
if (parent->scope_set)
return parent->scope;
fixup_partial_die (parent, cu);
grandparent_scope = partial_die_parent_scope (parent, cu);
if (parent->tag == DW_TAG_namespace
|| parent->tag == DW_TAG_structure_type
|| parent->tag == DW_TAG_class_type
|| parent->tag == DW_TAG_union_type)
{
if (grandparent_scope == NULL)
parent->scope = parent->name;
else
parent->scope = typename_concat (&cu->comp_unit_obstack, grandparent_scope,
parent->name, cu);
}
else if (parent->tag == DW_TAG_enumeration_type)
parent->scope = grandparent_scope;
else
{
complaint (&symfile_complaints,
_("unhandled containing DIE tag %d for DIE at %d"),
parent->tag, pdi->offset);
parent->scope = grandparent_scope;
}
parent->scope_set = 1;
return parent->scope;
}
static char *
partial_die_full_name (struct partial_die_info *pdi,
struct dwarf2_cu *cu)
{
char *parent_scope;
parent_scope = partial_die_parent_scope (pdi, cu);
if (parent_scope == NULL)
return NULL;
else
return typename_concat (NULL, parent_scope, pdi->name, cu);
}
static void
add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
CORE_ADDR addr = 0;
char *actual_name;
const struct partial_symbol *psym = NULL;
CORE_ADDR baseaddr;
int built_actual_name = 0;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
actual_name = NULL;
if (pdi_needs_namespace (pdi->tag))
{
actual_name = partial_die_full_name (pdi, cu);
if (actual_name)
built_actual_name = 1;
}
if (actual_name == NULL)
actual_name = pdi->name;
switch (pdi->tag)
{
case DW_TAG_subprogram:
if (pdi->is_external)
{
psym = add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
0, pdi->lowpc + baseaddr,
cu->language, objfile);
}
else
{
psym = add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
0, pdi->lowpc + baseaddr,
cu->language, objfile);
}
break;
case DW_TAG_variable:
if (pdi->is_external)
{
if (pdi->locdesc)
addr = decode_locdesc (pdi->locdesc, cu);
if (pdi->locdesc || pdi->has_type || pdi->has_repository_type)
psym = add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
0, addr + baseaddr,
cu->language, objfile);
}
else
{
if (pdi->locdesc == NULL)
return;
addr = decode_locdesc (pdi->locdesc, cu);
psym = add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
0, addr + baseaddr,
cu->language, objfile);
}
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
case DW_TAG_subrange_type:
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
case DW_TAG_namespace:
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
if (pdi->has_children == 0)
return;
add_psymbol_to_list (actual_name, strlen (actual_name),
STRUCT_DOMAIN, LOC_TYPEDEF,
(cu->language == language_cplus
|| cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
if (cu->language == language_cplus
|| cu->language == language_java)
{
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
}
break;
case DW_TAG_enumerator:
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_CONST,
(cu->language == language_cplus
|| cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
default:
break;
}
if (cu->language == language_cplus
&& cu->has_namespace_info == 0
&& psym != NULL
&& SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
objfile);
if (built_actual_name)
xfree (actual_name);
}
static int
pdi_needs_namespace (enum dwarf_tag tag)
{
switch (tag)
{
case DW_TAG_namespace:
case DW_TAG_typedef:
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
case DW_TAG_enumerator:
return 1;
default:
return 0;
}
}
static void
add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
struct dwarf2_cu *cu)
{
add_partial_symbol (pdi, cu);
if (pdi->has_children)
scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
}
static void
guess_structure_name (struct partial_die_info *struct_pdi,
struct dwarf2_cu *cu)
{
if ((cu->language == language_cplus
|| cu->language == language_java)
&& cu->has_namespace_info == 0
&& struct_pdi->has_children)
{
struct partial_die_info *child_pdi = struct_pdi->die_child;
struct partial_die_info *real_pdi;
real_pdi = struct_pdi;
while (real_pdi->has_specification)
real_pdi = find_partial_die (real_pdi->spec_offset, cu);
if (real_pdi->die_parent != NULL)
return;
while (child_pdi != NULL)
{
if (child_pdi->tag == DW_TAG_subprogram)
{
char *actual_class_name
= language_class_name_from_physname (cu->language_defn,
child_pdi->name);
if (actual_class_name != NULL)
{
struct_pdi->name
= obsavestring (actual_class_name,
strlen (actual_class_name),
&cu->comp_unit_obstack);
xfree (actual_class_name);
}
break;
}
child_pdi = child_pdi->die_sibling;
}
}
}
static void
add_partial_enumeration (struct partial_die_info *enum_pdi,
struct dwarf2_cu *cu)
{
struct partial_die_info *pdi;
if (enum_pdi->name != NULL)
add_partial_symbol (enum_pdi, cu);
pdi = enum_pdi->die_child;
while (pdi)
{
if (pdi->tag != DW_TAG_enumerator || pdi->name == NULL)
complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
else
add_partial_symbol (pdi, cu);
pdi = pdi->die_sibling;
}
}
static struct abbrev_info *
peek_die_abbrev (char *info_ptr, int *bytes_read, struct dwarf2_cu *cu)
{
bfd *abfd = cu->objfile->obfd;
unsigned int abbrev_number;
struct abbrev_info *abbrev;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, (unsigned *) bytes_read);
if (abbrev_number == 0)
return NULL;
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"), abbrev_number,
bfd_get_filename (abfd));
}
return abbrev;
}
static char *
skip_children (char *info_ptr, struct dwarf2_cu *cu)
{
struct abbrev_info *abbrev;
unsigned int bytes_read;
while (1)
{
abbrev = peek_die_abbrev (info_ptr, (int *) &bytes_read, cu);
if (abbrev == NULL)
return info_ptr + bytes_read;
else
info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
}
}
static char *
skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
struct dwarf2_cu *cu)
{
unsigned int bytes_read;
struct attribute attr;
bfd *abfd = cu->objfile->obfd;
unsigned int form, i;
for (i = 0; i < abbrev->num_attrs; i++)
{
if (abbrev->attrs[i].name == DW_AT_sibling)
{
read_attribute (&attr, &abbrev->attrs[i],
abfd, info_ptr, cu);
if (attr.form == DW_FORM_ref_addr)
complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
else
return dwarf2_per_objfile->info_buffer
+ dwarf2_get_ref_die_offset (&attr, cu);
}
form = abbrev->attrs[i].form;
skip_attribute:
switch (form)
{
case DW_FORM_addr:
case DW_FORM_ref_addr:
info_ptr += cu->header.addr_size;
break;
case DW_FORM_data1:
case DW_FORM_ref1:
case DW_FORM_flag:
info_ptr += 1;
break;
case DW_FORM_data2:
case DW_FORM_ref2:
info_ptr += 2;
break;
case DW_FORM_data4:
case DW_FORM_ref4:
info_ptr += 4;
break;
case DW_FORM_data8:
case DW_FORM_ref8:
info_ptr += 8;
break;
case DW_FORM_string:
read_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_strp:
info_ptr += cu->header.offset_size;
break;
case DW_FORM_block:
info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_block1:
info_ptr += 1 + read_1_byte (abfd, info_ptr);
break;
case DW_FORM_block2:
info_ptr += 2 + read_2_bytes (abfd, info_ptr);
break;
case DW_FORM_block4:
info_ptr += 4 + read_4_bytes (abfd, info_ptr);
break;
case DW_FORM_APPLE_db_str:
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
info_ptr = skip_leb128 (abfd, info_ptr);
break;
case DW_FORM_indirect:
form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
goto skip_attribute;
default:
error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
}
if (abbrev->has_children)
return skip_children (info_ptr, cu);
else
return info_ptr;
}
static char *
locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
bfd *abfd, struct dwarf2_cu *cu)
{
if (orig_pdi->sibling)
return orig_pdi->sibling;
if (!orig_pdi->has_children)
return info_ptr;
return skip_children (info_ptr, cu);
}
static void
dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
{
if (pst != NULL)
{
if (pst->readin)
{
warning (_("bug: psymtab for %s is already read in."), pst->filename);
}
else
{
if (info_verbose)
{
printf_filtered (_("Reading in symbols for %s..."), pst->filename);
gdb_flush (gdb_stdout);
}
dwarf2_per_objfile = objfile_data (pst->objfile,
dwarf2_objfile_data_key);
psymtab_to_symtab_1 (pst);
if (info_verbose)
printf_filtered (_("done.\n"));
}
}
}
static int
compare_map_entries_oso_addr (const void *a, const void *b)
{
struct oso_final_addr_tuple *map_a = (struct oso_final_addr_tuple *) a;
struct oso_final_addr_tuple *map_b = (struct oso_final_addr_tuple *) b;
if (map_a->oso_low_addr == map_b->oso_low_addr)
return 0;
if (map_a->oso_low_addr < map_b->oso_low_addr)
return -1;
return 1;
}
static int
compare_map_entries_name (const void *a, const void *b)
{
struct oso_final_addr_tuple *map_a = (struct oso_final_addr_tuple *) a;
struct oso_final_addr_tuple *map_b = (struct oso_final_addr_tuple *) b;
return (strcmp (map_a->name, map_b->name));
}
static struct oso_to_final_addr_map *
convert_oso_map_to_final_map (struct nlist_rec *nlists,
int oso_nlists_count,
char **oso_common_symnames,
int oso_common_symnames_count,
struct partial_symtab *pst)
{
int i, j;
struct oso_to_final_addr_map *map =
xmalloc (sizeof (struct oso_to_final_addr_map));
CORE_ADDR baseaddr = ANOFFSET (pst->objfile->section_offsets,
SECT_OFF_TEXT (pst->objfile));
map->tuples = (struct oso_final_addr_tuple *)
xmalloc (sizeof (struct oso_final_addr_tuple) * oso_nlists_count);
j = 0;
for (i = 0; i < oso_nlists_count; i++)
{
struct minimal_symbol *minsym;
struct partial_symbol *psym;
char *demangled = NULL;
int free_demangled = 0;
if (pst->language == language_cplus
|| pst->language == language_objcplus
|| pst->language == language_auto)
demangled = cplus_demangle (nlists[i].name, DMGL_PARAMS | DMGL_ANSI);
if (pst->language == language_java)
demangled = cplus_demangle (nlists[i].name,
DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
if (demangled != NULL)
free_demangled = 1;
else
demangled = nlists[i].name;
psym = lookup_partial_symbol (pst, demangled, nlists[i].name,
1, VAR_DOMAIN);
if (psym == NULL)
psym = lookup_partial_symbol (pst, demangled, nlists[i].name,
0, VAR_DOMAIN);
if (free_demangled)
xfree (demangled);
if (psym && SYMBOL_VALUE_ADDRESS (psym) != baseaddr)
minsym = lookup_minimal_symbol_by_pc_section_from_objfile
(SYMBOL_VALUE_ADDRESS (psym),
SYMBOL_BFD_SECTION (psym), pst->objfile);
else
minsym = lookup_minimal_symbol (nlists[i].name, NULL, pst->objfile);
if (minsym)
{
CORE_ADDR actual_address;
if (minsym->type == mst_abs)
actual_address = SYMBOL_VALUE_ADDRESS (minsym);
else
actual_address = SYMBOL_VALUE_ADDRESS (minsym) - baseaddr;
if (actual_address == 0 && nlists[i].addr == 0)
{
xfree ((char *) nlists[i].name);
continue;
}
map->tuples[j].name = nlists[i].name;
map->tuples[j].oso_low_addr = nlists[i].addr;
map->tuples[j].final_addr = actual_address;
map->tuples[j].present_in_final = 1;
j++;
}
else
{
map->tuples[j].name = nlists[i].name;
map->tuples[j].oso_low_addr = nlists[i].addr;
map->tuples[j].present_in_final = 0;
j++;
}
}
xfree (nlists);
qsort (map->tuples, j, sizeof (struct oso_final_addr_tuple),
compare_map_entries_oso_addr);
map->entries = j;
for (i = 0; i < map->entries - 1; i++)
map->tuples[i].oso_high_addr = map->tuples[i + 1].oso_low_addr;
map->tuples[map->entries - 1].oso_high_addr = (CORE_ADDR) -1;
if (oso_common_symnames_count == 0)
{
map->common_entries = 0;
map->common_pairs = NULL;
}
else
{
map->common_pairs = (struct oso_final_addr_tuple *)
xmalloc (sizeof (struct oso_final_addr_tuple) *
oso_common_symnames_count);
j = 0;
for (i = 0; i < oso_common_symnames_count; i++)
{
struct minimal_symbol *minsym;
CORE_ADDR baseaddr = ANOFFSET (pst->objfile->section_offsets,
SECT_OFF_DATA (pst->objfile));
minsym = lookup_minimal_symbol (oso_common_symnames[i], NULL,
pst->objfile);
if (minsym && minsym->type == mst_data)
{
CORE_ADDR actual_address = SYMBOL_VALUE_ADDRESS (minsym) -
baseaddr;
if (actual_address == 0)
{
xfree (oso_common_symnames[i]);
continue;
}
map->common_pairs[j].name = oso_common_symnames[i];
map->common_pairs[j].oso_low_addr = 0;
map->common_pairs[j].oso_high_addr = 0;
map->common_pairs[j].final_addr = actual_address;
j++;
}
else
xfree (oso_common_symnames[i]);
}
xfree (oso_common_symnames);
qsort (map->common_pairs, j, sizeof (struct oso_final_addr_tuple),
compare_map_entries_name);
map->common_entries = j;
}
return (map);
}
static void
free_address_map (struct oso_to_final_addr_map *map)
{
int i;
for (i = 0; i < map->entries; i++)
xfree (map->tuples[i].name);
for (i = 0; i < map->common_entries; i++)
xfree (map->common_pairs[i].name);
xfree (map->tuples);
}
static int
compare_translation_tuples_highpc (const void *key, const void *arrmem)
{
CORE_ADDR oso_addr = *((CORE_ADDR *) key);
CORE_ADDR tuple_oso_low_addr =
((struct oso_final_addr_tuple *) arrmem)->oso_low_addr;
CORE_ADDR tuple_oso_high_addr =
((struct oso_final_addr_tuple *) arrmem)->oso_high_addr;
if (oso_addr == tuple_oso_high_addr)
return 0;
if (oso_addr < tuple_oso_high_addr && oso_addr > tuple_oso_low_addr)
return 0;
if (oso_addr < tuple_oso_high_addr)
return -1;
return 1;
}
static int
compare_translation_tuples_nothighpc (const void *key, const void *arrmem)
{
CORE_ADDR oso_addr = *((CORE_ADDR *) key);
CORE_ADDR tuple_oso_low_addr =
((struct oso_final_addr_tuple *) arrmem)->oso_low_addr;
CORE_ADDR tuple_oso_high_addr =
((struct oso_final_addr_tuple *) arrmem)->oso_high_addr;
if (oso_addr == tuple_oso_low_addr)
return 0;
if (oso_addr > tuple_oso_low_addr && oso_addr < tuple_oso_high_addr)
return 0;
if (oso_addr < tuple_oso_low_addr)
return -1;
return 1;
}
static int
translate_debug_map_address (struct dwarf2_cu *cu, CORE_ADDR oso_addr,
CORE_ADDR *addr, int highpc)
{
struct oso_to_final_addr_map *map = cu->addr_map;
if (cu->addr_map == NULL)
{
*addr = oso_addr;
return 1;
}
if (map->tuples[0].oso_low_addr < oso_addr && map->entries == 1)
{
int delta = oso_addr - map->tuples[0].oso_low_addr;
*addr = map->tuples[0].final_addr + delta;
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: translated 0x%s to 0x%s sym '%s' in %s\n",
paddr_nz (oso_addr), paddr_nz (*addr),
map->tuples[0].name, cu->per_cu->psymtab->filename);
return 1;
}
struct oso_final_addr_tuple *match;
if (highpc == 0)
match = bsearch (&oso_addr, map->tuples, map->entries,
sizeof (struct oso_final_addr_tuple),
compare_translation_tuples_nothighpc);
else
match = bsearch (&oso_addr, map->tuples, map->entries,
sizeof (struct oso_final_addr_tuple),
compare_translation_tuples_highpc);
if (match == NULL || !match->present_in_final)
{
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: did not translate 0x%s in %s "
"highpc == %d\n",
paddr_nz (oso_addr), cu->per_cu->psymtab->filename,
highpc);
return 0;
}
int delta = oso_addr - match->oso_low_addr;
*addr = match->final_addr + delta;
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: translated 0x%s to 0x%s sym '%s' in %s\n",
paddr_nz (oso_addr), paddr_nz (*addr), match->name,
cu->per_cu->psymtab->filename);
return 1;
}
static int
translate_common_symbol_debug_map_address (struct dwarf2_cu *cu,
const char *name, CORE_ADDR *addr)
{
int i;
struct oso_to_final_addr_map *map = cu->addr_map;
if (map == NULL)
return 0;
for (i = 0; i < map->common_entries; i++)
if (strcmp (map->common_pairs[i].name, name) == 0)
{
*addr = map->common_pairs[i].final_addr;
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: translated common symbol '%s' to 0x%s in %s\n",
name, paddr_nz (*addr),
cu->per_cu->psymtab->filename);
return 1;
}
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: failed to translate common symbol '%s' in %s\n",
name, cu->per_cu->psymtab->filename);
return 0;
}
void
dwarf2_debug_map_psymtab_to_symtab (struct partial_symtab *pst)
{
bfd *containing_archive, *oso_bfd;
struct nlist_rec *oso_nlists;
int oso_nlists_count;
char **oso_common_symnames;
int oso_common_symnames_count;
struct oso_to_final_addr_map *addr_map;
struct dwarf2_per_cu_data *this_cu;
int bytes_read;
int i;
for (i = 0; i < pst->number_of_dependencies; i++)
if (!pst->dependencies[i]->readin)
{
if (info_verbose)
{
fputs_filtered (" ", gdb_stdout);
wrap_here ("");
fputs_filtered ("and ", gdb_stdout);
wrap_here ("");
printf_filtered ("%s...", pst->dependencies[i]->filename);
wrap_here ("");
gdb_flush (gdb_stdout);
}
dwarf2_debug_map_psymtab_to_symtab (pst->dependencies[i]);
}
if (PSYMTAB_OSO_NAME (pst) == NULL || pst->readin)
return;
oso_bfd = open_bfd_from_oso (pst, &containing_archive);
if (oso_bfd == NULL)
{
if (pst->objfile->separate_debug_objfile != NULL)
{
pst->readin = 1;
return;
}
else
error ("Couldn't open object file '%s'", PSYMTAB_OSO_NAME (pst));
}
if (!bfd_check_format (oso_bfd, bfd_object))
warning ("Not in bfd_object form");
read_oso_nlists (oso_bfd, pst, &oso_nlists, &oso_nlists_count,
&oso_common_symnames, &oso_common_symnames_count);
addr_map = convert_oso_map_to_final_map (oso_nlists, oso_nlists_count,
oso_common_symnames,
oso_common_symnames_count, pst);
dwarf2_has_info_1 (pst->objfile, oso_bfd);
dwarf2_copy_dwarf_from_file (pst->objfile, oso_bfd);
this_cu = (struct dwarf2_per_cu_data *)
obstack_alloc (&(pst->objfile->objfile_obstack),
sizeof (struct dwarf2_per_cu_data));
this_cu->offset = 0;
this_cu->length = read_initial_length (oso_bfd,
dwarf2_per_objfile->info_buffer,
NULL, &bytes_read);
this_cu->queued = 0;
this_cu->cu = NULL;
this_cu->psymtab = pst;
this_cu->type_hash = NULL;
load_full_comp_unit (this_cu, addr_map);
process_full_comp_unit (this_cu);
free_address_map (addr_map);
pst->readin = 1;
}
static void
queue_comp_unit (struct dwarf2_per_cu_data *per_cu)
{
struct dwarf2_queue_item *item;
per_cu->queued = 1;
item = xmalloc (sizeof (*item));
item->per_cu = per_cu;
item->next = NULL;
if (dwarf2_queue == NULL)
dwarf2_queue = item;
else
dwarf2_queue_tail->next = item;
dwarf2_queue_tail = item;
}
static void
process_queue (struct objfile *objfile)
{
struct dwarf2_queue_item *item, *next_item;
for (item = dwarf2_queue; item != NULL; item = item->next)
{
load_full_comp_unit (item->per_cu, NULL);
item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
dwarf2_per_objfile->read_in_chain = item->per_cu;
if (item->per_cu->psymtab->readin)
reset_die_and_siblings_types (item->per_cu->cu->dies,
item->per_cu->cu);
}
for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
{
if (!item->per_cu->psymtab->readin)
process_full_comp_unit (item->per_cu);
item->per_cu->queued = 0;
next_item = item->next;
xfree (item);
}
dwarf2_queue_tail = NULL;
}
static void
dwarf2_release_queue (void *dummy)
{
struct dwarf2_queue_item *item, *last;
item = dwarf2_queue;
while (item)
{
if (item->per_cu->queued)
{
if (item->per_cu->cu != NULL)
free_one_cached_comp_unit (item->per_cu->cu);
item->per_cu->queued = 0;
}
last = item;
item = item->next;
xfree (last);
}
dwarf2_queue = dwarf2_queue_tail = NULL;
}
static void
psymtab_to_symtab_1 (struct partial_symtab *pst)
{
struct dwarf2_per_cu_data *per_cu;
struct cleanup *back_to;
int i;
for (i = 0; i < pst->number_of_dependencies; i++)
if (!pst->dependencies[i]->readin)
{
if (info_verbose)
{
fputs_filtered (" ", gdb_stdout);
wrap_here ("");
fputs_filtered ("and ", gdb_stdout);
wrap_here ("");
printf_filtered ("%s...", pst->dependencies[i]->filename);
wrap_here ("");
gdb_flush (gdb_stdout);
}
psymtab_to_symtab_1 (pst->dependencies[i]);
}
per_cu = (struct dwarf2_per_cu_data *) pst->read_symtab_private;
if (per_cu == NULL)
{
pst->readin = 1;
return;
}
back_to = make_cleanup (dwarf2_release_queue, NULL);
queue_comp_unit (per_cu);
process_queue (pst->objfile);
age_cached_comp_units ();
do_cleanups (back_to);
}
static struct dwarf2_cu *
load_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
struct oso_to_final_addr_map *addr_map)
{
struct partial_symtab *pst = per_cu->psymtab;
bfd *abfd = pst->objfile->obfd;
struct dwarf2_cu *cu;
unsigned long offset;
char *info_ptr;
struct cleanup *back_to, *free_cu_cleanup;
struct attribute *attr;
offset = per_cu->offset;
info_ptr = dwarf2_per_objfile->info_buffer + offset;
cu = xmalloc (sizeof (struct dwarf2_cu));
memset (cu, 0, sizeof (struct dwarf2_cu));
free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
cu->objfile = pst->objfile;
info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);
dwarf2_read_abbrevs (abfd, cu);
back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
cu->header.offset = offset;
cu->addr_map = addr_map;
cu->per_cu = per_cu;
per_cu->cu = cu;
obstack_init (&cu->comp_unit_obstack);
cu->dies = read_comp_unit (info_ptr, abfd, cu);
attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
if (attr)
set_cu_language (DW_UNSND (attr), cu);
else
set_cu_language (language_minimal, cu);
do_cleanups (back_to);
discard_cleanups (free_cu_cleanup);
return cu;
}
static void
process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
{
struct partial_symtab *pst = per_cu->psymtab;
struct dwarf2_cu *cu = per_cu->cu;
struct objfile *objfile = pst->objfile;
CORE_ADDR lowpc, highpc;
struct symtab *symtab;
struct cleanup *back_to;
struct attribute *attr;
CORE_ADDR baseaddr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
processing_current_prefix = "";
buildsym_init ();
back_to = make_cleanup (really_free_pendings, NULL);
cu->list_in_scope = &file_symbols;
cu->header.base_known = 0;
cu->header.base_address = 0;
attr = dwarf2_attr (cu->dies, DW_AT_entry_pc, cu);
if (attr)
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, DW_ADDR (attr), &addr, 0))
{
cu->header.base_address = addr;
cu->header.base_known = 1;
}
else
attr = NULL;
}
if (attr == NULL)
{
attr = dwarf2_attr (cu->dies, DW_AT_low_pc, cu);
if (attr)
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, DW_ADDR (attr), &addr, 0))
cu->header.base_address = addr;
else
cu->header.base_address = cu->per_cu->psymtab->textlow;
cu->header.base_known = 1;
}
}
process_die (cu->dies, cu);
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
if (cu->addr_map != NULL && lowpc == -1 && highpc == 0)
{
lowpc = cu->per_cu->psymtab->textlow;
highpc = cu->per_cu->psymtab->texthigh;
}
symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
if (symtab != NULL
&& !(cu->language == language_c && symtab->language != language_c))
{
symtab->language = cu->language;
}
pst->symtab = symtab;
pst->readin = 1;
do_cleanups (back_to);
}
static void
process_die (struct die_info *die, struct dwarf2_cu *cu)
{
switch (die->tag)
{
case DW_TAG_padding:
break;
case DW_TAG_compile_unit:
read_file_scope (die, cu);
break;
case DW_TAG_subprogram:
read_subroutine_type (die, cu);
read_func_scope (die, cu);
break;
case DW_TAG_inlined_subroutine:
break;
case DW_TAG_lexical_block:
case DW_TAG_try_block:
case DW_TAG_catch_block:
read_lexical_block_scope (die, cu);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
read_structure_type (die, cu);
process_structure_scope (die, cu);
break;
case DW_TAG_enumeration_type:
read_enumeration_type (die, cu);
process_enumeration_scope (die, cu);
break;
case DW_TAG_subroutine_type:
read_subroutine_type (die, cu);
break;
case DW_TAG_array_type:
read_array_type (die, cu);
break;
case DW_TAG_pointer_type:
read_tag_pointer_type (die, cu);
break;
case DW_TAG_ptr_to_member_type:
read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
read_tag_reference_type (die, cu);
break;
case DW_TAG_string_type:
read_tag_string_type (die, cu);
break;
case DW_TAG_base_type:
read_base_type (die, cu);
new_symbol (die, die->type, cu);
break;
case DW_TAG_subrange_type:
read_subrange_type (die, cu);
new_symbol (die, die->type, cu);
break;
case DW_TAG_common_block:
read_common_block (die, cu);
break;
case DW_TAG_common_inclusion:
break;
case DW_TAG_namespace:
processing_has_namespace_info = 1;
read_namespace (die, cu);
break;
case DW_TAG_imported_declaration:
case DW_TAG_imported_module:
processing_has_namespace_info = 1;
gdb_assert (die->child == NULL);
break;
default:
new_symbol (die, NULL, cu);
break;
}
}
static void
initialize_cu_func_list (struct dwarf2_cu *cu)
{
cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
}
static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
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;
CORE_ADDR baseaddr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
if (cu->addr_map
&& cu->per_cu->psymtab->textlow != -1
&& cu->per_cu->psymtab->textlow != baseaddr
&& cu->per_cu->psymtab->texthigh != 0)
{
lowpc = cu->per_cu->psymtab->textlow;
highpc = cu->per_cu->psymtab->texthigh;
}
else
{
get_scope_pc_bounds (die, &lowpc, &highpc, cu);
if (lowpc == ((CORE_ADDR) -1))
lowpc = highpc;
lowpc += baseaddr;
highpc += baseaddr;
}
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr)
{
name = DW_STRING (attr);
}
attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
if (attr)
{
comp_dir = DW_STRING (attr);
if (comp_dir)
{
char *cp = strchr (comp_dir, ':');
if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
comp_dir = cp + 1;
}
cu->comp_dir = comp_dir;
}
attr = dwarf2_attr (die, DW_AT_language, cu);
if (attr)
{
set_cu_language (DW_UNSND (attr), cu);
}
attr = dwarf2_attr (die, DW_AT_producer, cu);
if (attr)
cu->producer = DW_STRING (attr);
processing_gcc_compilation = 2;
#if 0
if (dip->at_producer != NULL)
{
handle_producer (dip->at_producer);
}
#endif
memset (cu->ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
initialize_cu_func_list (cu);
if (die->child != NULL)
{
child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
if (attr)
{
unsigned int line_offset = DW_UNSND (attr);
line_header = dwarf_decode_line_header (line_offset, abfd, cu);
if (line_header)
{
make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) line_header);
dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL);
}
}
attr = dwarf2_attr (die, DW_AT_macro_info, cu);
if (attr && line_header)
{
unsigned int macro_offset = DW_UNSND (attr);
dwarf_decode_macros (line_header, macro_offset,
comp_dir, abfd, cu);
}
do_cleanups (back_to);
}
static void
add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
struct dwarf2_cu *cu)
{
struct function_range *thisfn;
thisfn = (struct function_range *)
obstack_alloc (&cu->comp_unit_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 (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct context_stack *new;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct die_info *child_die;
struct attribute *attr;
char *name;
const char *previous_prefix = processing_current_prefix;
struct cleanup *back_to = NULL;
CORE_ADDR baseaddr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
name = dwarf2_linkage_name (die, cu);
if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;
if (cu->language == language_cplus
|| cu->language == language_java)
{
struct die_info *spec_die = die_specification (die, cu);
if (spec_die != NULL)
{
char *specification_prefix = determine_prefix (spec_die, cu);
processing_current_prefix = specification_prefix;
back_to = make_cleanup (xfree, specification_prefix);
}
}
lowpc += baseaddr;
highpc += baseaddr;
add_to_cu_func_list (name, lowpc, highpc, cu);
new = push_context (0, lowpc);
new->name = new_symbol (die, die->type, cu);
attr = dwarf2_attr (die, DW_AT_frame_base, cu);
if (attr)
dwarf2_symbol_mark_computed (attr, new->name, cu);
cu->list_in_scope = &local_symbols;
if (die->child != NULL)
{
child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
new = pop_context ();
finish_block (new->name, &local_symbols, new->old_blocks,
lowpc, highpc, objfile);
local_symbols = new->locals;
param_symbols = new->params;
if (outermost_context_p ())
cu->list_in_scope = &file_symbols;
processing_current_prefix = previous_prefix;
if (back_to != NULL)
do_cleanups (back_to);
}
static void
read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct context_stack *new;
CORE_ADDR lowpc, highpc;
struct die_info *child_die;
CORE_ADDR baseaddr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;
lowpc += baseaddr;
highpc += baseaddr;
push_context (0, lowpc);
if (die->child != NULL)
{
child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
new = pop_context ();
if (local_symbols != NULL)
{
finish_block (0, &local_symbols, new->old_blocks, new->start_addr,
highpc, objfile);
}
local_symbols = new->locals;
}
static int
dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
CORE_ADDR *highpc, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct comp_unit_head *cu_header = &cu->header;
struct attribute *attr;
bfd *obfd = objfile->obfd;
CORE_ADDR low = 0;
CORE_ADDR high = 0;
int ret = 0;
attr = dwarf2_attr (die, DW_AT_high_pc, cu);
if (attr)
{
high = DW_ADDR (attr);
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
low = DW_ADDR (attr);
else
return 0;
ret = 1;
}
else
{
attr = dwarf2_attr (die, DW_AT_ranges, cu);
if (attr == NULL)
{
return 0;
}
else
{
unsigned int addr_size = cu_header->addr_size;
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
unsigned int offset = DW_UNSND (attr);
CORE_ADDR base;
int found_base;
int dummy;
char *buffer;
CORE_ADDR marker;
int low_set;
found_base = cu_header->base_known;
base = cu_header->base_address;
if (offset >= dwarf2_per_objfile->ranges_size)
{
complaint (&symfile_complaints,
_("Offset %d out of bounds for DW_AT_ranges attribute"),
offset);
return 0;
}
buffer = dwarf2_per_objfile->ranges_buffer + offset;
marker = read_address (obfd, buffer, cu, &dummy);
if ((marker & mask) == mask)
{
base = read_address (obfd, buffer + addr_size, cu, &dummy);
buffer += 2 * addr_size;
offset += 2 * addr_size;
found_base = 1;
}
low_set = 0;
while (1)
{
CORE_ADDR range_beginning, range_end;
range_beginning = read_address (obfd, buffer, cu, &dummy);
buffer += addr_size;
range_end = read_address (obfd, buffer, cu, &dummy);
buffer += addr_size;
offset += 2 * addr_size;
if (range_beginning == 0 && range_end == 0)
break;
if ((range_beginning & mask) == mask)
{
base = read_address (obfd, buffer + addr_size, cu, &dummy);
found_base = 1;
continue;
}
if (!found_base)
{
complaint (&symfile_complaints,
_("Invalid .debug_ranges data (no base address)"));
return 0;
}
if (cu->addr_map == NULL)
{
range_beginning += base;
range_end += base;
}
if (! low_set)
{
low = range_beginning;
high = range_end;
low_set = 1;
}
else
{
if (range_beginning < low)
low = range_beginning;
if (range_end > high)
high = range_end;
}
}
if (! low_set)
return 0;
ret = -1;
}
}
if (!translate_debug_map_address (cu, low, &low, 0) ||
!translate_debug_map_address (cu, high, &high, 1))
return 0;
if (high < low)
return 0;
if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
return 0;
*lowpc = low;
*highpc = high;
return ret;
}
static void
get_scope_pc_bounds (struct die_info *die,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
struct dwarf2_cu *cu)
{
CORE_ADDR best_low = (CORE_ADDR) -1;
CORE_ADDR best_high = (CORE_ADDR) 0;
CORE_ADDR current_low, current_high;
if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu))
{
best_low = current_low;
best_high = current_high;
}
else
{
struct die_info *child = die->child;
while (child && child->tag)
{
switch (child->tag) {
case DW_TAG_subprogram:
if (dwarf2_get_pc_bounds (child, ¤t_low, ¤t_high, cu))
{
best_low = min (best_low, current_low);
best_high = max (best_high, current_high);
}
break;
case DW_TAG_namespace:
get_scope_pc_bounds (child, ¤t_low, ¤t_high, cu);
if (current_low != ((CORE_ADDR) -1))
{
best_low = min (best_low, current_low);
best_high = max (best_high, current_high);
}
break;
default:
break;
}
child = sibling_die (child);
}
}
*lowpc = best_low;
*highpc = best_high;
}
static void
dwarf2_add_field (struct field_info *fip, struct die_info *die,
struct dwarf2_cu *cu)
{
struct nextfield *new_field;
struct attribute *attr;
struct field *fp;
char *fieldname = "";
new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
make_cleanup (xfree, new_field);
memset (new_field, 0, sizeof (struct nextfield));
new_field->next = fip->fields;
fip->fields = new_field;
fip->nfields++;
if (die->tag != DW_TAG_inheritance)
new_field->accessibility = DW_ACCESS_public;
else
new_field->accessibility = DW_ACCESS_private;
new_field->virtuality = DW_VIRTUALITY_none;
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
new_field->accessibility = DW_UNSND (attr);
if (new_field->accessibility != DW_ACCESS_public)
fip->non_public_fields = 1;
attr = dwarf2_attr (die, DW_AT_virtuality, cu);
if (attr)
new_field->virtuality = DW_UNSND (attr);
fp = &new_field->field;
if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
{
fp->type = die_type (die, cu);
FIELD_STATIC_KIND (*fp) = 0;
attr = dwarf2_attr (die, DW_AT_bit_size, cu);
if (attr)
{
FIELD_BITSIZE (*fp) = DW_UNSND (attr);
}
else
{
FIELD_BITSIZE (*fp) = 0;
}
attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
if (attr)
{
FIELD_BITPOS (*fp) =
decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte;
}
else
FIELD_BITPOS (*fp) = 0;
attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
if (attr)
{
if (BITS_BIG_ENDIAN)
{
FIELD_BITPOS (*fp) += DW_UNSND (attr);
}
else
{
int anonymous_size;
int bit_offset = DW_UNSND (attr);
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
anonymous_size = DW_UNSND (attr);
}
else
{
anonymous_size = TYPE_LENGTH (fp->type);
}
FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
- bit_offset - FIELD_BITSIZE (*fp);
}
}
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
fp->name = fieldname;
if (dwarf2_attr (die, DW_AT_artificial, cu))
{
new_field->accessibility = DW_ACCESS_private;
fip->non_public_fields = 1;
}
}
else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable)
{
char *physname;
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
else
return;
physname = dwarf2_linkage_name (die, cu);
SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = fieldname;
}
else if (die->tag == DW_TAG_inheritance)
{
attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
if (attr)
FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), cu)
* bits_per_byte);
FIELD_BITSIZE (*fp) = 0;
FIELD_STATIC_KIND (*fp) = 0;
FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
fip->nbaseclasses++;
}
}
static void
dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
struct dwarf2_cu *cu)
{
int nfields = fip->nfields;
TYPE_NFIELDS (type) = nfields;
TYPE_FIELDS (type) = (struct field *)
TYPE_ALLOC (type, sizeof (struct field) * nfields);
memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
if (fip->non_public_fields)
{
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FIELD_PRIVATE_BITS (type) =
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
TYPE_FIELD_PROTECTED_BITS (type) =
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
TYPE_FIELD_IGNORE_BITS (type) =
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
}
if (fip->nbaseclasses)
{
int num_bytes = B_BYTES (fip->nbaseclasses);
char *pointer;
ALLOCATE_CPLUS_STRUCT_TYPE (type);
pointer = (char *) TYPE_ALLOC (type, num_bytes);
TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
}
while (nfields-- > 0)
{
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_protected:
SET_TYPE_FIELD_PROTECTED (type, nfields);
break;
case DW_ACCESS_public:
break;
default:
{
complaint (&symfile_complaints, _("unsupported accessibility %d"),
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;
}
}
fip->fields = fip->fields->next;
}
}
static void
dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
struct type *type, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct attribute *attr;
struct fnfieldlist *flp;
int i;
struct fn_field *fnp;
char *fieldname;
char *physname;
struct nextfnfield *new_fnfield;
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
else
return;
physname = dwarf2_linkage_name (die, cu);
for (i = 0; i < fip->nfnfields; i++)
{
if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
break;
}
if (i < fip->nfnfields)
flp = &fip->fnfieldlists[i];
else
{
if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
{
fip->fnfieldlists = (struct fnfieldlist *)
xrealloc (fip->fnfieldlists,
(fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct fnfieldlist));
if (fip->nfnfields == 0)
make_cleanup (free_current_contents, &fip->fnfieldlists);
}
flp = &fip->fnfieldlists[fip->nfnfields];
flp->name = fieldname;
flp->length = 0;
flp->head = NULL;
fip->nfnfields++;
}
new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
make_cleanup (xfree, new_fnfield);
memset (new_fnfield, 0, sizeof (struct nextfnfield));
new_fnfield->next = flp->head;
flp->head = new_fnfield;
flp->length++;
fnp = &new_fnfield->fnfield;
fnp->physname = physname ? physname : "";
fnp->type = alloc_type (objfile);
if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
{
int nparams = TYPE_NFIELDS (die->type);
smash_to_method_type (fnp->type, type,
TYPE_TARGET_TYPE (die->type),
TYPE_FIELDS (die->type),
TYPE_NFIELDS (die->type),
TYPE_VARARGS (die->type));
if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
fnp->voffset = VOFFSET_STATIC;
}
else
complaint (&symfile_complaints, _("member function type missing for '%s'"),
physname);
if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
fnp->fcontext = die_containing_type (die, cu);
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
{
switch (DW_UNSND (attr))
{
case DW_ACCESS_private:
fnp->is_private = 1;
break;
case DW_ACCESS_protected:
fnp->is_protected = 1;
break;
}
}
attr = dwarf2_attr (die, DW_AT_artificial, cu);
if (attr && DW_UNSND (attr) != 0)
fnp->is_artificial = 1;
attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu);
if (attr)
{
if (attr_form_is_block (attr))
{
fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2;
}
else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
dwarf2_complex_location_expr_complaint ();
}
else
{
dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
fieldname);
}
}
}
static void
dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
struct dwarf2_cu *cu)
{
struct fnfieldlist *flp;
int total_length = 0;
int i;
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
{
struct nextfnfield *nfp = flp->head;
struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
int k;
TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
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;
total_length += flp->length;
}
TYPE_NFN_FIELDS (type) = fip->nfnfields;
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
static int
is_vtable_name (const char *name, struct dwarf2_cu *cu)
{
static const char vptr[] = "_vptr";
static const char vtable[] = "vtable";
if ((cu->language == language_java
&& strncmp (name, vtable, sizeof (vtable) - 1) == 0)
|| (strncmp (name, vptr, sizeof (vptr) - 1) == 0
&& is_cplus_marker (name[sizeof (vptr) - 1])))
return 1;
return 0;
}
static void
read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
const char *previous_prefix = processing_current_prefix;
struct cleanup *back_to = NULL;
if (die->type)
return;
type = alloc_type (objfile);
INIT_CPLUS_SPECIFIC (type);
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
if (cu->language == language_cplus
|| cu->language == language_java)
{
char *new_prefix = determine_class_name (die, cu);
TYPE_TAG_NAME (type) = obsavestring (new_prefix,
strlen (new_prefix),
&objfile->objfile_obstack);
back_to = make_cleanup (xfree, new_prefix);
processing_current_prefix = new_prefix;
}
else
{
TYPE_TAG_NAME (type) = DW_STRING (attr);
}
}
if (die->tag == DW_TAG_structure_type)
{
TYPE_CODE (type) = TYPE_CODE_STRUCT;
}
else if (die->tag == DW_TAG_union_type)
{
TYPE_CODE (type) = TYPE_CODE_UNION;
}
else
{
TYPE_CODE (type) = TYPE_CODE_CLASS;
}
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
TYPE_LENGTH (type) = DW_UNSND (attr);
}
else
{
TYPE_LENGTH (type) = 0;
}
if (die_is_declaration (die, cu))
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
set_die_type (die, type, cu);
if (die->child != NULL && ! die_is_declaration (die, cu))
{
struct field_info fi;
struct die_info *child_die;
struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
memset (&fi, 0, sizeof (struct field_info));
child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_member
|| child_die->tag == DW_TAG_variable)
{
dwarf2_add_field (&fi, child_die, cu);
}
else if (child_die->tag == DW_TAG_subprogram)
{
read_type_die (child_die, cu);
dwarf2_add_member_fn (&fi, child_die, type, cu);
}
else if (child_die->tag == DW_TAG_inheritance)
{
dwarf2_add_field (&fi, child_die, cu);
}
child_die = sibling_die (child_die);
}
if (fi.nfields)
dwarf2_attach_fields_to_type (&fi, type, cu);
if (fi.nfnfields)
{
dwarf2_attach_fn_fields_to_type (&fi, type, cu);
if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
{
struct type *t = die_containing_type (die, cu);
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
{
int i;
for (i = TYPE_NFIELDS (t) - 1;
i >= TYPE_N_BASECLASSES (t);
--i)
{
char *fieldname = TYPE_FIELD_NAME (t, i);
if (is_vtable_name (fieldname, cu))
{
TYPE_VPTR_FIELDNO (type) = i;
break;
}
}
if (i < TYPE_N_BASECLASSES (t))
complaint (&symfile_complaints,
_("virtual function table pointer not found when defining class '%s'"),
TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) :
"");
}
else
{
TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
}
}
}
do_cleanups (back_to);
}
processing_current_prefix = previous_prefix;
if (back_to != NULL)
do_cleanups (back_to);
}
static void
process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
{
const char *previous_prefix = processing_current_prefix;
struct die_info *child_die = die->child;
if (TYPE_TAG_NAME (die->type) != NULL)
processing_current_prefix = TYPE_TAG_NAME (die->type);
while (child_die != NULL && child_die->tag)
{
if (child_die->tag == DW_TAG_member
|| (child_die->tag == DW_TAG_variable
&& dwarf2_attr (child_die, DW_AT_const_value, cu) == NULL)
|| child_die->tag == DW_TAG_inheritance)
{
}
else
process_die (child_die, cu);
child_die = sibling_die (child_die);
}
if (die->child != NULL && ! die_is_declaration (die, cu))
new_symbol (die, die->type, cu);
processing_current_prefix = previous_prefix;
}
static void
read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
if (die->type)
return;
type = alloc_type (objfile);
TYPE_CODE (type) = TYPE_CODE_ENUM;
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
char *name = DW_STRING (attr);
if (processing_has_namespace_info)
{
TYPE_TAG_NAME (type) = typename_concat (&objfile->objfile_obstack,
processing_current_prefix,
name, cu);
}
else
{
TYPE_TAG_NAME (type) = name;
}
}
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
TYPE_LENGTH (type) = DW_UNSND (attr);
}
else
{
TYPE_LENGTH (type) = 0;
}
set_die_type (die, type, cu);
}
static char *
determine_class_name (struct die_info *die, struct dwarf2_cu *cu)
{
struct cleanup *back_to = NULL;
struct die_info *spec_die = die_specification (die, cu);
char *new_prefix = NULL;
if (spec_die != NULL)
{
char *specification_prefix = determine_prefix (spec_die, cu);
processing_current_prefix = specification_prefix;
back_to = make_cleanup (xfree, specification_prefix);
}
if (!processing_has_namespace_info)
{
struct die_info *child;
for (child = die->child;
child != NULL && child->tag != 0;
child = sibling_die (child))
{
if (child->tag == DW_TAG_subprogram)
{
new_prefix
= language_class_name_from_physname (cu->language_defn,
dwarf2_linkage_name
(child, cu));
if (new_prefix != NULL)
break;
}
}
}
if (new_prefix == NULL)
{
const char *name = dwarf2_name (die, cu);
new_prefix = typename_concat (NULL, processing_current_prefix,
name ? name : "<<anonymous>>",
cu);
}
if (back_to != NULL)
do_cleanups (back_to);
return new_prefix;
}
static void
process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *child_die;
struct field *fields;
struct attribute *attr;
struct symbol *sym;
int num_fields;
int unsigned_enum = 1;
num_fields = 0;
fields = NULL;
if (die->child != NULL)
{
child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag != DW_TAG_enumerator)
{
process_die (child_die, cu);
}
else
{
attr = dwarf2_attr (child_die, DW_AT_name, cu);
if (attr)
{
sym = new_symbol (child_die, die->type, cu);
if (SYMBOL_VALUE (sym) < 0)
unsigned_enum = 0;
if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
{
fields = (struct field *)
xrealloc (fields,
(num_fields + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct field));
}
FIELD_NAME (fields[num_fields]) = DEPRECATED_SYMBOL_NAME (sym);
FIELD_TYPE (fields[num_fields]) = NULL;
FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
FIELD_BITSIZE (fields[num_fields]) = 0;
FIELD_STATIC_KIND (fields[num_fields]) = 0;
num_fields++;
}
}
child_die = sibling_die (child_die);
}
if (num_fields)
{
TYPE_NFIELDS (die->type) = num_fields;
TYPE_FIELDS (die->type) = (struct field *)
TYPE_ALLOC (die->type, sizeof (struct field) * num_fields);
memcpy (TYPE_FIELDS (die->type), fields,
sizeof (struct field) * num_fields);
xfree (fields);
}
if (unsigned_enum)
TYPE_FLAGS (die->type) |= TYPE_FLAG_UNSIGNED;
}
new_symbol (die, die->type, cu);
}
static void
read_array_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct die_info *child_die;
struct type *type = NULL;
struct type *element_type, *range_type, *index_type;
struct type **range_types = NULL;
struct attribute *attr;
int ndim = 0;
struct cleanup *back_to;
if (die->type)
{
return;
}
element_type = die_type (die, cu);
if (die->child == NULL)
{
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
range_type = create_range_type (NULL, index_type, 0, -1);
set_die_type (die, create_array_type (NULL, element_type, range_type),
cu);
return;
}
back_to = make_cleanup (null_cleanup, NULL);
child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subrange_type)
{
read_subrange_type (child_die, cu);
if (child_die->type != NULL)
{
if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
{
range_types = (struct type **)
xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct type *));
if (ndim == 0)
make_cleanup (free_current_contents, &range_types);
}
range_types[ndim++] = child_die->type;
}
}
child_die = sibling_die (child_die);
}
type = element_type;
if (read_array_order (die, cu) == DW_ORD_col_major)
{
int i = 0;
while (i < ndim)
type = create_array_type (NULL, type, range_types[i++]);
}
else
{
while (ndim-- > 0)
type = create_array_type (NULL, type, range_types[ndim]);
}
attr = dwarf2_attr (die, DW_AT_GNU_vector, cu);
if (attr)
TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
do_cleanups (back_to);
set_die_type (die, type, cu);
}
static enum dwarf_array_dim_ordering
read_array_order (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_ordering, cu);
if (attr) return DW_SND (attr);
if (cu->language == language_fortran &&
cu->producer && strstr (cu->producer, "GNU F77"))
{
return DW_ORD_row_major;
}
switch (cu->language_defn->la_array_ordering)
{
case array_column_major:
return DW_ORD_col_major;
case array_row_major:
default:
return DW_ORD_row_major;
};
}
static void
read_common_block (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *child_die;
struct attribute *attr;
struct symbol *sym;
CORE_ADDR base = (CORE_ADDR) 0;
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
if (attr_form_is_block (attr))
{
base = decode_locdesc (DW_BLOCK (attr), cu);
}
else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
dwarf2_complex_location_expr_complaint ();
}
else
{
dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
"common block member");
}
}
if (die->child != NULL)
{
child_die = die->child;
while (child_die && child_die->tag)
{
sym = new_symbol (child_die, NULL, cu);
attr = dwarf2_attr (child_die, DW_AT_data_member_location, cu);
if (attr)
{
SYMBOL_VALUE_ADDRESS (sym) =
base + decode_locdesc (DW_BLOCK (attr), cu);
add_symbol_to_list (sym, &global_symbols);
}
child_die = sibling_die (child_die);
}
}
}
static void
read_namespace (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
const char *previous_prefix = processing_current_prefix;
const char *name;
int is_anonymous;
struct cleanup *back_to = make_cleanup (null_cleanup, 0);
name = namespace_name (die, &is_anonymous, cu);
if (previous_prefix[0] == '\0')
{
processing_current_prefix = name;
}
else
{
char *temp_name = typename_concat (NULL, previous_prefix, name, cu);
make_cleanup (xfree, temp_name);
processing_current_prefix = temp_name;
}
if (dwarf2_extension (die, cu) == NULL)
{
struct type *type;
type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
(char *) processing_current_prefix,
objfile);
TYPE_TAG_NAME (type) = TYPE_NAME (type);
new_symbol (die, type, cu);
set_die_type (die, type, cu);
if (is_anonymous)
cp_add_using_directive (processing_current_prefix,
strlen (previous_prefix),
strlen (processing_current_prefix));
}
if (die->child != NULL)
{
struct die_info *child_die = die->child;
while (child_die && child_die->tag)
{
process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
processing_current_prefix = previous_prefix;
do_cleanups (back_to);
}
static const char *
namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu)
{
struct die_info *current_die;
const char *name = NULL;
for (current_die = die;
current_die != NULL;
current_die = dwarf2_extension (die, cu))
{
name = dwarf2_name (current_die, cu);
if (name != NULL)
break;
}
*is_anonymous = (name == NULL);
if (*is_anonymous)
name = "(anonymous namespace)";
return name;
}
static void
read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct comp_unit_head *cu_header = &cu->header;
struct type *type;
struct attribute *attr_byte_size;
struct attribute *attr_address_class;
int byte_size, addr_class;
if (die->type)
{
return;
}
type = lookup_pointer_type (die_type (die, cu));
attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr_byte_size)
byte_size = DW_UNSND (attr_byte_size);
else
byte_size = cu_header->addr_size;
attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu);
if (attr_address_class)
addr_class = DW_UNSND (attr_address_class);
else
addr_class = DW_ADDR_none;
if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
{
if (ADDRESS_CLASS_TYPE_FLAGS_P ())
{
int type_flags;
type_flags = ADDRESS_CLASS_TYPE_FLAGS (byte_size, addr_class);
gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
type = make_type_with_address_space (type, type_flags);
}
else if (TYPE_LENGTH (type) != byte_size)
{
complaint (&symfile_complaints, _("invalid pointer size %d"), byte_size);
}
else {
}
}
TYPE_LENGTH (type) = byte_size;
set_die_type (die, type, cu);
}
static void
read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct type *type;
struct type *to_type;
struct type *domain;
if (die->type)
{
return;
}
type = alloc_type (objfile);
to_type = die_type (die, cu);
domain = die_containing_type (die, cu);
smash_to_member_type (type, domain, to_type);
set_die_type (die, type, cu);
}
static void
read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct comp_unit_head *cu_header = &cu->header;
struct type *type;
struct attribute *attr;
if (die->type)
{
return;
}
type = lookup_reference_type (die_type (die, cu));
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
TYPE_LENGTH (type) = DW_UNSND (attr);
}
else
{
TYPE_LENGTH (type) = cu_header->addr_size;
}
set_die_type (die, type, cu);
}
static void
read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type;
if (die->type)
{
return;
}
base_type = die_type (die, cu);
set_die_type (die, make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0),
cu);
}
static void
read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type;
if (die->type)
{
return;
}
base_type = die_type (die, cu);
set_die_type (die, make_cv_type (TYPE_CONST (base_type), 1, base_type, 0),
cu);
}
static void
read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct type *type, *range_type, *index_type, *char_type;
struct attribute *attr;
unsigned int length;
if (die->type)
{
return;
}
attr = dwarf2_attr (die, DW_AT_string_length, cu);
if (attr)
{
length = DW_UNSND (attr);
}
else
{
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
length = DW_UNSND (attr);
}
else
{
length = 1;
}
}
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
range_type = create_range_type (NULL, index_type, 1, length);
if (cu->language == language_fortran)
{
type = create_string_type (0, range_type);
}
else
{
char_type = dwarf2_fundamental_type (objfile, FT_CHAR, cu);
type = create_string_type (char_type, range_type);
}
set_die_type (die, type, cu);
}
static void
read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type;
struct type *ftype;
struct attribute *attr;
if (die->type)
{
return;
}
type = die_type (die, cu);
ftype = make_function_type (type, (struct type **) 0);
attr = dwarf2_attr (die, DW_AT_prototyped, cu);
if ((attr && (DW_UNSND (attr) != 0))
|| cu->language == language_cplus
|| cu->language == language_java)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
if (die->child != NULL)
{
struct die_info *child_die;
int nparams = 0;
int iparams = 0;
child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
nparams++;
else if (child_die->tag == DW_TAG_unspecified_parameters)
TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
child_die = sibling_die (child_die);
}
TYPE_NFIELDS (ftype) = nparams;
TYPE_FIELDS (ftype) = (struct field *)
TYPE_ALLOC (ftype, nparams * sizeof (struct field));
child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
{
attr = dwarf2_attr (child_die, DW_AT_artificial, cu);
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, cu);
iparams++;
}
child_die = sibling_die (child_die);
}
}
set_die_type (die, ftype, cu);
}
static void
read_typedef (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct attribute *attr;
char *name = NULL;
if (!die->type)
{
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
name = DW_STRING (attr);
}
set_die_type (die, init_type (TYPE_CODE_TYPEDEF, 0,
TYPE_FLAG_TARGET_STUB, name, objfile),
cu);
TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
}
}
static void
read_base_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
int encoding = 0, size = 0;
if (die->type)
{
return;
}
attr = dwarf2_attr (die, DW_AT_encoding, cu);
if (attr)
{
encoding = DW_UNSND (attr);
}
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
size = DW_UNSND (attr);
}
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
enum type_code code = TYPE_CODE_INT;
int type_flags = 0;
switch (encoding)
{
case DW_ATE_address:
code = TYPE_CODE_PTR;
type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_boolean:
code = TYPE_CODE_BOOL;
type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
break;
case DW_ATE_float:
code = TYPE_CODE_FLT;
break;
case DW_ATE_signed:
case DW_ATE_signed_char:
break;
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
type_flags |= TYPE_FLAG_UNSIGNED;
break;
default:
complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"),
dwarf_type_encoding_name (encoding));
break;
}
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,
cu);
else if (encoding == DW_ATE_complex_float)
{
if (size == 32)
TYPE_TARGET_TYPE (type)
= dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT, cu);
else if (size == 16)
TYPE_TARGET_TYPE (type)
= dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
else if (size == 8)
TYPE_TARGET_TYPE (type)
= dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
}
}
else
{
type = dwarf_base_type (encoding, size, cu);
}
set_die_type (die, type, cu);
}
static void
read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type;
struct type *range_type;
struct attribute *attr;
int low = 0;
int high = -1;
if (die->type)
return;
base_type = die_type (die, cu);
if (base_type == NULL)
{
complaint (&symfile_complaints,
_("DW_AT_type missing from DW_TAG_subrange_type"));
return;
}
if (TYPE_CODE (base_type) == TYPE_CODE_VOID)
base_type = alloc_type (NULL);
if (cu->language == language_fortran)
{
low = 1;
}
attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
if (attr)
low = dwarf2_get_attr_constant_value (attr, 0);
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
if (attr)
{
if (attr->form == DW_FORM_block1)
{
high = low - 1;
}
else
high = dwarf2_get_attr_constant_value (attr, 1);
}
range_type = create_range_type (NULL, base_type, low, high);
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
TYPE_NAME (range_type) = DW_STRING (attr);
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
TYPE_LENGTH (range_type) = DW_UNSND (attr);
set_die_type (die, range_type, cu);
}
static struct die_info *
read_comp_unit (char *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
{
return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL);
}
static struct die_info *
read_die_and_children (char *info_ptr, bfd *abfd,
struct dwarf2_cu *cu,
char **new_info_ptr,
struct die_info *parent)
{
struct die_info *die;
char *cur_ptr;
int has_children;
cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
store_in_ref_table (die->offset, die, cu);
if (has_children)
{
die->child = read_die_and_siblings (cur_ptr, abfd, cu,
new_info_ptr, die);
}
else
{
die->child = NULL;
*new_info_ptr = cur_ptr;
}
die->sibling = NULL;
die->parent = parent;
return die;
}
static struct die_info *
read_die_and_siblings (char *info_ptr, bfd *abfd,
struct dwarf2_cu *cu,
char **new_info_ptr,
struct die_info *parent)
{
struct die_info *first_die, *last_sibling;
char *cur_ptr;
cur_ptr = info_ptr;
first_die = last_sibling = NULL;
while (1)
{
struct die_info *die
= read_die_and_children (cur_ptr, abfd, cu, &cur_ptr, parent);
if (!first_die)
{
first_die = die;
}
else
{
last_sibling->sibling = die;
}
if (die->tag == 0)
{
*new_info_ptr = cur_ptr;
return first_die;
}
else
{
last_sibling = die;
}
}
}
static void
free_die_list (struct die_info *dies)
{
struct die_info *die, *next;
die = dies;
while (die)
{
if (die->child != NULL)
free_die_list (die->child);
next = die->sibling;
xfree (die->attrs);
xfree (die);
die = next;
}
}
char *
dwarf2_read_section (struct objfile *objfile, bfd *abfd, asection *sectp)
{
char *buf, *retbuf;
bfd_size_type size = bfd_get_section_size (sectp);
if (size == 0)
return NULL;
buf = (char *) obstack_alloc (&objfile->objfile_obstack, size);
retbuf
= (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
if (retbuf != NULL)
return retbuf;
if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
|| bfd_bread (buf, size, abfd) != size)
error (_("Dwarf Error: Can't read DWARF data from '%s'"),
bfd_get_filename (abfd));
return buf;
}
static void
dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
{
struct comp_unit_head *cu_header = &cu->header;
char *abbrev_ptr;
struct abbrev_info *cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
unsigned int abbrev_form, hash_number;
struct attr_abbrev *cur_attrs;
unsigned int allocated_attrs;
obstack_init (&cu->abbrev_obstack);
cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack,
(ABBREV_HASH_SIZE
* sizeof (struct abbrev_info *)));
memset (cu->dwarf2_abbrevs, 0,
ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
abbrev_ptr = dwarf2_per_objfile->abbrev_buffer + cu_header->abbrev_offset;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
allocated_attrs = ATTR_ALLOC_CHUNK;
cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev));
while (abbrev_number)
{
cur_abbrev = dwarf_alloc_abbrev (cu);
cur_abbrev->number = abbrev_number;
cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
abbrev_ptr += 1;
if (cur_abbrev->tag == DW_TAG_namespace)
cu->has_namespace_info = 1;
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
while (abbrev_name)
{
if (cur_abbrev->num_attrs == allocated_attrs)
{
allocated_attrs += ATTR_ALLOC_CHUNK;
cur_attrs
= xrealloc (cur_attrs, (allocated_attrs
* sizeof (struct attr_abbrev)));
}
if (abbrev_form == DW_FORM_ref_addr
|| abbrev_form == DW_FORM_indirect)
cu->has_form_ref_addr = 1;
cur_attrs[cur_abbrev->num_attrs].name = abbrev_name;
cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form;
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
}
cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack,
(cur_abbrev->num_attrs
* sizeof (struct attr_abbrev)));
memcpy (cur_abbrev->attrs, cur_attrs,
cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
hash_number = abbrev_number % ABBREV_HASH_SIZE;
cur_abbrev->next = cu->dwarf2_abbrevs[hash_number];
cu->dwarf2_abbrevs[hash_number] = cur_abbrev;
if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev_buffer)
>= dwarf2_per_objfile->abbrev_size)
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL)
break;
}
xfree (cur_attrs);
}
static void
dwarf2_free_abbrev_table (void *ptr_to_cu)
{
struct dwarf2_cu *cu = ptr_to_cu;
obstack_free (&cu->abbrev_obstack, NULL);
cu->dwarf2_abbrevs = NULL;
}
static struct abbrev_info *
dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
hash_number = number % ABBREV_HASH_SIZE;
abbrev = cu->dwarf2_abbrevs[hash_number];
while (abbrev)
{
if (abbrev->number == number)
return abbrev;
else
abbrev = abbrev->next;
}
return NULL;
}
static int
is_type_tag_for_partial (int tag)
{
switch (tag)
{
#if 0
case DW_TAG_array_type:
case DW_TAG_file_type:
case DW_TAG_ptr_to_member_type:
case DW_TAG_set_type:
case DW_TAG_string_type:
case DW_TAG_subroutine_type:
#endif
case DW_TAG_base_type:
case DW_TAG_class_type:
case DW_TAG_enumeration_type:
case DW_TAG_structure_type:
case DW_TAG_subrange_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
return 1;
default:
return 0;
}
}
static struct partial_die_info *
load_partial_dies (bfd *abfd, char *info_ptr, int building_psymtab,
struct dwarf2_cu *cu)
{
struct partial_die_info *part_die;
struct partial_die_info *parent_die, *last_die, *first_die = NULL;
struct abbrev_info *abbrev;
unsigned int bytes_read;
int nesting_level = 1;
parent_die = NULL;
last_die = NULL;
cu->partial_dies
= htab_create_alloc_ex (cu->header.length / 12,
partial_die_hash,
partial_die_eq,
NULL,
&cu->comp_unit_obstack,
hashtab_obstack_allocate,
dummy_obstack_deallocate);
part_die = obstack_alloc (&cu->comp_unit_obstack,
sizeof (struct partial_die_info));
while (1)
{
abbrev = peek_die_abbrev (info_ptr, (int *) &bytes_read, cu);
if (abbrev == NULL)
{
if (--nesting_level == 0)
{
return first_die;
}
info_ptr += bytes_read;
last_die = parent_die;
parent_die = parent_die->die_parent;
continue;
}
if (!is_type_tag_for_partial (abbrev->tag)
&& abbrev->tag != DW_TAG_enumerator
&& abbrev->tag != DW_TAG_subprogram
&& abbrev->tag != DW_TAG_variable
&& abbrev->tag != DW_TAG_namespace)
{
info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
continue;
}
info_ptr = read_partial_die (part_die, abbrev, bytes_read,
abfd, info_ptr, cu);
if (parent_die == NULL
&& part_die->has_specification == 0
&& part_die->is_declaration == 0
&& (part_die->tag == DW_TAG_typedef
|| part_die->tag == DW_TAG_base_type
|| part_die->tag == DW_TAG_subrange_type))
{
if (building_psymtab && part_die->name != NULL)
add_psymbol_to_list (part_die->name, strlen (part_die->name),
VAR_DOMAIN, LOC_TYPEDEF,
&cu->objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, cu->objfile);
info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
continue;
}
if (part_die->tag == DW_TAG_enumerator
&& parent_die != NULL
&& parent_die->die_parent == NULL
&& parent_die->tag == DW_TAG_enumeration_type
&& parent_die->has_specification == 0)
{
if (part_die->name == NULL)
complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
else if (building_psymtab)
add_psymbol_to_list (part_die->name, strlen (part_die->name),
VAR_DOMAIN, LOC_CONST,
(cu->language == language_cplus
|| cu->language == language_java)
? &cu->objfile->global_psymbols
: &cu->objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, cu->objfile);
info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
continue;
}
part_die->die_parent = parent_die;
part_die->die_sibling = NULL;
part_die->die_child = NULL;
if (last_die && last_die == parent_die)
last_die->die_child = part_die;
else if (last_die)
last_die->die_sibling = part_die;
last_die = part_die;
if (first_die == NULL)
first_die = part_die;
if (abbrev->tag == DW_TAG_subprogram
|| abbrev->tag == DW_TAG_variable
|| abbrev->tag == DW_TAG_namespace
|| part_die->is_declaration)
{
void **slot;
slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
part_die->offset, INSERT);
*slot = part_die;
}
part_die = obstack_alloc (&cu->comp_unit_obstack,
sizeof (struct partial_die_info));
if (last_die->has_children
&& (last_die->tag == DW_TAG_namespace
|| last_die->tag == DW_TAG_enumeration_type
|| (cu->language != language_c
&& (last_die->tag == DW_TAG_class_type
|| last_die->tag == DW_TAG_structure_type
|| last_die->tag == DW_TAG_union_type))))
{
nesting_level++;
parent_die = last_die;
continue;
}
info_ptr = locate_pdi_sibling (last_die, info_ptr, abfd, cu);
}
}
static char *
read_partial_die (struct partial_die_info *part_die,
struct abbrev_info *abbrev,
unsigned int abbrev_len, bfd *abfd,
char *info_ptr, struct dwarf2_cu *cu)
{
unsigned int i;
struct attribute attr;
int has_low_pc_attr = 0;
int has_high_pc_attr = 0;
memset (part_die, 0, sizeof (struct partial_die_info));
part_die->offset = info_ptr - dwarf2_per_objfile->info_buffer;
part_die->has_repository = 0;
part_die->has_repo_specification = 0;
part_die->has_repository_type = 0;
info_ptr += abbrev_len;
if (abbrev == NULL)
return info_ptr;
part_die->tag = abbrev->tag;
part_die->has_children = abbrev->has_children;
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu);
switch (attr.name)
{
case DW_AT_name:
if (part_die->name == NULL)
{
if (attr.form == DW_FORM_APPLE_db_str)
part_die->name = get_repository_name (&attr, cu);
else
part_die->name = DW_STRING (&attr);
}
break;
case DW_AT_APPLE_repository_file:
part_die->repo_name = DW_STRING (&attr);
part_die->has_repository = 1;
break;
case DW_AT_comp_dir:
if (part_die->dirname == NULL)
{
if (attr.form == DW_FORM_APPLE_db_str)
part_die->dirname = get_repository_name (&attr, cu);
else
part_die->dirname = DW_STRING (&attr);
}
break;
case DW_AT_MIPS_linkage_name:
{
if (attr.form == DW_FORM_APPLE_db_str)
part_die->name = get_repository_name (&attr, cu);
else
part_die->name = DW_STRING (&attr);
}
break;
case DW_AT_low_pc:
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, DW_ADDR (&attr), &addr, 0))
{
part_die->lowpc = addr;
has_low_pc_attr = 1;
}
}
break;
case DW_AT_high_pc:
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, DW_ADDR (&attr), &addr, 1))
{
has_high_pc_attr = 1;
part_die->highpc = addr;
}
}
break;
case DW_AT_location:
if (attr_form_is_block (&attr))
{
part_die->locdesc = DW_BLOCK (&attr);
}
else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
{
dwarf2_complex_location_expr_complaint ();
}
else
{
dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
"partial symbol information");
}
break;
case DW_AT_language:
part_die->language = DW_UNSND (&attr);
break;
case DW_AT_external:
part_die->is_external = DW_UNSND (&attr);
break;
case DW_AT_declaration:
part_die->is_declaration = DW_UNSND (&attr);
break;
case DW_AT_type:
part_die->has_type = 1;
break;
case DW_AT_abstract_origin:
case DW_AT_specification:
case DW_AT_extension:
part_die->has_specification = 1;
part_die->spec_offset = dwarf2_get_ref_die_offset (&attr, cu);
break;
case DW_AT_APPLE_repository_specification:
part_die->has_repo_specification = 1;
part_die->repo_spec_id = DW_UNSND (&attr);
break;
case DW_AT_APPLE_repository_type:
part_die->has_repository_type = 1;
break;
case DW_AT_sibling:
if (attr.form == DW_FORM_ref_addr)
complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
else
part_die->sibling = dwarf2_per_objfile->info_buffer
+ dwarf2_get_ref_die_offset (&attr, cu);
break;
case DW_AT_stmt_list:
part_die->has_stmt_list = 1;
part_die->line_offset = DW_UNSND (&attr);
break;
default:
break;
}
}
if (has_low_pc_attr && has_high_pc_attr
&& part_die->lowpc < part_die->highpc
&& (part_die->lowpc != 0
|| (bfd_get_file_flags (abfd) & HAS_RELOC)))
part_die->has_pc_info = 1;
if (part_die->has_repository)
open_dwarf_repository (part_die->dirname, part_die->repo_name,
cu->objfile, cu);
return info_ptr;
}
static struct partial_die_info *
find_partial_die_in_comp_unit (unsigned long offset, struct dwarf2_cu *cu)
{
struct partial_die_info *lookup_die = NULL;
struct partial_die_info part_die;
part_die.offset = offset;
lookup_die = htab_find_with_hash (cu->partial_dies, &part_die, offset);
if (lookup_die == NULL)
internal_error (__FILE__, __LINE__,
_("could not find partial DIE in cache\n"));
return lookup_die;
}
static struct partial_die_info *
find_partial_die (unsigned long offset, struct dwarf2_cu *cu)
{
struct dwarf2_per_cu_data *per_cu;
if (offset >= cu->header.offset
&& offset < cu->header.offset + cu->header.length)
return find_partial_die_in_comp_unit (offset, cu);
per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
if (per_cu->cu == NULL)
{
load_comp_unit (per_cu, cu->objfile);
per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
dwarf2_per_objfile->read_in_chain = per_cu;
}
per_cu->cu->last_used = 0;
return find_partial_die_in_comp_unit (offset, per_cu->cu);
}
static void
fixup_partial_die (struct partial_die_info *part_die,
struct dwarf2_cu *cu)
{
if (part_die->name == NULL && part_die->has_specification)
{
struct partial_die_info *spec_die;
spec_die = find_partial_die (part_die->spec_offset, cu);
fixup_partial_die (spec_die, cu);
if (spec_die->name)
{
part_die->name = spec_die->name;
if (spec_die->is_external)
part_die->is_external = spec_die->is_external;
}
}
if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type
|| part_die->tag == DW_TAG_class_type))
part_die->name = "(anonymous class)";
if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
part_die->name = "(anonymous namespace)";
if (part_die->tag == DW_TAG_structure_type
|| part_die->tag == DW_TAG_class_type
|| part_die->tag == DW_TAG_union_type)
guess_structure_name (part_die, cu);
}
static char *
read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
struct dwarf2_cu *cu, int *has_children)
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info *abbrev;
struct die_info *die;
char *repository_name = NULL;
char *comp_dir = NULL;
offset = info_ptr - dwarf2_per_objfile->info_buffer;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
if (!abbrev_number)
{
die = dwarf_alloc_die ();
die->tag = 0;
die->abbrev = abbrev_number;
die->type = NULL;
*diep = die;
*has_children = 0;
return info_ptr;
}
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
abbrev_number,
bfd_get_filename (abfd));
}
die = dwarf_alloc_die ();
die->offset = offset;
die->repository_id = 0;
die->tag = abbrev->tag;
die->abbrev = abbrev_number;
die->type = NULL;
die->num_attrs = abbrev->num_attrs;
die->attrs = (struct attribute *)
xmalloc (die->num_attrs * sizeof (struct attribute));
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
abfd, info_ptr, cu);
if (die->attrs[i].name == DW_AT_APPLE_repository_file)
repository_name = DW_STRING (&die->attrs[i]);
else if (die->attrs[i].name == DW_AT_comp_dir)
comp_dir = DW_STRING (&die->attrs[i]);
if (die->attrs[i].form == DW_FORM_ref_addr
&& (DW_ADDR (&die->attrs[i]) < cu->header.offset
|| (DW_ADDR (&die->attrs[i])
>= cu->header.offset + cu->header.length)))
{
struct dwarf2_per_cu_data *per_cu;
per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (&die->attrs[i]),
cu->objfile);
dwarf2_add_dependence (cu, per_cu);
if (per_cu->queued)
continue;
if (per_cu->cu != NULL)
{
per_cu->cu->last_used = 0;
continue;
}
queue_comp_unit (per_cu);
}
}
if (repository_name)
open_dwarf_repository (comp_dir, repository_name, cu->objfile, cu);
*diep = die;
*has_children = abbrev->has_children;
return info_ptr;
}
static char *
read_attribute_value (struct attribute *attr, unsigned form,
bfd *abfd, char *info_ptr,
struct dwarf2_cu *cu)
{
struct comp_unit_head *cu_header = &cu->header;
unsigned int bytes_read;
struct dwarf_block *blk;
attr->form = form;
switch (form)
{
case DW_FORM_addr:
case DW_FORM_ref_addr:
DW_ADDR (attr) = read_address (abfd, info_ptr, cu, (int *) &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_block2:
blk = dwarf_alloc_block (cu);
blk->size = read_2_bytes (abfd, info_ptr);
info_ptr += 2;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_block4:
blk = dwarf_alloc_block (cu);
blk->size = read_4_bytes (abfd, info_ptr);
info_ptr += 4;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_data2:
DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
info_ptr += 2;
break;
case DW_FORM_data4:
DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
info_ptr += 4;
break;
case DW_FORM_data8:
DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
case DW_FORM_string:
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 (cu);
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_block1:
blk = dwarf_alloc_block (cu);
blk->size = read_1_byte (abfd, info_ptr);
info_ptr += 1;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_data1:
DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
info_ptr += 1;
break;
case DW_FORM_flag:
DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
info_ptr += 1;
break;
case DW_FORM_sdata:
DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_APPLE_db_str:
case DW_FORM_udata:
DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_ref1:
DW_ADDR (attr) = cu->header.offset + read_1_byte (abfd, info_ptr);
info_ptr += 1;
break;
case DW_FORM_ref2:
DW_ADDR (attr) = cu->header.offset + read_2_bytes (abfd, info_ptr);
info_ptr += 2;
break;
case DW_FORM_ref4:
DW_ADDR (attr) = cu->header.offset + read_4_bytes (abfd, info_ptr);
info_ptr += 4;
break;
case DW_FORM_ref8:
DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
case DW_FORM_ref_udata:
DW_ADDR (attr) = (cu->header.offset
+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
info_ptr += bytes_read;
break;
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);
break;
default:
error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
return info_ptr;
}
static char *
read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
bfd *abfd, char *info_ptr, struct dwarf2_cu *cu)
{
attr->name = abbrev->name;
return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu);
}
static unsigned int
read_1_byte (bfd *abfd, char *buf)
{
return bfd_get_8 (abfd, (bfd_byte *) buf);
}
static int
read_1_signed_byte (bfd *abfd, char *buf)
{
return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
}
static unsigned int
read_2_bytes (bfd *abfd, char *buf)
{
return bfd_get_16 (abfd, (bfd_byte *) buf);
}
static int
read_2_signed_bytes (bfd *abfd, char *buf)
{
return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
}
static unsigned int
read_4_bytes (bfd *abfd, char *buf)
{
return bfd_get_32 (abfd, (bfd_byte *) buf);
}
static int
read_4_signed_bytes (bfd *abfd, char *buf)
{
return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
}
static unsigned long
read_8_bytes (bfd *abfd, char *buf)
{
return bfd_get_64 (abfd, (bfd_byte *) buf);
}
static CORE_ADDR
read_address (bfd *abfd, char *buf, struct dwarf2_cu *cu, int *bytes_read)
{
struct comp_unit_head *cu_header = &cu->header;
CORE_ADDR retval = 0;
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 [in module %s]"),
bfd_get_filename (abfd));
}
}
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 [in module %s]"),
bfd_get_filename (abfd));
}
}
*bytes_read = cu_header->addr_size;
return retval;
}
static LONGEST
read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
int *bytes_read)
{
LONGEST length = bfd_get_32 (abfd, (bfd_byte *) buf);
if (length == 0xffffffff)
{
length = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
*bytes_read = 12;
}
else if (length == 0)
{
length = bfd_get_64 (abfd, (bfd_byte *) buf);
*bytes_read = 8;
}
else
{
*bytes_read = 4;
}
if (cu_header)
{
gdb_assert (cu_header->initial_length_size == 0
|| cu_header->initial_length_size == 4
|| cu_header->initial_length_size == 8
|| cu_header->initial_length_size == 12);
if (cu_header->initial_length_size != 0
&& cu_header->initial_length_size != *bytes_read)
complaint (&symfile_complaints,
_("intermixed 32-bit and 64-bit DWARF sections"));
cu_header->initial_length_size = *bytes_read;
cu_header->offset_size = (*bytes_read == 4) ? 4 : 8;
}
return length;
}
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:
internal_error (__FILE__, __LINE__,
_("read_offset: bad switch [in module %s]"),
bfd_get_filename (abfd));
}
return retval;
}
static char *
read_n_bytes (bfd *abfd, char *buf, unsigned int size)
{
gdb_assert (HOST_CHAR_BIT == 8);
return buf;
}
static char *
read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
gdb_assert (HOST_CHAR_BIT == 8);
if (*buf == '\0')
{
*bytes_read_ptr = 1;
return NULL;
}
*bytes_read_ptr = strlen (buf) + 1;
return buf;
}
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 (dwarf2_per_objfile->str_buffer == NULL)
{
error (_("DW_FORM_strp used without .debug_str section [in module %s]"),
bfd_get_filename (abfd));
return NULL;
}
if (str_offset >= dwarf2_per_objfile->str_size)
{
error (_("DW_FORM_strp pointing outside of .debug_str section [in module %s]"),
bfd_get_filename (abfd));
return NULL;
}
gdb_assert (HOST_CHAR_BIT == 8);
if (dwarf2_per_objfile->str_buffer[str_offset] == '\0')
return NULL;
return dwarf2_per_objfile->str_buffer + str_offset;
}
static unsigned long
read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
unsigned long result;
unsigned int num_read;
int i, shift;
unsigned char byte;
result = 0;
shift = 0;
num_read = 0;
i = 0;
while (1)
{
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
num_read++;
result |= ((unsigned long)(byte & 127) << shift);
if ((byte & 128) == 0)
{
break;
}
shift += 7;
}
*bytes_read_ptr = num_read;
return result;
}
static long
read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
long result;
int i, shift, num_read;
unsigned char byte;
result = 0;
shift = 0;
num_read = 0;
i = 0;
while (1)
{
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
num_read++;
result |= ((long)(byte & 127) << shift);
shift += 7;
if ((byte & 128) == 0)
{
break;
}
}
if ((shift < 8 * sizeof (result)) && (byte & 0x40))
result |= -(((long)1) << shift);
*bytes_read_ptr = num_read;
return result;
}
static char *
skip_leb128 (bfd *abfd, char *buf)
{
int byte;
while (1)
{
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
if ((byte & 128) == 0)
return buf;
}
}
static void
set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
{
switch (lang)
{
case DW_LANG_C89:
case DW_LANG_C:
cu->language = language_c;
break;
case DW_LANG_C_plus_plus:
cu->language = language_cplus;
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_Ada95:
cu->language = language_ada;
break;
case DW_LANG_ObjC:
cu->language = language_objc;
break;
case DW_LANG_ObjC_plus_plus:
cu->language = language_objcplus;
break;
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
case DW_LANG_Pascal83:
case DW_LANG_Modula2:
default:
cu->language = language_minimal;
break;
}
cu->language_defn = language_def (cu->language);
}
static struct attribute *
dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
{
unsigned int i;
struct attribute *spec = NULL;
struct attribute *repository_spec = NULL;
for (i = 0; i < die->num_attrs; ++i)
{
if (die->attrs[i].name == name)
{
if (die->attrs[i].form == DW_FORM_APPLE_db_str)
return get_repository_name (&(die->attrs[i]), cu);
else
return &die->attrs[i];
}
if (die->attrs[i].name == DW_AT_specification
|| die->attrs[i].name == DW_AT_abstract_origin)
spec = &die->attrs[i];
if (die->attrs[i].name == DW_AT_APPLE_repository_specification)
repository_spec = &die->attrs[i];
if (cu->repository && die->attrs[i].name == DW_AT_APPLE_repository_name
&& name == DW_AT_name)
return get_repository_name (&(die->attrs[i]), cu);
}
if (spec)
return dwarf2_attr (follow_die_ref (die, spec, cu), name, cu);
if (repository_spec)
{
return dwarf2_attr (follow_db_ref (die, repository_spec, cu), name, cu);
}
return NULL;
}
static int
dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu)
{
struct attribute *attr = dwarf2_attr (die, name, cu);
return (attr && DW_UNSND (attr));
}
static int
die_is_declaration (struct die_info *die, struct dwarf2_cu *cu)
{
return (dwarf2_flag_true_p (die, DW_AT_declaration, cu)
&& dwarf2_attr (die, DW_AT_specification, cu) == NULL);
}
static struct die_info *
die_specification (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, cu);
if (spec_attr == NULL)
return NULL;
else
return follow_die_ref (die, spec_attr, cu);
}
static void
free_line_header (struct line_header *lh)
{
if (lh->standard_opcode_lengths)
xfree (lh->standard_opcode_lengths);
if (lh->file_names)
xfree (lh->file_names);
if (lh->include_dirs)
xfree (lh->include_dirs);
xfree (lh);
}
static void
add_include_dir (struct line_header *lh, char *include_dir)
{
if (lh->include_dirs_size == 0)
{
lh->include_dirs_size = 1;
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;
}
static void
add_file_name (struct line_header *lh,
char *name,
unsigned int dir_index,
unsigned int mod_time,
unsigned int length)
{
struct file_entry *fe;
if (lh->file_names_size == 0)
{
lh->file_names_size = 1;
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;
fe->included_p = 0;
}
static struct line_header *
dwarf_decode_line_header (unsigned int offset, bfd *abfd,
struct dwarf2_cu *cu)
{
struct cleanup *back_to;
struct line_header *lh;
char *line_ptr;
unsigned bytes_read;
int i;
char *cur_dir, *cur_file;
if (dwarf2_per_objfile->line_buffer == NULL)
{
complaint (&symfile_complaints, _("missing .debug_line section"));
return 0;
}
if (offset + 4 >= dwarf2_per_objfile->line_size)
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
}
lh = xmalloc (sizeof (*lh));
memset (lh, 0, sizeof (*lh));
back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) lh);
line_ptr = dwarf2_per_objfile->line_buffer + offset;
lh->total_length =
read_initial_length (abfd, line_ptr, &cu->header, (int *) &bytes_read);
line_ptr += bytes_read;
if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer
+ dwarf2_per_objfile->line_size))
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
}
lh->statement_program_end = line_ptr + lh->total_length;
lh->version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
lh->header_length = read_offset (abfd, line_ptr, &cu->header,
(int *) &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);
line_ptr += 1;
lh->line_base = read_1_signed_byte (abfd, line_ptr);
line_ptr += 1;
lh->line_range = read_1_byte (abfd, line_ptr);
line_ptr += 1;
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));
lh->standard_opcode_lengths[0] = 1;
for (i = 1; i < lh->opcode_base; ++i)
{
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;
add_include_dir (lh, cur_dir);
}
line_ptr += bytes_read;
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
unsigned int dir_index, mod_time, length;
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);
}
line_ptr += bytes_read;
lh->statement_program_start = line_ptr;
if (line_ptr > (dwarf2_per_objfile->line_buffer
+ dwarf2_per_objfile->line_size))
complaint (&symfile_complaints,
_("line number info header doesn't fit in `.debug_line' section"));
discard_cleanups (back_to);
return lh;
}
static CORE_ADDR
check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu)
{
struct function_range *fn;
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)
complaint (&symfile_complaints,
_("misplaced first line number at 0x%lx for '%s'"),
(unsigned long) address, fn->name);
fn->seen_line = 1;
return fn->lowpc;
}
static void
dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
struct dwarf2_cu *cu, struct partial_symtab *pst)
{
char *line_ptr;
char *line_end;
unsigned int bytes_read;
unsigned char op_code, extended_op, adj_opcode;
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
const int decode_for_pst_p = (pst != NULL);
int record_linetable_entry = 1;
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: reading line program for %s\n",
cu->per_cu->psymtab->filename);
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
line_ptr = lh->statement_program_start;
line_end = lh->statement_program_end;
while (line_ptr < line_end)
{
CORE_ADDR address = 0;
unsigned int file = 1;
unsigned int line = 1;
unsigned int column = 0;
int is_stmt = lh->default_is_stmt;
int basic_block = 0;
int end_sequence = 0;
if (!decode_for_pst_p && lh->num_file_names >= file)
{
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, cu->comp_dir);
}
while (!end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
if (op_code >= lh->opcode_base)
{
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);
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p && record_linetable_entry)
{
record_line (current_subfile, line,
check_cu_functions (address, cu));
}
basic_block = 1;
}
else switch (op_code)
{
case DW_LNS_extended_op:
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
extended_op = read_1_byte (abfd, line_ptr);
line_ptr += 1;
switch (extended_op)
{
case DW_LNE_end_sequence:
end_sequence = 1;
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p && record_linetable_entry)
record_line (current_subfile, 0, address);
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu,
(int *) &bytes_read);
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, address, &addr, 0))
{
address = addr;
record_linetable_entry = 1;
}
else
record_linetable_entry = 0;
}
line_ptr += bytes_read;
address += baseaddr;
break;
case DW_LNE_define_file:
{
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:
complaint (&symfile_complaints,
_("mangled .debug_line section"));
return;
}
break;
case DW_LNS_copy:
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p && record_linetable_entry)
record_line (current_subfile, line,
check_cu_functions (address, cu));
basic_block = 0;
break;
case DW_LNS_advance_pc:
address += lh->minimum_instruction_length
* read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_advance_line:
line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_set_file:
{
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;
if (!decode_for_pst_p)
dwarf2_start_subfile (fe->name, dir, cu->comp_dir);
}
break;
case DW_LNS_set_column:
column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_negate_stmt:
is_stmt = (!is_stmt);
break;
case DW_LNS_set_basic_block:
basic_block = 1;
break;
case DW_LNS_const_add_pc:
address += (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:
{
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;
}
}
}
}
}
if (decode_for_pst_p)
{
int file_index;
for (file_index = 0; file_index < lh->num_file_names; file_index++)
if (lh->file_names[file_index].included_p == 1)
{
const struct file_entry fe = lh->file_names [file_index];
char *include_name = fe.name;
char *dir_name = NULL;
char *pst_filename = pst->filename;
if (fe.dir_index)
dir_name = lh->include_dirs[fe.dir_index - 1];
if (!IS_ABSOLUTE_PATH (include_name) && dir_name != NULL)
{
include_name = concat (dir_name, SLASH_STRING,
include_name, (char *)NULL);
make_cleanup (xfree, include_name);
}
if (IS_ABSOLUTE_PATH (include_name)
&& !IS_ABSOLUTE_PATH (pst_filename)
&& pst->dirname != NULL)
{
pst_filename = concat (pst->dirname, SLASH_STRING,
pst_filename, (char *)NULL);
make_cleanup (xfree, pst_filename);
}
if (strcmp (include_name, pst_filename) != 0)
dwarf2_create_include_psymtab (include_name, pst, objfile);
}
}
if (debug_debugmap)
fprintf_unfiltered (gdb_stdlog,
"debugmap: finished reading line program for %s\n",
cu->per_cu->psymtab->filename);
}
static void
dwarf2_start_subfile (char *filename, char *dirname, char *comp_dir)
{
struct cleanup *clean = make_cleanup (null_cleanup, 0);
if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
{
struct subfile *subfile;
char *fullname = concat (dirname, "/", filename, (char *)NULL);
for (subfile = subfiles; subfile; subfile = subfile->next)
{
if (FILENAME_CMP (subfile->name, fullname) == 0)
{
current_subfile = subfile;
xfree (fullname);
return;
}
}
xfree (fullname);
}
if (!IS_ABSOLUTE_PATH (filename) && dirname == NULL)
dirname = comp_dir;
else
if (!IS_ABSOLUTE_PATH (filename) && !IS_ABSOLUTE_PATH (dirname))
{
dirname = concat (comp_dir, SLASH_STRING, dirname, (char *) NULL);
make_cleanup (xfree, dirname);
}
start_subfile (filename, dirname);
do_cleanups (clean);
}
static void
var_decode_location (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct comp_unit_head *cu_header = &cu->header;
if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)
{
SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
return;
}
if (attr_form_is_block (attr)
&& DW_BLOCK (attr)->size == 1 + cu_header->addr_size
&& DW_BLOCK (attr)->data[0] == DW_OP_addr)
{
int dummy;
CORE_ADDR symaddr = read_address (objfile->obfd,
DW_BLOCK (attr)->data + 1, cu, &dummy);
if (symaddr == 0)
{
CORE_ADDR actualaddr;
if (translate_common_symbol_debug_map_address
(cu, SYMBOL_LINKAGE_NAME (sym), &actualaddr))
symaddr = actualaddr;
SYMBOL_VALUE_ADDRESS (sym) = symaddr;
}
else
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, symaddr, &addr, 0))
SYMBOL_VALUE_ADDRESS (sym) = addr;
else
{
SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
return;
}
}
fixup_symbol_section (sym, objfile);
SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
return;
}
dwarf2_symbol_mark_computed (attr, sym, cu);
SYMBOL_CLASS (sym) = LOC_COMPUTED;
}
static struct symbol *
new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct symbol *sym = NULL;
char *name;
struct attribute *attr = NULL;
struct attribute *attr2 = NULL;
CORE_ADDR baseaddr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
if (die->tag != DW_TAG_namespace)
name = dwarf2_linkage_name (die, cu);
else
name = TYPE_NAME (type);
if (name)
{
sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
OBJSTAT (objfile, n_syms++);
memset (sym, 0, sizeof (struct symbol));
SYMBOL_LANGUAGE (sym) = cu->language;
SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
SYMBOL_CLASS (sym) = LOC_STATIC;
if (type != NULL)
SYMBOL_TYPE (sym) = type;
else
SYMBOL_TYPE (sym) = die_type (die, cu);
attr = dwarf2_attr (die, DW_AT_decl_line, cu);
if (attr)
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
}
switch (die->tag)
{
case DW_TAG_label:
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, DW_ADDR (attr), &addr, 0))
SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
else
return NULL;
}
SYMBOL_CLASS (sym) = LOC_LABEL;
break;
case DW_TAG_subprogram:
SYMBOL_CLASS (sym) = LOC_BLOCK;
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
{
add_symbol_to_list (sym, &global_symbols);
}
else
{
add_symbol_to_list (sym, cu->list_in_scope);
}
break;
case DW_TAG_variable:
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT,
TARGET_INT_BIT / HOST_CHAR_BIT, 0,
"<variable, no debug info>",
objfile);
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
dwarf2_const_value (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
add_symbol_to_list (sym, &global_symbols);
else
add_symbol_to_list (sym, cu->list_in_scope);
break;
}
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
var_decode_location (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
add_symbol_to_list (sym, &global_symbols);
else
add_symbol_to_list (sym, cu->list_in_scope);
}
else
{
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0)
&& dwarf2_attr (die, DW_AT_type, cu) != NULL)
{
SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
add_symbol_to_list (sym, &global_symbols);
}
}
break;
case DW_TAG_formal_parameter:
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
var_decode_location (attr, sym, cu);
if (SYMBOL_CLASS (sym) == LOC_COMPUTED)
SYMBOL_CLASS (sym) = LOC_COMPUTED_ARG;
}
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
dwarf2_const_value (attr, sym, cu);
}
add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_unspecified_parameters:
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
if (cu->language == language_cplus
|| cu->language == language_java)
{
struct type *type = SYMBOL_TYPE (sym);
if (TYPE_TAG_NAME (type) != NULL)
{
SYMBOL_LINKAGE_NAME (sym) = TYPE_TAG_NAME (type);
}
}
{
struct pending **list_to_add;
list_to_add = (cu->list_in_scope == &file_symbols
&& (cu->language == language_cplus
|| cu->language == language_java)
? &global_symbols : cu->list_in_scope);
add_symbol_to_list (sym, list_to_add);
if (cu->language == language_cplus
|| cu->language == language_java)
{
struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
*typedef_sym = *sym;
SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_SEARCH_NAME (sym);
add_symbol_to_list (typedef_sym, list_to_add);
}
}
break;
case DW_TAG_typedef:
if (processing_has_namespace_info
&& processing_current_prefix[0] != '\0')
{
SYMBOL_LINKAGE_NAME (sym) = typename_concat (&objfile->objfile_obstack,
processing_current_prefix,
name, cu);
}
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_base_type:
case DW_TAG_subrange_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_enumerator:
if (processing_has_namespace_info
&& processing_current_prefix[0] != '\0')
{
SYMBOL_LINKAGE_NAME (sym) = typename_concat (&objfile->objfile_obstack,
processing_current_prefix,
name, cu);
}
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
dwarf2_const_value (attr, sym, cu);
}
{
struct pending **list_to_add;
list_to_add = (cu->list_in_scope == &file_symbols
&& (cu->language == language_cplus
|| cu->language == language_java)
? &global_symbols : cu->list_in_scope);
add_symbol_to_list (sym, list_to_add);
}
break;
case DW_TAG_namespace:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
add_symbol_to_list (sym, &global_symbols);
break;
default:
complaint (&symfile_complaints, _("unsupported tag: '%s'"),
dwarf_tag_name (die->tag));
break;
}
}
return (sym);
}
static void
dwarf2_const_value (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct comp_unit_head *cu_header = &cu->header;
struct dwarf_block *blk;
switch (attr->form)
{
case DW_FORM_addr:
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
cu_header->addr_size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
obstack_alloc (&objfile->objfile_obstack, cu_header->addr_size);
{
CORE_ADDR addr;
if (translate_debug_map_address (cu, DW_ADDR (attr), &addr, 0))
store_unsigned_integer ((gdb_byte *) SYMBOL_VALUE_BYTES (sym),
cu_header->addr_size, addr);
else
{
SYMBOL_VALUE (sym) = 0;
SYMBOL_CLASS (sym) = LOC_CONST;
break;
}
}
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
blk = DW_BLOCK (attr);
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
blk->size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
obstack_alloc (&objfile->objfile_obstack, blk->size);
memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
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:
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_APPLE_db_str:
case DW_FORM_udata:
SYMBOL_VALUE (sym) = DW_UNSND (attr);
SYMBOL_CLASS (sym) = LOC_CONST;
break;
default:
complaint (&symfile_complaints,
_("unsupported const value attribute form: '%s'"),
dwarf_form_name (attr->form));
SYMBOL_VALUE (sym) = 0;
SYMBOL_CLASS (sym) = LOC_CONST;
break;
}
}
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;
}
static struct type *
die_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type;
struct attribute *type_attr;
struct die_info *type_die;
type_attr = dwarf2_attr (die, DW_AT_type, cu);
if (type_attr)
type_die = follow_die_ref (die, type_attr, cu);
else
{
type_attr = dwarf2_attr (die, DW_AT_APPLE_repository_type, cu);
if (type_attr)
type_die = follow_db_ref (die, type_attr, cu);
}
if (!type_attr)
{
return dwarf2_fundamental_type (cu->objfile, FT_VOID, cu);
}
type = tag_type_to_type (type_die, cu);
if (!type)
{
dump_die (type_die);
error (_("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]"),
cu->objfile->name);
}
return type;
}
static struct type *
die_containing_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type = NULL;
struct attribute *type_attr;
struct die_info *type_die = NULL;
type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
if (type_attr)
{
type_die = follow_die_ref (die, type_attr, cu);
type = tag_type_to_type (type_die, cu);
}
if (!type)
{
if (type_die)
dump_die (type_die);
error (_("Dwarf Error: Problem turning containing type into gdb type [in module %s]"),
cu->objfile->name);
}
return type;
}
static struct type *
tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu)
{
if (die->type)
{
return die->type;
}
else
{
read_type_die (die, cu);
if (!die->type)
{
dump_die (die);
error (_("Dwarf Error: Cannot find type of die [in module %s]"),
cu->objfile->name);
}
return die->type;
}
}
static void
read_type_die (struct die_info *die, struct dwarf2_cu *cu)
{
char *prefix = determine_prefix (die, cu);
const char *old_prefix = processing_current_prefix;
struct cleanup *back_to = make_cleanup (xfree, prefix);
processing_current_prefix = prefix;
switch (die->tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
read_structure_type (die, cu);
break;
case DW_TAG_enumeration_type:
read_enumeration_type (die, cu);
break;
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
read_subroutine_type (die, cu);
break;
case DW_TAG_array_type:
read_array_type (die, cu);
break;
case DW_TAG_pointer_type:
read_tag_pointer_type (die, cu);
break;
case DW_TAG_ptr_to_member_type:
read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
read_tag_reference_type (die, cu);
break;
case DW_TAG_const_type:
read_tag_const_type (die, cu);
break;
case DW_TAG_volatile_type:
read_tag_volatile_type (die, cu);
break;
case DW_TAG_string_type:
read_tag_string_type (die, cu);
break;
case DW_TAG_typedef:
read_typedef (die, cu);
break;
case DW_TAG_subrange_type:
read_subrange_type (die, cu);
break;
case DW_TAG_base_type:
read_base_type (die, cu);
break;
default:
complaint (&symfile_complaints, _("unexepected tag in read_type_die: '%s'"),
dwarf_tag_name (die->tag));
break;
}
processing_current_prefix = old_prefix;
do_cleanups (back_to);
}
static char *
determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *parent;
if (cu->language != language_cplus
&& cu->language != language_java)
return NULL;
parent = die->parent;
if (parent == NULL)
{
return xstrdup ("");
}
else
{
switch (parent->tag) {
case DW_TAG_namespace:
{
if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL)
{
return xstrdup (TYPE_TAG_NAME (parent->type));
}
else
{
int dummy;
char *parent_prefix = determine_prefix (parent, cu);
char *retval = typename_concat (NULL, parent_prefix,
namespace_name (parent, &dummy,
cu),
cu);
xfree (parent_prefix);
return retval;
}
}
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
{
if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL)
{
return xstrdup (TYPE_TAG_NAME (parent->type));
}
else
{
const char *old_prefix = processing_current_prefix;
char *new_prefix = determine_prefix (parent, cu);
char *retval;
processing_current_prefix = new_prefix;
retval = determine_class_name (parent, cu);
processing_current_prefix = old_prefix;
xfree (new_prefix);
return retval;
}
}
default:
return determine_prefix (parent, cu);
}
}
}
#define MAX_SEP_LEN 2
static char *
typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
struct dwarf2_cu *cu)
{
char *sep;
if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0')
sep = "";
else if (cu->language == language_java)
sep = ".";
else
sep = "::";
if (obs == NULL)
{
int suffixlen = 0, prefixlen = 0;
char *retval;
if (suffix != NULL)
suffixlen = strlen (suffix);
if (prefix != NULL)
prefixlen = strlen (prefix);
retval = xmalloc (prefixlen
+ MAX_SEP_LEN
+ suffixlen
+ 1);
retval[0] = '\0';
if (prefix)
{
strcpy (retval, prefix);
strcat (retval, sep);
}
if (suffix)
strcat (retval, suffix);
return retval;
}
else
{
return obconcat (obs, prefix ? prefix : "", sep, suffix ? suffix : "");
}
}
static struct type *
dwarf_base_type (int encoding, int size, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct type *type;
switch (encoding)
{
case DW_ATE_address:
type = dwarf2_fundamental_type (objfile, FT_VOID, cu);
return type;
case DW_ATE_boolean:
type = dwarf2_fundamental_type (objfile, FT_BOOLEAN, cu);
return type;
case DW_ATE_complex_float:
if (size == 16)
{
type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX, cu);
}
else
{
type = dwarf2_fundamental_type (objfile, FT_COMPLEX, cu);
}
return type;
case DW_ATE_float:
if (size == 8)
{
type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
}
else
{
type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
}
return type;
case DW_ATE_signed:
switch (size)
{
case 1:
type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR, cu);
break;
case 2:
type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT, cu);
break;
default:
case 4:
type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER, cu);
break;
}
return type;
case DW_ATE_signed_char:
type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR, cu);
return type;
case DW_ATE_unsigned:
switch (size)
{
case 1:
type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR, cu);
break;
case 2:
type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT, cu);
break;
default:
case 4:
type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER, cu);
break;
}
return type;
case DW_ATE_unsigned_char:
type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR, cu);
return type;
default:
type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER, cu);
return type;
}
}
#if 0
struct die_info *
copy_die (struct die_info *old_die)
{
struct die_info *new_die;
int i, num_attrs;
new_die = (struct die_info *) xmalloc (sizeof (struct die_info));
memset (new_die, 0, sizeof (struct die_info));
new_die->tag = old_die->tag;
new_die->has_children = old_die->has_children;
new_die->abbrev = old_die->abbrev;
new_die->offset = old_die->offset;
new_die->repository_id = old_die->repository_id;
new_die->type = NULL;
num_attrs = old_die->num_attrs;
new_die->num_attrs = num_attrs;
new_die->attrs = (struct attribute *)
xmalloc (num_attrs * sizeof (struct attribute));
for (i = 0; i < old_die->num_attrs; ++i)
{
new_die->attrs[i].name = old_die->attrs[i].name;
new_die->attrs[i].form = old_die->attrs[i].form;
new_die->attrs[i].u.addr = old_die->attrs[i].u.addr;
}
new_die->next = NULL;
return new_die;
}
#endif
static struct die_info *
sibling_die (struct die_info *die)
{
return die->sibling;
}
static char *
dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
if (attr && DW_STRING (attr))
return DW_STRING (attr);
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
return DW_STRING (attr);
return NULL;
}
static char *
dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
return DW_STRING (attr);
return NULL;
}
static struct die_info *
dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_extension, cu);
if (attr == NULL)
return NULL;
return follow_die_ref (die, attr, cu);
}
static char *
dwarf_tag_name (unsigned tag)
{
switch (tag)
{
case DW_TAG_padding:
return "DW_TAG_padding";
case DW_TAG_array_type:
return "DW_TAG_array_type";
case DW_TAG_class_type:
return "DW_TAG_class_type";
case DW_TAG_entry_point:
return "DW_TAG_entry_point";
case DW_TAG_enumeration_type:
return "DW_TAG_enumeration_type";
case DW_TAG_formal_parameter:
return "DW_TAG_formal_parameter";
case DW_TAG_imported_declaration:
return "DW_TAG_imported_declaration";
case DW_TAG_label:
return "DW_TAG_label";
case DW_TAG_lexical_block:
return "DW_TAG_lexical_block";
case DW_TAG_member:
return "DW_TAG_member";
case DW_TAG_pointer_type:
return "DW_TAG_pointer_type";
case DW_TAG_reference_type:
return "DW_TAG_reference_type";
case DW_TAG_compile_unit:
return "DW_TAG_compile_unit";
case DW_TAG_string_type:
return "DW_TAG_string_type";
case DW_TAG_structure_type:
return "DW_TAG_structure_type";
case DW_TAG_subroutine_type:
return "DW_TAG_subroutine_type";
case DW_TAG_typedef:
return "DW_TAG_typedef";
case DW_TAG_union_type:
return "DW_TAG_union_type";
case DW_TAG_unspecified_parameters:
return "DW_TAG_unspecified_parameters";
case DW_TAG_variant:
return "DW_TAG_variant";
case DW_TAG_common_block:
return "DW_TAG_common_block";
case DW_TAG_common_inclusion:
return "DW_TAG_common_inclusion";
case DW_TAG_inheritance:
return "DW_TAG_inheritance";
case DW_TAG_inlined_subroutine:
return "DW_TAG_inlined_subroutine";
case DW_TAG_module:
return "DW_TAG_module";
case DW_TAG_ptr_to_member_type:
return "DW_TAG_ptr_to_member_type";
case DW_TAG_set_type:
return "DW_TAG_set_type";
case DW_TAG_subrange_type:
return "DW_TAG_subrange_type";
case DW_TAG_with_stmt:
return "DW_TAG_with_stmt";
case DW_TAG_access_declaration:
return "DW_TAG_access_declaration";
case DW_TAG_base_type:
return "DW_TAG_base_type";
case DW_TAG_catch_block:
return "DW_TAG_catch_block";
case DW_TAG_const_type:
return "DW_TAG_const_type";
case DW_TAG_constant:
return "DW_TAG_constant";
case DW_TAG_enumerator:
return "DW_TAG_enumerator";
case DW_TAG_file_type:
return "DW_TAG_file_type";
case DW_TAG_friend:
return "DW_TAG_friend";
case DW_TAG_namelist:
return "DW_TAG_namelist";
case DW_TAG_namelist_item:
return "DW_TAG_namelist_item";
case DW_TAG_packed_type:
return "DW_TAG_packed_type";
case DW_TAG_subprogram:
return "DW_TAG_subprogram";
case DW_TAG_template_type_param:
return "DW_TAG_template_type_param";
case DW_TAG_template_value_param:
return "DW_TAG_template_value_param";
case DW_TAG_thrown_type:
return "DW_TAG_thrown_type";
case DW_TAG_try_block:
return "DW_TAG_try_block";
case DW_TAG_variant_part:
return "DW_TAG_variant_part";
case DW_TAG_variable:
return "DW_TAG_variable";
case DW_TAG_volatile_type:
return "DW_TAG_volatile_type";
case DW_TAG_dwarf_procedure:
return "DW_TAG_dwarf_procedure";
case DW_TAG_restrict_type:
return "DW_TAG_restrict_type";
case DW_TAG_interface_type:
return "DW_TAG_interface_type";
case DW_TAG_namespace:
return "DW_TAG_namespace";
case DW_TAG_imported_module:
return "DW_TAG_imported_module";
case DW_TAG_unspecified_type:
return "DW_TAG_unspecified_type";
case DW_TAG_partial_unit:
return "DW_TAG_partial_unit";
case DW_TAG_imported_unit:
return "DW_TAG_imported_unit";
case DW_TAG_MIPS_loop:
return "DW_TAG_MIPS_loop";
case DW_TAG_format_label:
return "DW_TAG_format_label";
case DW_TAG_function_template:
return "DW_TAG_function_template";
case DW_TAG_class_template:
return "DW_TAG_class_template";
default:
return "DW_TAG_<unknown>";
}
}
static char *
dwarf_attr_name (unsigned attr)
{
switch (attr)
{
case DW_AT_sibling:
return "DW_AT_sibling";
case DW_AT_location:
return "DW_AT_location";
case DW_AT_name:
return "DW_AT_name";
case DW_AT_ordering:
return "DW_AT_ordering";
case DW_AT_subscr_data:
return "DW_AT_subscr_data";
case DW_AT_byte_size:
return "DW_AT_byte_size";
case DW_AT_bit_offset:
return "DW_AT_bit_offset";
case DW_AT_bit_size:
return "DW_AT_bit_size";
case DW_AT_element_list:
return "DW_AT_element_list";
case DW_AT_stmt_list:
return "DW_AT_stmt_list";
case DW_AT_low_pc:
return "DW_AT_low_pc";
case DW_AT_high_pc:
return "DW_AT_high_pc";
case DW_AT_language:
return "DW_AT_language";
case DW_AT_member:
return "DW_AT_member";
case DW_AT_discr:
return "DW_AT_discr";
case DW_AT_discr_value:
return "DW_AT_discr_value";
case DW_AT_visibility:
return "DW_AT_visibility";
case DW_AT_import:
return "DW_AT_import";
case DW_AT_string_length:
return "DW_AT_string_length";
case DW_AT_common_reference:
return "DW_AT_common_reference";
case DW_AT_comp_dir:
return "DW_AT_comp_dir";
case DW_AT_const_value:
return "DW_AT_const_value";
case DW_AT_containing_type:
return "DW_AT_containing_type";
case DW_AT_default_value:
return "DW_AT_default_value";
case DW_AT_inline:
return "DW_AT_inline";
case DW_AT_is_optional:
return "DW_AT_is_optional";
case DW_AT_lower_bound:
return "DW_AT_lower_bound";
case DW_AT_producer:
return "DW_AT_producer";
case DW_AT_prototyped:
return "DW_AT_prototyped";
case DW_AT_return_addr:
return "DW_AT_return_addr";
case DW_AT_start_scope:
return "DW_AT_start_scope";
case DW_AT_stride_size:
return "DW_AT_stride_size";
case DW_AT_upper_bound:
return "DW_AT_upper_bound";
case DW_AT_abstract_origin:
return "DW_AT_abstract_origin";
case DW_AT_accessibility:
return "DW_AT_accessibility";
case DW_AT_address_class:
return "DW_AT_address_class";
case DW_AT_artificial:
return "DW_AT_artificial";
case DW_AT_base_types:
return "DW_AT_base_types";
case DW_AT_calling_convention:
return "DW_AT_calling_convention";
case DW_AT_count:
return "DW_AT_count";
case DW_AT_data_member_location:
return "DW_AT_data_member_location";
case DW_AT_decl_column:
return "DW_AT_decl_column";
case DW_AT_decl_file:
return "DW_AT_decl_file";
case DW_AT_decl_line:
return "DW_AT_decl_line";
case DW_AT_declaration:
return "DW_AT_declaration";
case DW_AT_discr_list:
return "DW_AT_discr_list";
case DW_AT_encoding:
return "DW_AT_encoding";
case DW_AT_external:
return "DW_AT_external";
case DW_AT_frame_base:
return "DW_AT_frame_base";
case DW_AT_friend:
return "DW_AT_friend";
case DW_AT_identifier_case:
return "DW_AT_identifier_case";
case DW_AT_macro_info:
return "DW_AT_macro_info";
case DW_AT_namelist_items:
return "DW_AT_namelist_items";
case DW_AT_priority:
return "DW_AT_priority";
case DW_AT_segment:
return "DW_AT_segment";
case DW_AT_specification:
return "DW_AT_specification";
case DW_AT_static_link:
return "DW_AT_static_link";
case DW_AT_type:
return "DW_AT_type";
case DW_AT_use_location:
return "DW_AT_use_location";
case DW_AT_variable_parameter:
return "DW_AT_variable_parameter";
case DW_AT_virtuality:
return "DW_AT_virtuality";
case DW_AT_vtable_elem_location:
return "DW_AT_vtable_elem_location";
case DW_AT_allocated:
return "DW_AT_allocated";
case DW_AT_associated:
return "DW_AT_associated";
case DW_AT_data_location:
return "DW_AT_data_location";
case DW_AT_stride:
return "DW_AT_stride";
case DW_AT_entry_pc:
return "DW_AT_entry_pc";
case DW_AT_use_UTF8:
return "DW_AT_use_UTF8";
case DW_AT_extension:
return "DW_AT_extension";
case DW_AT_ranges:
return "DW_AT_ranges";
case DW_AT_trampoline:
return "DW_AT_trampoline";
case DW_AT_call_column:
return "DW_AT_call_column";
case DW_AT_call_file:
return "DW_AT_call_file";
case DW_AT_call_line:
return "DW_AT_call_line";
#ifdef MIPS
case DW_AT_MIPS_fde:
return "DW_AT_MIPS_fde";
case DW_AT_MIPS_loop_begin:
return "DW_AT_MIPS_loop_begin";
case DW_AT_MIPS_tail_loop_begin:
return "DW_AT_MIPS_tail_loop_begin";
case DW_AT_MIPS_epilog_begin:
return "DW_AT_MIPS_epilog_begin";
case DW_AT_MIPS_loop_unroll_factor:
return "DW_AT_MIPS_loop_unroll_factor";
case DW_AT_MIPS_software_pipeline_depth:
return "DW_AT_MIPS_software_pipeline_depth";
#endif
case DW_AT_MIPS_linkage_name:
return "DW_AT_MIPS_linkage_name";
case DW_AT_sf_names:
return "DW_AT_sf_names";
case DW_AT_src_info:
return "DW_AT_src_info";
case DW_AT_mac_info:
return "DW_AT_mac_info";
case DW_AT_src_coords:
return "DW_AT_src_coords";
case DW_AT_body_begin:
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";
case DW_AT_APPLE_repository_file:
return "DW_AT_APPLE_repository_file";
case DW_AT_APPLE_repository_type:
return "DW_AT_APPLE_repository_type";
case DW_AT_APPLE_repository_name:
return "DW_AT_APPLE_repository_name";
case DW_AT_APPLE_repository_specification:
return "DW_AT_APPLE_repository_specification";
case DW_AT_APPLE_repository_import:
return "DW_AT_APPLE_repository_import";
case DW_AT_APPLE_repository_abstract_origin:
return "DW_AT_APPLE_repository_abstract_origin";
default:
return "DW_AT_<unknown>";
}
}
static char *
dwarf_form_name (unsigned form)
{
switch (form)
{
case DW_FORM_addr:
return "DW_FORM_addr";
case DW_FORM_block2:
return "DW_FORM_block2";
case DW_FORM_block4:
return "DW_FORM_block4";
case DW_FORM_data2:
return "DW_FORM_data2";
case DW_FORM_data4:
return "DW_FORM_data4";
case DW_FORM_data8:
return "DW_FORM_data8";
case DW_FORM_string:
return "DW_FORM_string";
case DW_FORM_block:
return "DW_FORM_block";
case DW_FORM_block1:
return "DW_FORM_block1";
case DW_FORM_data1:
return "DW_FORM_data1";
case DW_FORM_flag:
return "DW_FORM_flag";
case DW_FORM_sdata:
return "DW_FORM_sdata";
case DW_FORM_strp:
return "DW_FORM_strp";
case DW_FORM_udata:
return "DW_FORM_udata";
case DW_FORM_ref_addr:
return "DW_FORM_ref_addr";
case DW_FORM_ref1:
return "DW_FORM_ref1";
case DW_FORM_ref2:
return "DW_FORM_ref2";
case DW_FORM_ref4:
return "DW_FORM_ref4";
case DW_FORM_ref8:
return "DW_FORM_ref8";
case DW_FORM_ref_udata:
return "DW_FORM_ref_udata";
case DW_FORM_indirect:
return "DW_FORM_indirect";
case DW_FORM_APPLE_db_str:
return "DW_FORM_APPLE_db_str";
default:
return "DW_FORM_<unknown>";
}
}
static char *
dwarf_stack_op_name (unsigned op)
{
switch (op)
{
case DW_OP_addr:
return "DW_OP_addr";
case DW_OP_deref:
return "DW_OP_deref";
case DW_OP_const1u:
return "DW_OP_const1u";
case DW_OP_const1s:
return "DW_OP_const1s";
case DW_OP_const2u:
return "DW_OP_const2u";
case DW_OP_const2s:
return "DW_OP_const2s";
case DW_OP_const4u:
return "DW_OP_const4u";
case DW_OP_const4s:
return "DW_OP_const4s";
case DW_OP_const8u:
return "DW_OP_const8u";
case DW_OP_const8s:
return "DW_OP_const8s";
case DW_OP_constu:
return "DW_OP_constu";
case DW_OP_consts:
return "DW_OP_consts";
case DW_OP_dup:
return "DW_OP_dup";
case DW_OP_drop:
return "DW_OP_drop";
case DW_OP_over:
return "DW_OP_over";
case DW_OP_pick:
return "DW_OP_pick";
case DW_OP_swap:
return "DW_OP_swap";
case DW_OP_rot:
return "DW_OP_rot";
case DW_OP_xderef:
return "DW_OP_xderef";
case DW_OP_abs:
return "DW_OP_abs";
case DW_OP_and:
return "DW_OP_and";
case DW_OP_div:
return "DW_OP_div";
case DW_OP_minus:
return "DW_OP_minus";
case DW_OP_mod:
return "DW_OP_mod";
case DW_OP_mul:
return "DW_OP_mul";
case DW_OP_neg:
return "DW_OP_neg";
case DW_OP_not:
return "DW_OP_not";
case DW_OP_or:
return "DW_OP_or";
case DW_OP_plus:
return "DW_OP_plus";
case DW_OP_plus_uconst:
return "DW_OP_plus_uconst";
case DW_OP_shl:
return "DW_OP_shl";
case DW_OP_shr:
return "DW_OP_shr";
case DW_OP_shra:
return "DW_OP_shra";
case DW_OP_xor:
return "DW_OP_xor";
case DW_OP_bra:
return "DW_OP_bra";
case DW_OP_eq:
return "DW_OP_eq";
case DW_OP_ge:
return "DW_OP_ge";
case DW_OP_gt:
return "DW_OP_gt";
case DW_OP_le:
return "DW_OP_le";
case DW_OP_lt:
return "DW_OP_lt";
case DW_OP_ne:
return "DW_OP_ne";
case DW_OP_skip:
return "DW_OP_skip";
case DW_OP_lit0:
return "DW_OP_lit0";
case DW_OP_lit1:
return "DW_OP_lit1";
case DW_OP_lit2:
return "DW_OP_lit2";
case DW_OP_lit3:
return "DW_OP_lit3";
case DW_OP_lit4:
return "DW_OP_lit4";
case DW_OP_lit5:
return "DW_OP_lit5";
case DW_OP_lit6:
return "DW_OP_lit6";
case DW_OP_lit7:
return "DW_OP_lit7";
case DW_OP_lit8:
return "DW_OP_lit8";
case DW_OP_lit9:
return "DW_OP_lit9";
case DW_OP_lit10:
return "DW_OP_lit10";
case DW_OP_lit11:
return "DW_OP_lit11";
case DW_OP_lit12:
return "DW_OP_lit12";
case DW_OP_lit13:
return "DW_OP_lit13";
case DW_OP_lit14:
return "DW_OP_lit14";
case DW_OP_lit15:
return "DW_OP_lit15";
case DW_OP_lit16:
return "DW_OP_lit16";
case DW_OP_lit17:
return "DW_OP_lit17";
case DW_OP_lit18:
return "DW_OP_lit18";
case DW_OP_lit19:
return "DW_OP_lit19";
case DW_OP_lit20:
return "DW_OP_lit20";
case DW_OP_lit21:
return "DW_OP_lit21";
case DW_OP_lit22:
return "DW_OP_lit22";
case DW_OP_lit23:
return "DW_OP_lit23";
case DW_OP_lit24:
return "DW_OP_lit24";
case DW_OP_lit25:
return "DW_OP_lit25";
case DW_OP_lit26:
return "DW_OP_lit26";
case DW_OP_lit27:
return "DW_OP_lit27";
case DW_OP_lit28:
return "DW_OP_lit28";
case DW_OP_lit29:
return "DW_OP_lit29";
case DW_OP_lit30:
return "DW_OP_lit30";
case DW_OP_lit31:
return "DW_OP_lit31";
case DW_OP_reg0:
return "DW_OP_reg0";
case DW_OP_reg1:
return "DW_OP_reg1";
case DW_OP_reg2:
return "DW_OP_reg2";
case DW_OP_reg3:
return "DW_OP_reg3";
case DW_OP_reg4:
return "DW_OP_reg4";
case DW_OP_reg5:
return "DW_OP_reg5";
case DW_OP_reg6:
return "DW_OP_reg6";
case DW_OP_reg7:
return "DW_OP_reg7";
case DW_OP_reg8:
return "DW_OP_reg8";
case DW_OP_reg9:
return "DW_OP_reg9";
case DW_OP_reg10:
return "DW_OP_reg10";
case DW_OP_reg11:
return "DW_OP_reg11";
case DW_OP_reg12:
return "DW_OP_reg12";
case DW_OP_reg13:
return "DW_OP_reg13";
case DW_OP_reg14:
return "DW_OP_reg14";
case DW_OP_reg15:
return "DW_OP_reg15";
case DW_OP_reg16:
return "DW_OP_reg16";
case DW_OP_reg17:
return "DW_OP_reg17";
case DW_OP_reg18:
return "DW_OP_reg18";
case DW_OP_reg19:
return "DW_OP_reg19";
case DW_OP_reg20:
return "DW_OP_reg20";
case DW_OP_reg21:
return "DW_OP_reg21";
case DW_OP_reg22:
return "DW_OP_reg22";
case DW_OP_reg23:
return "DW_OP_reg23";
case DW_OP_reg24:
return "DW_OP_reg24";
case DW_OP_reg25:
return "DW_OP_reg25";
case DW_OP_reg26:
return "DW_OP_reg26";
case DW_OP_reg27:
return "DW_OP_reg27";
case DW_OP_reg28:
return "DW_OP_reg28";
case DW_OP_reg29:
return "DW_OP_reg29";
case DW_OP_reg30:
return "DW_OP_reg30";
case DW_OP_reg31:
return "DW_OP_reg31";
case DW_OP_breg0:
return "DW_OP_breg0";
case DW_OP_breg1:
return "DW_OP_breg1";
case DW_OP_breg2:
return "DW_OP_breg2";
case DW_OP_breg3:
return "DW_OP_breg3";
case DW_OP_breg4:
return "DW_OP_breg4";
case DW_OP_breg5:
return "DW_OP_breg5";
case DW_OP_breg6:
return "DW_OP_breg6";
case DW_OP_breg7:
return "DW_OP_breg7";
case DW_OP_breg8:
return "DW_OP_breg8";
case DW_OP_breg9:
return "DW_OP_breg9";
case DW_OP_breg10:
return "DW_OP_breg10";
case DW_OP_breg11:
return "DW_OP_breg11";
case DW_OP_breg12:
return "DW_OP_breg12";
case DW_OP_breg13:
return "DW_OP_breg13";
case DW_OP_breg14:
return "DW_OP_breg14";
case DW_OP_breg15:
return "DW_OP_breg15";
case DW_OP_breg16:
return "DW_OP_breg16";
case DW_OP_breg17:
return "DW_OP_breg17";
case DW_OP_breg18:
return "DW_OP_breg18";
case DW_OP_breg19:
return "DW_OP_breg19";
case DW_OP_breg20:
return "DW_OP_breg20";
case DW_OP_breg21:
return "DW_OP_breg21";
case DW_OP_breg22:
return "DW_OP_breg22";
case DW_OP_breg23:
return "DW_OP_breg23";
case DW_OP_breg24:
return "DW_OP_breg24";
case DW_OP_breg25:
return "DW_OP_breg25";
case DW_OP_breg26:
return "DW_OP_breg26";
case DW_OP_breg27:
return "DW_OP_breg27";
case DW_OP_breg28:
return "DW_OP_breg28";
case DW_OP_breg29:
return "DW_OP_breg29";
case DW_OP_breg30:
return "DW_OP_breg30";
case DW_OP_breg31:
return "DW_OP_breg31";
case DW_OP_regx:
return "DW_OP_regx";
case DW_OP_fbreg:
return "DW_OP_fbreg";
case DW_OP_bregx:
return "DW_OP_bregx";
case DW_OP_piece:
return "DW_OP_piece";
case DW_OP_deref_size:
return "DW_OP_deref_size";
case DW_OP_xderef_size:
return "DW_OP_xderef_size";
case DW_OP_nop:
return "DW_OP_nop";
case DW_OP_push_object_address:
return "DW_OP_push_object_address";
case DW_OP_call2:
return "DW_OP_call2";
case DW_OP_call4:
return "DW_OP_call4";
case DW_OP_call_ref:
return "DW_OP_call_ref";
case DW_OP_GNU_push_tls_address:
return "DW_OP_GNU_push_tls_address";
default:
return "OP_<unknown>";
}
}
static char *
dwarf_bool_name (unsigned mybool)
{
if (mybool)
return "TRUE";
else
return "FALSE";
}
static char *
dwarf_type_encoding_name (unsigned enc)
{
switch (enc)
{
case DW_ATE_address:
return "DW_ATE_address";
case DW_ATE_boolean:
return "DW_ATE_boolean";
case DW_ATE_complex_float:
return "DW_ATE_complex_float";
case DW_ATE_float:
return "DW_ATE_float";
case DW_ATE_signed:
return "DW_ATE_signed";
case DW_ATE_signed_char:
return "DW_ATE_signed_char";
case DW_ATE_unsigned:
return "DW_ATE_unsigned";
case DW_ATE_unsigned_char:
return "DW_ATE_unsigned_char";
case DW_ATE_imaginary_float:
return "DW_ATE_imaginary_float";
default:
return "DW_ATE_<unknown>";
}
}
#if 0
static char *
dwarf_cfi_name (unsigned cfi_opc)
{
switch (cfi_opc)
{
case DW_CFA_advance_loc:
return "DW_CFA_advance_loc";
case DW_CFA_offset:
return "DW_CFA_offset";
case DW_CFA_restore:
return "DW_CFA_restore";
case DW_CFA_nop:
return "DW_CFA_nop";
case DW_CFA_set_loc:
return "DW_CFA_set_loc";
case DW_CFA_advance_loc1:
return "DW_CFA_advance_loc1";
case DW_CFA_advance_loc2:
return "DW_CFA_advance_loc2";
case DW_CFA_advance_loc4:
return "DW_CFA_advance_loc4";
case DW_CFA_offset_extended:
return "DW_CFA_offset_extended";
case DW_CFA_restore_extended:
return "DW_CFA_restore_extended";
case DW_CFA_undefined:
return "DW_CFA_undefined";
case DW_CFA_same_value:
return "DW_CFA_same_value";
case DW_CFA_register:
return "DW_CFA_register";
case DW_CFA_remember_state:
return "DW_CFA_remember_state";
case DW_CFA_restore_state:
return "DW_CFA_restore_state";
case DW_CFA_def_cfa:
return "DW_CFA_def_cfa";
case DW_CFA_def_cfa_register:
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
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";
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
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
static void
dump_die (struct die_info *die)
{
unsigned int i;
fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
dwarf_bool_name (die->child != NULL));
fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
for (i = 0; i < die->num_attrs; ++i)
{
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_unfiltered (gdb_stderr, "address: ");
deprecated_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_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
fprintf_unfiltered (gdb_stderr, "constant ref: %ld (adjusted)",
(long) (DW_ADDR (&die->attrs[i])));
break;
case DW_FORM_APPLE_db_str:
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
case DW_FORM_udata:
case DW_FORM_sdata:
fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
case DW_FORM_string:
case DW_FORM_strp:
fprintf_unfiltered (gdb_stderr, "string: \"%s\"",
DW_STRING (&die->attrs[i])
? DW_STRING (&die->attrs[i]) : "");
break;
case DW_FORM_flag:
if (DW_UNSND (&die->attrs[i]))
fprintf_unfiltered (gdb_stderr, "flag: TRUE");
else
fprintf_unfiltered (gdb_stderr, "flag: FALSE");
break;
case DW_FORM_indirect:
fprintf_unfiltered (gdb_stderr, "unexpected attribute form: DW_FORM_indirect");
break;
default:
fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.",
die->attrs[i].form);
}
fprintf_unfiltered (gdb_stderr, "\n");
}
}
static void
dump_die_list (struct die_info *die)
{
while (die)
{
dump_die (die);
if (die->child != NULL)
dump_die_list (die->child);
if (die->sibling != NULL)
dump_die_list (die->sibling);
}
}
static void
store_in_ref_table (unsigned int offset, struct die_info *die,
struct dwarf2_cu *cu)
{
int h;
struct die_info *old;
h = (offset % REF_HASH_SIZE);
old = cu->die_ref_table[h];
die->next_ref = old;
cu->die_ref_table[h] = die;
}
static unsigned int
dwarf2_get_ref_die_offset (struct attribute *attr, struct dwarf2_cu *cu)
{
unsigned int result = 0;
switch (attr->form)
{
case DW_FORM_ref_addr:
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
result = DW_ADDR (attr);
break;
default:
complaint (&symfile_complaints,
_("unsupported die ref attribute form: '%s'"),
dwarf_form_name (attr->form));
}
return result;
}
static int
dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
{
if (attr->form == DW_FORM_sdata)
return 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_data8
|| attr->form == DW_FORM_APPLE_db_str)
return DW_UNSND (attr);
else
{
complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
dwarf_form_name (attr->form));
return default_value;
}
}
static struct die_info *
follow_die_ref (struct die_info *src_die, struct attribute *attr,
struct dwarf2_cu *cu)
{
struct die_info *die;
unsigned int offset;
int h;
struct dwarf2_cu *target_cu;
offset = dwarf2_get_ref_die_offset (attr, cu);
if (DW_ADDR (attr) < cu->header.offset
|| DW_ADDR (attr) >= cu->header.offset + cu->header.length)
{
struct dwarf2_per_cu_data *per_cu;
per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (attr),
cu->objfile);
target_cu = per_cu->cu;
}
else
target_cu = cu;
h = (offset % REF_HASH_SIZE);
die = target_cu->die_ref_table[h];
while (die)
{
if (die->offset == offset)
return die;
die = die->next_ref;
}
error (_("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE "
"at 0x%lx [in module %s]"),
(long) src_die->offset, (long) offset, cu->objfile->name);
return NULL;
}
static struct type *
dwarf2_fundamental_type (struct objfile *objfile, int typeid,
struct dwarf2_cu *cu)
{
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
{
error (_("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]"),
typeid, objfile->name);
}
if (cu->ftypes[typeid] == NULL)
{
cu->ftypes[typeid] = cu->language_defn->la_fund_type (objfile, typeid);
}
return (cu->ftypes[typeid]);
}
static CORE_ADDR
decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
int i;
int size = blk->size;
char *data = blk->data;
CORE_ADDR stack[64];
int stacki;
unsigned int bytes_read, unsnd;
unsigned char op;
i = 0;
stacki = 0;
stack[stacki] = 0;
isreg = 0;
while (i < size)
{
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:
case DW_OP_reg3:
case DW_OP_reg4:
case DW_OP_reg5:
case DW_OP_reg6:
case DW_OP_reg7:
case DW_OP_reg8:
case DW_OP_reg9:
case DW_OP_reg10:
case DW_OP_reg11:
case DW_OP_reg12:
case DW_OP_reg13:
case DW_OP_reg14:
case DW_OP_reg15:
case DW_OP_reg16:
case DW_OP_reg17:
case DW_OP_reg18:
case DW_OP_reg19:
case DW_OP_reg20:
case DW_OP_reg21:
case DW_OP_reg22:
case DW_OP_reg23:
case DW_OP_reg24:
case DW_OP_reg25:
case DW_OP_reg26:
case DW_OP_reg27:
case DW_OP_reg28:
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31:
isreg = 1;
stack[++stacki] = op - DW_OP_reg0;
if (i < size)
dwarf2_complex_location_expr_complaint ();
break;
case DW_OP_regx:
isreg = 1;
unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
stack[++stacki] = unsnd;
if (i < size)
dwarf2_complex_location_expr_complaint ();
break;
case DW_OP_addr:
{
CORE_ADDR addr;
if (translate_debug_map_address (cu,
read_address (objfile->obfd, &data[i],
cu, (int *) &bytes_read), &addr, 0))
stack[++stacki] = addr;
else
return 0;
}
i += bytes_read;
break;
case DW_OP_const1u:
stack[++stacki] = read_1_byte (objfile->obfd, &data[i]);
i += 1;
break;
case DW_OP_const1s:
stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]);
i += 1;
break;
case DW_OP_const2u:
stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]);
i += 2;
break;
case DW_OP_const2s:
stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]);
i += 2;
break;
case DW_OP_const4u:
stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]);
i += 4;
break;
case DW_OP_const4s:
stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]);
i += 4;
break;
case DW_OP_constu:
stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
&bytes_read);
i += bytes_read;
break;
case DW_OP_consts:
stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
break;
case DW_OP_dup:
stack[stacki + 1] = stack[stacki];
stacki++;
break;
case DW_OP_plus:
stack[stacki - 1] += stack[stacki];
stacki--;
break;
case DW_OP_plus_uconst:
stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
break;
case DW_OP_minus:
stack[stacki - 1] -= stack[stacki];
stacki--;
break;
case DW_OP_deref:
if (i < size)
dwarf2_complex_location_expr_complaint ();
break;
case DW_OP_GNU_push_tls_address:
if (i < size)
dwarf2_complex_location_expr_complaint ();
break;
default:
complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
dwarf_stack_op_name (op));
return (stack[stacki]);
}
}
return (stack[stacki]);
}
static struct dwarf_block *
dwarf_alloc_block (struct dwarf2_cu *cu)
{
struct dwarf_block *blk;
blk = (struct dwarf_block *)
obstack_alloc (&cu->comp_unit_obstack, sizeof (struct dwarf_block));
return (blk);
}
static struct abbrev_info *
dwarf_alloc_abbrev (struct dwarf2_cu *cu)
{
struct abbrev_info *abbrev;
abbrev = (struct abbrev_info *)
obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info));
memset (abbrev, 0, sizeof (struct abbrev_info));
return (abbrev);
}
static struct die_info *
dwarf_alloc_die (void)
{
struct die_info *die;
die = (struct die_info *) xmalloc (sizeof (struct die_info));
memset (die, 0, sizeof (struct die_info));
return (die);
}
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)
{
char *full_name = file_full_name (file, lh, comp_dir);
if (! pending_macros)
pending_macros = new_macro_table (&objfile->objfile_obstack,
objfile->macro_cache);
if (! current_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;
}
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 == ' ')
{
complaint (&symfile_complaints,
_("macro definition contains spaces in formal argument list:\n`%s'"),
body);
while (*p == ' ')
p++;
}
return p;
}
static void
parse_macro_definition (struct macro_source_file *file, int line,
const char *body)
{
const char *p;
for (p = body; *p; p++)
if (*p == ' ' || *p == '(')
break;
if (*p == ' ' || *p == '\0')
{
int name_len = p - body;
char *name = copy_string (body, name_len);
const char *replacement;
if (*p == ' ')
replacement = body + name_len + 1;
else
{
dwarf2_macro_malformed_definition_complaint (body);
replacement = body + name_len;
}
macro_define_object (file, line, name, replacement);
xfree (name);
}
else if (*p == '(')
{
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);
while (*p && *p != ')')
{
const char *arg_start = p;
while (*p && *p != ',' && *p != ')' && *p != ' ')
p++;
if (! *p || p == arg_start)
dwarf2_macro_malformed_definition_complaint (body);
else
{
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);
if (*p == ',')
{
p++;
p = consume_improper_spaces (p, body);
}
}
if (*p == ')')
{
p++;
if (*p == ' ')
macro_define_function (file, line, name,
argc, (const char **) argv,
p + 1);
else if (*p == '\0')
{
dwarf2_macro_malformed_definition_complaint (body);
macro_define_function (file, line, name,
argc, (const char **) argv,
p);
}
else
dwarf2_macro_malformed_definition_complaint (body);
}
else
dwarf2_macro_malformed_definition_complaint (body);
xfree (name);
{
int i;
for (i = 0; i < argc; i++)
xfree (argv[i]);
}
xfree (argv);
}
else
dwarf2_macro_malformed_definition_complaint (body);
}
static void
dwarf_decode_macros (struct line_header *lh, unsigned int offset,
char *comp_dir, bfd *abfd,
struct dwarf2_cu *cu)
{
char *mac_ptr, *mac_end;
struct macro_source_file *current_file = 0;
if (dwarf2_per_objfile->macinfo_buffer == NULL)
{
complaint (&symfile_complaints, _("missing .debug_macinfo section"));
return;
}
mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset;
mac_end = dwarf2_per_objfile->macinfo_buffer
+ dwarf2_per_objfile->macinfo_size;
for (;;)
{
enum dwarf_macinfo_record_type macinfo_type;
if (mac_ptr >= mac_end)
{
dwarf2_macros_too_long_complaint ();
return;
}
macinfo_type = read_1_byte (abfd, mac_ptr);
mac_ptr++;
switch (macinfo_type)
{
case 0:
return;
case DW_MACINFO_define:
case DW_MACINFO_undef:
{
unsigned 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)
complaint (&symfile_complaints,
_("debug info gives macro %s outside of any file: %s"),
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:
{
unsigned 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, cu->objfile);
}
break;
case DW_MACINFO_end_file:
if (! current_file)
complaint (&symfile_complaints,
_("macro debug info has an unmatched `close_file' directive"));
else
{
current_file = current_file->included_by;
if (! current_file)
{
enum dwarf_macinfo_record_type next_type;
if (mac_ptr >= mac_end)
{
dwarf2_macros_too_long_complaint ();
return;
}
next_type = read_1_byte (abfd, mac_ptr);
if (next_type != 0)
complaint (&symfile_complaints,
_("no terminating 0-type entry for macros in `.debug_macinfo' section"));
return;
}
}
break;
case DW_MACINFO_vendor_ext:
{
unsigned 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;
}
break;
}
}
}
static int
attr_form_is_block (struct attribute *attr)
{
return (attr == NULL ? 0 :
attr->form == DW_FORM_block1
|| attr->form == DW_FORM_block2
|| attr->form == DW_FORM_block4
|| attr->form == DW_FORM_block);
}
static void
dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
struct dwarf2_loclist_baton *baton;
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
baton->objfile = cu->objfile;
baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr);
baton->data = (gdb_byte *) dwarf2_per_objfile->loc_buffer + DW_UNSND (attr);
baton->base_address = cu->header.base_address;
if (cu->header.base_known == 0)
complaint (&symfile_complaints,
_("Location list used without specifying the CU base address."));
SYMBOL_OPS (sym) = &dwarf2_loclist_funcs;
SYMBOL_LOCATION_BATON (sym) = baton;
}
else
{
struct dwarf2_locexpr_baton *baton;
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_locexpr_baton));
baton->objfile = cu->objfile;
if (attr_form_is_block (attr))
{
baton->size = DW_BLOCK (attr)->size;
baton->data = (gdb_byte *) DW_BLOCK (attr)->data;
}
else
{
dwarf2_invalid_attrib_class_complaint ("location description",
SYMBOL_NATURAL_NAME (sym));
baton->size = 0;
baton->data = NULL;
}
SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs;
SYMBOL_LOCATION_BATON (sym) = baton;
}
}
static struct dwarf2_per_cu_data *
dwarf2_find_containing_comp_unit (unsigned long offset,
struct objfile *objfile)
{
struct dwarf2_per_cu_data *this_cu;
int low, high;
low = 0;
high = dwarf2_per_objfile->n_comp_units - 1;
while (high > low)
{
int mid = low + (high - low) / 2;
if (dwarf2_per_objfile->all_comp_units[mid]->offset >= offset)
high = mid;
else
low = mid + 1;
}
gdb_assert (low == high);
if (dwarf2_per_objfile->all_comp_units[low]->offset > offset)
{
if (low == 0)
error (_("Dwarf Error: could not find partial DIE containing "
"offset 0x%lx [in module %s]"),
(long) offset, bfd_get_filename (objfile->obfd));
gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset <= offset);
return dwarf2_per_objfile->all_comp_units[low-1];
}
else
{
this_cu = dwarf2_per_objfile->all_comp_units[low];
if (low == dwarf2_per_objfile->n_comp_units - 1
&& offset >= this_cu->offset + this_cu->length)
error (_("invalid dwarf2 offset %ld"), offset);
gdb_assert (offset < this_cu->offset + this_cu->length);
return this_cu;
}
}
static struct dwarf2_per_cu_data *
dwarf2_find_comp_unit (unsigned long offset, struct objfile *objfile)
{
struct dwarf2_per_cu_data *this_cu;
this_cu = dwarf2_find_containing_comp_unit (offset, objfile);
if (this_cu->offset != offset)
error (_("no compilation unit with offset %ld."), offset);
return this_cu;
}
static void
free_one_comp_unit (void *data)
{
struct dwarf2_cu *cu = data;
if (cu->per_cu != NULL)
cu->per_cu->cu = NULL;
cu->per_cu = NULL;
obstack_free (&cu->comp_unit_obstack, NULL);
if (cu->dies)
free_die_list (cu->dies);
xfree (cu);
}
static void
free_stack_comp_unit (void *data)
{
struct dwarf2_cu *cu = data;
obstack_free (&cu->comp_unit_obstack, NULL);
cu->partial_dies = NULL;
if (cu->per_cu != NULL)
{
cu->per_cu->cu = NULL;
cu->per_cu = NULL;
age_cached_comp_units ();
}
}
static void
free_cached_comp_units (void *data)
{
struct dwarf2_per_cu_data *per_cu, **last_chain;
per_cu = dwarf2_per_objfile->read_in_chain;
last_chain = &dwarf2_per_objfile->read_in_chain;
while (per_cu != NULL)
{
struct dwarf2_per_cu_data *next_cu;
next_cu = per_cu->cu->read_in_chain;
free_one_comp_unit (per_cu->cu);
*last_chain = next_cu;
per_cu = next_cu;
}
}
static void
age_cached_comp_units (void)
{
struct dwarf2_per_cu_data *per_cu, **last_chain;
dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain);
per_cu = dwarf2_per_objfile->read_in_chain;
while (per_cu != NULL)
{
per_cu->cu->last_used ++;
if (per_cu->cu->last_used <= dwarf2_max_cache_age)
dwarf2_mark (per_cu->cu);
per_cu = per_cu->cu->read_in_chain;
}
per_cu = dwarf2_per_objfile->read_in_chain;
last_chain = &dwarf2_per_objfile->read_in_chain;
while (per_cu != NULL)
{
struct dwarf2_per_cu_data *next_cu;
next_cu = per_cu->cu->read_in_chain;
if (!per_cu->cu->mark)
{
free_one_comp_unit (per_cu->cu);
*last_chain = next_cu;
}
else
last_chain = &per_cu->cu->read_in_chain;
per_cu = next_cu;
}
}
static void
free_one_cached_comp_unit (void *target_cu)
{
struct dwarf2_per_cu_data *per_cu, **last_chain;
per_cu = dwarf2_per_objfile->read_in_chain;
last_chain = &dwarf2_per_objfile->read_in_chain;
while (per_cu != NULL)
{
struct dwarf2_per_cu_data *next_cu;
next_cu = per_cu->cu->read_in_chain;
if (per_cu->cu == target_cu)
{
free_one_comp_unit (per_cu->cu);
*last_chain = next_cu;
break;
}
else
last_chain = &per_cu->cu->read_in_chain;
per_cu = next_cu;
}
}
struct dwarf2_offset_and_type
{
unsigned int offset;
struct type *type;
};
static hashval_t
offset_and_type_hash (const void *item)
{
const struct dwarf2_offset_and_type *ofs = item;
return ofs->offset;
}
static int
offset_and_type_eq (const void *item_lhs, const void *item_rhs)
{
const struct dwarf2_offset_and_type *ofs_lhs = item_lhs;
const struct dwarf2_offset_and_type *ofs_rhs = item_rhs;
return ofs_lhs->offset == ofs_rhs->offset;
}
static void
set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
{
struct dwarf2_offset_and_type **slot, ofs;
die->type = type;
if (cu->per_cu == NULL)
return;
if (cu->per_cu->type_hash == NULL)
cu->per_cu->type_hash
= htab_create_alloc_ex (cu->header.length / 24,
offset_and_type_hash,
offset_and_type_eq,
NULL,
&cu->objfile->objfile_obstack,
hashtab_obstack_allocate,
dummy_obstack_deallocate);
ofs.offset = die->offset;
ofs.type = type;
slot = (struct dwarf2_offset_and_type **)
htab_find_slot_with_hash (cu->per_cu->type_hash, &ofs, ofs.offset, INSERT);
*slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot));
**slot = ofs;
}
static struct type *
get_die_type (struct die_info *die, htab_t type_hash)
{
struct dwarf2_offset_and_type *slot, ofs;
ofs.offset = die->offset;
slot = htab_find_with_hash (type_hash, &ofs, ofs.offset);
if (slot)
return slot->type;
else
return NULL;
}
static void
reset_die_and_siblings_types (struct die_info *start_die, struct dwarf2_cu *cu)
{
struct die_info *die;
if (cu->per_cu->type_hash == NULL)
return;
for (die = start_die; die != NULL; die = die->sibling)
{
die->type = get_die_type (die, cu->per_cu->type_hash);
if (die->child != NULL)
reset_die_and_siblings_types (die->child, cu);
}
}
static void
dwarf2_add_dependence (struct dwarf2_cu *cu,
struct dwarf2_per_cu_data *ref_per_cu)
{
void **slot;
if (cu->dependencies == NULL)
cu->dependencies
= htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer,
NULL, &cu->comp_unit_obstack,
hashtab_obstack_allocate,
dummy_obstack_deallocate);
slot = htab_find_slot (cu->dependencies, ref_per_cu, INSERT);
if (*slot == NULL)
*slot = ref_per_cu;
}
static int
dwarf2_mark_helper (void **slot, void *data)
{
struct dwarf2_per_cu_data *per_cu;
per_cu = (struct dwarf2_per_cu_data *) *slot;
if (per_cu->cu->mark)
return 1;
per_cu->cu->mark = 1;
if (per_cu->cu->dependencies != NULL)
htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL);
return 1;
}
static void
dwarf2_mark (struct dwarf2_cu *cu)
{
if (cu->mark)
return;
cu->mark = 1;
if (cu->dependencies != NULL)
htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL);
}
static void
dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu)
{
while (per_cu)
{
per_cu->cu->mark = 0;
per_cu = per_cu->cu->read_in_chain;
}
}
static void *
hashtab_obstack_allocate (void *data, size_t size, size_t count)
{
unsigned int total = size * count;
void *ptr = obstack_alloc ((struct obstack *) data, total);
memset (ptr, 0, total);
return ptr;
}
static void
dummy_obstack_deallocate (void *object, void *data)
{
return;
}
static hashval_t
partial_die_hash (const void *item)
{
const struct partial_die_info *part_die = item;
return part_die->offset;
}
static int
partial_die_eq (const void *item_lhs, const void *item_rhs)
{
const struct partial_die_info *part_die_lhs = item_lhs;
const struct partial_die_info *part_die_rhs = item_rhs;
return part_die_lhs->offset == part_die_rhs->offset;
}
static struct cmd_list_element *set_dwarf2_cmdlist;
static struct cmd_list_element *show_dwarf2_cmdlist;
static void
set_dwarf2_cmd (char *args, int from_tty)
{
help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout);
}
static void
show_dwarf2_cmd (char *args, int from_tty)
{
cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
}
void _initialize_dwarf2_read (void);
void
_initialize_dwarf2_read (void)
{
dwarf2_objfile_data_key = register_objfile_data ();
add_prefix_cmd ("dwarf2", class_maintenance, set_dwarf2_cmd, _("\
Set DWARF 2 specific variables.\n\
Configure DWARF 2 variables such as the cache size"),
&set_dwarf2_cmdlist, "maintenance set dwarf2 ",
0, &maintenance_set_cmdlist);
add_prefix_cmd ("dwarf2", class_maintenance, show_dwarf2_cmd, _("\
Show DWARF 2 specific variables\n\
Show DWARF 2 variables such as the cache size"),
&show_dwarf2_cmdlist, "maintenance show dwarf2 ",
0, &maintenance_show_cmdlist);
add_setshow_zinteger_cmd ("debugmap", class_maintenance, &debug_debugmap, _("\
Set DWARF debug map debugging."), _("\
Show DWARF debug map debugging."), _("\
When non-zero, debug map specific debugging is enabled."),
NULL,
show_debug_debugmap,
&setdebuglist, &showdebuglist);
add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
&dwarf2_max_cache_age, _("\
Set the upper bound on the age of cached dwarf2 compilation units."), _("\
Show the upper bound on the age of cached dwarf2 compilation units."), _("\
A higher limit means that cached compilation units will be stored\n\
in memory longer, and more total memory will be used. Zero disables\n\
caching, which can slow down startup."),
NULL,
show_dwarf2_max_cache_age,
&set_dwarf2_cmdlist,
&show_dwarf2_cmdlist);
}
enum rb_tree_colors { RED, BLACK, UNINIT };
struct rb_tree_node {
int key;
struct type *type_data;
struct die_info *die_data;
enum rb_tree_colors color;
struct rb_tree_node *parent;
struct rb_tree_node *left;
struct rb_tree_node *right;
};
static struct rb_tree_node *
rb_tree_find_node (struct rb_tree_node *root, int key)
{
if (!root)
return NULL;
if (key == root->key)
return root;
else if (key < root->key)
return rb_tree_find_node (root->left, key);
else
return rb_tree_find_node (root->right, key);
}
static void
left_rotate (struct rb_tree_node **root, struct rb_tree_node *x)
{
struct rb_tree_node *y;
if (!x->right)
return;
y = x->right;
x->right = y->left;
if (y->left != NULL)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == NULL)
*root = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
static void
right_rotate (struct rb_tree_node **root, struct rb_tree_node *x)
{
struct rb_tree_node *y;
if (!x->left)
return;
y = x->left;
x->left = y->right;
if (y->right != NULL)
y->right->parent = x;
y->parent = x->parent;
if (x->parent == NULL)
*root = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->right = x;
x->parent = y;
}
static void
plain_tree_insert (struct rb_tree_node **root, struct rb_tree_node *new_node)
{
struct rb_tree_node *tree = *root;
if (tree == NULL)
*root = new_node;
else if (new_node->key < tree->key)
{
if (tree->left)
plain_tree_insert (&tree->left, new_node);
else
{
tree->left = new_node;
new_node->parent = tree;
}
}
else if (new_node->key > tree->key)
{
if (tree->right)
plain_tree_insert (&tree->right, new_node);
else
{
tree->right = new_node;
new_node->parent = tree;
}
}
}
static void
rb_tree_insert (struct rb_tree_node **root, struct rb_tree_node *tree,
struct rb_tree_node *new_node)
{
struct rb_tree_node *y;
plain_tree_insert (root, new_node);
new_node->color = RED;
while (new_node != *root
&& new_node->parent->color == RED)
{
if (new_node->parent == new_node->parent->parent->left)
{
y = new_node->parent->parent->right;
if (y && y->color == RED)
{
new_node->parent->color = BLACK;
y->color = BLACK;
new_node->parent->parent->color = RED;
new_node = new_node->parent->parent;
}
else if (new_node == new_node->parent->right)
{
new_node = new_node->parent;
left_rotate (root, new_node);
}
else
{
new_node->parent->color = BLACK;
new_node->parent->parent->color = RED;
right_rotate (root, new_node->parent->parent);
}
}
else
{
y = new_node->parent->parent->left;
if (y && y->color == RED)
{
new_node->parent->color = BLACK;
y->color = BLACK;
new_node->parent->parent->color = RED;
new_node = new_node->parent->parent;
}
else if (new_node == new_node->parent->left)
{
new_node = new_node->parent;
right_rotate (root, new_node);
}
else
{
new_node->parent->color = BLACK;
new_node->parent->parent->color = RED;
left_rotate (root, new_node->parent->parent);
}
}
}
(*root)->color = BLACK;
}
#define MAX_OPEN_DBS 100
struct database_info *repositories = NULL;
int num_open_dbs = 0;
static struct database_info *
find_open_repository (sqlite3 *db)
{
int i;
for (i = 0; i < num_open_dbs; i++)
{
if (repositories[i].db == db)
return &(repositories[i]);
}
return NULL;
}
static void *
lookup_repository_type (int type_id, sqlite3 *db, struct dwarf2_cu *cu,
int return_die)
{
struct database_info *repository = NULL;
struct type *temp_type = NULL;
struct die_info *type_die = NULL;
struct rb_tree_node *new_node = NULL;
repository = find_open_repository (db);
if (repository)
{
if (repository->db_types)
{
new_node = rb_tree_find_node (repository->db_types, type_id);
if (new_node)
{
temp_type = new_node->type_data;
type_die = new_node->die_data;
}
}
if (!new_node)
{
type_die = db_lookup_type (type_id, db, repository->abbrev_table);
new_node = (struct rb_tree_node *)
xmalloc (sizeof(struct rb_tree_node));
new_node->key = type_id;
new_node->die_data = type_die;
new_node->type_data = NULL;
new_node->left = NULL;
new_node->right = NULL;
new_node->parent = NULL;
new_node->color = UNINIT;
rb_tree_insert (&repository->db_types,
repository->db_types, new_node);
temp_type = tag_type_to_type (type_die, cu);
new_node->type_data = temp_type;
}
}
else
internal_error (__FILE__, __LINE__,
_("Cannot find open repository.\n"));
if (temp_type && !type_die->type)
type_die->type = temp_type;
if (return_die)
return type_die;
else
return temp_type;
}
static void
initialize_repositories (void)
{
int i;
repositories = (struct database_info *) xmalloc (MAX_OPEN_DBS *
sizeof (struct database_info));
for (i = 0; i < MAX_OPEN_DBS; i++)
{
repositories[i].fullname = NULL;
repositories[i].abbrev_table = NULL;
repositories[i].current_status = DB_UNKNOWN;
repositories[i].num_uses = NULL;
repositories[i].db_types = NULL;
repositories[i].dummy_cu = NULL;
repositories[i].dummy_objfile = NULL;
repositories[i].db = NULL;
}
}
static int
open_dwarf_repository (char *dirname, char *filename, struct objfile *objfile,
struct dwarf2_cu *cu)
{
int db_status;
int i;
char *fullname;
if (!repositories)
initialize_repositories();
fullname = (char *) xmalloc (strlen (dirname) + strlen (filename) + 2);
sprintf (fullname, "%s/%s", dirname, filename);
if (cu->repository)
{
if (strcmp (cu->repository_name, fullname) == 0)
return SQLITE_OK;
else
internal_error (__FILE__, __LINE__,
_("Multiple repositories found for a single cu\n"));
}
else
{
for (i = 0; i < num_open_dbs; i++)
{
if (strcmp (fullname, repositories[i].fullname) == 0)
{
sqlite3 *db = repositories[i].db;
if (repositories[i].current_status != DB_OPEN
&& repositories[i].current_status != DB_ABBREVS_LOADED)
{
sqlite3_open (fullname, &(repositories[i].db));
cu->repository = repositories[i].db;
}
else
cu->repository = db;
if (!repositories[i].dummy_objfile)
{
repositories[i].dummy_objfile = build_dummy_objfile (objfile);
}
if (!repositories[i].dummy_cu)
{
repositories[i].dummy_cu = build_dummy_cu (objfile, cu);
repositories[i].dummy_cu->objfile =
repositories[i].dummy_objfile;
repositories[i].dummy_cu->repository = repositories[i].db;
}
increment_use_count (&(repositories[i]), objfile);
objfile->uses_sql_repository = 1;
cu->repository_name = fullname;
return SQLITE_OK;
}
}
}
db_status = sqlite3_open (fullname, &(repositories[num_open_dbs].db));
cu->repository = repositories[num_open_dbs].db;
if (db_status != SQLITE_OK)
db_error ("main", "sqlite3_open failed", cu->repository);
objfile->uses_sql_repository = 1;
cu->repository_name = fullname;
if (num_open_dbs < MAX_OPEN_DBS)
{
repositories[num_open_dbs].fullname = fullname;
repositories[num_open_dbs].current_status = DB_OPEN;
increment_use_count (&(repositories[num_open_dbs]), objfile);
repositories[num_open_dbs].dummy_cu = build_dummy_cu (objfile, cu);
repositories[num_open_dbs].dummy_objfile = build_dummy_objfile (objfile);
num_open_dbs++;
}
else
internal_error (__FILE__, __LINE__,
_("Too many databases open at once.\n"));
return db_status;
}
int
close_dwarf_repositories (struct objfile *objfile)
{
sqlite3 *db;
int db_status;
int i;
for (i = 0; i < num_open_dbs; i++)
{
decrement_use_count (&(repositories[i]), objfile);
if (repositories[i].num_uses == NULL)
{
db = repositories[i].db;
finalize_stmts (db);
db_status = sqlite3_close (db);
repositories[i].abbrev_table = NULL;
repositories[i].current_status = DB_CLOSED;
repositories[i].db_types = NULL;
repositories[i].dummy_cu = NULL;
obstack_free (&repositories[i].dummy_objfile->objfile_obstack, 0);
repositories[i].dummy_objfile = NULL;
repositories[i].db = NULL;
}
}
return db_status;
}
static void
dwarf2_read_repository_abbrevs (struct dwarf2_cu *cu)
{
sqlite3 *db;
struct database_info *repository = NULL;
db = cu->repository;
repository = find_open_repository (db);
if (repository)
{
if (!repository->abbrev_table)
read_in_db_abbrev_table (&(repository->abbrev_table), db);
}
}
#define SELECT_DIE_STR "SELECT long_canonical FROM debug_info WHERE die_id == ?"
#define FIND_STRING_STR "SELECT string FROM debug_str WHERE string_id == ?"
sqlite3_stmt *db_stmt1 = NULL;
sqlite3_stmt *db_stmt2 = NULL;
static uint32_t
get_uleb128 (uint8_t **addr)
{
uint32_t result = 0;
int shift = 0;
const uint8_t *src = *addr;
uint8_t byte;
int bytecount = 0;
while (1)
{
bytecount++;
byte = *src++;
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
}
*addr += bytecount;
return result;
}
struct attr_pair {
int attribute;
int form;
struct attr_pair *next;
};
static void
read_in_db_abbrev_table (struct abbrev_info **abbrev_table, sqlite3 *db)
{
struct attr_pair *attr_node;
struct attr_pair *a_list;
struct attr_pair *tail;
int cur_table_size = 100;
int db_status;
const char *select_string = "SELECT ALL abbrev_id, attribute_data FROM debug_abbrev";
const char *pzTail;
sqlite3_stmt *dbStmt15;
int abbrev_id;
int new_size;
uint8_t *attributes;
uint8_t *temp_bytes;
uint8_t *a_ptr;
int num_attribs;
int attrib;
int form;
int max_id = 0;
int idx;
int attributes_len;
*abbrev_table = (struct abbrev_info *) xmalloc (cur_table_size
* sizeof (struct abbrev_info));
db_status = sqlite3_prepare (db, select_string, strlen (select_string),
&dbStmt15, &pzTail);
if (db_status == SQLITE_OK)
{
db_status = sqlite3_step (dbStmt15);
while (db_status == SQLITE_ROW)
{
abbrev_id = sqlite3_column_int (dbStmt15, 0);
attributes_len = sqlite3_column_bytes (dbStmt15, 1);
temp_bytes = (uint8_t *) sqlite3_column_blob (dbStmt15, 1);
attributes = (uint8_t *) xmalloc (attributes_len);
memcpy (attributes, temp_bytes, attributes_len);
if (abbrev_id >= cur_table_size)
{
if (abbrev_id > 2 * cur_table_size)
new_size = abbrev_id;
else
new_size = cur_table_size;
*abbrev_table = (struct abbrev_info *) realloc (*abbrev_table,
new_size * sizeof (struct abbrev_info));
cur_table_size = new_size;
}
if (abbrev_id > max_id)
max_id = abbrev_id;
a_ptr = attributes;
(*abbrev_table)[abbrev_id].number = abbrev_id;
(*abbrev_table)[abbrev_id].tag = get_uleb128 (&a_ptr);
(*abbrev_table)[abbrev_id].has_children = (int) *a_ptr;
(*abbrev_table)[abbrev_id].next = NULL;
a_ptr++;
num_attribs = 0;
a_list = NULL;
tail = NULL;
do {
attrib = get_uleb128 (&a_ptr);
form = get_uleb128 (&a_ptr);
if (form || attrib)
{
num_attribs++;
attr_node = (struct attr_pair *) xmalloc (sizeof
(struct attr_pair));
attr_node->attribute = attrib;
attr_node->form = form;
if (!a_list)
a_list = attr_node;
if (tail)
tail->next = attr_node;
tail = attr_node;
}
} while (attrib != 0 || form != 0);
(*abbrev_table)[abbrev_id].num_attrs = num_attribs;
(*abbrev_table)[abbrev_id].attrs =
(struct attr_abbrev *)
xmalloc (num_attribs * sizeof (struct attr_abbrev));
for (attr_node = a_list, idx = 0; attr_node && idx < num_attribs;
attr_node = attr_node->next, idx++)
{
if (attr_node->attribute == DW_AT_type)
(*abbrev_table)[abbrev_id].attrs[idx].name =
DW_AT_APPLE_repository_type;
else
(*abbrev_table)[abbrev_id].attrs[idx].name = attr_node->attribute;
(*abbrev_table)[abbrev_id].attrs[idx].form = attr_node->form;
}
db_status = sqlite3_step (dbStmt15);
}
if (db_status != SQLITE_OK && db_status != SQLITE_DONE)
db_error ("read_in_abbrev_table", "sqlite3_step failed", db);
}
else
db_error ("read_in_abbrev_table", "sqlite3_prepare failed", db);
db_status = sqlite3_finalize (dbStmt15);
if (db_status != SQLITE_OK)
db_error ("read_in_abbrev_table", "sqlite3_finalize failed", db);
}
static void
fill_in_die_info (struct die_info *new_die, int die_len, uint8_t *die_bytes,
uint8_t *d_ptr, struct abbrev_info *abbrev_table,
sqlite3 *db)
{
int i;
struct abbrev_info abbrev;
int abbrev_id = new_die->abbrev;
int num_attrs = new_die->num_attrs;
abbrev = abbrev_table[abbrev_id];
new_die->attrs = (struct attribute *)
xmalloc (num_attrs * sizeof (struct attribute));
for (i = 0; i < abbrev.num_attrs; i++)
{
new_die->attrs[i].name = abbrev.attrs[i].name;
db_read_attribute_value (&(new_die->attrs[i]),
abbrev.attrs[i].form,
&d_ptr);
}
if (abbrev.has_children)
{
int j;
int num_children = get_uleb128 (&d_ptr);
struct die_info *last_child = NULL;
for (j = 0; (j < num_children
&& (d_ptr < (die_bytes + die_len))); j++)
{
int child_id = get_uleb128 (&d_ptr);
if (child_id == new_die->repository_id)
internal_error (__FILE__, __LINE__,
_("Recursive child id in repository?\n"));
if (!last_child)
{
new_die->child = db_lookup_type (child_id, db, abbrev_table);
last_child = new_die->child;
last_child->parent = new_die;
}
else
{
last_child->sibling = db_lookup_type (child_id, db, abbrev_table);
last_child = last_child->sibling;
last_child->parent = new_die;
}
}
}
}
static struct die_info *
db_lookup_type (int type_id, sqlite3 *db, struct abbrev_info *abbrev_table)
{
int db_status;
int die_len;
uint8_t *tmp_bytes;
uint8_t *die_bytes;
uint8_t *d_ptr;
const char *pzTail;
struct die_info *new_die = NULL;
db_status = sqlite3_prepare (db, SELECT_DIE_STR,
strlen (SELECT_DIE_STR), &db_stmt1, &pzTail);
if (db_status == SQLITE_OK)
{
db_status = sqlite3_bind_int (db_stmt1, 1, type_id);
if (db_status != SQLITE_OK)
db_error ("db_lookup_type", "sqlite3_bind_int failed", db);
db_status = sqlite3_step (db_stmt1);
if (db_status == SQLITE_ROW)
{
die_len = sqlite3_column_bytes (db_stmt1, 0);
tmp_bytes = (uint8_t *) sqlite3_column_blob (db_stmt1, 0);
die_bytes = (uint8_t *) xmalloc (die_len);
memcpy (die_bytes, tmp_bytes, die_len);
d_ptr = die_bytes;
new_die = (struct die_info *) xmalloc (sizeof (struct die_info));
new_die->abbrev = get_uleb128 (&d_ptr);
new_die->tag = abbrev_table[new_die->abbrev].tag;
new_die->offset = 0;
new_die->repository_id = type_id;
new_die->next_ref = NULL;
new_die->type = NULL;
new_die->child = NULL;
new_die->sibling = NULL;
new_die->parent = NULL;
new_die->num_attrs = abbrev_table[new_die->abbrev].num_attrs;
fill_in_die_info (new_die, die_len, die_bytes, d_ptr, abbrev_table, db);
}
else if (db_status != SQLITE_OK && db_status != SQLITE_DONE)
db_error ("db_lookup_type", "sqlite3_step failed", db);
while (db_status == SQLITE_ROW)
db_status = sqlite3_step (db_stmt1);
}
else
db_error ("db_lookup_type",
db_stmt1 ? "sqlite3_reset failed" : "sqlite3_prepare failed", db);
return new_die;
}
static void
db_error (char *function_name, char *db_action_description, sqlite3 *db)
{
int len = strlen (sqlite3_errmsg (db)) + 1;
char *message = (char *) xmalloc (len);
strcpy (message, sqlite3_errmsg (db));
finalize_stmts (db);
sqlite3_close (db);
internal_error (__FILE__, __LINE__, _(message));
}
static struct dwarf2_cu *
build_dummy_cu (struct objfile *old_objfile, struct dwarf2_cu *old_cu)
{
struct dwarf2_cu *new_cu;
new_cu = xmalloc (sizeof (struct dwarf2_cu));
memset (new_cu, 0, sizeof (struct dwarf2_cu));
obstack_init (&old_cu->comp_unit_obstack);
new_cu->language = old_cu->language;
if (old_cu->producer)
new_cu->producer = xstrdup (old_cu->producer);
if (old_cu->comp_dir)
new_cu->comp_dir = xstrdup (old_cu->comp_dir);
new_cu->language_defn = old_cu->language_defn;
new_cu->repository = old_cu->repository;
if (old_cu->repository_name)
{
new_cu->repository_name = (char *) xmalloc
(strlen (old_cu->repository_name) + 1);
strcpy (new_cu->repository_name, old_cu->repository_name);
}
memset (new_cu->ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
return new_cu;
}
static struct objfile *
build_dummy_objfile (struct objfile *old_objfile)
{
struct objfile *new_objfile;
new_objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
memset (new_objfile, 0, sizeof (struct objfile));
new_objfile->md = NULL;
obstack_specify_allocation (&new_objfile->objfile_obstack, 0, 0, xmalloc,
xfree);
new_objfile->data = NULL;
new_objfile->num_data = get_objfile_registry_num_registrations ();
new_objfile->data = XCALLOC (new_objfile->num_data, void *);
new_objfile->sect_index_text = -1;
new_objfile->sect_index_data = -1;
new_objfile->sect_index_bss = -1;
new_objfile->sect_index_rodata = -1;
new_objfile->uses_sql_repository = 1;
return new_objfile;
}
static uint8_t
db_read_1_byte (uint8_t *info_ptr)
{
uint8_t src = *info_ptr;
return src;
}
static uint16_t
db_read_2_bytes (uint8_t *info_ptr)
{
uint16_t src = *((uint16_t *) info_ptr);
if (byte_swap_p)
return (uint16_t) (src & 0x00ff) << 8 | (src & 0xff00) >> 8;
else
return src;
}
static uint32_t
db_read_4_bytes (uint8_t *info_ptr)
{
uint32_t src = *((uint32_t *) info_ptr);
if (byte_swap_p)
return (uint32_t)
(src & 0x000000ff) << 24 |
(src & 0x0000ff00) << 8 |
(src & 0x00ff0000) >> 8 |
(src & 0xff000000) >> 24;
else
return (uint32_t) src;
}
static uint64_t
db_read_8_bytes (uint8_t *info_ptr)
{
union {
char c[8];
uint64_t i;
} in, out;
in.i = *((uint64_t *) info_ptr);
if (byte_swap_p)
{
out.c[0] = in.c[7];
out.c[1] = in.c[6];
out.c[2] = in.c[5];
out.c[3] = in.c[4];
out.c[4] = in.c[3];
out.c[5] = in.c[2];
out.c[6] = in.c[1];
out.c[7] = in.c[0];
}
else
out.i = in.i;
return out.i;
}
static uint8_t *
db_read_n_bytes (uint8_t *info_ptr, unsigned int num_bytes)
{
gdb_assert (HOST_CHAR_BIT == 8);
return info_ptr;
}
static uint32_t
db_read_unsigned_leb128 (uint8_t *info_ptr, unsigned int *bytes_read)
{
uint32_t result = 0;
int shift = 0;
const uint8_t *src = (const uint8_t *) info_ptr;
uint8_t byte;
int bytecount = 0;
while (1)
{
bytecount++;
byte = *src++;
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
}
*bytes_read = bytecount;
return result;
}
static int32_t
db_read_signed_leb128 (uint8_t *info_ptr, unsigned int *bytes_read)
{
int32_t result = 0;
int shift = 0;
int size = sizeof (uint32_t) * 8;
const uint8_t *src = (const uint8_t *) info_ptr;
uint8_t byte;
int bytecount = 0;
while (1)
{
bytecount++;
byte = *src++;
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
}
if (shift < size && (byte & 0x40))
result |= - (1 << shift);
*bytes_read = bytecount;
return result;
}
static uint8_t *
db_read_attribute_value (struct attribute *attr, unsigned form,
uint8_t **info_ptr)
{
unsigned int bytes_read;
struct dwarf_block *blk;
attr->form = form;
switch (form)
{
case DW_FORM_block2:
blk = (struct dwarf_block *) xmalloc (sizeof (struct dwarf_block));
blk->size = db_read_2_bytes (*info_ptr);
*info_ptr += 2;
blk->data = (char *) db_read_n_bytes (*info_ptr, blk->size);
*info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_block4:
blk = (struct dwarf_block *) xmalloc (sizeof (struct dwarf_block));
blk->size = db_read_4_bytes (*info_ptr);
*info_ptr += 4;
blk->data = (char *) db_read_n_bytes (*info_ptr, blk->size);
*info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_data2:
DW_UNSND (attr) = db_read_2_bytes (*info_ptr);
*info_ptr += 2;
break;
case DW_FORM_data4:
DW_UNSND (attr) = db_read_4_bytes (*info_ptr);
*info_ptr += 4;
break;
case DW_FORM_data8:
DW_UNSND (attr) = db_read_8_bytes (*info_ptr);
*info_ptr += 8;
break;
case DW_FORM_block:
blk = (struct dwarf_block *) xmalloc (sizeof (struct dwarf_block));
blk->size = db_read_unsigned_leb128 (*info_ptr, &bytes_read);
*info_ptr += bytes_read;
blk->data = (char *) db_read_n_bytes (*info_ptr, blk->size);
*info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_block1:
blk = (struct dwarf_block *) xmalloc (sizeof (struct dwarf_block));
blk->size = db_read_1_byte (*info_ptr);
*info_ptr += 1;
blk->data = (char *) db_read_n_bytes (*info_ptr, blk->size);
*info_ptr += blk->size;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_data1:
DW_UNSND (attr) = db_read_1_byte (*info_ptr);
*info_ptr += 1;
break;
case DW_FORM_flag:
DW_UNSND (attr) = db_read_1_byte (*info_ptr);
*info_ptr += 1;
break;
case DW_FORM_sdata:
DW_SND (attr) = db_read_signed_leb128 (*info_ptr, &bytes_read);
*info_ptr += bytes_read;
break;
case DW_FORM_APPLE_db_str:
case DW_FORM_udata:
DW_UNSND (attr) = db_read_unsigned_leb128 (*info_ptr, &bytes_read);
*info_ptr += bytes_read;
break;
case DW_FORM_indirect:
form = db_read_unsigned_leb128 (*info_ptr, &bytes_read);
*info_ptr += bytes_read;
*info_ptr = db_read_attribute_value (attr, form, info_ptr);
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
case DW_FORM_addr:
case DW_FORM_ref_addr:
case DW_FORM_string:
case DW_FORM_strp:
default:
error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
"db_read_attribute_value");
}
return *info_ptr;
}
static struct die_info *
follow_db_ref (struct die_info *die, struct attribute *repository_spec,
struct dwarf2_cu *cu)
{
int db_id;
int want_die_p = 1;
sqlite3 *db = cu->repository;
struct die_info *db_die;
db_id = DW_UNSND (repository_spec);
db_die = (struct die_info *) lookup_repository_type (db_id, db, cu, want_die_p);
return db_die;
}
static void
set_repository_cu_language (unsigned int language, struct dwarf2_cu *old_cu)
{
sqlite3 *db = old_cu->repository;
struct database_info *repository = NULL;
if (!db)
internal_error (__FILE__, __LINE__, _("Missing database.\n"));
repository = find_open_repository (db);
if (repository)
set_cu_language (language, repository->dummy_cu);
}
static struct attribute *
get_repository_name (struct attribute *attr, struct dwarf2_cu *cu)
{
sqlite3 *db = cu->repository;
int string_id;
int db_status;
struct attribute *name_attribute = NULL;
const char *pzTail;
char *name;
string_id = DW_UNSND (attr);
if (db)
{
db_status = sqlite3_prepare (db, FIND_STRING_STR,
strlen (FIND_STRING_STR), &db_stmt2,
&pzTail);
if (db_status != SQLITE_OK)
db_error ("get_repository_name",
(db_stmt2 ? "sqlite3_reset failed" : "sqlite_prepare3 failed"),
db);
db_status = sqlite3_bind_int (db_stmt2, 1, string_id);
if (db_status != SQLITE_OK)
db_error ("get_repository_name", "sqlite3_bind_int failed", db);
db_status = sqlite3_step (db_stmt2);
while (db_status == SQLITE_ROW)
{
name = (char *) sqlite3_column_text (db_stmt2, 0);
db_status = sqlite3_step (db_stmt2);
}
if (name)
{
name_attribute = (struct attribute *) xmalloc
(sizeof (struct attribute));
name_attribute->name = DW_AT_name;
name_attribute->form = DW_FORM_string;
DW_STRING(name_attribute) = (char *) xmalloc (strlen (name) + 1);
strcpy (DW_STRING(name_attribute), name);
}
}
return name_attribute;
}
static int
finalize_stmts (sqlite3 *db)
{
int db_status;
db_status = sqlite3_finalize (db_stmt1);
if (db_status != SQLITE_OK)
db_error ("finalize_stmts", "failed on db_stmt1", db);
db_status = sqlite3_finalize (db_stmt2);
if (db_status != SQLITE_OK)
db_error ("finalize_stmts", "failed on db_stmt2", db);
db_stmt1 = NULL;
db_stmt2 = NULL;
return db_status;
}
static void
increment_use_count (struct database_info *repository, struct objfile *ofile)
{
struct objfile_list_node *current;
struct objfile_list_node *new_node;
for (current = repository->num_uses; current; current = current->next)
if (current->ofile == ofile)
return;
new_node = (struct objfile_list_node *) xmalloc (sizeof (struct objfile_list_node));
new_node->ofile = ofile;
new_node->next = repository->num_uses;
repository->num_uses = new_node;
}
static void
decrement_use_count (struct database_info *repository, struct objfile *ofile)
{
struct objfile_list_node *current;
struct objfile_list_node *prev;
if (repository->num_uses == NULL)
return;
for (prev = NULL, current = repository->num_uses; current;
prev = current, current = current->next)
{
if (current->ofile == ofile)
{
if (prev)
prev->next = current->next;
else
repository->num_uses = current->next;
return;
}
}
}