2003-06-23 H.J. Lu <hongjiu.lu@intel.com>
[binutils-gdb.git] / bfd / elflink.h
index 8acb7a93632a5b9e309e8dac72d27da2ab1f0ea9..75689466bea8ffa79a29618c171c7023d3bf375e 100644 (file)
@@ -5005,9 +5005,9 @@ elf_link_input_bfd (finfo, input_bfd)
             from discarded sections and section symbols from
             removed link-once sections.  Complain about relocs
             against discarded sections.  Zero relocs against removed
-            link-once sections.  */
-         if (!finfo->info->relocateable
-             && !elf_section_ignore_discarded_relocs (o))
+            link-once sections.  Preserve debug information as much
+            as we can.  */
+         if (!elf_section_ignore_discarded_relocs (o))
            {
              Elf_Internal_Rela *rel, *relend;
 
@@ -5016,6 +5016,7 @@ elf_link_input_bfd (finfo, input_bfd)
              for ( ; rel < relend; rel++)
                {
                  unsigned long r_symndx = ELF_R_SYM (rel->r_info);
+                 asection *sec;
 
                  if (r_symndx >= locsymcount
                      || (elf_bad_symtab (input_bfd)
@@ -5030,14 +5031,22 @@ elf_link_input_bfd (finfo, input_bfd)
 
                      /* Complain if the definition comes from a
                         discarded section.  */
+                     sec = h->root.u.def.section;
                      if ((h->root.type == bfd_link_hash_defined
                           || h->root.type == bfd_link_hash_defweak)
-                         && elf_discarded_section (h->root.u.def.section))
+                         && elf_discarded_section (sec))
                        {
                          if ((o->flags & SEC_DEBUGGING) != 0)
                            {
                              BFD_ASSERT (r_symndx != 0);
-                             memset (rel, 0, sizeof (*rel));
+                             /* Try to preserve debug information.  */
+                             if ((o->flags & SEC_DEBUGGING) != 0
+                                 && sec->kept_section != NULL
+                                 && sec->_raw_size == sec->kept_section->_raw_size)
+                               h->root.u.def.section
+                                 = sec->kept_section;
+                             else
+                               memset (rel, 0, sizeof (*rel));
                            }
                          else
                            finfo->info->callbacks->error_handler
@@ -5051,7 +5060,7 @@ elf_link_input_bfd (finfo, input_bfd)
                    }
                  else
                    {
-                     asection *sec = finfo->sections[r_symndx];
+                     sec = finfo->sections[r_symndx];
 
                      if (sec != NULL && elf_discarded_section (sec))
                        {
@@ -5059,9 +5068,18 @@ elf_link_input_bfd (finfo, input_bfd)
                              || (sec->flags & SEC_LINK_ONCE) != 0)
                            {
                              BFD_ASSERT (r_symndx != 0);
-                             rel->r_info
-                               = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
-                             rel->r_addend = 0;
+                             /* Try to preserve debug information.  */
+                             if ((o->flags & SEC_DEBUGGING) != 0
+                                 && sec->kept_section != NULL
+                                 && sec->_raw_size == sec->kept_section->_raw_size)
+                               finfo->sections[r_symndx]
+                                 = sec->kept_section;
+                             else
+                               {
+                                 rel->r_info
+                                   = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
+                                 rel->r_addend = 0;
+                               }
                            }
                          else
                            {
@@ -6285,23 +6303,25 @@ elf_gc_record_vtentry (abfd, sec, h, addend)
 
   if (addend >= h->vtable_entries_size)
     {
-      size_t size, bytes;
+      size_t size, bytes, file_align;
       bfd_boolean *ptr = h->vtable_entries_used;
 
       /* While the symbol is undefined, we have to be prepared to handle
         a zero size.  */
+      file_align = 1 << log_file_align;
       if (h->root.type == bfd_link_hash_undefined)
-       size = addend;
+       size = addend + file_align;
       else
        {
          size = h->size;
-         if (size < addend)
+         if (addend >= size)
            {
              /* Oops!  We've got a reference past the defined end of
                 the table.  This is probably a bug -- shall we warn?  */
-             size = addend;
+             size = addend + file_align;
            }
        }
+      size = (size + file_align - 1) & -file_align;
 
       /* Allocate one extra entry for use as a "done" flag for the
         consolidation pass.  */