* merge.c (struct sec_merge_hash_entry): Add u.entsize and u.suffix
authorJakub Jelinek <jakub@redhat.com>
Fri, 11 May 2001 12:23:48 +0000 (12:23 +0000)
committerJakub Jelinek <jakub@redhat.com>
Fri, 11 May 2001 12:23:48 +0000 (12:23 +0000)
fields, change sec into secinfo.
(struct sec_merge_info): Add chain, remove last fields.
(struct sec_merge_sec_info): Add next, sec, psecinfo fields.
(sec_merge_hash_lookup): If lookup could not use a string only
because it has bad alignment, mark the old string for deletion.
(sec_merge_add): Add secinfo argument. Don't compute entry's
position, instead record the section.
(sec_merge_emit): Update for the sec into secinfo change in
struct sec_merge_hash_entry.
(_bfd_merge_section): Only record the section for merging, defer
putting strings into the hash table.
(cmplengthentry, last4_eq, last_eq, record_section, merge_strings,
_bfd_merge_sections): New functions.
(_bfd_merged_section_offset): Update for the sec_merge_hash_entry
changes.
* libbfd-in.h (_bfd_merge_sections): Add prototype.
(_bfd_nolink_bfd_merge_sections): Define.
* libbfd.h: Likewise.
(bfd_generic_merge_sections): Add prototype.
* targets.c (BFD_JUMP_TABLE_LINK): Add _bfd_merge_sections.
(struct bfd_target): Likewise.
* bfd.c (bfd_merge_sections): Define.
* bfd-in2.h: Rebuilt.
* elf.c (_bfd_elf_merge_sections): New function.
* elf-bfd.h (_bfd_elf_merge_sections): Add prototype.
* elfxx-target.h (bfd_elfNN_bfd_merge_sections): Define.
* reloc.c (bfd_generic_merge_sections): New function.
* vms.c (vms_bfd_merge_sections): New function.
* aout-adobe.c (aout_32_bfd_merge_sections): Define.
* aout-target.h (MY_bfd_merge_sections): Define.
* aout-tic30.c (MY_bfd_merge_sections): Define.
* binary.c (binary_bfd_merge_sections): Define.
* bout.c (b_out_bfd_merge_sections): Define.
* coff-alpha.c (_bfd_ecoff_bfd_merge_sections): Define.
* coffcode.c (coff_bfd_merge_sections): Define.
* coff-mips.c (_bfd_ecoff_bfd_merge_sections): Define.
* i386msdos.c (msdos_bfd_merge_sections): Define.
* i386os9k.c (os9k_bfd_merge_sections): Define.
* ieee.c (ieee_bfd_merge_sections): Define.
* ihex.c (ihex_bfd_merge_sections): Define.
* nlm-target.h (nlm_bfd_merge_sections): Define.
* oasys.c (oasys_bfd_merge_sections): Define.
* ppcboot.c (ppcboot_bfd_merge_sections): Define.
* som.c (som_bfd_merge_sections): Define.
* srec.c (srec_bfd_merge_sections): Define.
* tekhex.c (tekhex_bfd_merge_sections): Define.
* versados.c (versados_bfd_merge_sections): Define.
* xcoff-target.h (_bfd_xcoff_bfd_merge_sections): Define.

* ldlang.c (lang_process): Call bfd_merge_sections.

34 files changed:
bfd/ChangeLog
bfd/aout-adobe.c
bfd/aout-target.h
bfd/aout-tic30.c
bfd/bfd-in2.h
bfd/bfd.c
bfd/binary.c
bfd/bout.c
bfd/coff-alpha.c
bfd/coff-mips.c
bfd/coffcode.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elfxx-target.h
bfd/i386msdos.c
bfd/i386os9k.c
bfd/ieee.c
bfd/ihex.c
bfd/libbfd-in.h
bfd/libbfd.h
bfd/merge.c
bfd/nlm-target.h
bfd/oasys.c
bfd/ppcboot.c
bfd/reloc.c
bfd/som.c
bfd/srec.c
bfd/targets.c
bfd/tekhex.c
bfd/versados.c
bfd/vms.c
bfd/xcoff-target.h
ld/ChangeLog
ld/ldlang.c

