Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index c7d8bca710215008a452908c8bb7903500cdb893..ecd4c6d03c6d8c946b0260bc18cbb165e7bbfc90 100644 (file)
@@ -1426,7 +1426,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
          break;
        }
 
-      if (!h->def_regular && !h->def_dynamic)
+      if (!SYMBOL_DEFINED_NON_SHARED_P (h) && !h->def_dynamic)
        und = _("undefined ");
     }
   else
@@ -1855,6 +1855,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       const char *name;
       bfd_boolean size_reloc;
       bfd_boolean converted_reloc;
+      bfd_boolean do_check_pic;
 
       r_symndx = htab->r_sym (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -2130,6 +2131,13 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
          size_reloc = TRUE;
          goto do_size;
 
+       case R_X86_64_PC8:
+       case R_X86_64_PC16:
+       case R_X86_64_PC32:
+       case R_X86_64_PC32_BND:
+         do_check_pic = TRUE;
+         goto check_pic;
+
        case R_X86_64_32:
          if (!ABI_64_P (abfd))
            goto pointer;
@@ -2153,13 +2161,11 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                                        &x86_64_elf_howto_table[r_type]);
          /* Fall through.  */
 
-       case R_X86_64_PC8:
-       case R_X86_64_PC16:
-       case R_X86_64_PC32:
-       case R_X86_64_PC32_BND:
        case R_X86_64_PC64:
        case R_X86_64_64:
 pointer:
+         do_check_pic = FALSE;
+check_pic:
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->zero_undefweak |= 0x2;
          /* We are called after all symbols have been resolved.  Only
@@ -2223,6 +2229,69 @@ pointer:
                }
            }
 
+         if (do_check_pic)
+           {
+             /* Don't complain about -fPIC if the symbol is undefined
+                when building executable unless it is unresolved weak
+                symbol, references a dynamic definition in PIE or
+                -z nocopyreloc is used.  */
+             bfd_boolean no_copyreloc_p
+               = (info->nocopyreloc
+                  || (h != NULL
+                      && !h->root.linker_def
+                      && !h->root.ldscript_def
+                      && eh->def_protected
+                      && elf_has_no_copy_on_protected (h->root.u.def.section->owner)));
+             if ((sec->flags & SEC_ALLOC) != 0
+                 && (sec->flags & SEC_READONLY) != 0
+                 && h != NULL
+                 && ((bfd_link_executable (info)
+                      && ((h->root.type == bfd_link_hash_undefweak
+                           && (eh == NULL
+                               || !UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+                                                                    eh)))
+                          || (bfd_link_pie (info)
+                              && !SYMBOL_DEFINED_NON_SHARED_P (h)
+                              && h->def_dynamic)
+                          || (no_copyreloc_p
+                              && h->def_dynamic
+                              && !(h->root.u.def.section->flags & SEC_CODE))))
+                     || bfd_link_dll (info)))
+               {
+                 bfd_boolean fail = FALSE;
+                 if (SYMBOL_REFERENCES_LOCAL_P (info, h))
+                   {
+                     /* Symbol is referenced locally.  Make sure it is
+                        defined locally.  */
+                     fail = !SYMBOL_DEFINED_NON_SHARED_P (h);
+                   }
+                 else if (bfd_link_pie (info))
+                   {
+                     /* We can only use PC-relative relocations in PIE
+                        from non-code sections.  */
+                     if (h->type == STT_FUNC
+                         && (sec->flags & SEC_CODE) != 0)
+                       fail = TRUE;
+                   }
+                 else if (no_copyreloc_p || bfd_link_dll (info))
+                   {
+                     /* Symbol doesn't need copy reloc and isn't
+                        referenced locally.  Don't allow PC-relative
+                        relocations against default and protected
+                        symbols since address of protected function
+                        and location of protected data may not be in
+                        the shared object.   */
+                     fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                             || ELF_ST_VISIBILITY (h->other) == STV_PROTECTED);
+                   }
+
+                 if (fail)
+                   return elf_x86_64_need_pic (info, abfd, sec, h,
+                                               symtab_hdr, isym,
+                                               &x86_64_elf_howto_table[r_type]);
+               }
+           }
+
          size_reloc = FALSE;
 do_size:
          if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
