2003-02-01 Michal Ludvig * dwarf2read.c (struct loclist_block) (struct loclist_master): New structures. (loclist_base, dwarf_loc_buffer): New variables. (struct dwarf2_pinfo): New items dwarf_loc_buffer and dwarf_loc_size. (DWARF_LOC_BUFFER, DWARF_LOC_SIZE): New macros. (dwarf2_read_loclist, dwarf2_read_loclist_blocks) (dwarf_alloc_loclist_block, dwarf_alloc_loclist_master) (dwarf2_loclist_lookup_block): New functions. (psymtab_to_symtab_1): Call dwarf2_read_loclist(). (new_symbol): Handle .debug_loc references. Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.66.2.2 diff -u -p -r1.66.2.2 dwarf2read.c --- dwarf2read.c 25 Nov 2002 21:46:54 -0000 1.66.2.2 +++ dwarf2read.c 31 Jan 2003 18:10:53 -0000 @@ -312,6 +312,22 @@ struct dwarf_block char *data; }; +struct loclist_block + { + CORE_ADDR lowpc, highpc; /* Range where attribute is valid. */ + struct dwarf_block blk; + struct loclist_block *next; + }; + +struct loclist_master + { + unsigned int offset; /* Offset of this block in .debug_loc. */ + struct loclist_block *blocks; + struct loclist_master *next; + }; + +static struct loclist_master *loclist_base; + /* We only hold one compilation unit's abbrevs in memory at any one time. */ #ifndef ABBREV_HASH_SIZE @@ -352,6 +368,7 @@ static char *dwarf_abbrev_buffer; static char *dwarf_line_buffer; static char *dwarf_str_buffer; static char *dwarf_macinfo_buffer; +static char *dwarf_loc_buffer; /* A zeroed version of a partial die for initialization purposes. */ static struct partial_die_info zeroed_partial_die; @@ -454,6 +471,13 @@ struct dwarf2_pinfo unsigned int dwarf_macinfo_size; + /* Pointer to start of dwarf location list buffer for the objfile. */ + + char *dwarf_loc_buffer; + + /* Size of dwarf location list section for the objfile. */ + + unsigned int dwarf_loc_size; }; #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) @@ -467,6 +491,8 @@ struct dwarf2_pinfo #define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size) #define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer) #define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size) +#define DWARF_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer) +#define DWARF_LOC_SIZE(p) (PST_PRIVATE(p)->dwarf_loc_size) /* Maintain an array of referenced fundamental types for the current compilation unit being read. For DWARF version 1, we have to construct @@ -688,6 +714,8 @@ char *dwarf2_read_section (struct objfil static void dwarf2_read_abbrevs (bfd *, unsigned int); +static void dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header); + static void dwarf2_empty_abbrev_table (PTR); static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int); @@ -874,12 +902,6 @@ static char *dwarf_bool_name (unsigned i 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 *); @@ -906,6 +928,9 @@ static struct abbrev_info *dwarf_alloc_a static struct die_info *dwarf_alloc_die (void); +static struct loclist_block *dwarf_alloc_loclist_block (void); +static struct loclist_master *dwarf_alloc_loclist_master (void); + static void initialize_cu_func_list (void); static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR); @@ -927,6 +952,7 @@ dwarf2_has_info (bfd *abfd) dwarf_line_offset = 0; dwarf_str_offset = 0; dwarf_macinfo_offset = 0; + dwarf_loc_offset = 0; dwarf_frame_offset = 0; dwarf_eh_frame_offset = 0; bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); @@ -1035,6 +1061,13 @@ dwarf2_build_psymtabs (struct objfile *o else dwarf_macinfo_buffer = NULL; + if (dwarf_loc_offset) + dwarf_loc_buffer = dwarf2_read_section (objfile, + dwarf_loc_offset, + dwarf_loc_size); + else + dwarf_loc_buffer = NULL; + if (mainline || (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)) @@ -1245,6 +1280,8 @@ dwarf2_build_psymtabs_hard (struct objfi DWARF_STR_SIZE (pst) = dwarf_str_size; DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer; DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size; + DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer; + DWARF_LOC_SIZE (pst) = dwarf_loc_size; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); /* Store the function that reads in the rest of the symbol table */ @@ -1581,6 +1618,8 @@ psymtab_to_symtab_1 (struct partial_symt dwarf_str_size = DWARF_STR_SIZE (pst); dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst); dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst); + dwarf_loc_buffer = DWARF_LOC_BUFFER (pst); + dwarf_loc_size = DWARF_LOC_SIZE (pst); baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; @@ -1598,6 +1637,7 @@ psymtab_to_symtab_1 (struct partial_symt dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset); make_cleanup (dwarf2_empty_abbrev_table, NULL); + dwarf2_read_loclist (abfd, &cu_header); dies = read_comp_unit (info_ptr, abfd, &cu_header); make_cleanup_free_die_list (dies); @@ -3408,6 +3448,115 @@ dwarf2_read_section (struct objfile *obj return buf; } +static struct loclist_block * +dwarf2_loclist_lookup_block (unsigned int offset) +{ + /* .debug_loc goes here ... mludvig */ + struct dwarf_block *blkp; + struct loclist_master *ll_ptr; + + ll_ptr = loclist_base; + + while (ll_ptr && ll_ptr->offset != offset) + ll_ptr = ll_ptr->next; + + if(!ll_ptr) + { + warning ("Couldn't find appropriate location list for offset %u\n", + offset); + return NULL; + } + + if (ll_ptr && !ll_ptr->blocks) + { + warning ("Loclist for off=%u doesn't have any blocks?\n", offset); + return NULL; + } + + return ll_ptr->blocks; +} + +static struct loclist_block * +dwarf2_read_loclist_blocks (bfd *abfd, char **base, char *end, + unsigned int addr_size) +{ + char *ptr; + CORE_ADDR lopc, hipc; + unsigned int data_size; + char *data_ptr; + struct loclist_block *llb_first = NULL, *llb_last = NULL; + + ptr = *base; + + while (ptr < end) { + if (addr_size == 4) { + lopc = read_4_bytes (abfd, ptr); + ptr += 4; + hipc = read_4_bytes (abfd, ptr); + ptr += 4; + } + else if (addr_size == 8) { + lopc = read_8_bytes (abfd, ptr); + ptr += 8; + hipc = read_8_bytes (abfd, ptr); + ptr += 8; + } + else + error ("Address size == %d ... unsupported!", addr_size); + + if (lopc == 0 && hipc == 0) + break; + + if (lopc == 0 && llb_last != NULL) + { + ptr -= 8; + break; + } + + if (llb_last == NULL) { + llb_last = dwarf_alloc_loclist_block (); + llb_first = llb_last; + } + else { + llb_last->next = dwarf_alloc_loclist_block (); + llb_last = llb_last->next; + } + + llb_last->lowpc = lopc; + llb_last->highpc = hipc; + + llb_last->blk.size = read_2_bytes (abfd, ptr); + ptr += 2; + llb_last->blk.data = ptr; + ptr += llb_last->blk.size; + } + + *base = ptr; + return llb_first; +} + +static void +dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header) +{ + char *loclist_ptr, *loclist_end; + struct loclist_master *ll_master; + + loclist_ptr = dwarf_loc_buffer; + loclist_end = dwarf_loc_buffer + dwarf_loc_size; + + while (loclist_ptr < loclist_end) + { + ll_master = dwarf_alloc_loclist_master(); + ll_master->next = loclist_base; + loclist_base = ll_master; + + ll_master->offset = loclist_ptr - dwarf_loc_buffer; + ll_master->blocks = dwarf2_read_loclist_blocks + (abfd, &loclist_ptr, loclist_end, + cu_header->addr_size); + } +} + /* In DWARF version 2, the description of the debugging information is stored in a separate .debug_abbrev section. Before we read any dies from a section we read in all abbreviations and install them @@ -4785,7 +4942,16 @@ new_symbol (struct die_info *die, struct else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) { - complain (&dwarf2_complex_location_expr); + struct dwarf_block *blkp = NULL; + struct loclist_block *llbp; + + llbp = dwarf2_loclist_lookup_block ( + (unsigned int)DW_ADDR (attr)); + if (llbp) + blkp = &llbp->blk; + if (blkp) + SYMBOL_VALUE_ADDRESS (sym) = + decode_locdesc (blkp, objfile, cu_header); } else { @@ -4823,7 +4989,16 @@ new_symbol (struct die_info *die, struct else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) { - complain (&dwarf2_complex_location_expr); + struct dwarf_block *blkp = NULL; + struct loclist_block *llbp; + + llbp = dwarf2_loclist_lookup_block ( + (unsigned int)DW_ADDR (attr)); + if (llbp) + blkp = &llbp->blk; + if (blkp) + SYMBOL_VALUE_ADDRESS (sym) = addr = + decode_locdesc (blkp, objfile, cu_header); } else { @@ -4882,8 +5057,31 @@ new_symbol (struct die_info *die, struct attr = dwarf_attr (die, DW_AT_location); if (attr) { - SYMBOL_VALUE (sym) = - decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + if (attr_form_is_block (attr)) + { + SYMBOL_VALUE (sym) = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + struct dwarf_block *blkp = NULL; + struct loclist_block *llbp; + + llbp = dwarf2_loclist_lookup_block ( + (unsigned int)DW_ADDR (attr)); + if (llbp) + blkp = &llbp->blk; + if (blkp) + SYMBOL_VALUE_ADDRESS (sym) = + decode_locdesc (blkp, objfile, cu_header); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "external variable"); + addr = 0; + } if (isreg) { SYMBOL_CLASS (sym) = LOC_REGPARM; @@ -6660,6 +6863,26 @@ dwarf_alloc_die (void) die = (struct die_info *) xmalloc (sizeof (struct die_info)); memset (die, 0, sizeof (struct die_info)); return (die); +} + +static struct loclist_block * +dwarf_alloc_loclist_block (void) +{ + struct loclist_block *llb; + + llb = (struct loclist_block *) xmalloc (sizeof (struct loclist_block)); + memset (llb, 0, sizeof (struct loclist_block)); + return (llb); +} + +static struct loclist_master * +dwarf_alloc_loclist_master (void) +{ + struct loclist_master *llm; + + llm = (struct loclist_master *) xmalloc (sizeof (struct loclist_master)); + memset (llm, 0, sizeof (struct loclist_master)); + return (llm); }