Add x86 size relocation support to bfd
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index 99e8f45c86e9923d12f577af5912995a6ef1e55b..368c8d58668623e49327f1bf0add59c1403a33e9 100644 (file)
@@ -133,7 +133,9 @@ static reloc_howto_type elf_howto_table[]=
   HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_TLS_TPOFF32",
        TRUE, 0xffffffff, 0xffffffff, FALSE),
-  EMPTY_HOWTO (38),
+  HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned,
+       bfd_elf_generic_reloc, "R_386_SIZE32",
+       TRUE, 0xffffffff, 0xffffffff, FALSE),
   HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
        TRUE, 0xffffffff, 0xffffffff, FALSE),
@@ -312,6 +314,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       TRACE ("BFD_RELOC_386_TLS_TPOFF32");
       return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset];
 
+    case BFD_RELOC_SIZE32:
+      TRACE ("BFD_RELOC_SIZE32");
+      return &elf_howto_table[R_386_SIZE32 - R_386_tls_offset];
+
     case BFD_RELOC_386_TLS_GOTDESC:
       TRACE ("BFD_RELOC_386_TLS_GOTDESC");
       return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset];
@@ -1680,6 +1686,7 @@ elf_i386_check_relocs (bfd *abfd,
 
        case R_386_32:
        case R_386_PC32:
+       case R_386_SIZE32:
          if (h != NULL && info->executable)
            {
              /* If this reloc is in a read-only section, we might
@@ -1959,6 +1966,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
 
        case R_386_32:
        case R_386_PC32:
+       case R_386_SIZE32:
          if (info->shared
              && (h == NULL || h->type != STT_GNU_IFUNC))
            break;
@@ -3185,6 +3193,7 @@ elf_i386_relocate_section (bfd *output_bfd,
       bfd_reloc_status_type r;
       unsigned int indx;
       int tls_type;
+      bfd_vma st_size;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == R_386_GNU_VTINHERIT
@@ -3217,6 +3226,7 @@ elf_i386_relocate_section (bfd *output_bfd,
          relocation = (sec->output_section->vma
                        + sec->output_offset
                        + sym->st_value);
+         st_size = sym->st_size;
 
          if (ELF_ST_TYPE (sym->st_info) == STT_SECTION
              && ((sec->flags & SEC_MERGE) != 0
@@ -3309,6 +3319,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h, sec, relocation,
                                   unresolved_reloc, warned);
+         st_size = h->size;
        }
 
       if (sec != NULL && discarded_section (sec))
@@ -3670,6 +3681,25 @@ elf_i386_relocate_section (bfd *output_bfd,
          unresolved_reloc = FALSE;
          break;
 
+       case R_386_SIZE32:
+         if (h
+             && h->type == STT_TLS
+             && (h->root.type == bfd_link_hash_defined
+                 || h->root.type == bfd_link_hash_defweak)
+             && h->root.u.def.section->output_section != NULL
+             && htab->elf.tls_sec == NULL)
+           {
+             (*_bfd_error_handler)
+               (_("%B: `%s' accessed both as normal and thread local symbol"),
+                input_bfd, h->root.root.string);
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
+
+         /* Set to symbol size.  */
+         relocation = st_size;
+         /* Fall through.  */
+
        case R_386_32:
        case R_386_PC32:
          if ((input_section->flags & SEC_ALLOC) == 0
@@ -3680,7 +3710,7 @@ elf_i386_relocate_section (bfd *output_bfd,
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                   || h->root.type != bfd_link_hash_undefweak)
-              && (r_type != R_386_PC32
+              && ((r_type != R_386_PC32 && r_type != R_386_SIZE32)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
                  && !info->shared
This page took 0.027462 seconds and 4 git commands to generate.