@@ -2944,14 +3013,14 @@ skip_ifunc:
                       && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
                {
                  _bfd_error_handler
-             /* xgettext:c-format */
+                   /* xgettext:c-format */
                    (_("%pB: relocation R_X86_64_GOTOFF64 against protected %s"
                       " `%s' can not be used when making a shared object"),
                     input_bfd,
                     h->type == STT_FUNC ? "function" : "data",
                     h->root.root.string);
                  bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+                 return FALSE;
                }
            }
 
@@ -3065,56 +3134,14 @@ use_plt:
        case R_X86_64_PC16:
        case R_X86_64_PC32:
        case R_X86_64_PC32_BND:
-         /* Don't complain about -fPIC if the symbol is undefined when
-            building executable unless it is unresolved weak symbol,
-            references a dynamic definition in PIE or -z nocopyreloc
-            is used.  */
-         if ((input_section->flags & SEC_ALLOC) != 0
-             && (input_section->flags & SEC_READONLY) != 0
-             && h != NULL
-             && ((bfd_link_executable (info)
-                  && ((h->root.type == bfd_link_hash_undefweak
-                       && !resolved_to_zero)
-                      || (bfd_link_pie (info)
-                          && !h->def_regular
-                          && h->def_dynamic)
-                      || ((info->nocopyreloc
-                           || (eh->def_protected
-                               && elf_has_no_copy_on_protected (h->root.u.def.section->owner)))
-                          && h->def_dynamic
-                          && !(h->root.u.def.section->flags & SEC_CODE))))
-                 || bfd_link_dll (info)))
-           {
-             bfd_boolean fail = FALSE;
-             if (SYMBOL_REFERENCES_LOCAL_P (info, h))
-               {
-                 /* Symbol is referenced locally.  Make sure it is
-                    defined locally.  */
-                 fail = !(h->def_regular || ELF_COMMON_DEF_P (h));
-               }
-             else if (!(bfd_link_pie (info)
-                        && (h->needs_copy || eh->needs_copy)))
-               {
-                 /* Symbol doesn't need copy reloc and isn't referenced
-                    locally.  Address of protected function may not be
-                    reachable at run-time.  */
-                 fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                         || (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED
-                             && h->type == STT_FUNC));
-               }
-
-             if (fail)
-               return elf_x86_64_need_pic (info, input_bfd, input_section,
-                                           h, NULL, NULL, howto);
-           }
          /* Since x86-64 has PC-relative PLT, we can use PLT in PIE
             as function address.  */
-         else if (h != NULL
-                  && (input_section->flags & SEC_CODE) == 0
-                  && bfd_link_pie (info)
-                  && h->type == STT_FUNC
-                  && !h->def_regular
-                  && h->def_dynamic)
+         if (h != NULL
+             && (input_section->flags & SEC_CODE) == 0
+             && bfd_link_pie (info)
+             && h->type == STT_FUNC
+             && !h->def_regular
+             && h->def_dynamic)
            goto use_plt;
          /* Fall through.  */
 
@@ -3334,20 +3361,39 @@ direct:
                    {
                      if (contents[roff + 5] == 0xb8)
                        {
+                         if (roff < 3
+                             || (roff - 3 + 22) > input_section->size)
+                           {
+corrupt_input:
+                             info->callbacks->einfo
+                               (_("%F%P: corrupt input: %pB\n"),
+                                input_bfd);
+                             return FALSE;
+                           }
                          memcpy (contents + roff - 3,
                                  "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80"
                                  "\0\0\0\0\x66\x0f\x1f\x44\0", 22);
                          largepic = 1;
                        }
                      else
-                       memcpy (contents + roff - 4,
-                               "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
-                               16);
+                       {
+                         if (roff < 4
+                             || (roff - 4 + 16) > input_section->size)
+                           goto corrupt_input;
+                         memcpy (contents + roff - 4,
+                                 "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
+                                 16);
+                       }
                    }
                  else