index afb0e26..c2bb974 100644 (file)
@@ -1,3 +1,55 @@
+2001-05-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * merge.c (struct sec_merge_hash_entry): Add u.entsize and u.suffix
+       fields, change sec into secinfo.
+       (struct sec_merge_info): Add chain, remove last fields.
+       (struct sec_merge_sec_info): Add next, sec, psecinfo fields.
+       (sec_merge_hash_lookup): If lookup could not use a string only
+       because it has bad alignment, mark the old string for deletion.
+       (sec_merge_add): Add secinfo argument. Don't compute entry's
+       position, instead record the section.
+       (sec_merge_emit): Update for the sec into secinfo change in
+       struct sec_merge_hash_entry.
+       (_bfd_merge_section): Only record the section for merging, defer
+       putting strings into the hash table.
+       (cmplengthentry, last4_eq, last_eq, record_section, merge_strings,
+       _bfd_merge_sections): New functions.
+       (_bfd_merged_section_offset): Update for the sec_merge_hash_entry
+       changes.
+       * libbfd-in.h (_bfd_merge_sections): Add prototype.
+       (_bfd_nolink_bfd_merge_sections): Define.
+       * libbfd.h: Likewise.
+       (bfd_generic_merge_sections): Add prototype.
+       * targets.c (BFD_JUMP_TABLE_LINK): Add _bfd_merge_sections.
+       (struct bfd_target): Likewise.
+       * bfd.c (bfd_merge_sections): Define.
+       * bfd-in2.h: Rebuilt.
+       * elf.c (_bfd_elf_merge_sections): New function.
+       * elf-bfd.h (_bfd_elf_merge_sections): Add prototype.
+       * elfxx-target.h (bfd_elfNN_bfd_merge_sections): Define.
+       * reloc.c (bfd_generic_merge_sections): New function.
+       * vms.c (vms_bfd_merge_sections): New function.
+       * aout-adobe.c (aout_32_bfd_merge_sections): Define.
+       * aout-target.h (MY_bfd_merge_sections): Define.
+       * aout-tic30.c (MY_bfd_merge_sections): Define.
+       * binary.c (binary_bfd_merge_sections): Define.
+       * bout.c (b_out_bfd_merge_sections): Define.
+       * coff-alpha.c (_bfd_ecoff_bfd_merge_sections): Define.
+       * coffcode.c (coff_bfd_merge_sections): Define.
+       * coff-mips.c (_bfd_ecoff_bfd_merge_sections): Define.
+       * i386msdos.c (msdos_bfd_merge_sections): Define.
+       * i386os9k.c (os9k_bfd_merge_sections): Define.
+       * ieee.c (ieee_bfd_merge_sections): Define.
+       * ihex.c (ihex_bfd_merge_sections): Define.
+       * nlm-target.h (nlm_bfd_merge_sections): Define.
+       * oasys.c (oasys_bfd_merge_sections): Define.
+       * ppcboot.c (ppcboot_bfd_merge_sections): Define.
+       * som.c (som_bfd_merge_sections): Define.
+       * srec.c (srec_bfd_merge_sections): Define.
+       * tekhex.c (tekhex_bfd_merge_sections): Define.
+       * versados.c (versados_bfd_merge_sections): Define.
+       * xcoff-target.h (_bfd_xcoff_bfd_merge_sections): Define.
+
 2001-05-11  Nick Clifton  <nickc@cambridge.redhat.com>
 
        * dwarf1.c (_bfd_dwarf1_find_nearest_line): Change type of 'addr'
index 03acacb..e7c9fc9 100644 (file)
@@ -513,6 +513,7 @@ aout_adobe_sizeof_headers (ignore_abfd, ignore)
 #define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
 #define aout_32_bfd_relax_section       bfd_generic_relax_section
 #define aout_32_bfd_gc_sections         bfd_generic_gc_sections
+#define aout_32_bfd_merge_sections     bfd_generic_merge_sections
 #define aout_32_bfd_link_hash_table_create \
   _bfd_generic_link_hash_table_create
 #define aout_32_bfd_link_add_symbols   _bfd_generic_link_add_symbols
index 1b8d3a5..2d1e289 100644 (file)
@@ -507,6 +507,9 @@ MY_bfd_final_link (abfd, info)
 #ifndef MY_bfd_gc_sections
 #define MY_bfd_gc_sections bfd_generic_gc_sections
 #endif
+#ifndef MY_bfd_merge_sections
+#define MY_bfd_merge_sections bfd_generic_merge_sections
+#endif
 #ifndef MY_bfd_reloc_type_lookup
 #define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup)
 #endif
index a3e977d..d02cf0d 100644 (file)
@@ -940,6 +940,9 @@ tic30_aout_set_arch_mach (abfd, arch, machine)
 #ifndef MY_bfd_gc_sections
 #define MY_bfd_gc_sections bfd_generic_gc_sections
 #endif
+#ifndef MY_bfd_merge_sections
+#define MY_bfd_merge_sections bfd_generic_merge_sections
+#endif
 #ifndef MY_bfd_reloc_type_lookup
 #define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
 #endif
index 230b24a..bce9c0e 100644 (file)
@@ -3229,6 +3229,9 @@ bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
 #define bfd_gc_sections(abfd, link_info) \
        BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
 
+#define bfd_merge_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
 #define bfd_link_hash_table_create(abfd) \
        BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
 
@@ -3525,7 +3528,8 @@ CAT(NAME,_bfd_link_hash_table_create),\
 CAT(NAME,_bfd_link_add_symbols),\
 CAT(NAME,_bfd_final_link),\
 CAT(NAME,_bfd_link_split_section),\
