This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Ping: [Patch]: fix addr2line on AIX5.3


No comment received so far for this patch.

Tristan.

On Jul 13, 2007, at 3:19 PM, Tristan Gingold wrote:

Hi,

on AIX (tested only with version 5.3), addr2line is not reliable because native linker doesn't sort
line tables. This patch fixes the issue by sorting the line table when they are read only if they aren't
already. This approach should be pretty safe and almost transparent to other coff backend.


I am not sure this is the right approach so comments are very welcome.

Tristan.

bfd:
2007-07-13  Tristan Gingold  <gingold@adacore.com>

	* coffcode.h (coff_sort_func_alent): New function.
	(coff_slurp_line_table): Sort line table if not already sorted.

diff -c -p -r1.140 coffcode.h
*** coffcode.h  12 Jul 2007 07:16:40 -0000      1.140
--- coffcode.h  13 Jul 2007 13:11:09 -0000
*************** SUBSUBSECTION
*** 4253,4264 ****
--- 4253,4286 ----
        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;
+ else
+ 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);

*************** coff_slurp_line_table (bfd *abfd, asecti
*** 4274,4336 ****
    lineno_cache = bfd_alloc (abfd, amt);
    if (lineno_cache == NULL)
      return FALSE;
!   else
      {
!       unsigned int counter = 0;
!       alent *cache_ptr = lineno_cache;
!       LINENO *src = native_lineno;

!       while (counter < asect->lineno_count)
        {
!         struct internal_lineno dst;

!         bfd_coff_swap_lineno_in (abfd, src, &dst);
!         cache_ptr->line_number = dst.l_lnno;

! if (cache_ptr->line_number == 0)
{
! 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;
}
! else
! cache_ptr->u.offset = dst.l_addr.l_paddr
! - bfd_section_vma (abfd, asect);
!
! cache_ptr++;
! src++;
! counter++;
}
- cache_ptr->line_number = 0;
-
}
asect->lineno = lineno_cache;
! /* FIXME, free native_lineno here, or use alloca or something. */
return TRUE;
}


--- 4296,4407 ----
    lineno_cache = bfd_alloc (abfd, amt);
    if (lineno_cache == NULL)
      return FALSE;
!
!   cache_ptr = lineno_cache;
!   src = native_lineno;
!   nbr_func = 0;
!
!   for (counter = 0; counter < asect->lineno_count; counter++)
      {
!       struct internal_lineno dst;
!
!       bfd_coff_swap_lineno_in (abfd, src, &dst);
!       cache_ptr->line_number = dst.l_lnno;

! if (cache_ptr->line_number == 0)
{
! bfd_boolean warned;
! bfd_signed_vma symndx;
! coff_symbol_type *sym;
!
! nbr_func++;
! 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;
! if (sym->symbol.value < prev_offset)
! ordered = 0;
! prev_offset = sym->symbol.value;
! }
! 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;
! bfd_release (abfd, native_lineno);
return TRUE;
}




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]