2006-03-05 H.J. Lu <hongjiu.lu@intel.com>

Alan Modra  <amodra@bigpond.net.au>

	PR binutils/2338
	* dwarf2.c (loadable_section): New struct.
	(dwarf2_debug): Add loadable_section_count and
	loadable_sections.
	(new_line_sorts_after): New.
	(add_line_info): Use new_line_sorts_after to compare line
	addresses.
	(check_function_name): Removed.
	(unset_sections): New.
	(place_sections): New.
	(_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
	and unset_sections on relocatable files.
	(_bfd_dwarf2_find_line): Likewise.
This commit is contained in:
H.J. Lu
2006-03-06 01:36:52 +00:00
parent 7e1dd15ac7
commit d4c32a815a
2 changed files with 211 additions and 69 deletions

View File

@ -1,3 +1,20 @@
2006-03-05 H.J. Lu <hongjiu.lu@intel.com>
Alan Modra <amodra@bigpond.net.au>
PR binutils/2338
* dwarf2.c (loadable_section): New struct.
(dwarf2_debug): Add loadable_section_count and
loadable_sections.
(new_line_sorts_after): New.
(add_line_info): Use new_line_sorts_after to compare line
addresses.
(check_function_name): Removed.
(unset_sections): New.
(place_sections): New.
(_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
and unset_sections on relocatable files.
(_bfd_dwarf2_find_line): Likewise.
2006-03-03 Nick Clifton <nickc@redhat.com> 2006-03-03 Nick Clifton <nickc@redhat.com>
* cpu-avr.c: Update to ISO-C90 formatting. * cpu-avr.c: Update to ISO-C90 formatting.

View File

@ -74,6 +74,12 @@ struct dwarf_block
bfd_byte *data; bfd_byte *data;
}; };
struct loadable_section
{
asection *section;
bfd_vma adj_vma;
};
struct dwarf2_debug struct dwarf2_debug
{ {
/* A list of all previously read comp_units. */ /* A list of all previously read comp_units. */
@ -124,6 +130,12 @@ struct dwarf2_debug
calling chain for subsequent calls to bfd_find_inliner_info to calling chain for subsequent calls to bfd_find_inliner_info to
use. */ use. */
struct funcinfo *inliner_chain; struct funcinfo *inliner_chain;
/* Number of loadable sections. */
unsigned int loadable_section_count;
/* Array of loadable sections. */
struct loadable_section *loadable_sections;
}; };
struct arange struct arange
@ -744,6 +756,17 @@ struct varinfo
unsigned int stack: 1; unsigned int stack: 1;
}; };
/* Return TRUE if NEW_LINE should sort after LINE. */
static inline bfd_boolean
new_line_sorts_after (struct line_info *new_line, struct line_info *line)
{
return (new_line->address > line->address
|| (new_line->address == line->address
&& new_line->end_sequence < line->end_sequence));
}
/* Adds a new entry to the line_info list in the line_info_table, ensuring /* Adds a new entry to the line_info list in the line_info_table, ensuring
that the list is sorted. Note that the line_info list is sorted from that the list is sorted. Note that the line_info list is sorted from
highest to lowest VMA (with possible duplicates); that is, highest to lowest VMA (with possible duplicates); that is,
@ -760,6 +783,21 @@ add_line_info (struct line_info_table *table,
bfd_size_type amt = sizeof (struct line_info); bfd_size_type amt = sizeof (struct line_info);
struct line_info* info = bfd_alloc (table->abfd, amt); struct line_info* info = bfd_alloc (table->abfd, amt);
/* Set member data of 'info'. */
info->address = address;
info->line = line;
info->column = column;
info->end_sequence = end_sequence;
if (filename && filename[0])
{
info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
if (info->filename)
strcpy (info->filename, filename);
}
else
info->filename = NULL;
/* Find the correct location for 'info'. Normally we will receive /* Find the correct location for 'info'. Normally we will receive
new line_info data 1) in order and 2) with increasing VMAs. new line_info data 1) in order and 2) with increasing VMAs.
However some compilers break the rules (cf. decode_line_info) and However some compilers break the rules (cf. decode_line_info) and
@ -777,7 +815,7 @@ add_line_info (struct line_info_table *table,
while (1) while (1)
if (!table->last_line if (!table->last_line
|| address >= table->last_line->address) || new_line_sorts_after (info, table->last_line))
{ {
/* Normal case: add 'info' to the beginning of the list */ /* Normal case: add 'info' to the beginning of the list */
info->prev_line = table->last_line; info->prev_line = table->last_line;
@ -789,7 +827,7 @@ add_line_info (struct line_info_table *table,
break; break;
} }
else if (!table->lcl_head->prev_line else if (!table->lcl_head->prev_line
&& table->lcl_head->address > address) && !new_line_sorts_after (info, table->lcl_head))
{ {
/* Abnormal but easy: lcl_head is 1) at the *end* of the line /* Abnormal but easy: lcl_head is 1) at the *end* of the line
list and 2) the head of 'info'. */ list and 2) the head of 'info'. */
@ -798,8 +836,8 @@ add_line_info (struct line_info_table *table,
break; break;
} }
else if (table->lcl_head->prev_line else if (table->lcl_head->prev_line
&& table->lcl_head->address > address && !new_line_sorts_after (info, table->lcl_head)
&& address >= table->lcl_head->prev_line->address) && new_line_sorts_after (info, table->lcl_head->prev_line))
{ {
/* Abnormal but easy: lcl_head is 1) in the *middle* of the line /* Abnormal but easy: lcl_head is 1) in the *middle* of the line
list and 2) the head of 'info'. */ list and 2) the head of 'info'. */
@ -816,7 +854,8 @@ add_line_info (struct line_info_table *table,
while (li1) while (li1)
{ {
if (li2->address > address && address >= li1->address) if (!new_line_sorts_after (info, li2)
&& new_line_sorts_after (info, li1))
break; break;
li2 = li1; /* always non-NULL */ li2 = li1; /* always non-NULL */
@ -824,21 +863,6 @@ add_line_info (struct line_info_table *table,
} }
table->lcl_head = li2; table->lcl_head = li2;
} }
/* Set member data of 'info'. */
info->address = address;
info->line = line;
info->column = column;
info->end_sequence = end_sequence;
if (filename && filename[0])
{
info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
if (info->filename)
strcpy (info->filename, filename);
}
else
info->filename = NULL;
} }
/* Extract a fully qualified filename from a line info table. /* Extract a fully qualified filename from a line info table.
@ -2179,28 +2203,91 @@ find_debug_info (bfd *abfd, asection *after_sec)
return NULL; return NULL;
} }
/* Return TRUE if there is no mismatch bewteen function FUNC and /* Unset vmas for loadable sections in STASH. */
section SECTION from symbol table SYMBOLS in ABFD. */
static void
unset_sections (struct dwarf2_debug *stash)
{
unsigned int i;
struct loadable_section *p;
i = stash->loadable_section_count;
p = stash->loadable_sections;
for (; i > 0; i--, p++)
p->section->vma = 0;
}
/* Set unique vmas for loadable sections in ABFD and save vmas in
STASH for unset_sections. */
static bfd_boolean static bfd_boolean
check_function_name (bfd *abfd, asection *section, asymbol **symbols, place_sections (bfd *abfd, struct dwarf2_debug *stash)
const char *func)
{ {
/* Mismatch can only happen when we have 2 functions with the same struct loadable_section *p;
address. It can only occur in a relocatable file. */ unsigned int i;
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
&& func != NULL
&& section != NULL
&& symbols != NULL)
{
asymbol **p;
for (p = symbols; *p != NULL; p++) if (stash->loadable_section_count != 0)
{ {
if (((*p)->flags & BSF_FUNCTION) != 0 i = stash->loadable_section_count;
&& (*p)->name != NULL p = stash->loadable_sections;
&& strcmp ((*p)->name, func) == 0) for (; i > 0; i--, p++)
return (*p)->section == section; p->section->vma = p->adj_vma;
}
else
{
asection *sect;
bfd_vma last_vma = 0;
bfd_size_type amt;
struct loadable_section *p;
i = 0;
for (sect = abfd->sections; sect != NULL; sect = sect->next)
{
bfd_size_type sz;
if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
continue;
sz = sect->rawsize ? sect->rawsize : sect->size;
if (sz == 0)
continue;
i++;
}
amt = i * sizeof (struct loadable_section);
p = (struct loadable_section *) bfd_zalloc (abfd, amt);
if (! p)
return FALSE;
stash->loadable_sections = p;
stash->loadable_section_count = i;
for (sect = abfd->sections; sect != NULL; sect = sect->next)
{
bfd_size_type sz;
if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
continue;
sz = sect->rawsize ? sect->rawsize : sect->size;
if (sz == 0)
continue;
p->section = sect;
if (last_vma != 0)
{
/* Align the new address to the current section
alignment. */
last_vma = ((last_vma
+ ~((bfd_vma) -1 << sect->alignment_power))
& ((bfd_vma) -1 << sect->alignment_power));
sect->vma = last_vma;
}
p->adj_vma = sect->vma;
last_vma += sect->vma + sz;
p++;
} }
} }
@ -2239,7 +2326,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
struct comp_unit* each; struct comp_unit* each;
bfd_vma found = FALSE;
stash = *pinfo; stash = *pinfo;
if (! stash)
{
bfd_size_type amt = sizeof (struct dwarf2_debug);
stash = bfd_zalloc (abfd, amt);
if (! stash)
return FALSE;
}
/* In a relocatable file, 2 functions may have the same address.
We change the section vma so that they won't overlap. */
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
{
if (! place_sections (abfd, stash))
return FALSE;
}
addr = offset; addr = offset;
if (section->output_section) if (section->output_section)
addr += section->output_section->vma + section->output_offset; addr += section->output_section->vma + section->output_offset;
@ -2256,15 +2363,10 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
addr_size = 4; addr_size = 4;
BFD_ASSERT (addr_size == 4 || addr_size == 8); BFD_ASSERT (addr_size == 4 || addr_size == 8);
if (! stash) if (! *pinfo)
{ {
bfd_size_type total_size; bfd_size_type total_size;
asection *msec; asection *msec;
bfd_size_type amt = sizeof (struct dwarf2_debug);
stash = bfd_zalloc (abfd, amt);
if (! stash)
return FALSE;
*pinfo = stash; *pinfo = stash;
@ -2273,7 +2375,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
/* No dwarf2 info. Note that at this point the stash /* No dwarf2 info. Note that at this point the stash
has been allocated, but contains zeros, this lets has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */ future calls to this function fail quicker. */
return FALSE; goto done;
/* There can be more than one DWARF2 info section in a BFD these days. /* There can be more than one DWARF2 info section in a BFD these days.
Read them all in and produce one large stash. We do this in two Read them all in and produce one large stash. We do this in two
@ -2285,7 +2387,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
stash->info_ptr = bfd_alloc (abfd, total_size); stash->info_ptr = bfd_alloc (abfd, total_size);
if (stash->info_ptr == NULL) if (stash->info_ptr == NULL)
return FALSE; goto done;
stash->info_ptr_end = stash->info_ptr; stash->info_ptr_end = stash->info_ptr;
@ -2319,7 +2421,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
/* A null info_ptr indicates that there is no dwarf2 info /* A null info_ptr indicates that there is no dwarf2 info
(or that an error occured while setting up the stash). */ (or that an error occured while setting up the stash). */
if (! stash->info_ptr) if (! stash->info_ptr)
return FALSE; goto done;
stash->inliner_chain = NULL; stash->inliner_chain = NULL;
@ -2328,10 +2430,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
if (comp_unit_contains_address (each, addr) if (comp_unit_contains_address (each, addr)
&& comp_unit_find_nearest_line (each, addr, filename_ptr, && comp_unit_find_nearest_line (each, addr, filename_ptr,
functionname_ptr, functionname_ptr,
linenumber_ptr, stash) linenumber_ptr, stash))
&& check_function_name (abfd, section, symbols, {
*functionname_ptr)) found = TRUE;
return TRUE; goto done;
}
/* Read each remaining comp. units checking each as they are read. */ /* Read each remaining comp. units checking each as they are read. */
while (stash->info_ptr < stash->info_ptr_end) while (stash->info_ptr < stash->info_ptr_end)
@ -2398,15 +2501,20 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
filename_ptr, filename_ptr,
functionname_ptr, functionname_ptr,
linenumber_ptr, linenumber_ptr,
stash) stash))
&& check_function_name (abfd, section, symbols, {
*functionname_ptr)) found = TRUE;
return TRUE; goto done;
}
} }
} }
} }
return FALSE; done:
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
unset_sections (stash);
return found;
} }
/* The DWARF2 version of find_line. Return TRUE if the line is found /* The DWARF2 version of find_line. Return TRUE if the line is found
@ -2438,10 +2546,29 @@ _bfd_dwarf2_find_line (bfd *abfd,
asection *section; asection *section;
bfd_boolean found; bfd_boolean found = FALSE;
section = bfd_get_section (symbol); section = bfd_get_section (symbol);
stash = *pinfo;
if (! stash)
{
bfd_size_type amt = sizeof (struct dwarf2_debug);
stash = bfd_zalloc (abfd, amt);
if (! stash)
return FALSE;
}
/* In a relocatable file, 2 functions may have the same address.
We change the section vma so that they won't overlap. */
if (!stash && (abfd->flags & (EXEC_P | DYNAMIC)) == 0)
{
if (! place_sections (abfd, stash))
return FALSE;
}
addr = symbol->value; addr = symbol->value;
if (section->output_section) if (section->output_section)
addr += section->output_section->vma + section->output_offset; addr += section->output_section->vma + section->output_offset;
@ -2449,19 +2576,13 @@ _bfd_dwarf2_find_line (bfd *abfd,
addr += section->vma; addr += section->vma;
*filename_ptr = NULL; *filename_ptr = NULL;
stash = *pinfo;
*filename_ptr = NULL; *filename_ptr = NULL;
*linenumber_ptr = 0; *linenumber_ptr = 0;
if (! stash) if (! *pinfo)
{ {
bfd_size_type total_size; bfd_size_type total_size;
asection *msec; asection *msec;
bfd_size_type amt = sizeof (struct dwarf2_debug);
stash = bfd_zalloc (abfd, amt);
if (! stash)
return FALSE;
*pinfo = stash; *pinfo = stash;
@ -2470,7 +2591,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
/* No dwarf2 info. Note that at this point the stash /* No dwarf2 info. Note that at this point the stash
has been allocated, but contains zeros, this lets has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */ future calls to this function fail quicker. */
return FALSE; goto done;
/* There can be more than one DWARF2 info section in a BFD these days. /* There can be more than one DWARF2 info section in a BFD these days.
Read them all in and produce one large stash. We do this in two Read them all in and produce one large stash. We do this in two
@ -2482,7 +2603,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
stash->info_ptr = bfd_alloc (abfd, total_size); stash->info_ptr = bfd_alloc (abfd, total_size);
if (stash->info_ptr == NULL) if (stash->info_ptr == NULL)
return FALSE; goto done;
stash->info_ptr_end = stash->info_ptr; stash->info_ptr_end = stash->info_ptr;
@ -2516,7 +2637,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
/* A null info_ptr indicates that there is no dwarf2 info /* A null info_ptr indicates that there is no dwarf2 info
(or that an error occured while setting up the stash). */ (or that an error occured while setting up the stash). */
if (! stash->info_ptr) if (! stash->info_ptr)
return FALSE; goto done;
stash->inliner_chain = NULL; stash->inliner_chain = NULL;
@ -2528,7 +2649,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
found = comp_unit_find_line (each, symbol, addr, filename_ptr, found = comp_unit_find_line (each, symbol, addr, filename_ptr,
linenumber_ptr, stash); linenumber_ptr, stash);
if (found) if (found)
return found; goto done;
} }
/* The DWARF2 spec says that the initial length field, and the /* The DWARF2 spec says that the initial length field, and the
@ -2605,12 +2726,16 @@ _bfd_dwarf2_find_line (bfd *abfd,
linenumber_ptr, linenumber_ptr,
stash)); stash));
if (found) if (found)
return TRUE; goto done;
} }
} }
} }
return FALSE; done:
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
unset_sections (stash);
return found;
} }
bfd_boolean bfd_boolean