* coffcode.h (coff_sort_func_alent): New function.

(coff_slurp_line_table): Sort line table if not already sorted.
This commit is contained in:
Nick Clifton 2007-08-01 16:55:54 +00:00
parent 0fdaa00544
commit e708816d5a
2 changed files with 126 additions and 46 deletions

View File

@ -1,3 +1,8 @@
2007-08-01 Tristan Gingold <gingold@adacore.com>
* coffcode.h (coff_sort_func_alent): New function.
(coff_slurp_line_table): Sort line table if not already sorted.
2007-08-01 Jakub Jelinek <jakub@redhat.com>
* elf.c (_bfd_elf_map_sections_to_segments): Work around buggy

View File

@ -4253,12 +4253,34 @@ SUBSUBSECTION
How does this work ?
*/
static int
coff_sort_func_alent (const void * arg1, const void * arg2)
{
const alent *al1 = *(const alent **) arg1;
const alent *al2 = *(const alent **) arg2;
const coff_symbol_type *s1 = (const coff_symbol_type *) (al1->u.sym);
const coff_symbol_type *s2 = (const coff_symbol_type *) (al2->u.sym);
if (s1->symbol.value < s2->symbol.value)
return -1;
else if (s1->symbol.value > s2->symbol.value)
return 1;
return 0;
}
static bfd_boolean
coff_slurp_line_table (bfd *abfd, asection *asect)
{
LINENO *native_lineno;
alent *lineno_cache;
bfd_size_type amt;
unsigned int counter;
alent *cache_ptr;
bfd_vma prev_offset = 0;
int ordered = 1;
unsigned int nbr_func;
LINENO *src;
BFD_ASSERT (asect->lineno == NULL);
@ -4270,67 +4292,120 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
(_("%B: warning: line number table read failed"), abfd);
return FALSE;
}
amt = ((bfd_size_type) asect->lineno_count + 1) * sizeof (alent);
lineno_cache = bfd_alloc (abfd, amt);
if (lineno_cache == NULL)
return FALSE;
else
cache_ptr = lineno_cache;
src = native_lineno;
nbr_func = 0;
for (counter = 0; counter < asect->lineno_count; counter++)
{
unsigned int counter = 0;
alent *cache_ptr = lineno_cache;
LINENO *src = native_lineno;
struct internal_lineno dst;
while (counter < asect->lineno_count)
bfd_coff_swap_lineno_in (abfd, src, &dst);
cache_ptr->line_number = dst.l_lnno;
if (cache_ptr->line_number == 0)
{
struct internal_lineno dst;
bfd_boolean warned;
bfd_signed_vma symndx;
coff_symbol_type *sym;
bfd_coff_swap_lineno_in (abfd, src, &dst);
cache_ptr->line_number = dst.l_lnno;
if (cache_ptr->line_number == 0)
nbr_func++;
warned = FALSE;
symndx = dst.l_addr.l_symndx;
if (symndx < 0
|| (bfd_vma) symndx >= obj_raw_syment_count (abfd))
{
bfd_boolean warned;
bfd_signed_vma symndx;
coff_symbol_type *sym;
warned = FALSE;
symndx = dst.l_addr.l_symndx;
if (symndx < 0
|| (bfd_vma) symndx >= obj_raw_syment_count (abfd))
{
(*_bfd_error_handler)
(_("%B: warning: illegal symbol index %ld in line numbers"),
abfd, dst.l_addr.l_symndx);
symndx = 0;
warned = TRUE;
}
/* FIXME: We should not be casting between ints and
pointers like this. */
sym = ((coff_symbol_type *)
((symndx + obj_raw_syments (abfd))
->u.syment._n._n_n._n_zeroes));
cache_ptr->u.sym = (asymbol *) sym;
if (sym->lineno != NULL && ! warned)
{
(*_bfd_error_handler)
(_("%B: warning: duplicate line number information for `%s'"),
abfd, bfd_asymbol_name (&sym->symbol));
}
sym->lineno = cache_ptr;
(*_bfd_error_handler)
(_("%B: warning: illegal symbol index %ld in line numbers"),
abfd, dst.l_addr.l_symndx);
symndx = 0;
warned = TRUE;
}
else
cache_ptr->u.offset = dst.l_addr.l_paddr
- bfd_section_vma (abfd, asect);
cache_ptr++;
src++;
counter++;
/* FIXME: We should not be casting between ints and
pointers like this. */
sym = ((coff_symbol_type *)
((symndx + obj_raw_syments (abfd))
->u.syment._n._n_n._n_zeroes));
cache_ptr->u.sym = (asymbol *) sym;
if (sym->lineno != NULL && ! warned)
(*_bfd_error_handler)
(_("%B: warning: duplicate line number information for `%s'"),
abfd, bfd_asymbol_name (&sym->symbol));
sym->lineno = cache_ptr;
if (sym->symbol.value < prev_offset)
ordered = 0;
prev_offset = sym->symbol.value;
}
cache_ptr->line_number = 0;
else
cache_ptr->u.offset = dst.l_addr.l_paddr
- bfd_section_vma (abfd, asect);
cache_ptr++;
src++;
}
cache_ptr->line_number = 0;
/* On some systems (eg AIX5.3) the lineno table may not be sorted. */
if (!ordered)
{
/* Sort the table. */
alent **func_table;
alent *n_lineno_cache;
/* Create a table of functions. */
func_table = bfd_malloc (nbr_func * sizeof (alent *));
if (func_table != NULL)
{
alent **p = func_table;
unsigned int i;
for (i = 0; i < counter; i++)
if (lineno_cache[i].line_number == 0)
*p++ = &lineno_cache[i];
/* Sort by functions. */
qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
/* Create the new sorted table. */
n_lineno_cache = bfd_alloc (abfd, amt);
if (n_lineno_cache != NULL)
{
alent *n_cache_ptr = n_lineno_cache;
for (i = 0; i < nbr_func; i++)
{
coff_symbol_type *sym;
alent *old_ptr = func_table[i];
/* Copy the function entry and update it. */
*n_cache_ptr = *old_ptr;
sym = (coff_symbol_type *)n_cache_ptr->u.sym;
sym->lineno = n_cache_ptr;
n_cache_ptr++;
old_ptr++;
/* Copy the line number entries. */
while (old_ptr->line_number != 0)
*n_cache_ptr++ = *old_ptr++;
}
n_cache_ptr->line_number = 0;
bfd_release (abfd, lineno_cache);
lineno_cache = n_lineno_cache;
}
free (func_table);
}
}
asect->lineno = lineno_cache;
/* FIXME, free native_lineno here, or use alloca or something. */
bfd_release (abfd, native_lineno);
return TRUE;
}