-CAT(NAME,_bfd_gc_sections)
+CAT(NAME,_bfd_gc_sections),\
+CAT(NAME,_bfd_merge_sections)
   int        (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
   bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
                     struct bfd_link_info *, struct bfd_link_order *,
@@ -3552,6 +3556,9 @@ CAT(NAME,_bfd_gc_sections)
   /* Remove sections that are not referenced from the output.  */
   boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
 
+  /* Attempt to merge SEC_MERGE sections.  */
+  boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
   /* Routines to handle dynamic symbols and relocs.  */
 #define BFD_JUMP_TABLE_DYNAMIC(NAME)\
 CAT(NAME,_get_dynamic_symtab_upper_bound),\
index 3afcd3d..1f92762 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1126,6 +1126,9 @@ DESCRIPTION
 .#define bfd_gc_sections(abfd, link_info) \
 .      BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
 .
+.#define bfd_merge_sections(abfd, link_info) \
+.      BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+.
 .#define bfd_link_hash_table_create(abfd) \
 .      BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
 .
index a008f90..7fd01b3 100644 (file)
@@ -345,6 +345,7 @@ binary_sizeof_headers (abfd, exec)
   bfd_generic_get_relocated_section_contents
 #define binary_bfd_relax_section bfd_generic_relax_section
 #define binary_bfd_gc_sections bfd_generic_gc_sections
+#define binary_bfd_merge_sections bfd_generic_merge_sections
 #define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define binary_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define binary_bfd_final_link _bfd_generic_final_link
index 1b663d1..165dd24 100644 (file)
@@ -1436,6 +1436,7 @@ b_out_bfd_get_relocated_section_contents (output_bfd, link_info, link_order,
 #define b_out_bfd_final_link _bfd_generic_final_link
 #define b_out_bfd_link_split_section  _bfd_generic_link_split_section
 #define b_out_bfd_gc_sections  bfd_generic_gc_sections
+#define b_out_bfd_merge_sections  bfd_generic_merge_sections
 
 #define aout_32_get_section_contents_in_window \
   _bfd_generic_get_section_contents_in_window
index b3cd0c7..d0db6a8 100644 (file)
@@ -2359,6 +2359,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
 /* Relaxing sections is generic.  */
 #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
 #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
+#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
 
 const bfd_target ecoffalpha_little_vec =
 {
index ac16802..805824a 100644 (file)
@@ -2600,6 +2600,9 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
 /* GC of sections is not done.  */
 #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
 
+/* Merging of sections is not done.  */
+#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
+
 extern const bfd_target ecoff_big_vec;
 
 const bfd_target ecoff_little_vec =
index 2cdc137..7415b96 100644 (file)
@@ -5258,6 +5258,10 @@ static const bfd_coff_backend_data bfd_coff_std_swap_table =
 #define coff_bfd_gc_sections               bfd_generic_gc_sections
 #endif
 
+#ifndef coff_bfd_merge_sections
+#define coff_bfd_merge_sections                    bfd_generic_merge_sections
+#endif
+
 #define CREATE_BIG_COFF_TARGET_VEC(VAR, NAME, EXTRA_O_FLAGS, EXTRA_S_FLAGS, UNDER, ALTERNATIVE)        \
 const bfd_target VAR =                                                 \
 {                                                                      \
index e1b61a2..fd3f347 100644 (file)
@@ -1006,6 +1006,9 @@ extern boolean _bfd_elf_link_hash_table_init
                                       const char *)));
 extern boolean _bfd_elf_slurp_version_tables PARAMS ((bfd *));
 
+extern boolean _bfd_elf_merge_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+
 extern boolean _bfd_elf_copy_private_symbol_data
   PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
 extern boolean _bfd_elf_copy_private_section_data
index d0cd62d..e424ce8 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -558,6 +558,18 @@ bfd_elf_generic_reloc (abfd,
   return bfd_reloc_continue;
 }
 \f
+/* Finish SHF_MERGE section merging.  */
+
+boolean
+_bfd_elf_merge_sections (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  if (elf_hash_table (info)->merge_info)
+    _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info);
+  return true;
+}
+\f
 /* Print out the program headers.  */
 
 boolean
index 782b5da..8c39a4a 100644 (file)
@@ -111,6 +111,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define bfd_elfNN_bfd_gc_sections _bfd_elfNN_gc_sections
 #endif
 
+#ifndef bfd_elfNN_bfd_merge_sections
+#define bfd_elfNN_bfd_merge_sections \
+  _bfd_elf_merge_sections
+#endif
+
 #define bfd_elfNN_bfd_make_debug_symbol \
   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
 
index c42f365..91e4d9d 100644 (file)
@@ -170,6 +170,7 @@ msdos_set_section_contents (abfd, section, location, offset, count)
   bfd_generic_get_relocated_section_contents
 #define msdos_bfd_relax_section bfd_generic_relax_section
 #define msdos_bfd_gc_sections bfd_generic_gc_sections
+#define msdos_bfd_merge_sections bfd_generic_merge_sections
 #define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define msdos_bfd_final_link _bfd_generic_final_link
index 7122479..5f6a5a3 100644 (file)
@@ -328,6 +328,7 @@ os9k_sizeof_headers (ignore_abfd, ignore)
   bfd_generic_get_relocated_section_contents
 #define os9k_bfd_relax_section bfd_generic_relax_section
 #define os9k_bfd_gc_sections bfd_generic_gc_sections
+#define os9k_bfd_merge_sections bfd_generic_merge_sections
 #define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define os9k_bfd_final_link _bfd_generic_final_link
index 8414424..cf2bfaa 100644 (file)
@@ -3926,6 +3926,7 @@ ieee_bfd_debug_info_accumulate (abfd, section)
   bfd_generic_get_relocated_section_contents
 #define ieee_bfd_relax_section bfd_generic_relax_section
 #define ieee_bfd_gc_sections bfd_generic_gc_sections
+#define ieee_bfd_merge_sections bfd_generic_merge_sections
 #define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define ieee_bfd_final_link _bfd_generic_final_link
index 738da81..700dfa9 100644 (file)
@@ -983,6 +983,7 @@ ihex_sizeof_headers (abfd, exec)
   bfd_generic_get_relocated_section_contents
 #define ihex_bfd_relax_section bfd_generic_relax_section
 #define ihex_bfd_gc_sections bfd_generic_gc_sections
+#define ihex_bfd_merge_sections bfd_generic_merge_sections
 #define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define ihex_bfd_final_link _bfd_generic_final_link
index dae7635..14a4c1b 100644 (file)
@@ -323,6 +323,10 @@ extern boolean _bfd_generic_set_section_contents
   ((boolean (*) \
     PARAMS ((bfd *, struct bfd_link_info *))) \
    bfd_false)
+#define _bfd_nolink_bfd_merge_sections \
+  ((boolean (*) \
+    PARAMS ((bfd *, struct bfd_link_info *))) \
+   bfd_false)
 #define _bfd_nolink_bfd_link_hash_table_create \
   ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr)
 #define _bfd_nolink_bfd_link_add_symbols \
@@ -467,6 +471,11 @@ extern bfd_vma _bfd_stab_section_offset
 extern boolean _bfd_merge_section
   PARAMS ((bfd *, PTR *, asection *, PTR *));
 
+/* Attempt to merge SEC_MERGE sections.  */
+
+extern boolean _bfd_merge_sections
+  PARAMS ((bfd *, PTR));
+
 /* Write out a merged section.  */
 
 extern boolean _bfd_write_merged_section
index 675a6a1..9ce8e57 100644 (file)
@@ -323,6 +323,10 @@ extern boolean _bfd_generic_set_section_contents
   ((boolean (*) \
     PARAMS ((bfd *, struct bfd_link_info *))) \
    bfd_false)
