/* Support for the generic parts of most COFF variants, for BFD.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Written by Cygnus Support.
. bfd_boolean (*_bfd_coff_final_link_postscript)
. (bfd *, struct coff_final_link_info *);
.
+. bfd_boolean (*_bfd_coff_print_pdata)
+. (bfd *, void *);
+.
.} bfd_coff_backend_data;
.
.#define coff_backend_info(abfd) \
.#define bfd_coff_final_link_postscript(a,p) \
. ((coff_backend_info (a)->_bfd_coff_final_link_postscript) (a, p))
.
+.#define bfd_coff_have_print_pdata(a) \
+. (coff_backend_info (a)->_bfd_coff_print_pdata)
+.#define bfd_coff_print_pdata(a,p) \
+. ((coff_backend_info (a)->_bfd_coff_print_pdata) (a, p))
+.
*/
/* See whether the magic number matches. */
#else /* ! COFF_ALIGN_IN_SECTION_HEADER */
#ifdef COFF_WITH_PE
-/* A couple of macros to help setting the alignment power field. */
-#define ALIGN_SET(field, x, y) \
- if (((field) & IMAGE_SCN_ALIGN_64BYTES) == x)\
- {\
- section->alignment_power = y;\
- }
-
-#define ELIFALIGN_SET(field, x, y) \
- else if (((field) & IMAGE_SCN_ALIGN_64BYTES) == x) \
- {\
- section->alignment_power = y;\
- }
-
static void
coff_set_alignment_hook (bfd * abfd ATTRIBUTE_UNUSED,
asection * section,
{
struct internal_scnhdr *hdr = (struct internal_scnhdr *) scnhdr;
bfd_size_type amt;
+ unsigned int alignment_power_const
+ = hdr->s_flags & IMAGE_SCN_ALIGN_POWER_BIT_MASK;
- ALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_64BYTES, 6)
- ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_32BYTES, 5)
- ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_16BYTES, 4)
- ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_8BYTES, 3)
- ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_4BYTES, 2)
- ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_2BYTES, 1)
- ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_1BYTES, 0)
+ switch (alignment_power_const)
+ {
+ case IMAGE_SCN_ALIGN_8192BYTES:
+ case IMAGE_SCN_ALIGN_4096BYTES:
+ case IMAGE_SCN_ALIGN_2048BYTES:
+ case IMAGE_SCN_ALIGN_1024BYTES:
+ case IMAGE_SCN_ALIGN_512BYTES:
+ case IMAGE_SCN_ALIGN_256BYTES:
+ case IMAGE_SCN_ALIGN_128BYTES:
+ case IMAGE_SCN_ALIGN_64BYTES:
+ case IMAGE_SCN_ALIGN_32BYTES:
+ case IMAGE_SCN_ALIGN_16BYTES:
+ case IMAGE_SCN_ALIGN_8BYTES:
+ case IMAGE_SCN_ALIGN_4BYTES:
+ case IMAGE_SCN_ALIGN_2BYTES:
+ case IMAGE_SCN_ALIGN_1BYTES:
+ section->alignment_power
+ = IMAGE_SCN_ALIGN_POWER_NUM (alignment_power_const);
+ break;
+ default:
+ break;
+ }
/* In a PE image file, the s_paddr field holds the virtual size of a
section, while the s_size field holds the raw size. We also keep
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);
(_("%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;
+
+ bfd_coff_swap_lineno_in (abfd, src, &dst);
+ cache_ptr->line_number = dst.l_lnno;
- while (counter < asect->lineno_count)
+ if (cache_ptr->line_number == 0)
{
- struct internal_lineno dst;
+ 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;
+ }
- bfd_coff_swap_lineno_in (abfd, src, &dst);
- cache_ptr->line_number = dst.l_lnno;
+ /* 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;
- if (cache_ptr->line_number == 0)
+ /* 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)
{
- 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)
+ alent *n_cache_ptr = n_lineno_cache;
+
+ for (i = 0; i < nbr_func; i++)
{
- (*_bfd_error_handler)
- (_("%B: warning: duplicate line number information for `%s'"),
- abfd, bfd_asymbol_name (&sym->symbol));
+ 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++;
}
- sym->lineno = cache_ptr;
+ n_cache_ptr->line_number = 0;
+ bfd_release (abfd, lineno_cache);
+ lineno_cache = n_lineno_cache;
}
- else
- cache_ptr->u.offset = dst.l_addr.l_paddr
- - bfd_section_vma (abfd, asect);
-
- cache_ptr++;
- src++;
- counter++;
+ free (func_table);
}
- cache_ptr->line_number = 0;
-
}
+
asect->lineno = lineno_cache;
- /* FIXME, free native_lineno here, or use alloca or something. */
+ bfd_release (abfd, native_lineno);
return TRUE;
}
coff_classify_symbol, coff_compute_section_file_positions,
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
coff_adjust_symndx, coff_link_add_one_symbol,
- coff_link_output_has_begun, coff_final_link_postscript
+ coff_link_output_has_begun, coff_final_link_postscript,
+ bfd_pe_print_pdata
};
#ifdef TICOFF
coff_classify_symbol, coff_compute_section_file_positions,
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
coff_adjust_symndx, coff_link_add_one_symbol,
- coff_link_output_has_begun, coff_final_link_postscript
+ coff_link_output_has_begun, coff_final_link_postscript,
+ bfd_pe_print_pdata
};
#endif
coff_classify_symbol, coff_compute_section_file_positions,
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
coff_adjust_symndx, coff_link_add_one_symbol,
- coff_link_output_has_begun, coff_final_link_postscript
+ coff_link_output_has_begun, coff_final_link_postscript,
+ bfd_pe_print_pdata /* huh */
};
#endif