Set LC_ALL=C rather than unsetting LC_COLLATE for sort.
[deliverable/binutils-gdb.git] / bfd / coffcode.h
index 5a858dd1220f5975109d4cf7cb0d5647337bc0dc..78269829f764c3eea53f7cc2da5e5c0f97733174 100644 (file)
@@ -1,6 +1,6 @@
 /* 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.
 
@@ -1292,6 +1292,9 @@ Special entry points for gdb to swap in coff symbol table parts:
 .  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) \
@@ -1424,6 +1427,11 @@ Special entry points for gdb to swap in coff symbol table parts:
 .#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.  */
@@ -1628,19 +1636,6 @@ coff_set_alignment_hook (bfd * abfd ATTRIBUTE_UNUSED,
 #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,
@@ -1648,14 +1643,31 @@ coff_set_alignment_hook (bfd * abfd ATTRIBUTE_UNUSED,
 {
   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
@@ -4253,12 +4265,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 +4304,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;
+
+      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;
 }
 
@@ -5184,7 +5271,8 @@ static const bfd_coff_backend_data bfd_coff_std_swap_table ATTRIBUTE_UNUSED =
   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
@@ -5227,7 +5315,8 @@ static const bfd_coff_backend_data ticoff0_swap_table =
   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
 
@@ -5271,7 +5360,8 @@ static const bfd_coff_backend_data ticoff1_swap_table =
   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
 
This page took 0.026749 seconds and 4 git commands to generate.