bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 30 Oct 2006 23:25:51 +0000 (23:25 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 30 Oct 2006 23:25:51 +0000 (23:25 +0000)
2006-10-30  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/3111
* elf-bfd.h (elf_obj_tdata): Add symbuf.
(_bfd_elf_section_already_linked): Add struct bfd_link_info *.
(_bfd_elf_check_kept_section): Likewise.
(bfd_elf_match_symbols_in_sections): Likewise.

* elf.c (assign_section_numbers): Updated to add
struct bfd_link_info *.
(bfd_elf_match_symbols_in_sections): Updated. Cache symbol
buffer if info->reduce_memory_overheads is false.

* elflink.c (match_group_member): Updated to add
struct bfd_link_info *.
(_bfd_elf_check_kept_section): Likewise.
(elf_link_input_bfd): Likewise.
(_bfd_elf_section_already_linked): Likewise.
(bfd_elf_final_link): Free symbol buffer if
info->reduce_memory_overheads is false.

* libbfd-in.h (_bfd_nolink_section_already_linked): Add
struct bfd_link_info *.
(_bfd_generic_section_already_linked): Likewise.
* libbfd.h: Regenerated.

* linker.c (bfd_section_already_linked): Add
struct bfd_link_info *.
(_bfd_generic_section_already_linked): Likewise.
* targets.c (bfd_target): Add struct bfd_link_info * to
_section_already_linked.
* bfd-in2.h: Regenerated.

include/

2006-10-30  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/3111
* bfdlink.h (bfd_link_info): Add reduce_memory_overheads.

ld/

2006-10-30  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/3111
* ld.h (args_type): Remove reduce_memory_overheads.

* ldlang.c (lang_map): Updated.
(section_already_linked): Likewise.
(print_input_section): Likewise.
* ldmain.c (main): Likewise.
* lexsup.c (parse_args): Likewise.

16 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.c
bfd/libbfd-in.h
bfd/libbfd.h
bfd/linker.c
bfd/targets.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/ld.h
ld/ldlang.c
ld/ldmain.c
ld/lexsup.c

index ac69c75..cd3a99f 100644 (file)
@@ -1,3 +1,38 @@
+bfd/
+
+2006-10-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/3111
+       * elf-bfd.h (elf_obj_tdata): Add symbuf.
+       (_bfd_elf_section_already_linked): Add struct bfd_link_info *.
+       (_bfd_elf_check_kept_section): Likewise.
+       (bfd_elf_match_symbols_in_sections): Likewise.
+
+       * elf.c (assign_section_numbers): Updated to add
+       struct bfd_link_info *.
+       (bfd_elf_match_symbols_in_sections): Updated. Cache symbol
+       buffer if info->reduce_memory_overheads is false.
+
+       * elflink.c (match_group_member): Updated to add
+       struct bfd_link_info *.
+       (_bfd_elf_check_kept_section): Likewise.
+       (elf_link_input_bfd): Likewise.
+       (_bfd_elf_section_already_linked): Likewise.
+       (bfd_elf_final_link): Free symbol buffer if
+       info->reduce_memory_overheads is false.
+
+       * libbfd-in.h (_bfd_nolink_section_already_linked): Add
+       struct bfd_link_info *.
+       (_bfd_generic_section_already_linked): Likewise.
+       * libbfd.h: Regenerated.
+
+       * linker.c (bfd_section_already_linked): Add
+       struct bfd_link_info *.
+       (_bfd_generic_section_already_linked): Likewise.
+       * targets.c (bfd_target): Add struct bfd_link_info * to
+       _section_already_linked.
+       * bfd-in2.h: Regenerated.
+
 2006-10-30  Alan Modra  <amodra@bigpond.net.au>
 
        * bfd.c (bfd_error_type): Add bfd_error_on_input.
index eef70d3..e4c92d7 100644 (file)
@@ -5201,7 +5201,8 @@ typedef struct bfd_target
 
   /* Check if SEC has been already linked during a reloceatable or
      final link.  */
-  void (*_section_already_linked) (bfd *, struct bfd_section *);
+  void (*_section_already_linked) (bfd *, struct bfd_section *,
+                                   struct bfd_link_info *);
 
   /* Routines to handle dynamic symbols and relocs.  */
 #define BFD_JUMP_TABLE_DYNAMIC(NAME) \
@@ -5261,10 +5262,11 @@ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
 #define bfd_link_split_section(abfd, sec) \
        BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
 
-void bfd_section_already_linked (bfd *abfd, asection *sec);
+void bfd_section_already_linked (bfd *abfd, asection *sec,
+    struct bfd_link_info *info);
 
-#define bfd_section_already_linked(abfd, sec) \
-       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+#define bfd_section_already_linked(abfd, sec, info) \
+       BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
 
 /* Extracted from simple.c.  */
 bfd_byte *bfd_simple_get_relocated_section_contents
index bb86c4e..85a7693 100644 (file)
@@ -1404,6 +1404,9 @@ struct elf_obj_tdata
 
   /* Used to determine if the e_flags field has been initialized */
   bfd_boolean flags_init;
+
+  /* Symbol buffer.  */
+  Elf_Internal_Sym *symbuf;
 };
 
 #define elf_tdata(bfd)         ((bfd) -> tdata.elf_obj_data)
