Hello,

this patch improves COFF linker for undefined weak symbols
and avoids writing symbols for discarded sections - if linker tells so
-, and for IR generated sections.

ChangeLog

2011-10-09  Kai Tietz  <kti...@redhat.com>

        * cofflink.c (coff_link_check_ar_symbols): Allow
        adding of archive-file if symbol was undefined weak.
        (_bfd_coff_write_global_sym): Skip write for symbol
        in discared section, or if section is coming from IR, or
        if input section has explicit SEC_EXCLUDED set.
        (_bfd_coff_generic_relocate_section): For undefined weak
        symbol and replacing it by another undefined weak, mark
        section as absolute.

Regression tested for i686-w64-mingw32, x86_64-w64-mingw32, and
i686-pc-cygwin.  Ok for apply?

Regards,
Kai


Index: src/bfd/cofflink.c
===================================================================
--- src.orig/bfd/cofflink.c
+++ src/bfd/cofflink.c
@@ -242,7 +242,8 @@ coff_link_check_ar_symbols (bfd *abfd,
             COFF linkers do not bring in an object file which defines
             it.  */
          if (h != (struct bfd_link_hash_entry *) NULL
-             && h->type == bfd_link_hash_undefined)
+             && (h->type == bfd_link_hash_undefined
+                 || h->type == bfd_link_hash_undefweak))
            {
              if (!(*info->callbacks
                    ->add_archive_element) (info, abfd, name, subsbfd))
@@ -2527,6 +2528,7 @@ _bfd_coff_write_global_sym (struct bfd_h
   bfd_size_type symesz;
   unsigned int i;
   file_ptr pos;
+  asection *input_sec;

   output_bfd = finfo->output_bfd;

@@ -2547,6 +2549,21 @@ _bfd_coff_write_global_sym (struct bfd_h
                                   h->root.root.string, FALSE, FALSE)
                  == NULL))))
     return TRUE;
+  else if (h->indx != -2
+           && (h->root.type == bfd_link_hash_defined
+              || h->root.type == bfd_link_hash_defweak)
+          && ((finfo->info->strip_discarded
+               && !bfd_is_abs_section (h->root.u.def.section)
+               && bfd_is_abs_section (h->root.u.def.section->output_section))
+              || (h->root.u.def.section->owner != NULL
+                  && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)))
+    return TRUE;
+  else if (h->indx != -2
+           && (h->root.type == bfd_link_hash_undefined
+              || h->root.type == bfd_link_hash_undefweak)
+          && h->root.u.undef.abfd != NULL
+          && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
+    return TRUE;

   switch (h->root.type)
     {
@@ -2560,26 +2577,37 @@ _bfd_coff_write_global_sym (struct bfd_h
     case bfd_link_hash_undefweak:
       isym.n_scnum = N_UNDEF;
       isym.n_value = 0;
+      input_sec = bfd_und_section_ptr;
       break;

     case bfd_link_hash_defined:
     case bfd_link_hash_defweak:
-      {
-       asection *sec;
+      input_sec = h->root.u.def.section;
+      if (input_sec->output_section != NULL)
+       {
+         asection *sec;

-       sec = h->root.u.def.section->output_section;
-       if (bfd_is_abs_section (sec))
-         isym.n_scnum = N_ABS;
-       else
-         isym.n_scnum = sec->target_index;
-       isym.n_value = (h->root.u.def.value
-                       + h->root.u.def.section->output_offset);
-       if (! obj_pe (finfo->output_bfd))
-         isym.n_value += sec->vma;
-      }
+         sec = h->root.u.def.section->output_section;
+         if (bfd_is_abs_section (sec))
+           isym.n_scnum = N_ABS;
+         else
+           isym.n_scnum = sec->target_index;
+         isym.n_value = (h->root.u.def.value
+                         + h->root.u.def.section->output_offset);
+         if (! obj_pe (finfo->output_bfd))
+           isym.n_value += sec->vma;
+       }
+      else
+        {
+         BFD_ASSERT (input_sec->owner == NULL);
+         isym.n_scnum = N_UNDEF;
+         isym.n_value = 0;
+         input_sec = bfd_und_section_ptr;
+       }
       break;

     case bfd_link_hash_common:
+      input_sec = h->root.u.c.p->section;
       isym.n_scnum = N_UNDEF;
       isym.n_value = h->root.u.c.size;
       break;
@@ -2589,6 +2617,9 @@ _bfd_coff_write_global_sym (struct bfd_h
       return TRUE;
     }

+  if ((input_sec->flags & SEC_EXCLUDE) != 0)
+    return TRUE;
+
   if (strlen (h->root.root.string) <= SYMNMLEN)
     strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
   else
@@ -3013,7 +3044,8 @@ _bfd_coff_generic_relocate_section (bfd
                    h->auxbfd->tdata.coff_obj_data->sym_hashes[
                    h->aux->x_sym.x_tagndx.l];

-                 if (!h2 || h2->root.type == bfd_link_hash_undefined)
+                 if (!h2 || h2->root.type == bfd_link_hash_undefined
+                     || h2->root.type == bfd_link_hash_undefweak)
                    {
                      sec = bfd_abs_section_ptr;
                      val = 0;

Reply via email to