+#define _bfd_nolink_bfd_merge_sections \
+  ((boolean (*) \
+    PARAMS ((bfd *, struct bfd_link_info *))) \
+   bfd_false)
 #define _bfd_nolink_bfd_link_hash_table_create \
   ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr)
 #define _bfd_nolink_bfd_link_add_symbols \
@@ -467,6 +471,11 @@ extern bfd_vma _bfd_stab_section_offset
 extern boolean _bfd_merge_section
   PARAMS ((bfd *, PTR *, asection *, PTR *));
 
+/* Attempt to merge SEC_MERGE sections.  */
+
+extern boolean _bfd_merge_sections
+  PARAMS ((bfd *, PTR));
+
 /* Write out a merged section.  */
 
 extern boolean _bfd_write_merged_section
@@ -1080,6 +1089,9 @@ bfd_generic_relax_section PARAMS ((bfd *abfd,
 boolean
 bfd_generic_gc_sections PARAMS ((bfd *, struct bfd_link_info *));
 
+boolean
+bfd_generic_merge_sections PARAMS ((bfd *, struct bfd_link_info *));
+
 bfd_byte *
 bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd,
     struct bfd_link_info *link_info,
index 6619dcd..3d09041 100644 (file)
@@ -24,9 +24,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
+#include "hashtab.h"
 
 #include <ctype.h>
 
+struct sec_merge_sec_info;
+
 /* An entry in the section merge hash table.  */
 
 struct sec_merge_hash_entry
@@ -37,10 +40,16 @@ struct sec_merge_hash_entry
   /* Start of this string needs to be aligned to
      alignment octets (not 1 << align).  */
   unsigned int alignment;
-  /* Index within the merged section.  */
-  bfd_size_type index;
+  union {
+    /* Index within the merged section.  */
+    bfd_size_type index;
+    /* Entity size (if present in suffix hash tables).  */
+    unsigned int entsize;
+    /* Entry this is a suffix of (if alignment is 0).  */
+    struct sec_merge_hash_entry *suffix;
+  } u;
   /* Which section is it in.  */
-  asection *sec;
+  struct sec_merge_sec_info *secinfo;
   /* Next entity in the hash table.  */
   struct sec_merge_hash_entry *next;
 };
@@ -66,14 +75,20 @@ struct sec_merge_info
 {
   /* Chain of sec_merge_infos.  */
   struct sec_merge_info *next;
+  /* Chain of sec_merge_sec_infos.  */
+  struct sec_merge_sec_info *chain;
   /* A hash table used to hold section content.  */
   struct sec_merge_hash *htab;
-  /* The last section attempted for merge.  */
-  asection *last;
 };
 
 struct sec_merge_sec_info
 {
+  /* Chain of sec_merge_sec_infos.  */
+  struct sec_merge_sec_info *next;
+  /* The corresponding section.  */
+  asection *sec;
+  /* Pointer to merge_info pointing to us.  */
+  PTR *psecinfo;
   /* A hash table used to hold section content.  */
   struct sec_merge_hash *htab;
   /* First string in this section.  */
@@ -89,7 +104,8 @@ static struct sec_merge_hash_entry *sec_merge_hash_lookup
 static struct sec_merge_hash *sec_merge_init
   PARAMS ((unsigned int, boolean));
 static struct sec_merge_hash_entry *sec_merge_add
-  PARAMS ((struct sec_merge_hash *, const char *, unsigned int));
+  PARAMS ((struct sec_merge_hash *, const char *, unsigned int,
+          struct sec_merge_sec_info *));
 static boolean sec_merge_emit
   PARAMS ((bfd *, struct sec_merge_hash_entry *));
 
@@ -118,9 +134,9 @@ sec_merge_hash_newfunc (entry, table, string)
   if (ret)
     {
       /* Initialize the local fields.  */
-      ret->index = (bfd_size_type) -1;
+      ret->u.suffix = NULL;
       ret->alignment = 0;
-      ret->sec = NULL;
+      ret->secinfo = NULL;
       ret->next = NULL;
     }
 
@@ -202,11 +218,14 @@ sec_merge_hash_lookup (table, string, alignment, create)
          && memcmp (hashp->root.string, string, len) == 0)
        {
          /* If the string we found does not have at least the required
-            alignment, we need to insert another copy.
-            FIXME: The old copy could be removed and the space allocated
-            for it filled by some new string (similarly with padding).  */
+            alignment, we need to insert another copy.  */
          if (hashp->alignment < alignment)
-           break;
+           {
+             /*  Mark the less aligned copy as deleted.  */
+             hashp->len = 0;
+             hashp->alignment = 0;
+             break;
+           }
          return hashp;
        }
     }
@@ -262,10 +281,11 @@ sec_merge_init (entsize, strings)
    already present.  */
 
 static struct sec_merge_hash_entry *
-sec_merge_add (tab, str, alignment)
+sec_merge_add (tab, str, alignment, secinfo)
      struct sec_merge_hash *tab;
      const char *str;
      unsigned int alignment;