@@ -1538,11 +1541,11 @@ extern bfd_boolean _bfd_elf_match_sections_by_type
 extern bfd_boolean bfd_elf_is_group_section
   (bfd *, const struct bfd_section *);
 extern void _bfd_elf_section_already_linked
-  (bfd *, struct bfd_section *);
+  (bfd *, struct bfd_section *, struct bfd_link_info *);
 extern void bfd_elf_set_group_contents
   (bfd *, asection *, void *);
 extern asection *_bfd_elf_check_kept_section
-  (asection *);
+  (asection *, struct bfd_link_info *);
 extern void _bfd_elf_link_just_syms
   (asection *, struct bfd_link_info *);
 extern bfd_boolean _bfd_elf_copy_private_header_data
@@ -1744,7 +1747,7 @@ extern bfd_boolean _bfd_elf_symbol_refs_local_p
   (struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean);
 
 extern bfd_boolean bfd_elf_match_symbols_in_sections
-  (asection *sec1, asection *sec2);
+  (asection *, asection *, struct bfd_link_info *);
 
 extern bfd_boolean _bfd_elf_setup_sections
   (bfd *);
index 747310b..2594e21 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3173,7 +3173,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                         s, s->owner);
                      /* Point to the kept section if it has the same
                         size as the discarded one.  */
-                     kept = _bfd_elf_check_kept_section (s);
+                     kept = _bfd_elf_check_kept_section (s, link_info);
                      if (kept == NULL)
                        {
                          bfd_set_error (bfd_error_bad_value);
@@ -8674,7 +8674,8 @@ elf_sym_name_compare (const void *arg1, const void *arg2)
    symbols.  */
 
 bfd_boolean
-bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2)
+bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
+                                  struct bfd_link_info *info)
 {
   bfd *bfd1, *bfd2;
   const struct elf_backend_data *bed1, *bed2;
@@ -8730,21 +8731,37 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2)
   if (symcount1 == 0 || symcount2 == 0)
     return FALSE;
 
-  isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
-                                  NULL, NULL, NULL);
-  isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
-                                  NULL, NULL, NULL);
-
   result = FALSE;
-  if (isymbuf1 == NULL || isymbuf2 == NULL)
-    goto done;
+  isymbuf1 = elf_tdata (bfd1)->symbuf;
+  isymbuf2 = elf_tdata (bfd2)->symbuf;
 
