From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22788 invoked by alias); 5 Jul 2002 03:23:51 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 22380 invoked from network); 5 Jul 2002 03:23:37 -0000 Received: from unknown (HELO zwingli.cygnus.com) (208.245.165.35) by sources.redhat.com with SMTP; 5 Jul 2002 03:23:37 -0000 Received: by zwingli.cygnus.com (Postfix, from userid 442) id 1C87F5EA11; Thu, 4 Jul 2002 22:23:34 -0500 (EST) To: Petr Sorfa Cc: "gdb-patches@sources.redhat.com" Subject: Re: [PATCH] Support for multiple DWARF comp unit headers References: <3D2365EA.E739FE66@caldera.com> From: Jim Blandy Date: Thu, 04 Jul 2002 20:27:00 -0000 In-Reply-To: <3D2365EA.E739FE66@caldera.com> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2002-07/txt/msg00096.txt.bz2 I think this patch is too big to review in one gulp. Could you break this up into a succession of smaller patches? For example, moving the abbrev tables into the CU header structure could be the first patch; making it possible to have more than one CU read in at a time would be the next (even though no code would use more than one yet); and adding support for DW_FORM_ref_addr could be the last. Perhaps you can see finer divisions to make; the finer you can get them, the better. Why does build_die_ref reject the result from follow_die_ref when its type isn't filled in? If the DIE being referred to doesn't represent a type, won't this cause it to be re-read unnecessarily? What happens if we hit a DW_FORM_ref_addr pointing to a DIE, and then later hit a DW_FORM_ref_addr pointing to one of its parents? Won't we end up calling find_die_ref twice, and adding the dies in the first tree to the reference hash table twice? Just out of curiosity --- after we've built `struct die_info' objects for a CU, we don't need the abbrev table any more, do we? I may be misremembering the way the code behaves, but it seems to me that one could construct an abbrev table before calling read_comp_unit, and then throw it away when done. Perhaps the abbrev tables are not big enough for this to be worth thinking about. Petr Sorfa writes: > Hi, > > Patch for supporting multiple DWARF comp unit headers. This is necessary > for supporting DW_FORM_ref_addr properly when the reference is to a > compilation unit outside of the current one. The current code only > supports one comp unit at a time. > > 2002-07-03 Petr Sorfa (petrs@caldera.com) > > * dwarf2read.c (build_die_ref): New function that builds > a new die reference if necessary, will search across > multiple comp units to find the reference. > (find_die_ref): New function that searches for a die > reference for a given comp unit. > (find_cu_header_from_begin_offset): New function that > searches through a link list of comp unit headers for > a comp unit that matches the given offset. > (register_cu_header): New function that registers a > comp unit header by allocating space for it and > adding it to the comp unit header list. > (free_cu_header_list): New function that frees up the > memory taken up by the list of comp unit headers > associated with a process. > (dwarf_new_init): New function that initializes DWARF > information for a new process. > (struct comp_unit_head): Adds several new members > to contain fully all the comp unit head's info. > (first_cu_header): A new global variable that points > to the first comp unit head for the process. > (cu_header_offset): Global variable removed, as is now > present in each comp unit head. > (dwarf_abbrevs): Global variable removed, as is now > present in each comp unit head. > (dwarf2_read_abbrevs): > (dwarf2_empty_abbrev_table): > (dwarf2_lookup_abbrev): > (dwarf_attr): > (die_is_declaration): > (read_base_type): > (dwarf2_get_pc_bounds): > (read_tag_string_type): > (dwarf2_linkage_name): > (dwarf2_get_ref_die_offset): > All of these functions have a new argument added to > pass the current comp unit header. All calls to these > functions have been updated to handle the additional > argument. > > * elfread.c (elf_new_init): Now calls dwarf_new_init() > to initialize DWARF related information for the > new process.? err > ? 1 > Index: dwarf2read.c > =================================================================== > RCS file: /cvs/src/src/gdb/dwarf2read.c,v > retrieving revision 1.60 > diff -c -p -r1.60 dwarf2read.c > *** dwarf2read.c 22 Jun 2002 00:05:59 -0000 1.60 > --- dwarf2read.c 3 Jul 2002 20:35:37 -0000 > *************** unsigned int dwarf_eh_frame_size; > *** 162,167 **** > --- 162,172 ---- > > /* local data types */ > > + /* We hold several abbreviation tables at the same time in memory */ > + #ifndef ABBREV_HASH_SIZE > + #define ABBREV_HASH_SIZE 121 > + #endif > + > /* The data in a compilation unit header, after target2host > translation, looks like this. */ > struct comp_unit_head > *************** struct comp_unit_head > *** 174,179 **** > --- 179,193 ---- > unsigned int offset_size; /* size of file offsets; either 4 or 8 */ > unsigned int initial_length_size; /* size of the length field; either > 4 or 12 */ > + /* New information for the comp unit head so as to keep a list > + of available ones for a program. */ > + unsigned int offset; /* Offset of the cu_header in .debug_info */ > + char *base_offset; /* Base offset after cu_header into program */ > + char *begin_offset; /* Base offset of cu_header into program */ > + struct comp_unit_head *next; /* Next comp unit head in program */ > + > + struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; /* DWARF abbrev > + table */ > }; > > /* The line number information for a compilation unit (found in the > *************** struct dwarf_block > *** 312,327 **** > char *data; > }; > > - /* We only hold one compilation unit's abbrevs in > - memory at any one time. */ > - #ifndef ABBREV_HASH_SIZE > - #define ABBREV_HASH_SIZE 121 > - #endif > #ifndef ATTR_ALLOC_CHUNK > #define ATTR_ALLOC_CHUNK 4 > #endif > > ! static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; > > /* A hash table of die offsets for following references. */ > #ifndef REF_HASH_SIZE > --- 326,337 ---- > char *data; > }; > > #ifndef ATTR_ALLOC_CHUNK > #define ATTR_ALLOC_CHUNK 4 > #endif > > ! /* First comp unit head in the program */ > ! struct comp_unit_head *first_cu_header = NULL; > > /* A hash table of die offsets for following references. */ > #ifndef REF_HASH_SIZE > *************** static struct die_info *die_ref_table[RE > *** 333,342 **** > /* Obstack for allocating temporary storage used during symbol reading. */ > static struct obstack dwarf2_tmp_obstack; > > - /* Offset to the first byte of the current compilation unit header, > - for resolving relative reference dies. */ > - static unsigned int cu_header_offset; > - > /* Allocate fields for structs, unions and enums in this size. */ > #ifndef DW_FIELD_ALLOC_CHUNK > #define DW_FIELD_ALLOC_CHUNK 4 > --- 343,348 ---- > *************** static void psymtab_to_symtab_1 (struct > *** 682,692 **** > > char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int); > > ! static void dwarf2_read_abbrevs (bfd *, unsigned int); > > ! static void dwarf2_empty_abbrev_table (PTR); > > ! static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int); > > static char *read_partial_die (struct partial_die_info *, > bfd *, char *, > --- 688,699 ---- > > char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int); > > ! static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header); > > ! static void dwarf2_empty_abbrev_table (struct comp_unit_head *cu_header); > > ! static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int, > ! const struct comp_unit_head *cu_header); > > static char *read_partial_die (struct partial_die_info *, > bfd *, char *, > *************** static long read_signed_leb128 (bfd *, c > *** 733,741 **** > > static void set_cu_language (unsigned int); > > ! static struct attribute *dwarf_attr (struct die_info *, unsigned int); > > ! static int die_is_declaration (struct die_info *); > > static void free_line_header (struct line_header *lh); > > --- 740,750 ---- > > static void set_cu_language (unsigned int); > > ! static struct attribute *dwarf_attr (struct die_info *, unsigned int, > ! const struct comp_unit_head *); > > ! static int die_is_declaration (struct die_info *, > ! const struct comp_unit_head *); > > static void free_line_header (struct line_header *lh); > > *************** static void read_type_die (struct die_in > *** 778,784 **** > static void read_typedef (struct die_info *, struct objfile *, > const struct comp_unit_head *); > > ! static void read_base_type (struct die_info *, struct objfile *); > > static void read_file_scope (struct die_info *, struct objfile *, > const struct comp_unit_head *); > --- 787,794 ---- > static void read_typedef (struct die_info *, struct objfile *, > const struct comp_unit_head *); > > ! static void read_base_type (struct die_info *, struct objfile *, > ! const struct comp_unit_head *); > > static void read_file_scope (struct die_info *, struct objfile *, > const struct comp_unit_head *); > *************** static void read_lexical_block_scope (st > *** 790,796 **** > const struct comp_unit_head *); > > static int dwarf2_get_pc_bounds (struct die_info *, > ! CORE_ADDR *, CORE_ADDR *, struct objfile *); > > static void dwarf2_add_field (struct field_info *, struct die_info *, > struct objfile *, const struct comp_unit_head *); > --- 800,807 ---- > const struct comp_unit_head *); > > static int dwarf2_get_pc_bounds (struct die_info *, > ! CORE_ADDR *, CORE_ADDR *, struct objfile *, > ! const struct comp_unit_head *); > > static void dwarf2_add_field (struct field_info *, struct die_info *, > struct objfile *, const struct comp_unit_head *); > *************** static void read_tag_const_type (struct > *** 837,843 **** > static void read_tag_volatile_type (struct die_info *, struct objfile *, > const struct comp_unit_head *); > > ! static void read_tag_string_type (struct die_info *, struct objfile *); > > static void read_subroutine_type (struct die_info *, struct objfile *, > const struct comp_unit_head *); > --- 848,855 ---- > static void read_tag_volatile_type (struct die_info *, struct objfile *, > const struct comp_unit_head *); > > ! static void read_tag_string_type (struct die_info *, struct objfile *, > ! const struct comp_unit_head *); > > static void read_subroutine_type (struct die_info *, struct objfile *, > const struct comp_unit_head *); > *************** static struct cleanup *make_cleanup_free > *** 852,858 **** > static void process_die (struct die_info *, struct objfile *, > const struct comp_unit_head *); > > ! static char *dwarf2_linkage_name (struct die_info *); > > static char *dwarf_tag_name (unsigned int); > > --- 864,871 ---- > static void process_die (struct die_info *, struct objfile *, > const struct comp_unit_head *); > > ! static char *dwarf2_linkage_name (struct die_info *, > ! const struct comp_unit_head *); > > static char *dwarf_tag_name (unsigned int); > > *************** static void store_in_ref_table (unsigned > *** 882,893 **** > > static void dwarf2_empty_hash_tables (void); > > ! static unsigned int dwarf2_get_ref_die_offset (struct attribute *); > > static struct die_info *follow_die_ref (unsigned int); > > static struct type *dwarf2_fundamental_type (struct objfile *, int); > > /* memory allocation interface */ > > static void dwarf2_free_tmp_obstack (PTR); > --- 895,917 ---- > > static void dwarf2_empty_hash_tables (void); > > ! static unsigned int dwarf2_get_ref_die_offset (struct attribute *, > ! const struct comp_unit_head *); > > static struct die_info *follow_die_ref (unsigned int); > > static struct type *dwarf2_fundamental_type (struct objfile *, int); > > + static struct die_info *build_die_ref (struct attribute *, struct objfile *, > + const struct comp_unit_head *); > + static struct die_info *find_die_ref (unsigned int target_offset, bfd *abfd, > + const struct comp_unit_head *cu_header); > + static struct comp_unit_head *find_cu_header_from_begin_offset (char *); > + static struct comp_unit_head *find_cu_header (unsigned int); > + static void register_cu_header (const struct comp_unit_head *); > + static void free_cu_header_list (void); > + void dwarf_new_init (void); > + > /* memory allocation interface */ > > static void dwarf2_free_tmp_obstack (PTR); > *************** static void dwarf_decode_macros (struct > *** 906,911 **** > --- 930,942 ---- > char *, bfd *, const struct comp_unit_head *, > struct objfile *); > > + /* Initialize DWARF environment for new binary */ > + void > + dwarf_new_init (void) > + { > + free_cu_header_list (); > + } > + > /* Try to locate the sections we need for DWARF 2 debugging > information and return true if we have enough to do something. */ > > *************** dwarf2_build_psymtabs_hard (struct objfi > *** 1201,1208 **** > return; > } > /* Read the abbrevs for this compilation unit into a table */ > ! dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); > ! make_cleanup (dwarf2_empty_abbrev_table, NULL); > > /* Read the compilation unit die */ > info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr, > --- 1232,1244 ---- > return; > } > /* Read the abbrevs for this compilation unit into a table */ > ! dwarf2_read_abbrevs (abfd, &cu_header); > ! > ! cu_header.offset = beg_of_comp_unit - dwarf_info_buffer; > ! cu_header.base_offset = info_ptr; > ! cu_header.begin_offset = beg_of_comp_unit; > ! > ! register_cu_header (&cu_header); > > /* Read the compilation unit die */ > info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr, > *************** dwarf2_build_psymtabs_hard (struct objfi > *** 1220,1226 **** > > pst->read_symtab_private = (char *) > obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo)); > ! cu_header_offset = beg_of_comp_unit - dwarf_info_buffer; > DWARF_INFO_BUFFER (pst) = dwarf_info_buffer; > DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer; > DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer; > --- 1256,1262 ---- > > pst->read_symtab_private = (char *) > obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo)); > ! > DWARF_INFO_BUFFER (pst) = dwarf_info_buffer; > DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer; > DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer; > *************** psymtab_to_symtab_1 (struct partial_symt > *** 1515,1521 **** > { > struct objfile *objfile = pst->objfile; > bfd *abfd = objfile->obfd; > ! struct comp_unit_head cu_header; > struct die_info *dies; > unsigned long offset; > CORE_ADDR lowpc, highpc; > --- 1551,1557 ---- > { > struct objfile *objfile = pst->objfile; > bfd *abfd = objfile->obfd; > ! struct comp_unit_head *cu_header; > struct die_info *dies; > unsigned long offset; > CORE_ADDR lowpc, highpc; > *************** psymtab_to_symtab_1 (struct partial_symt > *** 1536,1542 **** > dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst); > dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst); > baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); > - cu_header_offset = offset; > info_ptr = dwarf_info_buffer + offset; > > obstack_init (&dwarf2_tmp_obstack); > --- 1572,1577 ---- > *************** psymtab_to_symtab_1 (struct partial_symt > *** 1545,1565 **** > buildsym_init (); > make_cleanup (really_free_pendings, NULL); > > ! /* read in the comp_unit header */ > ! info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd); > > ! /* Read the abbrevs for this compilation unit */ > ! dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); > ! make_cleanup (dwarf2_empty_abbrev_table, NULL); > > ! dies = read_comp_unit (info_ptr, abfd, &cu_header); > > make_cleanup_free_die_list (dies); > > /* Do line number decoding in read_file_scope () */ > ! process_die (dies, objfile, &cu_header); > > ! if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile)) > { > /* Some compilers don't define a DW_AT_high_pc attribute for > the compilation unit. If the DW_AT_high_pc is missing, > --- 1580,1603 ---- > buildsym_init (); > make_cleanup (really_free_pendings, NULL); > > ! cu_header = find_cu_header_from_begin_offset (info_ptr); > ! > ! if (cu_header == NULL) > ! { > ! error ("Failed to find cu_header at base offset[0x%lx]\n", info_ptr); > ! } > > ! /* Update the info ptr */ > ! info_ptr = cu_header->base_offset; > > ! dies = read_comp_unit (info_ptr, abfd, cu_header); > > make_cleanup_free_die_list (dies); > > /* Do line number decoding in read_file_scope () */ > ! process_die (dies, objfile, cu_header); > > ! if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, cu_header)) > { > /* Some compilers don't define a DW_AT_high_pc attribute for > the compilation unit. If the DW_AT_high_pc is missing, > *************** psymtab_to_symtab_1 (struct partial_symt > *** 1574,1580 **** > { > CORE_ADDR low, high; > > ! if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) > { > highpc = max (highpc, high); > } > --- 1612,1619 ---- > { > CORE_ADDR low, high; > > ! if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile, > ! cu_header)) > { > highpc = max (highpc, high); > } > *************** process_die (struct die_info *die, struc > *** 1649,1659 **** > read_tag_reference_type (die, objfile, cu_header); > break; > case DW_TAG_string_type: > ! read_tag_string_type (die, objfile); > break; > case DW_TAG_base_type: > ! read_base_type (die, objfile); > ! if (dwarf_attr (die, DW_AT_name)) > { > /* Add a typedef symbol for the base type definition. */ > new_symbol (die, die->type, objfile, cu_header); > --- 1688,1698 ---- > read_tag_reference_type (die, objfile, cu_header); > break; > case DW_TAG_string_type: > ! read_tag_string_type (die, objfile, cu_header); > break; > case DW_TAG_base_type: > ! read_base_type (die, objfile, cu_header); > ! if (dwarf_attr (die, DW_AT_name, cu_header)) > { > /* Add a typedef symbol for the base type definition. */ > new_symbol (die, die->type, objfile, cu_header); > *************** read_file_scope (struct die_info *die, s > *** 1690,1696 **** > bfd *abfd = objfile->obfd; > struct line_header *line_header = 0; > > ! if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) > { > if (die->has_children) > { > --- 1729,1735 ---- > bfd *abfd = objfile->obfd; > struct line_header *line_header = 0; > > ! if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) > { > if (die->has_children) > { > *************** read_file_scope (struct die_info *die, s > *** 1701,1707 **** > { > CORE_ADDR low, high; > > ! if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) > { > lowpc = min (lowpc, low); > highpc = max (highpc, high); > --- 1740,1747 ---- > { > CORE_ADDR low, high; > > ! if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile, > ! cu_header)) > { > lowpc = min (lowpc, low); > highpc = max (highpc, high); > *************** read_file_scope (struct die_info *die, s > *** 1719,1730 **** > lowpc += baseaddr; > highpc += baseaddr; > > ! attr = dwarf_attr (die, DW_AT_name); > if (attr) > { > name = DW_STRING (attr); > } > ! attr = dwarf_attr (die, DW_AT_comp_dir); > if (attr) > { > comp_dir = DW_STRING (attr); > --- 1759,1770 ---- > lowpc += baseaddr; > highpc += baseaddr; > > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr) > { > name = DW_STRING (attr); > } > ! attr = dwarf_attr (die, DW_AT_comp_dir, cu_header); > if (attr) > { > comp_dir = DW_STRING (attr); > *************** read_file_scope (struct die_info *die, s > *** 1746,1752 **** > objfile->ei.entry_file_highpc = highpc; > } > > ! attr = dwarf_attr (die, DW_AT_language); > if (attr) > { > set_cu_language (DW_UNSND (attr)); > --- 1786,1792 ---- > objfile->ei.entry_file_highpc = highpc; > } > > ! attr = dwarf_attr (die, DW_AT_language, cu_header); > if (attr) > { > set_cu_language (DW_UNSND (attr)); > *************** read_file_scope (struct die_info *die, s > *** 1783,1789 **** > } > > /* Decode line number information if present. */ > ! attr = dwarf_attr (die, DW_AT_stmt_list); > if (attr) > { > unsigned int line_offset = DW_UNSND (attr); > --- 1823,1829 ---- > } > > /* Decode line number information if present. */ > ! attr = dwarf_attr (die, DW_AT_stmt_list, cu_header); > if (attr) > { > unsigned int line_offset = DW_UNSND (attr); > *************** read_file_scope (struct die_info *die, s > *** 1801,1807 **** > refers to information in the line number info statement program > header, so we can only read it if we've read the header > successfully. */ > ! attr = dwarf_attr (die, DW_AT_macro_info); > if (attr) > { > unsigned int macro_offset = DW_UNSND (attr); > --- 1841,1847 ---- > refers to information in the line number info statement program > header, so we can only read it if we've read the header > successfully. */ > ! attr = dwarf_attr (die, DW_AT_macro_info, cu_header); > if (attr) > { > unsigned int macro_offset = DW_UNSND (attr); > *************** read_func_scope (struct die_info *die, s > *** 1843,1853 **** > struct attribute *attr; > char *name; > > ! name = dwarf2_linkage_name (die); > > /* Ignore functions with missing or empty names and functions with > missing or invalid low and high pc attributes. */ > ! if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) > return; > > lowpc += baseaddr; > --- 1883,1894 ---- > struct attribute *attr; > char *name; > > ! name = dwarf2_linkage_name (die, cu_header); > > /* Ignore functions with missing or empty names and functions with > missing or invalid low and high pc attributes. */ > ! if (name == NULL || > ! !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) > return; > > lowpc += baseaddr; > *************** read_func_scope (struct die_info *die, s > *** 1867,1873 **** > for DW_OP_fbreg operands in decode_locdesc. */ > frame_base_reg = -1; > frame_base_offset = 0; > ! attr = dwarf_attr (die, DW_AT_frame_base); > if (attr) > { > CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); > --- 1908,1914 ---- > for DW_OP_fbreg operands in decode_locdesc. */ > frame_base_reg = -1; > frame_base_offset = 0; > ! attr = dwarf_attr (die, DW_AT_frame_base, cu_header); > if (attr) > { > CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); > *************** read_lexical_block_scope (struct die_inf > *** 1917,1923 **** > struct die_info *child_die; > > /* Ignore blocks with missing or invalid low and high pc attributes. */ > ! if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) > return; > lowpc += baseaddr; > highpc += baseaddr; > --- 1958,1964 ---- > struct die_info *child_die; > > /* Ignore blocks with missing or invalid low and high pc attributes. */ > ! if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) > return; > lowpc += baseaddr; > highpc += baseaddr; > *************** read_lexical_block_scope (struct die_inf > *** 1947,1964 **** > > static int > dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, > ! struct objfile *objfile) > { > struct attribute *attr; > CORE_ADDR low; > CORE_ADDR high; > > ! attr = dwarf_attr (die, DW_AT_low_pc); > if (attr) > low = DW_ADDR (attr); > else > return 0; > ! attr = dwarf_attr (die, DW_AT_high_pc); > if (attr) > high = DW_ADDR (attr); > else > --- 1988,2006 ---- > > static int > dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, > ! struct objfile *objfile, > ! const struct comp_unit_head *cu_header) > { > struct attribute *attr; > CORE_ADDR low; > CORE_ADDR high; > > ! attr = dwarf_attr (die, DW_AT_low_pc, cu_header); > if (attr) > low = DW_ADDR (attr); > else > return 0; > ! attr = dwarf_attr (die, DW_AT_high_pc, cu_header); > if (attr) > high = DW_ADDR (attr); > else > *************** dwarf2_add_field (struct field_info *fip > *** 2012,2023 **** > new_field->accessibility = DW_ACCESS_private; > new_field->virtuality = DW_VIRTUALITY_none; > > ! attr = dwarf_attr (die, DW_AT_accessibility); > if (attr) > new_field->accessibility = DW_UNSND (attr); > if (new_field->accessibility != DW_ACCESS_public) > fip->non_public_fields = 1; > ! attr = dwarf_attr (die, DW_AT_virtuality); > if (attr) > new_field->virtuality = DW_UNSND (attr); > > --- 2054,2065 ---- > new_field->accessibility = DW_ACCESS_private; > new_field->virtuality = DW_VIRTUALITY_none; > > ! attr = dwarf_attr (die, DW_AT_accessibility, cu_header); > if (attr) > new_field->accessibility = DW_UNSND (attr); > if (new_field->accessibility != DW_ACCESS_public) > fip->non_public_fields = 1; > ! attr = dwarf_attr (die, DW_AT_virtuality, cu_header); > if (attr) > new_field->virtuality = DW_UNSND (attr); > > *************** dwarf2_add_field (struct field_info *fip > *** 2028,2034 **** > fp->type = die_type (die, objfile, cu_header); > > /* Get bit size of field (zero if none). */ > ! attr = dwarf_attr (die, DW_AT_bit_size); > if (attr) > { > FIELD_BITSIZE (*fp) = DW_UNSND (attr); > --- 2070,2076 ---- > fp->type = die_type (die, objfile, cu_header); > > /* Get bit size of field (zero if none). */ > ! attr = dwarf_attr (die, DW_AT_bit_size, cu_header); > if (attr) > { > FIELD_BITSIZE (*fp) = DW_UNSND (attr); > *************** dwarf2_add_field (struct field_info *fip > *** 2039,2045 **** > } > > /* Get bit offset of field. */ > ! attr = dwarf_attr (die, DW_AT_data_member_location); > if (attr) > { > FIELD_BITPOS (*fp) = > --- 2081,2087 ---- > } > > /* Get bit offset of field. */ > ! attr = dwarf_attr (die, DW_AT_data_member_location, cu_header); > if (attr) > { > FIELD_BITPOS (*fp) = > *************** dwarf2_add_field (struct field_info *fip > *** 2047,2053 **** > } > else > FIELD_BITPOS (*fp) = 0; > ! attr = dwarf_attr (die, DW_AT_bit_offset); > if (attr) > { > if (BITS_BIG_ENDIAN) > --- 2089,2095 ---- > } > else > FIELD_BITPOS (*fp) = 0; > ! attr = dwarf_attr (die, DW_AT_bit_offset, cu_header); > if (attr) > { > if (BITS_BIG_ENDIAN) > *************** dwarf2_add_field (struct field_info *fip > *** 2070,2076 **** > int anonymous_size; > int bit_offset = DW_UNSND (attr); > > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > /* The size of the anonymous object containing > --- 2112,2118 ---- > int anonymous_size; > int bit_offset = DW_UNSND (attr); > > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > /* The size of the anonymous object containing > *************** dwarf2_add_field (struct field_info *fip > *** 2092,2098 **** > } > > /* Get name of field. */ > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > fieldname = DW_STRING (attr); > fp->name = obsavestring (fieldname, strlen (fieldname), > --- 2134,2140 ---- > } > > /* Get name of field. */ > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > fieldname = DW_STRING (attr); > fp->name = obsavestring (fieldname, strlen (fieldname), > *************** dwarf2_add_field (struct field_info *fip > *** 2100,2106 **** > > /* Change accessibility for artificial fields (e.g. virtual table > pointer or virtual base class pointer) to private. */ > ! if (dwarf_attr (die, DW_AT_artificial)) > { > new_field->accessibility = DW_ACCESS_private; > fip->non_public_fields = 1; > --- 2142,2148 ---- > > /* Change accessibility for artificial fields (e.g. virtual table > pointer or virtual base class pointer) to private. */ > ! if (dwarf_attr (die, DW_AT_artificial, cu_header)) > { > new_field->accessibility = DW_ACCESS_private; > fip->non_public_fields = 1; > *************** dwarf2_add_field (struct field_info *fip > *** 2112,2125 **** > > /* C++ static member. > Get name of field. */ > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > fieldname = DW_STRING (attr); > else > return; > > /* Get physical name. */ > ! physname = dwarf2_linkage_name (die); > > SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname), > &objfile->type_obstack)); > --- 2154,2167 ---- > > /* C++ static member. > Get name of field. */ > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > fieldname = DW_STRING (attr); > else > return; > > /* Get physical name. */ > ! physname = dwarf2_linkage_name (die, cu_header); > > SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname), > &objfile->type_obstack)); > *************** dwarf2_add_field (struct field_info *fip > *** 2130,2136 **** > else if (die->tag == DW_TAG_inheritance) > { > /* C++ base class field. */ > ! attr = dwarf_attr (die, DW_AT_data_member_location); > if (attr) > FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header) > * bits_per_byte); > --- 2172,2178 ---- > else if (die->tag == DW_TAG_inheritance) > { > /* C++ base class field. */ > ! attr = dwarf_attr (die, DW_AT_data_member_location, cu_header); > if (attr) > FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header) > * bits_per_byte); > *************** dwarf2_add_member_fn (struct field_info > *** 2244,2257 **** > struct nextfnfield *new_fnfield; > > /* Get name of member function. */ > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > fieldname = DW_STRING (attr); > else > return; > > /* Get the mangled name. */ > ! physname = dwarf2_linkage_name (die); > > /* Look up member function name in fieldlist. */ > for (i = 0; i < fip->nfnfields; i++) > --- 2286,2299 ---- > struct nextfnfield *new_fnfield; > > /* Get name of member function. */ > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > fieldname = DW_STRING (attr); > else > return; > > /* Get the mangled name. */ > ! physname = dwarf2_linkage_name (die, cu_header); > > /* Look up member function name in fieldlist. */ > for (i = 0; i < fip->nfnfields; i++) > *************** dwarf2_add_member_fn (struct field_info > *** 2319,2332 **** > complain (&dwarf2_missing_member_fn_type_complaint, physname); > > /* Get fcontext from DW_AT_containing_type if present. */ > ! if (dwarf_attr (die, DW_AT_containing_type) != NULL) > fnp->fcontext = die_containing_type (die, objfile, cu_header); > > /* dwarf2 doesn't have stubbed physical names, so the setting of is_const > and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ > > /* Get accessibility. */ > ! attr = dwarf_attr (die, DW_AT_accessibility); > if (attr) > { > switch (DW_UNSND (attr)) > --- 2361,2374 ---- > complain (&dwarf2_missing_member_fn_type_complaint, physname); > > /* Get fcontext from DW_AT_containing_type if present. */ > ! if (dwarf_attr (die, DW_AT_containing_type, cu_header) != NULL) > fnp->fcontext = die_containing_type (die, objfile, cu_header); > > /* dwarf2 doesn't have stubbed physical names, so the setting of is_const > and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ > > /* Get accessibility. */ > ! attr = dwarf_attr (die, DW_AT_accessibility, cu_header); > if (attr) > { > switch (DW_UNSND (attr)) > *************** dwarf2_add_member_fn (struct field_info > *** 2341,2352 **** > } > > /* Check for artificial methods. */ > ! attr = dwarf_attr (die, DW_AT_artificial); > if (attr && DW_UNSND (attr) != 0) > fnp->is_artificial = 1; > > /* Get index in virtual function table if it is a virtual member function. */ > ! attr = dwarf_attr (die, DW_AT_vtable_elem_location); > if (attr) > fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2; > } > --- 2383,2394 ---- > } > > /* Check for artificial methods. */ > ! attr = dwarf_attr (die, DW_AT_artificial, cu_header); > if (attr && DW_UNSND (attr) != 0) > fnp->is_artificial = 1; > > /* Get index in virtual function table if it is a virtual member function. */ > ! attr = dwarf_attr (die, DW_AT_vtable_elem_location, cu_header); > if (attr) > fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2; > } > *************** read_structure_scope (struct die_info *d > *** 2411,2417 **** > type = alloc_type (objfile); > > INIT_CPLUS_SPECIFIC (type); > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > { > TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), > --- 2453,2459 ---- > type = alloc_type (objfile); > > INIT_CPLUS_SPECIFIC (type); > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > { > TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), > *************** read_structure_scope (struct die_info *d > *** 2434,2440 **** > TYPE_CODE (type) = TYPE_CODE_CLASS; > } > > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > --- 2476,2482 ---- > TYPE_CODE (type) = TYPE_CODE_CLASS; > } > > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > *************** read_structure_scope (struct die_info *d > *** 2449,2455 **** > type within the structure itself. */ > die->type = type; > > ! if (die->has_children && ! die_is_declaration (die)) > { > struct field_info fi; > struct die_info *child_die; > --- 2491,2497 ---- > type within the structure itself. */ > die->type = type; > > ! if (die->has_children && ! die_is_declaration (die, cu_header)) > { > struct field_info fi; > struct die_info *child_die; > *************** read_structure_scope (struct die_info *d > *** 2499,2505 **** > class itself) which contains the vtable pointer for the current > class from the DW_AT_containing_type attribute. */ > > ! if (dwarf_attr (die, DW_AT_containing_type) != NULL) > { > struct type *t = die_containing_type (die, objfile, cu_header); > > --- 2541,2547 ---- > class itself) which contains the vtable pointer for the current > class from the DW_AT_containing_type attribute. */ > > ! if (dwarf_attr (die, DW_AT_containing_type, cu_header) != NULL) > { > struct type *t = die_containing_type (die, objfile, cu_header); > > *************** read_enumeration (struct die_info *die, > *** 2572,2578 **** > type = alloc_type (objfile); > > TYPE_CODE (type) = TYPE_CODE_ENUM; > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > { > TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), > --- 2614,2620 ---- > type = alloc_type (objfile); > > TYPE_CODE (type) = TYPE_CODE_ENUM; > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > { > TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), > *************** read_enumeration (struct die_info *die, > *** 2580,2586 **** > &objfile->type_obstack); > } > > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > --- 2622,2628 ---- > &objfile->type_obstack); > } > > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > *************** read_enumeration (struct die_info *die, > *** 2603,2609 **** > } > else > { > ! attr = dwarf_attr (child_die, DW_AT_name); > if (attr) > { > sym = new_symbol (child_die, type, objfile, cu_header); > --- 2645,2651 ---- > } > else > { > ! attr = dwarf_attr (child_die, DW_AT_name, cu_header); > if (attr) > { > sym = new_symbol (child_die, type, objfile, cu_header); > *************** read_array_type (struct die_info *die, s > *** 2698,2704 **** > } > > index_type = die_type (child_die, objfile, cu_header); > ! attr = dwarf_attr (child_die, DW_AT_lower_bound); > if (attr) > { > if (attr->form == DW_FORM_sdata) > --- 2740,2746 ---- > } > > index_type = die_type (child_die, objfile, cu_header); > ! attr = dwarf_attr (child_die, DW_AT_lower_bound, cu_header); > if (attr) > { > if (attr->form == DW_FORM_sdata) > *************** read_array_type (struct die_info *die, s > *** 2725,2731 **** > #endif > } > } > ! attr = dwarf_attr (child_die, DW_AT_upper_bound); > if (attr) > { > if (attr->form == DW_FORM_sdata) > --- 2767,2773 ---- > #endif > } > } > ! attr = dwarf_attr (child_die, DW_AT_upper_bound, cu_header); > if (attr) > { > if (attr->form == DW_FORM_sdata) > *************** read_array_type (struct die_info *die, s > *** 2788,2794 **** > custom vendor extension. The main difference between a regular > array and the vector variant is that vectors are passed by value > to functions. */ > ! attr = dwarf_attr (die, DW_AT_GNU_vector); > if (attr) > TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR; > > --- 2830,2836 ---- > custom vendor extension. The main difference between a regular > array and the vector variant is that vectors are passed by value > to functions. */ > ! attr = dwarf_attr (die, DW_AT_GNU_vector, cu_header); > if (attr) > TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR; > > *************** read_common_block (struct die_info *die, > *** 2809,2815 **** > struct symbol *sym; > CORE_ADDR base = (CORE_ADDR) 0; > > ! attr = dwarf_attr (die, DW_AT_location); > if (attr) > { > base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); > --- 2851,2857 ---- > struct symbol *sym; > CORE_ADDR base = (CORE_ADDR) 0; > > ! attr = dwarf_attr (die, DW_AT_location, cu_header); > if (attr) > { > base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); > *************** read_common_block (struct die_info *die, > *** 2820,2826 **** > while (child_die && child_die->tag) > { > sym = new_symbol (child_die, NULL, objfile, cu_header); > ! attr = dwarf_attr (child_die, DW_AT_data_member_location); > if (attr) > { > SYMBOL_VALUE_ADDRESS (sym) = > --- 2862,2868 ---- > while (child_die && child_die->tag) > { > sym = new_symbol (child_die, NULL, objfile, cu_header); > ! attr = dwarf_attr (child_die, DW_AT_data_member_location, cu_header); > if (attr) > { > SYMBOL_VALUE_ADDRESS (sym) = > *************** read_tag_pointer_type (struct die_info * > *** 2848,2854 **** > } > > type = lookup_pointer_type (die_type (die, objfile, cu_header)); > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > --- 2890,2896 ---- > } > > type = lookup_pointer_type (die_type (die, objfile, cu_header)); > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > *************** read_tag_reference_type (struct die_info > *** 2900,2906 **** > } > > type = lookup_reference_type (die_type (die, objfile, cu_header)); > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > --- 2942,2948 ---- > } > > type = lookup_reference_type (die_type (die, objfile, cu_header)); > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > TYPE_LENGTH (type) = DW_UNSND (attr); > *************** read_tag_volatile_type (struct die_info > *** 2948,2954 **** > attribute to reference it. */ > > static void > ! read_tag_string_type (struct die_info *die, struct objfile *objfile) > { > struct type *type, *range_type, *index_type, *char_type; > struct attribute *attr; > --- 2990,2997 ---- > attribute to reference it. */ > > static void > ! read_tag_string_type (struct die_info *die, struct objfile *objfile, > ! const struct comp_unit_head *cu_header) > { > struct type *type, *range_type, *index_type, *char_type; > struct attribute *attr; > *************** read_tag_string_type (struct die_info *d > *** 2959,2965 **** > return; > } > > ! attr = dwarf_attr (die, DW_AT_string_length); > if (attr) > { > length = DW_UNSND (attr); > --- 3002,3008 ---- > return; > } > > ! attr = dwarf_attr (die, DW_AT_string_length, cu_header); > if (attr) > { > length = DW_UNSND (attr); > *************** read_tag_string_type (struct die_info *d > *** 2967,2973 **** > else > { > /* check for the DW_AT_byte_size attribute */ > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > length = DW_UNSND (attr); > --- 3010,3016 ---- > else > { > /* check for the DW_AT_byte_size attribute */ > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > length = DW_UNSND (attr); > *************** read_subroutine_type (struct die_info *d > *** 3021,3027 **** > ftype = lookup_function_type (type); > > /* All functions in C++ have prototypes. */ > ! attr = dwarf_attr (die, DW_AT_prototyped); > if ((attr && (DW_UNSND (attr) != 0)) > || cu_language == language_cplus) > TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED; > --- 3064,3070 ---- > ftype = lookup_function_type (type); > > /* All functions in C++ have prototypes. */ > ! attr = dwarf_attr (die, DW_AT_prototyped, cu_header); > if ((attr && (DW_UNSND (attr) != 0)) > || cu_language == language_cplus) > TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED; > *************** read_subroutine_type (struct die_info *d > *** 3060,3066 **** > parameter for non-static member functions (which is the > this pointer) as artificial. We pass this information > to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */ > ! attr = dwarf_attr (child_die, DW_AT_artificial); > if (attr) > TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); > else > --- 3103,3109 ---- > parameter for non-static member functions (which is the > this pointer) as artificial. We pass this information > to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */ > ! attr = dwarf_attr (child_die, DW_AT_artificial, cu_header); > if (attr) > TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); > else > *************** read_typedef (struct die_info *die, stru > *** 3085,3091 **** > > if (!die->type) > { > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > { > name = DW_STRING (attr); > --- 3128,3134 ---- > > if (!die->type) > { > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > { > name = DW_STRING (attr); > *************** read_typedef (struct die_info *die, stru > *** 3099,3105 **** > it in the TYPE field of the die. */ > > static void > ! read_base_type (struct die_info *die, struct objfile *objfile) > { > struct type *type; > struct attribute *attr; > --- 3142,3149 ---- > it in the TYPE field of the die. */ > > static void > ! read_base_type (struct die_info *die, struct objfile *objfile, > ! const struct comp_unit_head *cu_header) > { > struct type *type; > struct attribute *attr; > *************** read_base_type (struct die_info *die, st > *** 3111,3127 **** > return; > } > > ! attr = dwarf_attr (die, DW_AT_encoding); > if (attr) > { > encoding = DW_UNSND (attr); > } > ! attr = dwarf_attr (die, DW_AT_byte_size); > if (attr) > { > size = DW_UNSND (attr); > } > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > { > enum type_code code = TYPE_CODE_INT; > --- 3155,3171 ---- > return; > } > > ! attr = dwarf_attr (die, DW_AT_encoding, cu_header); > if (attr) > { > encoding = DW_UNSND (attr); > } > ! attr = dwarf_attr (die, DW_AT_byte_size, cu_header); > if (attr) > { > size = DW_UNSND (attr); > } > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > { > enum type_code code = TYPE_CODE_INT; > *************** read_comp_unit (char *info_ptr, bfd *abf > *** 3227,3232 **** > --- 3271,3416 ---- > return first_die; > } > > + /* Register a cu_header, by making a copy of the header and then > + adding it to the cu_header list. */ > + static void > + register_cu_header (const struct comp_unit_head *cu_header) > + { > + struct comp_unit_head *head; > + > + head = xmalloc (sizeof (struct comp_unit_head)); > + memcpy (head, cu_header, sizeof (struct comp_unit_head)); > + > + head->next = first_cu_header; > + first_cu_header = head; > + } > + > + /* Attempt to find matching cu_header from given offset */ > + static struct comp_unit_head * > + find_cu_header_from_begin_offset (char *begin_offset) > + { > + struct comp_unit_head *cu_header; > + > + for (cu_header = first_cu_header; > + cu_header != NULL; > + cu_header = cu_header->next) > + { > + if (begin_offset == cu_header->begin_offset) > + { > + return cu_header; > + } > + } > + > + /* Failed to find cu_header at the given offset. */ > + return NULL; > + } > + > + /* Attempt to find matching cu_header from given offset > + within the cu_header range. */ > + static struct comp_unit_head * > + find_cu_header (unsigned int offset) > + { > + struct comp_unit_head *cu_header; > + > + for (cu_header = first_cu_header; > + cu_header != NULL; > + cu_header = cu_header->next) > + { > + if (offset >= cu_header->offset > + && offset < cu_header->offset + cu_header->length) > + { > + return cu_header; > + } > + } > + > + /* Failed to find in cu_header range the given offset. */ > + return NULL; > + } > + > + static struct die_info * > + find_die_ref (unsigned int target_offset, bfd *abfd, > + const struct comp_unit_head *cu_header) > + { > + struct die_info *die, *target_die; > + char *cur_ptr; > + int nesting_level; > + > + cur_ptr = cu_header->base_offset; > + nesting_level = 0; > + target_die = NULL; > + do > + { > + cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header); > + > + if (die->has_children) > + { > + nesting_level++; > + } > + if (die->tag == 0) > + { > + nesting_level--; > + } > + > + die->next = NULL; > + > + /* Enter die in reference hash table */ > + store_in_ref_table (die->offset, die); > + > + if (die->offset == target_offset) > + { > + /* Found the requested die */ > + target_die = die; > + } > + } > + while (nesting_level > 0); > + > + return target_die; > + } > + > + static struct die_info * > + build_die_ref (struct attribute *attr, struct objfile *objfile, > + const struct comp_unit_head *base_cu_header) > + { > + struct comp_unit_head *cu_header = NULL; > + struct die_info *die_ref = NULL; > + unsigned int offset = 0; > + > + /* Get the offset */ > + offset = dwarf2_get_ref_die_offset (attr, base_cu_header); > + > + /* If not a DW_FORM_ref_addr, use current settings to return > + the offset */ > + if (attr->form != DW_FORM_ref_addr) > + { > + return follow_die_ref (offset); > + } > + > + /* Check whether die has been constructed before */ > + die_ref = follow_die_ref (offset); > + > + if (die_ref != NULL && die_ref->type != NULL) > + { > + return die_ref; > + } > + > + /* Find the appropriate cu_header */ > + cu_header = find_cu_header (offset); > + > + /* Find the correct die */ > + die_ref = find_die_ref (offset, objfile->obfd, cu_header); > + > + /* Make sure that the cu_header has its dwarf abbreviation table */ > + if (cu_header->dwarf2_abbrevs == NULL) > + { > + error ("No DWARF abbreviation table for comp unit header"); > + } > + > + /* Construct the die's type */ > + die_type (die_ref, objfile, cu_header); > + > + return die_ref; > + } > + > /* Free a linked list of dies. */ > > static void > *************** make_cleanup_free_die_list (struct die_i > *** 3256,3261 **** > --- 3440,3464 ---- > return make_cleanup (do_free_die_list_cleanup, dies); > } > > + /* Free linked list of cu_headers */ > + static void > + free_cu_header_list (void) > + { > + struct comp_unit_head *head = first_cu_header; > + struct comp_unit_head *thead; > + > + while (head != NULL) > + { > + thead = head; > + head = head->next; > + > + /* empty the abbrev table */ > + dwarf2_empty_abbrev_table (thead); > + xfree (thead); > + } > + > + first_cu_header = NULL; > + } > > /* Read the contents of the section at OFFSET and of size SIZE from the > object file specified by OBJFILE into the psymbol_obstack and return it. */ > *************** dwarf2_read_section (struct objfile *obj > *** 3287,3306 **** > in a hash table. */ > > static void > ! dwarf2_read_abbrevs (bfd *abfd, unsigned int offset) > { > char *abbrev_ptr; > struct abbrev_info *cur_abbrev; > unsigned int abbrev_number, bytes_read, abbrev_name; > unsigned int abbrev_form, hash_number; > > ! /* empty the table */ > ! dwarf2_empty_abbrev_table (NULL); > ! > ! abbrev_ptr = dwarf_abbrev_buffer + offset; > abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); > abbrev_ptr += bytes_read; > > /* loop until we reach an abbrev number of 0 */ > while (abbrev_number) > { > --- 3490,3510 ---- > in a hash table. */ > > static void > ! dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header) > { > char *abbrev_ptr; > struct abbrev_info *cur_abbrev; > unsigned int abbrev_number, bytes_read, abbrev_name; > unsigned int abbrev_form, hash_number; > > ! abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset; > abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); > abbrev_ptr += bytes_read; > > + /* Initialize dwarf2 abbrevs */ > + memset (cu_header->dwarf2_abbrevs, 0, > + ABBREV_HASH_SIZE*sizeof (struct abbrev_info *)); > + > /* loop until we reach an abbrev number of 0 */ > while (abbrev_number) > { > *************** dwarf2_read_abbrevs (bfd *abfd, unsigned > *** 3336,3343 **** > } > > hash_number = abbrev_number % ABBREV_HASH_SIZE; > ! cur_abbrev->next = dwarf2_abbrevs[hash_number]; > ! dwarf2_abbrevs[hash_number] = cur_abbrev; > > /* Get next abbreviation. > Under Irix6 the abbreviations for a compilation unit are not > --- 3540,3547 ---- > } > > hash_number = abbrev_number % ABBREV_HASH_SIZE; > ! cur_abbrev->next = cu_header->dwarf2_abbrevs[hash_number]; > ! cu_header->dwarf2_abbrevs[hash_number] = cur_abbrev; > > /* Get next abbreviation. > Under Irix6 the abbreviations for a compilation unit are not > *************** dwarf2_read_abbrevs (bfd *abfd, unsigned > *** 3351,3358 **** > break; > abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); > abbrev_ptr += bytes_read; > ! if (dwarf2_lookup_abbrev (abbrev_number) != NULL) > ! break; > } > } > > --- 3555,3565 ---- > break; > abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); > abbrev_ptr += bytes_read; > ! if (dwarf2_lookup_abbrev (abbrev_number, cu_header) != NULL) > ! { > ! /* Could not find abbrev just created */ > ! break; > ! } > } > } > > *************** dwarf2_read_abbrevs (bfd *abfd, unsigned > *** 3360,3366 **** > > /* ARGSUSED */ > static void > ! dwarf2_empty_abbrev_table (PTR ignore) > { > int i; > struct abbrev_info *abbrev, *next; > --- 3567,3573 ---- > > /* ARGSUSED */ > static void > ! dwarf2_empty_abbrev_table (struct comp_unit_head *cu_header) > { > int i; > struct abbrev_info *abbrev, *next; > *************** dwarf2_empty_abbrev_table (PTR ignore) > *** 3368,3374 **** > for (i = 0; i < ABBREV_HASH_SIZE; ++i) > { > next = NULL; > ! abbrev = dwarf2_abbrevs[i]; > while (abbrev) > { > next = abbrev->next; > --- 3575,3581 ---- > for (i = 0; i < ABBREV_HASH_SIZE; ++i) > { > next = NULL; > ! abbrev = cu_header->dwarf2_abbrevs[i]; > while (abbrev) > { > next = abbrev->next; > *************** dwarf2_empty_abbrev_table (PTR ignore) > *** 3376,3395 **** > xfree (abbrev); > abbrev = next; > } > ! dwarf2_abbrevs[i] = NULL; > } > } > > /* Lookup an abbrev_info structure in the abbrev hash table. */ > > static struct abbrev_info * > ! dwarf2_lookup_abbrev (unsigned int number) > { > unsigned int hash_number; > struct abbrev_info *abbrev; > > hash_number = number % ABBREV_HASH_SIZE; > ! abbrev = dwarf2_abbrevs[hash_number]; > > while (abbrev) > { > --- 3583,3603 ---- > xfree (abbrev); > abbrev = next; > } > ! cu_header->dwarf2_abbrevs[i] = NULL; > } > } > > /* Lookup an abbrev_info structure in the abbrev hash table. */ > > static struct abbrev_info * > ! dwarf2_lookup_abbrev (unsigned int number, > ! const struct comp_unit_head *cu_header) > { > unsigned int hash_number; > struct abbrev_info *abbrev; > > hash_number = number % ABBREV_HASH_SIZE; > ! abbrev = cu_header->dwarf2_abbrevs[hash_number]; > > while (abbrev) > { > *************** read_partial_die (struct partial_die_inf > *** 3421,3427 **** > if (!abbrev_number) > return info_ptr; > > ! abbrev = dwarf2_lookup_abbrev (abbrev_number); > if (!abbrev) > { > error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number); > --- 3629,3635 ---- > if (!abbrev_number) > return info_ptr; > > ! abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header); > if (!abbrev) > { > error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number); > *************** read_partial_die (struct partial_die_inf > *** 3484,3490 **** > complain (&dwarf2_absolute_sibling_complaint); > else > part_die->sibling = > ! dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr); > break; > default: > break; > --- 3692,3698 ---- > complain (&dwarf2_absolute_sibling_complaint); > else > part_die->sibling = > ! dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr, cu_header); > break; > default: > break; > *************** read_partial_die (struct partial_die_inf > *** 3500,3506 **** > char *spec_ptr; > int dummy; > > ! spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr); > read_partial_die (&spec_die, abfd, spec_ptr, cu_header); > if (spec_die.name) > { > --- 3708,3715 ---- > char *spec_ptr; > int dummy; > > ! spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr, > ! cu_header); > read_partial_die (&spec_die, abfd, spec_ptr, cu_header); > if (spec_die.name) > { > *************** read_full_die (struct die_info **diep, b > *** 3552,3558 **** > return info_ptr; > } > > ! abbrev = dwarf2_lookup_abbrev (abbrev_number); > if (!abbrev) > { > error ("Dwarf Error: could not find abbrev number %d.", abbrev_number); > --- 3761,3767 ---- > return info_ptr; > } > > ! abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header); > if (!abbrev) > { > error ("Dwarf Error: could not find abbrev number %d.", abbrev_number); > *************** set_cu_language (unsigned int lang) > *** 4031,4037 **** > /* Return the named attribute or NULL if not there. */ > > static struct attribute * > ! dwarf_attr (struct die_info *die, unsigned int name) > { > unsigned int i; > struct attribute *spec = NULL; > --- 4240,4247 ---- > /* Return the named attribute or NULL if not there. */ > > static struct attribute * > ! dwarf_attr (struct die_info *die, unsigned int name, > ! const struct comp_unit_head *cu_header) > { > unsigned int i; > struct attribute *spec = NULL; > *************** dwarf_attr (struct die_info *die, unsign > *** 4049,4071 **** > if (spec) > { > struct die_info *ref_die = > ! follow_die_ref (dwarf2_get_ref_die_offset (spec)); > > if (ref_die) > ! return dwarf_attr (ref_die, name); > } > > return NULL; > } > > static int > ! die_is_declaration (struct die_info *die) > { > ! return (dwarf_attr (die, DW_AT_declaration) > ! && ! dwarf_attr (die, DW_AT_specification)); > } > > - > /* Free the line_header structure *LH, and any arrays and strings it > refers to. */ > static void > --- 4259,4281 ---- > if (spec) > { > struct die_info *ref_die = > ! follow_die_ref (dwarf2_get_ref_die_offset (spec, cu_header)); > > if (ref_die) > ! return dwarf_attr (ref_die, name, cu_header); > } > > return NULL; > } > > static int > ! die_is_declaration (struct die_info *die, > ! const struct comp_unit_head *cu_header) > { > ! return (dwarf_attr (die, DW_AT_declaration, cu_header) > ! && ! dwarf_attr (die, DW_AT_specification, cu_header)); > } > > /* Free the line_header structure *LH, and any arrays and strings it > refers to. */ > static void > *************** new_symbol (struct die_info *die, struct > *** 4524,4530 **** > struct attribute *attr2 = NULL; > CORE_ADDR addr; > > ! name = dwarf2_linkage_name (die); > if (name) > { > sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, > --- 4734,4740 ---- > struct attribute *attr2 = NULL; > CORE_ADDR addr; > > ! name = dwarf2_linkage_name (die, cu_header); > if (name) > { > sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, > *************** new_symbol (struct die_info *die, struct > *** 4542,4548 **** > SYMBOL_TYPE (sym) = type; > else > SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header); > ! attr = dwarf_attr (die, DW_AT_decl_line); > if (attr) > { > SYMBOL_LINE (sym) = DW_UNSND (attr); > --- 4752,4758 ---- > SYMBOL_TYPE (sym) = type; > else > SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header); > ! attr = dwarf_attr (die, DW_AT_decl_line, cu_header); > if (attr) > { > SYMBOL_LINE (sym) = DW_UNSND (attr); > *************** new_symbol (struct die_info *die, struct > *** 4559,4565 **** > switch (die->tag) > { > case DW_TAG_label: > ! attr = dwarf_attr (die, DW_AT_low_pc); > if (attr) > { > SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr; > --- 4769,4775 ---- > switch (die->tag) > { > case DW_TAG_label: > ! attr = dwarf_attr (die, DW_AT_low_pc, cu_header); > if (attr) > { > SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr; > *************** new_symbol (struct die_info *die, struct > *** 4570,4576 **** > /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by > finish_block. */ > SYMBOL_CLASS (sym) = LOC_BLOCK; > ! attr2 = dwarf_attr (die, DW_AT_external); > if (attr2 && (DW_UNSND (attr2) != 0)) > { > add_symbol_to_list (sym, &global_symbols); > --- 4780,4786 ---- > /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by > finish_block. */ > SYMBOL_CLASS (sym) = LOC_BLOCK; > ! attr2 = dwarf_attr (die, DW_AT_external, cu_header); > if (attr2 && (DW_UNSND (attr2) != 0)) > { > add_symbol_to_list (sym, &global_symbols); > *************** new_symbol (struct die_info *die, struct > *** 4589,4609 **** > TARGET_INT_BIT / HOST_CHAR_BIT, 0, > "", > objfile); > ! attr = dwarf_attr (die, DW_AT_const_value); > if (attr) > { > dwarf2_const_value (attr, sym, objfile, cu_header); > ! attr2 = dwarf_attr (die, DW_AT_external); > if (attr2 && (DW_UNSND (attr2) != 0)) > add_symbol_to_list (sym, &global_symbols); > else > add_symbol_to_list (sym, list_in_scope); > break; > } > ! attr = dwarf_attr (die, DW_AT_location); > if (attr) > { > ! attr2 = dwarf_attr (die, DW_AT_external); > if (attr2 && (DW_UNSND (attr2) != 0)) > { > SYMBOL_VALUE_ADDRESS (sym) = > --- 4799,4819 ---- > TARGET_INT_BIT / HOST_CHAR_BIT, 0, > "", > objfile); > ! attr = dwarf_attr (die, DW_AT_const_value, cu_header); > if (attr) > { > dwarf2_const_value (attr, sym, objfile, cu_header); > ! attr2 = dwarf_attr (die, DW_AT_external, cu_header); > if (attr2 && (DW_UNSND (attr2) != 0)) > add_symbol_to_list (sym, &global_symbols); > else > add_symbol_to_list (sym, list_in_scope); > break; > } > ! attr = dwarf_attr (die, DW_AT_location, cu_header); > if (attr) > { > ! attr2 = dwarf_attr (die, DW_AT_external, cu_header); > if (attr2 && (DW_UNSND (attr2) != 0)) > { > SYMBOL_VALUE_ADDRESS (sym) = > *************** new_symbol (struct die_info *die, struct > *** 4670,4678 **** > The address of the variable will then be determined from > the minimal symbol table whenever the variable is > referenced. */ > ! attr2 = dwarf_attr (die, DW_AT_external); > if (attr2 && (DW_UNSND (attr2) != 0) > ! && dwarf_attr (die, DW_AT_type) != NULL) > { > SYMBOL_CLASS (sym) = LOC_UNRESOLVED; > add_symbol_to_list (sym, &global_symbols); > --- 4880,4888 ---- > The address of the variable will then be determined from > the minimal symbol table whenever the variable is > referenced. */ > ! attr2 = dwarf_attr (die, DW_AT_external, cu_header); > if (attr2 && (DW_UNSND (attr2) != 0) > ! && dwarf_attr (die, DW_AT_type, cu_header) != NULL) > { > SYMBOL_CLASS (sym) = LOC_UNRESOLVED; > add_symbol_to_list (sym, &global_symbols); > *************** new_symbol (struct die_info *die, struct > *** 4680,4686 **** > } > break; > case DW_TAG_formal_parameter: > ! attr = dwarf_attr (die, DW_AT_location); > if (attr) > { > SYMBOL_VALUE (sym) = > --- 4890,4896 ---- > } > break; > case DW_TAG_formal_parameter: > ! attr = dwarf_attr (die, DW_AT_location, cu_header); > if (attr) > { > SYMBOL_VALUE (sym) = > *************** new_symbol (struct die_info *die, struct > *** 4710,4716 **** > SYMBOL_CLASS (sym) = LOC_ARG; > } > } > ! attr = dwarf_attr (die, DW_AT_const_value); > if (attr) > { > dwarf2_const_value (attr, sym, objfile, cu_header); > --- 4920,4926 ---- > SYMBOL_CLASS (sym) = LOC_ARG; > } > } > ! attr = dwarf_attr (die, DW_AT_const_value, cu_header); > if (attr) > { > dwarf2_const_value (attr, sym, objfile, cu_header); > *************** new_symbol (struct die_info *die, struct > *** 4755,4761 **** > add_symbol_to_list (sym, list_in_scope); > break; > case DW_TAG_enumerator: > ! attr = dwarf_attr (die, DW_AT_const_value); > if (attr) > { > dwarf2_const_value (attr, sym, objfile, cu_header); > --- 4965,4971 ---- > add_symbol_to_list (sym, list_in_scope); > break; > case DW_TAG_enumerator: > ! attr = dwarf_attr (die, DW_AT_const_value, cu_header); > if (attr) > { > dwarf2_const_value (attr, sym, objfile, cu_header); > *************** die_type (struct die_info *die, struct o > *** 4880,4886 **** > struct die_info *type_die; > unsigned int ref; > > ! type_attr = dwarf_attr (die, DW_AT_type); > if (!type_attr) > { > /* A missing DW_AT_type represents a void type. */ > --- 5090,5096 ---- > struct die_info *type_die; > unsigned int ref; > > ! type_attr = dwarf_attr (die, DW_AT_type, cu_header); > if (!type_attr) > { > /* A missing DW_AT_type represents a void type. */ > *************** die_type (struct die_info *die, struct o > *** 4888,4899 **** > } > else > { > ! ref = dwarf2_get_ref_die_offset (type_attr); > type_die = follow_die_ref (ref); > if (!type_die) > { > ! error ("Dwarf Error: Cannot find referent at offset %d.", ref); > ! return NULL; > } > } > type = tag_type_to_type (type_die, objfile, cu_header); > --- 5098,5115 ---- > } > else > { > ! ref = dwarf2_get_ref_die_offset (type_attr, cu_header); > type_die = follow_die_ref (ref); > if (!type_die) > { > ! /* Attempt to find the die in another comp unit */ > ! type_die = build_die_ref (type_attr, objfile, cu_header); > ! > ! if (!type_die) > ! { > ! error ("Dwarf Error: Cannot find referent at offset %d.", ref); > ! return NULL; > ! } > } > } > type = tag_type_to_type (type_die, objfile, cu_header); > *************** die_containing_type (struct die_info *di > *** 4917,4926 **** > struct die_info *type_die = NULL; > unsigned int ref; > > ! type_attr = dwarf_attr (die, DW_AT_containing_type); > if (type_attr) > { > ! ref = dwarf2_get_ref_die_offset (type_attr); > type_die = follow_die_ref (ref); > if (!type_die) > { > --- 5133,5142 ---- > struct die_info *type_die = NULL; > unsigned int ref; > > ! type_attr = dwarf_attr (die, DW_AT_containing_type, cu_header); > if (type_attr) > { > ! ref = dwarf2_get_ref_die_offset (type_attr, cu_header); > type_die = follow_die_ref (ref); > if (!type_die) > { > *************** read_type_die (struct die_info *die, str > *** 5013,5025 **** > read_tag_volatile_type (die, objfile, cu_header); > break; > case DW_TAG_string_type: > ! read_tag_string_type (die, objfile); > break; > case DW_TAG_typedef: > read_typedef (die, objfile, cu_header); > break; > case DW_TAG_base_type: > ! read_base_type (die, objfile); > break; > default: > complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag)); > --- 5229,5241 ---- > read_tag_volatile_type (die, objfile, cu_header); > break; > case DW_TAG_string_type: > ! read_tag_string_type (die, objfile, cu_header); > break; > case DW_TAG_typedef: > read_typedef (die, objfile, cu_header); > break; > case DW_TAG_base_type: > ! read_base_type (die, objfile, cu_header); > break; > default: > complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag)); > *************** sibling_die (struct die_info *die) > *** 5183,5196 **** > /* Get linkage name of a die, return NULL if not found. */ > > static char * > ! dwarf2_linkage_name (struct die_info *die) > { > struct attribute *attr; > > ! attr = dwarf_attr (die, DW_AT_MIPS_linkage_name); > if (attr && DW_STRING (attr)) > return DW_STRING (attr); > ! attr = dwarf_attr (die, DW_AT_name); > if (attr && DW_STRING (attr)) > return DW_STRING (attr); > return NULL; > --- 5399,5413 ---- > /* Get linkage name of a die, return NULL if not found. */ > > static char * > ! dwarf2_linkage_name (struct die_info *die, > ! const struct comp_unit_head *cu_header) > { > struct attribute *attr; > > ! attr = dwarf_attr (die, DW_AT_MIPS_linkage_name, cu_header); > if (attr && DW_STRING (attr)) > return DW_STRING (attr); > ! attr = dwarf_attr (die, DW_AT_name, cu_header); > if (attr && DW_STRING (attr)) > return DW_STRING (attr); > return NULL; > *************** dwarf2_empty_hash_tables (void) > *** 6043,6049 **** > } > > static unsigned int > ! dwarf2_get_ref_die_offset (struct attribute *attr) > { > unsigned int result = 0; > > --- 6260,6267 ---- > } > > static unsigned int > ! dwarf2_get_ref_die_offset (struct attribute *attr, > ! const struct comp_unit_head *cu_header) > { > unsigned int result = 0; > > *************** dwarf2_get_ref_die_offset (struct attrib > *** 6057,6063 **** > case DW_FORM_ref4: > case DW_FORM_ref8: > case DW_FORM_ref_udata: > ! result = cu_header_offset + DW_UNSND (attr); > break; > default: > complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form)); > --- 6275,6281 ---- > case DW_FORM_ref4: > case DW_FORM_ref8: > case DW_FORM_ref_udata: > ! result = cu_header->offset + DW_UNSND (attr); > break; > default: > complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form)); > Index: elfread.c > =================================================================== > RCS file: /cvs/src/src/gdb/elfread.c,v > retrieving revision 1.22 > diff -c -p -r1.22 elfread.c > *** elfread.c 22 Jun 2002 00:05:59 -0000 1.22 > --- elfread.c 3 Jul 2002 20:35:38 -0000 > *************** > *** 36,41 **** > --- 36,42 ---- > #include "demangle.h" > > extern void _initialize_elfread (void); > + extern void dwarf_new_init (void); > > /* The struct elfinfo is available only during ELF symbol table and > psymtab reading. It is destroyed at the completion of psymtab-reading. > *************** elf_new_init (struct objfile *ignore) > *** 664,669 **** > --- 665,671 ---- > { > stabsread_new_init (); > buildsym_new_init (); > + dwarf_new_init (); > } > > /* Perform any local cleanups required when we are done with a particular