+     struct sec_merge_sec_info *secinfo;
 {
   register struct sec_merge_hash_entry *entry;
 
@@ -273,11 +293,10 @@ sec_merge_add (tab, str, alignment)
   if (entry == NULL)
     return NULL;
 
-  if (entry->index == (bfd_size_type) -1)
+  if (entry->secinfo == NULL)
     {
-      tab->size = (tab->size + alignment - 1) & ~((bfd_vma) alignment - 1);
-      entry->index = tab->size;
-      tab->size += entry->len;
+      tab->size++;
+      entry->secinfo = secinfo;
       if (tab->first == NULL)
        tab->first = entry;
       else
@@ -293,7 +312,8 @@ sec_merge_emit (abfd, entry)
      register bfd *abfd;
      struct sec_merge_hash_entry *entry;
 {
-  asection *sec = entry->sec;
+  struct sec_merge_sec_info *secinfo = entry->secinfo;
+  asection *sec = secinfo->sec;
   char *pad = "";
   bfd_size_type off = 0;
   int alignment_power = bfd_get_section_alignment (abfd, sec->output_section);
@@ -301,7 +321,7 @@ sec_merge_emit (abfd, entry)
   if (alignment_power)
     pad = bfd_zmalloc (1 << alignment_power);
 
-  for (; entry != NULL && entry->sec == sec; entry = entry->next)
+  for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
     {
       register const char *str;
       register size_t len;
@@ -327,7 +347,7 @@ sec_merge_emit (abfd, entry)
   if (alignment_power)
     free (pad);
 
-  return entry == NULL || entry->sec != sec;
+  return entry == NULL || entry->secinfo != secinfo;
 }
 
 /* This function is called for each input file from the add_symbols
@@ -340,15 +360,12 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
      asection *sec;
      PTR *psecinfo;
 {
-  boolean first, nul;
   struct sec_merge_info *sinfo;
   struct sec_merge_sec_info *secinfo;
-  unsigned char *p, *end;
-  bfd_vma mask, eltalign;
   unsigned int align;
-  unsigned int i;
 
   if (sec->_raw_size == 0
+      || (sec->flags & SEC_EXCLUDE)
       || (sec->flags & SEC_MERGE) == 0
       || sec->entsize == 0)
     return true;
@@ -367,7 +384,7 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
       return true;
     }
 
-  align = bfd_get_section_alignment (abfd, sec);
+  align = bfd_get_section_alignment (sec->owner, sec);
   if ((sec->entsize < (unsigned int)(1 << align)
        && ((sec->entsize & (sec->entsize - 1))
           || !(sec->flags & SEC_STRINGS)))
@@ -383,23 +400,22 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
       return true;
     }
 
-  first = false;
-
   for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
-    if (! ((sinfo->last->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
-       && sinfo->last->entsize == sec->entsize
-       && ! strcmp (sinfo->last->name, sec->name))
+    if ((secinfo = sinfo->chain)
+       && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
+       && secinfo->sec->entsize == sec->entsize
+       && ! strcmp (secinfo->sec->name, sec->name))
       break;
 
   if (sinfo == NULL)
     {
       /* Initialize the information we need to keep track of.  */
-      first = true;
       sinfo = (struct sec_merge_info *)
              bfd_alloc (abfd, sizeof (struct sec_merge_info));
       if (sinfo == NULL)
        goto error_return;
       sinfo->next = (struct sec_merge_info *) *psinfo;
+      sinfo->chain = NULL;
       *psinfo = (PTR) sinfo;
       sinfo->htab =
        sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
@@ -415,14 +431,121 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
     goto error_return;
 
   secinfo = (struct sec_merge_sec_info *)*psecinfo;
+  if (sinfo->chain)
+    {
+      secinfo->next = sinfo->chain->next;
+      sinfo->chain->next = secinfo;
+    }
+  else
+    secinfo->next = secinfo;
+  sinfo->chain = secinfo;
+  secinfo->sec = sec;
+  secinfo->psecinfo = psecinfo;
   secinfo->htab = sinfo->htab;
-  sinfo->htab->size = 0;
   secinfo->first = NULL;
 
-  if (! bfd_get_section_contents (abfd, sec, secinfo->contents, 0,
+  if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents, 0,
                                  sec->_raw_size))
     goto error_return;
 
+  return true;
+
+ error_return:
+  *psecinfo = NULL;
+  return false;
+}
+
+/* Compare two sec_merge_hash_entry structures.  This is called via qsort.  */
+
+static int
+cmplengthentry (a, b)
+     const PTR a;
+     const PTR b;
+{
+  struct sec_merge_hash_entry * A = *(struct sec_merge_hash_entry **) a;
+  struct sec_merge_hash_entry * B = *(struct sec_merge_hash_entry **) b;
+              
+  if (A->len < B->len)
+    return 1;
+  else if (A->len > B->len)
+    return -1;
+
+  return memcmp (A->root.string, B->root.string, A->len);
+}
+
+static int
+last4_eq (a, b)
+     const void *a, *b;
+{
+  struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
+  struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
+
+  if (memcmp (A->root.string + A->len - 5 * A->u.entsize,
+             B->root.string + B->len - 5 * A->u.entsize,
+             4 * A->u.entsize) != 0)
+    /* This was a hashtable collision.  */
+    return 0;
+
+  if (A->len <= B->len)
+    /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
+       not to be equal by the hash table.  */
+    return 0;
+
+  if (A->alignment < B->alignment
+      || ((A->len - B->len) & (B->alignment - 1)))
+    /* The suffix is not sufficiently aligned.  */
+    return 0;
+
+  return memcmp (A->root.string + (A->len - B->len),
+                B->root.string, B->len - 5 * A->u.entsize) == 0;
+}
+
+static int
+last_eq (a, b)
+     const void *a, *b;
+{
+  struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
+  struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
+
+  if (B->len >= 5 * A->u.entsize)
+    /* Longer strings are just pushed into the hash table,
+       they'll be used when looking up for very short strings.  */
+    return 0;
+
+  if (memcmp (A->root.string + A->len - 2 * A->u.entsize,
+             B->root.string + B->len - 2 * A->u.entsize,
+             A->u.entsize) != 0)
+    /* This was a hashtable collision.  */
+    return 0;
+
+  if (A->len <= B->len)
+    /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
+       not to be equal by the hash table.  */
+    return 0;
+
+  if (A->alignment < B->alignment
+      || ((A->len - B->len) & (B->alignment - 1)))
+    /* The suffix is not sufficiently aligned.  */
+    return 0;
+
+  return memcmp (A->root.string + (A->len - B->len),
+                B->root.string, B->len - 2 * A->u.entsize) == 0;
+}
+
+/* Record one section into the hash table.  */
+static boolean
+record_section (sinfo, secinfo)
+     struct sec_merge_info *sinfo;
+     struct sec_merge_sec_info *secinfo;
+{
+  asection *sec = secinfo->sec;
+  struct sec_merge_hash_entry *entry;
+  boolean nul;
+  unsigned char *p, *end;
+  bfd_vma mask, eltalign;
+  unsigned int align, i;
+
+  align = bfd_get_section_alignment (sec->owner, sec);
   end = secinfo->contents + sec->_raw_size;
   nul = false;
   mask = ((bfd_vma)1 << align) - 1;
@@ -430,19 +553,13 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
     {
       for (p = secinfo->contents; p < end;)
        {
-         struct sec_merge_hash_entry *entry;
-
          eltalign = p - secinfo->contents;
          eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
          if (!eltalign || eltalign > mask)
            eltalign = mask + 1;
-         entry = sec_merge_add (sinfo->htab, p, eltalign);
-         if (entry->sec == NULL)
-           {
-             if (secinfo->first == NULL)
-               secinfo->first = entry;
-             entry->sec = sec;
-           }
+         entry = sec_merge_add (sinfo->htab, p, eltalign, secinfo);
+         if (! entry)
+           goto error_return;
          p += entry->len;
          if (sec->entsize == 1)
            {
@@ -451,13 +568,10 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
                  if (!nul && !((p - secinfo->contents) & mask))
                    {
                      nul = true;
-                     entry = sec_merge_add (sinfo->htab, "", mask + 1);
-                     if (entry->sec == NULL)
-                       {
-                         if (secinfo->first == NULL)
-                           secinfo->first = entry;
-                         entry->sec = sec;
-                       }
+                     entry = sec_merge_add (sinfo->htab, "", mask + 1,
+                                            secinfo);
+                     if (! entry)
+                       goto error_return;
                    }
                  p++;
                }
@@ -474,13 +588,10 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
                  if (!nul && !((p - secinfo->contents) & mask))
                    {
                      nul = true;
-                     entry = sec_merge_add (sinfo->htab, p, mask + 1);
-                     if (entry->sec == NULL)
-                       {
-                         if (secinfo->first == NULL)
-                           secinfo->first = entry;
-                         entry->sec = sec;
-                       }
+                     entry = sec_merge_add (sinfo->htab, p, mask + 1,
+                                            secinfo);
+                     if (! entry)
+                       goto error_return;
                    }
                  p += sec->entsize;
                }
@@ -491,29 +602,235 @@ _bfd_merge_section (abfd, psinfo, sec, psecinfo)
     {
       for (p = secinfo->contents; p < end; p += sec->entsize)
        {
-         struct sec_merge_hash_entry *entry;
+         entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
+         if (! entry)
+           goto error_return;
+       }
+    }
+
+  return true;
+
+error_return:
+  for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
+    *secinfo->psecinfo = NULL;
+  return false;
+}
+
+/* This is a helper function for _bfd_merge_sections.  It attempts to
+   merge strings matching suffixes of longer strings.  */
+static void
+merge_strings (sinfo)
+     struct sec_merge_info *sinfo;
+{
+  struct sec_merge_hash_entry **array, **a, **end, *e;
+  struct sec_merge_sec_info *secinfo;
+  htab_t lasttab = NULL, last4tab = NULL;
+  bfd_size_type size;
+
+  /* Now sort the strings by length, longest first.  */
+  array = (struct sec_merge_hash_entry **)
+         malloc (sinfo->htab->size
+                 * sizeof (struct sec_merge_hash_entry *));
+  if (array == NULL)
+    goto alloc_failure;
+
+  for (e = sinfo->htab->first, a = array; e; e = e->next)
+    if (e->alignment)
+      *a++ = e;
+
+  sinfo->htab->size = a - array;
 
-         entry = sec_merge_add (sinfo->htab, p, 1);
-         if (entry->sec == NULL)
+  qsort (array, sinfo->htab->size, sizeof (struct sec_merge_hash_entry *),
+        cmplengthentry);
+
+  last4tab = htab_create (sinfo->htab->size * 4, NULL, last4_eq, NULL);
+  lasttab = htab_create (sinfo->htab->size * 4, NULL, last_eq, NULL);
+  if (lasttab == NULL || last4tab == NULL)
+    goto alloc_failure;
+
+  /* Now insert the strings into hash tables (strings with last 4 characters
+     and strings with last character equal), look for longer strings which
+     we're suffix of.  */
+  for (a = array, end = array + sinfo->htab->size; a < end; a++)
+    {
+      register hashval_t hash;
+      unsigned int c;
+      unsigned int i;
+      const unsigned char *s;
+      PTR *p;
+
+      e = *a;
+      e->u.entsize = sinfo->htab->entsize;
+      if (e->len <= e->u.entsize)
+       break;
+      if (e->len > 4 * e->u.entsize)
+       {
+         s = e->root.string + e->len - e->u.entsize;
+         hash = 0;
+         for (i = 0; i < 4 * e->u.entsize; i++)
            {
-             if (secinfo->first == NULL)
-               secinfo->first = entry;
-             entry->sec = sec;
+             c = *--s;
+             hash += c + (c << 17);
+             hash ^= hash >> 2;
+           }
+         p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
+         if (p == NULL)
+           goto alloc_failure;
+         if (*p)
+           {
+             struct sec_merge_hash_entry *ent;
+
+             ent = (struct sec_merge_hash_entry *) *p;
+             e->u.suffix = ent;
+             e->alignment = 0;
+             continue;
            }
+         else
+           *p = (PTR) e;
+       }
+      s = e->root.string + e->len - e->u.entsize;
+      hash = 0;
+      for (i = 0; i < e->u.entsize; i++)
+       {
+         c = *--s;
+         hash += c + (c << 17);
+         hash ^= hash >> 2;
+       }
+      p = htab_find_slot_with_hash (lasttab, e, hash, INSERT);
+      if (p == NULL)
+       goto alloc_failure;
+      if (*p)
+       {
+         struct sec_merge_hash_entry *ent;
+
+         ent = (struct sec_merge_hash_entry *) *p;
+         e->u.suffix = ent;
+         e->alignment = 0;
        }
+      else
+       *p = (PTR) e;
     }
 
-  sec->_cooked_size = sinfo->htab->size;
-  if (!sec->_cooked_size)
-    sec->flags |= SEC_EXCLUDE;
-  sinfo->last = sec;
-  return true;
+alloc_failure:
+  if (array)
+    free (array);
+  if (lasttab)
+    htab_delete (lasttab);
+  if (last4tab)
+    htab_delete (last4tab);
+
+  /* Now assign positions to the strings we want to keep.  */
+  size = 0;
+  secinfo = sinfo->htab->first->secinfo;
+  for (e = sinfo->htab->first; e; e = e->next)
+    {
+      if (e->secinfo != secinfo)
+       {
+         secinfo->sec->_cooked_size = size;
+         secinfo = e->secinfo;
+       }
+      if (e->alignment)
+       {
+         if (e->secinfo->first == NULL)
+           {
+             e->secinfo->first = e;
+             size = 0;
+           }
+         size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
+         e->u.index = size;
+         size += e->len;
+       }
+    }
+  secinfo->sec->_cooked_size = size;
+
+  /* And now adjust the rest, removing them from the chain (but not hashtable)
+     at the same time.  */
+  for (a = &sinfo->htab->first, e = *a; e; e = e->next)
+    if (e->alignment)
+      a = &e->next;
+    else
+      {
+       *a = e->next;
+       if (e->len)
+         {
+           e->secinfo = e->u.suffix->secinfo;
+           e->alignment = e->u.suffix->alignment;
+           e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
+         }
+      }
+}
 
- error_return:
-  if (*psecinfo != NULL)
-    free (*psecinfo);
-  *psecinfo = NULL;
-  return false;
+/* This function is called once after all SEC_MERGE sections are registered
+   with _bfd_merge_section.  */
+
+boolean
+_bfd_merge_sections (abfd, xsinfo)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     PTR xsinfo;
+{
+  struct sec_merge_info *sinfo;
+
+  for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
+    {
+      struct sec_merge_sec_info * secinfo;
+
+      if (! sinfo->chain)
+       continue;
+
+      /* Move sinfo->chain to head of the chain, terminate it.  */
+      secinfo = sinfo->chain;
+      sinfo->chain = secinfo->next;
+      secinfo->next = NULL;
+
+      /* Record the sections into the hash table.  */
+      for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
+       if (secinfo->sec->flags & SEC_EXCLUDE)
+         *secinfo->psecinfo = NULL;
+       else if (! record_section (sinfo, secinfo))
+         break;
+
+      if (secinfo)
+       continue;
+
+      if (sinfo->htab->strings)
+       merge_strings (sinfo);
+      else
+       {
+         struct sec_merge_hash_entry *e;
+         bfd_size_type size = 0;
+
+         /* Things are much simpler for non-strings.
+            Just assign them slots in the section.  */
+         secinfo = NULL;
+         for (e = sinfo->htab->first; e; e = e->next)
+           {
+             if (e->secinfo->first == NULL)
+               {
+                 if (secinfo)
+                   secinfo->sec->_cooked_size = size;
+                 e->secinfo->first = e;
+                 size = 0;
+               }
+             size = (size + e->alignment - 1)
+                    & ~((bfd_vma) e->alignment - 1);
+             e->u.index = size;
+             size += e->len;
+             secinfo = e->secinfo;
+           }
+         secinfo->sec->_cooked_size = size;
+       }
+
+       /* Finally shrink all input sections which have not made it into
+          the hash table at all.  */
+       for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
+         if (secinfo->first == NULL)
+           {
+             secinfo->sec->_cooked_size = 0;
+             secinfo->sec->flags |= SEC_EXCLUDE;
+           }
+    }
+
+  return true;
 }
 
 /* Write out the merged section.  */
@@ -619,6 +936,6 @@ _bfd_merged_section_offset (output_bfd, psec, psecinfo, offset, addend)
          - entry->len;
     }
 
-  *psec = entry->sec;
-  return entry->index + (secinfo->contents + offset - p);
+  *psec = entry->secinfo->sec;
+  return entry->u.index + (secinfo->contents + offset - p);
 }
index 02ba031..c1b086b 100644 (file)
@@ -1,5 +1,5 @@
 /* Target definitions for 32/64-bit NLM (NetWare Loadable Module)
-   Copyright 1993, 1994, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
   bfd_generic_get_relocated_section_contents
 #define nlm_bfd_relax_section bfd_generic_relax_section
 #define nlm_bfd_gc_sections bfd_generic_gc_sections
+#define nlm_bfd_merge_sections bfd_generic_merge_sections
 #define nlm_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define nlm_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define nlm_bfd_final_link _bfd_generic_final_link
index 6552a1d..47e30cb 100644 (file)
@@ -1476,6 +1476,7 @@ oasys_sizeof_headers (abfd, exec)
   bfd_generic_get_relocated_section_contents
 #define oasys_bfd_relax_section bfd_generic_relax_section
 #define oasys_bfd_gc_sections bfd_generic_gc_sections
+#define oasys_bfd_merge_sections bfd_generic_merge_sections
 #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define oasys_bfd_final_link _bfd_generic_final_link
index b2250a0..eccbe79 100644 (file)
@@ -475,6 +475,7 @@ ppcboot_bfd_print_private_bfd_data (abfd, farg)
   bfd_generic_get_relocated_section_contents
 #define ppcboot_bfd_relax_section bfd_generic_relax_section
 #define ppcboot_bfd_gc_sections bfd_generic_gc_sections
+#define ppcboot_bfd_merge_sections bfd_generic_merge_sections
 #define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define ppcboot_bfd_final_link _bfd_generic_final_link
index 226d1e9..5823a23 100644 (file)
@@ -3254,6 +3254,28 @@ bfd_generic_gc_sections (abfd, link_info)
 
 /*
 INTERNAL_FUNCTION
+       bfd_generic_merge_sections
+
+SYNOPSIS
+       boolean bfd_generic_merge_sections
+        (bfd *, struct bfd_link_info *);
+
+DESCRIPTION
+       Provides default handling for SEC_MERGE section merging for back ends
+       which don't have SEC_MERGE support -- i.e., does nothing.
+*/
+
+/*ARGSUSED*/
+boolean
+bfd_generic_merge_sections (abfd, link_info)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+/*
+INTERNAL_FUNCTION
        bfd_generic_get_relocated_section_contents
 
 SYNOPSIS
index 50cdbf9..f92b7a0 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -6286,6 +6286,7 @@ som_bfd_link_split_section (abfd, sec)
 #define som_bfd_final_link _bfd_generic_final_link
 
 #define som_bfd_gc_sections            bfd_generic_gc_sections
+#define som_bfd_merge_sections         bfd_generic_merge_sections
 
 const bfd_target som_vec = {
   "som",                       /* name */
index 33dfaa7..43ac9a5 100644 (file)
@@ -1262,6 +1262,7 @@ srec_print_symbol (ignore_abfd, afile, symbol, how)
   bfd_generic_get_relocated_section_contents
 #define srec_bfd_relax_section bfd_generic_relax_section
 #define srec_bfd_gc_sections bfd_generic_gc_sections
+#define srec_bfd_merge_sections bfd_generic_merge_sections
 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define srec_bfd_final_link _bfd_generic_final_link
index 0e2ca4d..c46ecc3 100644 (file)
@@ -416,7 +416,8 @@ BFD_JUMP_TABLE macros.
 .CAT(NAME,_bfd_link_add_symbols),\
 .CAT(NAME,_bfd_final_link),\
 .CAT(NAME,_bfd_link_split_section),\
-.CAT(NAME,_bfd_gc_sections)
+.CAT(NAME,_bfd_gc_sections),\
+.CAT(NAME,_bfd_merge_sections)
 .  int        (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
 .  bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
 .                    struct bfd_link_info *, struct bfd_link_order *,
@@ -443,6 +444,9 @@ BFD_JUMP_TABLE macros.
 .  {* Remove sections that are not referenced from the output.  *}
 .  boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
 .
+.  {* Attempt to merge SEC_MERGE sections.  *}
+.  boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+.
 .  {* Routines to handle dynamic symbols and relocs.  *}
 .#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
 .CAT(NAME,_get_dynamic_symtab_upper_bound),\
index ccfe7d8..13ce00e 100644 (file)
@@ -1001,6 +1001,7 @@ tekhex_print_symbol (ignore_abfd, filep, symbol, how)
   bfd_generic_get_relocated_section_contents
 #define tekhex_bfd_relax_section bfd_generic_relax_section
 #define tekhex_bfd_gc_sections bfd_generic_gc_sections
+#define tekhex_bfd_merge_sections bfd_generic_merge_sections
 #define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define tekhex_bfd_final_link _bfd_generic_final_link
index 04df49a..e281d71 100644 (file)
@@ -840,6 +840,7 @@ versados_canonicalize_reloc (abfd, section, relptr, symbols)
   bfd_generic_get_relocated_section_contents
 #define versados_bfd_relax_section bfd_generic_relax_section
 #define versados_bfd_gc_sections bfd_generic_gc_sections
+#define versados_bfd_merge_sections bfd_generic_merge_sections
 #define versados_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define versados_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define versados_bfd_final_link _bfd_generic_final_link
index 273c6f9..add9c2c 100644 (file)
--- a/bfd/vms.c
+++ b/bfd/vms.c
@@ -110,6 +110,8 @@ static boolean vms_bfd_relax_section
           boolean *again));
 static boolean vms_bfd_gc_sections
   PARAMS ((bfd *abfd, struct bfd_link_info *link_info));