-  /* Sort symbols by binding and section. Global definitions are at
-     the beginning.  */
-  qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym),
-        elf_sort_elf_symbol);
-  qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym),
-        elf_sort_elf_symbol);
+  if (isymbuf1 == NULL)
+    {
+      isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
+                                      NULL, NULL, NULL);
+      if (isymbuf1 == NULL)
+       goto done;
+      /* Sort symbols by binding and section. Global definitions are at
+        the beginning.  */
+      qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym),
+            elf_sort_elf_symbol);
+      if (!info->reduce_memory_overheads)
+       elf_tdata (bfd1)->symbuf = isymbuf1;
+    }
+
+  if (isymbuf2 == NULL)
+    {
+      isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
+                                      NULL, NULL, NULL);
+      if (isymbuf2 == NULL)
+       goto done;
+      /* Sort symbols by binding and section. Global definitions are at
+        the beginning.  */
+      qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym),
+            elf_sort_elf_symbol);
+      if (!info->reduce_memory_overheads)
+       elf_tdata (bfd2)->symbuf = isymbuf2;
+    }
 
   /* Count definitions in the section.  */
   count1 = 0;
@@ -8828,10 +8845,13 @@ done:
     free (symtable1);
   if (symtable2)
     free (symtable2);
-  if (isymbuf1)
-    free (isymbuf1);
-  if (isymbuf2)
-    free (isymbuf2);
+  if (info->reduce_memory_overheads)
+    {
+      if (isymbuf1)
+       free (isymbuf1);
+      if (isymbuf2)
+       free (isymbuf2);
+    }
 
   return result;
 }
index 1dad504..df7b899 100644 (file)
@@ -7267,14 +7267,15 @@ _bfd_elf_default_action_discarded (asection *sec)
 /* Find a match between a section and a member of a section group.  */
 
 static asection *
