Relax assertion in BFIN linker to allow for discard GOT relocs.
[binutils-gdb.git] / bfd / elf.c
index b2a50bff3e76dc942c45ee83ef183b0780e04f10..90319a2702116799567a73444d5b79772005feab 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -42,7 +42,7 @@ SECTION
 #include "elf-bfd.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
-#include "elf-linux-psinfo.h"
+#include "elf-linux-core.h"
 
 #ifdef CORE_HEADER
 #include CORE_HEADER
@@ -3355,6 +3355,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   /* SHT_GROUP sections are in relocatable files only.  */
   if (link_info == NULL || bfd_link_relocatable (link_info))
     {
+      bfd_size_type reloc_count = 0;
+
       /* Put SHT_GROUP sections first.  */
       for (sec = abfd->sections; sec != NULL; sec = sec->next)
        {
@@ -3371,7 +3373,14 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
              else
                d->this_idx = section_number++;
            }
+
+         /* Count relocations.  */
+         reloc_count += sec->reloc_count;
        }
+
+      /* Clear HAS_RELOC if there are no relocations.  */
+      if (reloc_count == 0)
+       abfd->flags &= ~HAS_RELOC;
     }
 
   for (sec = abfd->sections; sec; sec = sec->next)
@@ -7461,12 +7470,16 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
        }
       else if (bfd_is_com_section (syms[idx]->section))
        {
-#ifdef USE_STT_COMMON
-         if (type == STT_OBJECT)
-           sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON);
-         else
-#endif
-           sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
+         if (type != STT_TLS)
+           {
+             if ((abfd->flags & BFD_CONVERT_ELF_COMMON))
+               type = ((abfd->flags & BFD_USE_ELF_STT_COMMON)
+                       ? STT_COMMON : STT_OBJECT);
+             else
+               type = ((flags & BSF_ELF_COMMON) != 0
+                       ? STT_COMMON : STT_OBJECT);
+           }
+         sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
        }
       else if (bfd_is_und_section (syms[idx]->section))
        sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
@@ -9791,9 +9804,7 @@ elfcore_write_linux_prpsinfo32
 {
   struct elf_external_linux_prpsinfo32 data;
 
-  memset (&data, 0, sizeof (data));
-  LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
-
+  swap_linux_prpsinfo32_out (abfd, prpsinfo, &data);
   return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
                             &data, sizeof (data));
 }
@@ -9805,9 +9816,7 @@ elfcore_write_linux_prpsinfo64
 {
   struct elf_external_linux_prpsinfo64 data;
 
-  memset (&data, 0, sizeof (data));
-  LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data);
-
+  swap_linux_prpsinfo64_out (abfd, prpsinfo, &data);
   return elfcore_write_note (abfd, buf, bufsiz,
                             "CORE", NT_PRPSINFO, &data, sizeof (data));
 }
@@ -10455,6 +10464,12 @@ _bfd_elf_rel_local_sym (bfd *abfd,
                                     sym->st_value + addend);
 }
 
+/* Adjust an address within a section.  Given OFFSET within SEC, return
+   the new offset within the section, based upon changes made to the
+   section.  Returns -1 if the offset is now invalid.
+   The offset (in abnd out) is in target sized bytes, however big a
+   byte may be.  */
+
 bfd_vma
 _bfd_elf_section_offset (bfd *abfd,
                         struct bfd_link_info *info,
@@ -10468,12 +10483,17 @@ _bfd_elf_section_offset (bfd *abfd,
                                       offset);
     case SEC_INFO_TYPE_EH_FRAME:
       return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
+
     default:
       if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0)
        {
+         /* Reverse the offset.  */
          const struct elf_backend_data *bed = get_elf_backend_data (abfd);
          bfd_size_type address_size = bed->s->arch_size / 8;
-         offset = sec->size - offset - address_size;
+
+         /* address_size and sec->size are in octets.  Convert
+            to bytes before subtracting the original offset.  */
+         offset = (sec->size - address_size) / bfd_octets_per_byte (abfd) - offset;
        }
       return offset;
     }