-                   memcpy (contents + roff - 3,
-                           "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
-                           15);
+                   {
+                     if (roff < 3
+                         || (roff - 3 + 15) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + roff - 3,
+                             "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
+                             15);
+                   }
                  bfd_put_32 (output_bfd,
                              elf_x86_64_tpoff (info, relocation),
                              contents + roff + 8 + largepic);
@@ -3368,6 +3414,8 @@ direct:
 
                  unsigned int val, type;
 
+                 if (roff < 3)
+                   goto corrupt_input;
                  type = bfd_get_8 (input_bfd, contents + roff - 3);
                  val = bfd_get_8 (input_bfd, contents + roff - 1);
                  bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
@@ -3414,7 +3462,11 @@ direct:
                  if (roff >= 3)
                    val = bfd_get_8 (input_bfd, contents + roff - 3);
                  else
-                   val = 0;
+                   {
+                     if (roff < 2)
+                       goto corrupt_input;
+                     val = 0;
+                   }
                  type = bfd_get_8 (input_bfd, contents + roff - 2);
                  reg = bfd_get_8 (input_bfd, contents + roff - 1);
                  reg >>= 3;
@@ -3422,11 +3474,19 @@ direct:
                    {
                      /* movq */
                      if (val == 0x4c)
-                       bfd_put_8 (output_bfd, 0x49,
-                                  contents + roff - 3);
+                       {
+                         if (roff < 3)
+                           goto corrupt_input;
+                         bfd_put_8 (output_bfd, 0x49,
+                                    contents + roff - 3);
+                       }
                      else if (!ABI_64_P (output_bfd) && val == 0x44)
-                       bfd_put_8 (output_bfd, 0x41,
-                                  contents + roff - 3);
+                       {
+                         if (roff < 3)
+                           goto corrupt_input;
+                         bfd_put_8 (output_bfd, 0x41,
+                                    contents + roff - 3);
+                       }
                      bfd_put_8 (output_bfd, 0xc7,
                                 contents + roff - 2);
                      bfd_put_8 (output_bfd, 0xc0 | reg,
@@ -3437,11 +3497,19 @@ direct:
                      /* addq/addl -> addq/addl - addressing with %rsp/%r12
                         is special  */
                      if (val == 0x4c)
-                       bfd_put_8 (output_bfd, 0x49,
-                                  contents + roff - 3);
+                       {
+                         if (roff < 3)
+                           goto corrupt_input;
+                         bfd_put_8 (output_bfd, 0x49,
+                                    contents + roff - 3);
+                       }
                      else if (!ABI_64_P (output_bfd) && val == 0x44)
-                       bfd_put_8 (output_bfd, 0x41,
-                                  contents + roff - 3);
+                       {
+                         if (roff < 3)
+                           goto corrupt_input;
+                         bfd_put_8 (output_bfd, 0x41,
+                                    contents + roff - 3);
+                       }
                      bfd_put_8 (output_bfd, 0x81,
                                 contents + roff - 2);
                      bfd_put_8 (output_bfd, 0xc0 | reg,
@@ -3451,11 +3519,19 @@ direct:
                    {
                      /* addq/addl -> leaq/leal */
                      if (val == 0x4c)
-                       bfd_put_8 (output_bfd, 0x4d,
-                                  contents + roff - 3);
+                       {
+                         if (roff < 3)
+                           goto corrupt_input;
+                         bfd_put_8 (output_bfd, 0x4d,
+                                    contents + roff - 3);
+                       }
                      else if (!ABI_64_P (output_bfd) && val == 0x44)
-                       bfd_put_8 (output_bfd, 0x45,
-                                  contents + roff - 3);
+                       {
+                         if (roff < 3)
+                           goto corrupt_input;
+                         bfd_put_8 (output_bfd, 0x45,
+                                    contents + roff - 3);
+                       }
                      bfd_put_8 (output_bfd, 0x8d,
                                 contents + roff - 2);
                      bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3),
@@ -3625,20 +3701,33 @@ direct:
                    {
                      if (contents[roff + 5] == 0xb8)
                        {
+                         if (roff < 3
+                             || (roff - 3 + 22) > input_section->size)
+                           goto corrupt_input;
                          memcpy (contents + roff - 3,
                                  "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05"
                                  "\0\0\0\0\x66\x0f\x1f\x44\0", 22);
                          largepic = 1;
                        }
                      else
-                       memcpy (contents + roff - 4,
-                               "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0",
-                               16);
+                       {
+                         if (roff < 4
+                             || (roff - 4 + 16) > input_section->size)
+                           goto corrupt_input;
+                         memcpy (contents + roff - 4,
+                                 "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0",
+                                 16);
+                       }
                    }
                  else
-                   memcpy (contents + roff - 3,
-                           "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0",
-                           15);
+                   {
+                     if (roff < 3
+                         || (roff - 3 + 15) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + roff - 3,
+                             "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0",
+                             15);
+                   }
 
                  relocation = (htab->elf.sgot->output_section->vma
                                + htab->elf.sgot->output_offset + off
@@ -3667,6 +3756,8 @@ direct:
                     turn a leaq into a movq in the form we use it, it
                     suffices to change the second byte from 0x8d to
                     0x8b.  */
+                 if (roff < 2)
+                   goto corrupt_input;
                  bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
 
                  bfd_put_32 (output_bfd,
@@ -3735,28 +3826,58 @@ direct:
              BFD_ASSERT (r_type == R_X86_64_TPOFF32);
              if (ABI_64_P (output_bfd))
                {
+                 if ((rel->r_offset + 5) >= input_section->size)
+                   goto corrupt_input;
                  if (contents[rel->r_offset + 5] == 0xb8)
-                   memcpy (contents + rel->r_offset - 3,
-                           "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0"
-                           "\x64\x48\x8b\x04\x25\0\0\0", 22);
+                   {
+                     if (rel->r_offset < 3
+                         || (rel->r_offset - 3 + 22) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + rel->r_offset - 3,
+                             "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0"
+                             "\x64\x48\x8b\x04\x25\0\0\0", 22);
+                   }
                  else if (contents[rel->r_offset + 4] == 0xff
                           || contents[rel->r_offset + 4] == 0x67)
-                   memcpy (contents + rel->r_offset - 3,
-                           "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0",
-                           13);
+                   {
+                     if (rel->r_offset < 3
+                         || (rel->r_offset - 3 + 13) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + rel->r_offset - 3,
+                             "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0",
+                             13);
+
+                   }
                  else
-                   memcpy (contents + rel->r_offset - 3,
-                           "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
+                   {
+                     if (rel->r_offset < 3
+                         || (rel->r_offset - 3 + 12) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + rel->r_offset - 3,
+                             "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
+                   }
                }
              else
                {
+                 if ((rel->r_offset + 4) >= input_section->size)
+                   goto corrupt_input;
                  if (contents[rel->r_offset + 4] == 0xff)
-                   memcpy (contents + rel->r_offset - 3,
-                           "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0",
-                           13);
+                   {
+                     if (rel->r_offset < 3
+                         || (rel->r_offset - 3 + 13) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + rel->r_offset - 3,
+                             "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0",
+                             13);
+                   }
                  else
-                   memcpy (contents + rel->r_offset - 3,
-                           "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12);
+                   {
+                     if (rel->r_offset < 3
+                         || (rel->r_offset - 3 + 12) > input_section->size)
+                       goto corrupt_input;
+                     memcpy (contents + rel->r_offset - 3,
+                             "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12);
+                   }
                }
              /* Skip R_X86_64_PC32, R_X86_64_PLT32, R_X86_64_GOTPCRELX
                 and R_X86_64_PLTOFF64.  */
@@ -4271,7 +4392,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       else if (bfd_link_pic (info)
               && SYMBOL_REFERENCES_LOCAL_P (info, h))
        {
-         if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
+         if (!SYMBOL_DEFINED_NON_SHARED_P (h))
            return FALSE;
          BFD_ASSERT((h->got.offset & 1) != 0);
          rela.r_info = htab->r_info (0, R_X86_64_RELATIVE);
This page took 0.0361 seconds and 4 git commands to generate.