-match_group_member (asection *sec, asection *group)
+match_group_member (asection *sec, asection *group,
+                   struct bfd_link_info *info)
 {
   asection *first = elf_next_in_group (group);
   asection *s = first;
 
   while (s != NULL)
     {
-      if (bfd_elf_match_symbols_in_sections (s, sec))
+      if (bfd_elf_match_symbols_in_sections (s, sec, info))
        return s;
 
       s = elf_next_in_group (s);
@@ -7290,7 +7291,7 @@ match_group_member (asection *sec, asection *group)
    NULL. */
 
 asection *
-_bfd_elf_check_kept_section (asection *sec)
+_bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
 {
   asection *kept;
 
@@ -7298,7 +7299,7 @@ _bfd_elf_check_kept_section (asection *sec)
   if (kept != NULL)
     {
       if (elf_sec_group (sec) != NULL)
-       kept = match_group_member (sec, kept);
+       kept = match_group_member (sec, kept, info);
       if (kept != NULL && sec->size != kept->size)
        kept = NULL;
     }
@@ -7651,7 +7652,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                        {
                          asection *kept;
 
-                         kept = _bfd_elf_check_kept_section (sec);
+                         kept = _bfd_elf_check_kept_section (sec,
+                                                             finfo->info);
                          if (kept != NULL)
                            {
                              *ps = kept;
@@ -8800,6 +8802,17 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
+  /* Free symbol buffer if needed.  */
+  if (!info->reduce_memory_overheads)
+    {
+      for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+       if (elf_tdata (sub)->symbuf)
+         {
+           free (elf_tdata (sub)->symbuf);
+           elf_tdata (sub)->symbuf = NULL;
+         }
+    }
+
   /* Output any global symbols that got converted to local in a
      version script or due to symbol visibility.  We do this in a
      separate step since ELF requires all local symbols to appear
@@ -10296,7 +10309,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
 }
 
 void
-_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
+_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
+                                struct bfd_link_info *info)
 {
   flagword flags;
   const char *name, *p;
@@ -10462,7 +10476,8 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
        if ((l->sec->flags & SEC_GROUP) == 0
            && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL
            && bfd_elf_match_symbols_in_sections (l->sec,
-                                                 elf_next_in_group (sec)))
+                                                 elf_next_in_group (sec),
+                                                 info))
          {
            elf_next_in_group (sec)->output_section = bfd_abs_section_ptr;
            elf_next_in_group (sec)->kept_section = l->sec;
@@ -10483,7 +10498,7 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 
          if (first != NULL
              && elf_next_in_group (first) == first
-             && bfd_elf_match_symbols_in_sections (first, sec))
+             && bfd_elf_match_symbols_in_sections (first, sec, info))
            {
              sec->output_section = bfd_abs_section_ptr;
              sec->kept_section = l->sec;
index 52172c1..a9c96db 100644 (file)
@@ -410,7 +410,7 @@ extern bfd_boolean _bfd_generic_set_section_contents
 #define _bfd_nolink_bfd_link_split_section \
   ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
 #define _bfd_nolink_section_already_linked \
-  ((void (*) (bfd *, struct bfd_section *)) bfd_void)
+  ((void (*) (bfd *, struct bfd_section *, struct bfd_link_info *)) bfd_void)
 
 /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not
    have dynamic symbols or relocs.  Use BFD_JUMP_TABLE_DYNAMIC
@@ -524,7 +524,7 @@ extern bfd_boolean _bfd_generic_link_split_section
   (bfd *, struct bfd_section *);
 
 extern void _bfd_generic_section_already_linked
-  (bfd *, struct bfd_section *);
+  (bfd *, struct bfd_section *, struct bfd_link_info *);
 
 /* Generic reloc_link_order processing routine.  */
 extern bfd_boolean _bfd_generic_reloc_link_order
index a4c4f01..92dfc15 100644 (file)
@@ -415,7 +415,7 @@ extern bfd_boolean _bfd_generic_set_section_contents
 #define _bfd_nolink_bfd_link_split_section \
   ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
 #define _bfd_nolink_section_already_linked \
-  ((void (*) (bfd *, struct bfd_section *)) bfd_void)
+  ((void (*) (bfd *, struct bfd_section *, struct bfd_link_info *)) bfd_void)
 
 /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not
    have dynamic symbols or relocs.  Use BFD_JUMP_TABLE_DYNAMIC
@@ -529,7 +529,7 @@ extern bfd_boolean _bfd_generic_link_split_section
   (bfd *, struct bfd_section *);
 
 extern void _bfd_generic_section_already_linked
-  (bfd *, struct bfd_section *);
+  (bfd *, struct bfd_section *, struct bfd_link_info *);
 
 /* Generic reloc_link_order processing routine.  */
 extern bfd_boolean _bfd_generic_reloc_link_order
index 8d881c6..b9aaf00 100644 (file)
@@ -2876,14 +2876,15 @@ FUNCTION
        bfd_section_already_linked
 
 SYNOPSIS
-        void bfd_section_already_linked (bfd *abfd, asection *sec);
+        void bfd_section_already_linked (bfd *abfd, asection *sec,
+                                        struct bfd_link_info *info);
 
 DESCRIPTION
        Check if @var{sec} has been already linked during a reloceatable
        or final link.
 
-.#define bfd_section_already_linked(abfd, sec) \
-.       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.#define bfd_section_already_linked(abfd, sec, info) \
+.       BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
 .
 
 */
@@ -2969,7 +2970,8 @@ bfd_section_already_linked_table_free (void)
 /* This is used on non-ELF inputs.  */
 
 void
-_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec,
+                                    struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   flagword flags;
   const char *name;
index dac1136..71e3337 100644 (file)
@@ -481,7 +481,8 @@ BFD_JUMP_TABLE macros.
 .
 .  {* Check if SEC has been already linked during a reloceatable or
 .     final link.  *}
-.  void (*_section_already_linked) (bfd *, struct bfd_section *);
+.  void (*_section_already_linked) (bfd *, struct bfd_section *,
+.                                  struct bfd_link_info *);
 .
 .  {* Routines to handle dynamic symbols and relocs.  *}
 .#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
index 23841a5..3edbe8d 100644 (file)
@@ -1,3 +1,8 @@
+2006-10-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/3111
+       * bfdlink.h (bfd_link_info): Add reduce_memory_overheads.
+
 2006-10-25  Trevor Smigiel  <Trevor_Smigiel@playstation.sony.com>
            Yukishige Shibata  <shibata@rd.scei.sony.co.jp>
            Nobuhisa Fujinami  <fnami@rd.scei.sony.co.jp>
index 0cc9177..228cab8 100644 (file)
@@ -335,6 +335,11 @@ struct bfd_link_info
   /* TRUE if .gnu.hash section should be created.  */
   unsigned int emit_gnu_hash: 1;
 
+  /* If TRUE reduce memory overheads, at the expense of speed. This will
+     cause map file generation to use an O(N^2) algorithm and disable
+     caching ELF symbol buffer.  */
+  unsigned int reduce_memory_overheads: 1;
+
   /* What to do with unresolved symbols in an object file.
      When producing executables the default is GENERATE_ERROR.
      When producing shared libraries the default is IGNORE.  The
index e3864b7..314d6fe 100644 (file)
@@ -1,3 +1,14 @@
+2006-10-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/3111
+       * ld.h (args_type): Remove reduce_memory_overheads.
+
+       * ldlang.c (lang_map): Updated.
+       (section_already_linked): Likewise.
+       (print_input_section): Likewise.
+       * ldmain.c (main): Likewise.
+       * lexsup.c (parse_args): Likewise.
+
 2006-10-29  Pedro Alves  <pedro_alves@portugalmail.pt>
 
        * pe-dll.c (make_singleton_name_thunk): Re-add the NULL terminator.
diff --git a/ld/ld.h b/ld/ld.h
index 0b574d5..0b978e5 100644 (file)
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -200,11 +200,6 @@ typedef struct {
      behaviour of the linker.  The new default behaviour is to reject such
      input files.  */
   bfd_boolean accept_unknown_input_arch;
-
-  /* If TRUE reduce memory overheads, at the expense of speed.
-     This will cause map file generation to use an O(N^2) algorithm.  */
-  bfd_boolean reduce_memory_overheads;
-
 } args_type;
 
 extern args_type command_line;
index 5df5170..a5ceabd 100644 (file)
@@ -1794,7 +1794,7 @@ lang_map (void)
 
   fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
 
-  if (! command_line.reduce_memory_overheads)
+  if (! link_info.reduce_memory_overheads)
     {
       obstack_begin (&map_obstack, 1000);
       for (p = link_info.input_bfds; p != (bfd *) NULL; p = p->link_next)
@@ -1873,7 +1873,7 @@ init_os (lang_output_section_statement_type *s, asection *isec,
   s->bfd_section->output_section = s->bfd_section;
   s->bfd_section->output_offset = 0;
 
-  if (!command_line.reduce_memory_overheads)
+  if (!link_info.reduce_memory_overheads)
     {
       fat_section_userdata_type *new
        = stat_alloc (sizeof (fat_section_userdata_type));
@@ -1966,7 +1966,7 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
     }
 
   if (!(abfd->flags & DYNAMIC))
-    bfd_section_already_linked (abfd, sec);
+    bfd_section_already_linked (abfd, sec, &link_info);
 }
 \f
 /* The wild routines.
@@ -3659,7 +3659,7 @@ print_input_section (asection *i)
 
   if (i->output_section != NULL && i->output_section->owner == output_bfd)
     {
-      if (command_line.reduce_memory_overheads)
+      if (link_info.reduce_memory_overheads)
        bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
       else
        print_all_symbols (i);
index bc03e02..1784b16 100644 (file)
@@ -256,7 +256,6 @@ main (int argc, char **argv)
   command_line.warn_mismatch = TRUE;
   command_line.check_section_addresses = TRUE;
   command_line.accept_unknown_input_arch = FALSE;
-  command_line.reduce_memory_overheads = FALSE;
 
   sort_section = none;
 
@@ -320,6 +319,7 @@ main (int argc, char **argv)
   link_info.gc_sections = FALSE;
   link_info.print_gc_sections = FALSE;
   link_info.dynamic = NULL;
+  link_info.reduce_memory_overheads = FALSE;
 
   config.maxpagesize = 0;
   config.commonpagesize = 0;
index 1d267f4..347d6fc 100644 (file)
@@ -1370,7 +1370,7 @@ parse_args (unsigned argc, char **argv)
          break;
 
        case OPTION_REDUCE_MEMORY_OVERHEADS:
-         command_line.reduce_memory_overheads = TRUE;
+         link_info.reduce_memory_overheads = TRUE;
          if (config.hash_table_size == 0)
            config.hash_table_size = 1021;
          break;