2006-09-29 H.J. Lu PR ld/3191 * dwarf2.c (find_abstract_instance_name): Pass a pointer to attribute instead of offset. For DW_FORM_ref_addr, get the entry at the offset from the .debug_info section. (scan_unit_for_symbols): Updated. (_bfd_dwarf2_find_nearest_line): Adjust debug_info section vma when needed. --- bfd/dwarf2.c.ref_addr 2006-09-21 13:55:25.000000000 -0700 +++ bfd/dwarf2.c 2006-09-29 10:07:14.000000000 -0700 @@ -1556,16 +1556,30 @@ lookup_symbol_in_variable_table (struct } static char * -find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref) +find_abstract_instance_name (struct comp_unit *unit, + struct attribute *attr_ptr) { bfd *abfd = unit->abfd; bfd_byte *info_ptr; unsigned int abbrev_number, bytes_read, i; struct abbrev_info *abbrev; + bfd_uint64_t die_ref = attr_ptr->u.val; struct attribute attr; char *name = 0; - info_ptr = unit->info_ptr_unit + die_ref; + /* DW_FORM_ref_addr can reference an entry in a different CU. It + is an offset from the .debug_info section, not the current CU. */ + if (attr_ptr->form == DW_FORM_ref_addr) + { + /* FIXME: How to handle DW_FORM_ref_addr references an entry in + a different file? */ + if (!die_ref) + abort (); + + info_ptr = unit->stash->sec_info_ptr + die_ref; + } + else + info_ptr = unit->info_ptr_unit + die_ref; abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; @@ -1591,7 +1605,7 @@ find_abstract_instance_name (struct comp name = attr.u.str; break; case DW_AT_specification: - name = find_abstract_instance_name (unit, attr.u.val); + name = find_abstract_instance_name (unit, &attr); break; case DW_AT_MIPS_linkage_name: name = attr.u.str; @@ -1751,7 +1765,7 @@ scan_unit_for_symbols (struct comp_unit break; case DW_AT_abstract_origin: - func->name = find_abstract_instance_name (unit, attr.u.val); + func->name = find_abstract_instance_name (unit, &attr); break; case DW_AT_name: @@ -2375,6 +2389,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd { bfd_size_type total_size; asection *msec; + bfd_vma last_vma; + bfd_size_type size; + asection *first_msec; + asection **msecs = NULL; + unsigned int i, count; *pinfo = stash; @@ -2389,9 +2408,28 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd Read them all in and produce one large stash. We do this in two passes - in the first pass we just accumulate the section sizes. In the second pass we read in the section's contents. The allows - us to avoid reallocing the data as we add sections to the stash. */ + us to avoid reallocing the data as we add sections to the stash. + + We may need to adjust debug_info section vmas since we will + concatenate them together. Otherwise relocations may be + incorrect. */ + first_msec = msec; + last_vma = 0; + count = 0; for (total_size = 0; msec; msec = find_debug_info (abfd, msec)) - total_size += msec->size; + { + size = msec->size; + if (size == 0) + continue; + + total_size += size; + + BFD_ASSERT (msec->vma == 0 && msec->alignment_power == 0); + + msec->vma = last_vma; + last_vma += size; + count++; + } stash->info_ptr = bfd_alloc (abfd, total_size); if (stash->info_ptr == NULL) @@ -2399,17 +2437,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd stash->info_ptr_end = stash->info_ptr; - for (msec = find_debug_info (abfd, NULL); + if (count > 1) + { + count--; + msecs = (asection **) bfd_malloc2 (count, sizeof (*msecs)); + } + + for (i = 0, msec = first_msec; msec; msec = find_debug_info (abfd, msec)) { - bfd_size_type size; bfd_size_type start; size = msec->size; if (size == 0) continue; + if (i && msecs) + msecs [i - 1] = msec; + + i++; + start = stash->info_ptr_end - stash->info_ptr; if ((bfd_simple_get_relocated_section_contents @@ -2419,9 +2467,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd stash->info_ptr_end = stash->info_ptr + start + size; } + /* Restore section vma. */ + if (count) + { + if (msecs) + { + for (i = 0; i < count; i++) + msecs [i]->vma = 0; + free (msecs); + } + else + { + for (msec = find_debug_info (abfd, first_msec); + msec; + msec = find_debug_info (abfd, msec)) + msec->vma = 0; + } + } + BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size); - stash->sec = find_debug_info (abfd, NULL); + stash->sec = first_msec; stash->sec_info_ptr = stash->info_ptr; stash->syms = symbols; }