+static boolean vms_bfd_merge_sections
+  PARAMS ((bfd *abfd, struct bfd_link_info *link_info));
 static struct bfd_link_hash_table *vms_bfd_link_hash_table_create
   PARAMS ((bfd *abfd));
 static boolean vms_bfd_link_add_symbols
@@ -1784,6 +1786,17 @@ vms_bfd_gc_sections (abfd, link_info)
   return true;
 }
 
+static boolean
+vms_bfd_merge_sections (abfd, link_info)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+{
+#if VMS_DEBUG
+  vms_debug (1, "vms_bfd_merge_sections(%p, %p)\n", abfd, link_info);
+#endif
+  return true;
+}
+
 /* Create a hash table for the linker.  Different backends store
    different information in this table.  */
 
index a3cc0c0..0787b8d 100644 (file)
@@ -97,6 +97,7 @@ extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
   coff_bfd_get_relocated_section_contents
 #define _bfd_xcoff_bfd_relax_section coff_bfd_relax_section
 #define _bfd_xcoff_bfd_gc_sections coff_bfd_gc_sections
+#define _bfd_xcoff_bfd_merge_sections coff_bfd_merge_sections
 #define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
 
 /* XCOFF archives do not have anything which corresponds to an
index fbb3dec..3cd9391 100644 (file)
@@ -1,3 +1,7 @@
+2001-05-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * ldlang.c (lang_process): Call bfd_merge_sections.
+
 2001-05-07  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
 
        * ldgram.y: Fix typo.
index a89fcf6..6aea882 100644 (file)
@@ -4130,6 +4130,12 @@ lang_process ()
   if (command_line.gc_sections)
     lang_gc_sections ();
 
+  /* If there were any SEC_MERGE sections, finish their merging, so that
+     section sizes can be computed.  This has to be done after GC of sections,
+     so that GCed sections are not merged, but before assigning output
+     sections, since removing whole input sections is hard then.  */
+  bfd_merge_sections (output_bfd, &link_info);
+
   /* Size up the common data.  */
   lang_common ();