OSDN Git Service

bfd/
authorJakub Jelinek <jakub@redhat.com>
Tue, 11 May 2004 17:08:38 +0000 (17:08 +0000)
committerJakub Jelinek <jakub@redhat.com>
Tue, 11 May 2004 17:08:38 +0000 (17:08 +0000)
* elflink.c (elf_bfd_final_link): Don't output STT_SECTION symbol
into .dynsym if elf_section_data (sec)->dynindx <= 0.
Adjust counting of last_local.
(_bfd_elf_link_renumber_dynsyms): Don't assign dynindx to sections
other than SHT_PROGBITS/SHT_NOBITS and neither for .got/.got.plt/.plt
created by the linker nor !SHF_ALLOC.

* elf32-i386.c (elf_i386_finish_dynamic_sections): Point
DT_PLTGOT to the start of the .got.plt section instead of the
.got output section.  Set sh_entsize for .got section in addition
to .got.plt.
(elf_i386_relocate_section): Don't assume _GLOBAL_OFFSET_TABLE_
is at sgot->output_section->vma.
* elf64-x86-64.c (elf64_x86_64_finish_dynamic_sections): Point
DT_PLTGOT to the start of the .got.plt section instead of the
.got output section.
(elf64_x86_64_relocate_section): Don't assume _GLOBAL_OFFSET_TABLE_
is at sgot->output_section->vma.  Set sh_entsize for .got section
in addition to .got.plt.
* elf.c (_bfd_elf_print_private_bfd_data): Handle PT_GNU_RELRO.
(bfd_section_from_phdr): Likewise.
(map_sections_to_segments): Likewise.
(assign_file_positions_for_segments): Likewise.
(get_program_header_size): Likewise.
* elflink.c (bfd_elf_size_dynamic_sections): Set
elf_tdata (output_bfd)->relro from info->relro.
* elf-bfd.h (struct elf_obj_tdata): Add relro field.
include/
* bfdlink.h (struct bfd_link_info): Add relro, relro_start and
relro_end fields.
* elf/common.h (PT_GNU_EH_FRAME, PT_GNU_STACK): Add comments.
(PT_GNU_RELRO): Define.
binutils/
* readelf.c (get_segment_type): Handle PT_GNU_RELRO.
ld/
* genscripts.sh: Generate -z combreloc -z now -z relro scripts
for binaries, -shared and -pie.
* emulparams/elf_i386.sh (SEPARATE_GOTPLT): Set.
* emulparams/elf_x86_64.sh (SEPARATE_GOTPLT): Set.
* emulparams/elf32ppc.sh (OTHER_READWRITE_SECTIONS): Rename to...
(OTHER_RELRO_SECTIONS): ... this.
* ldlex.l (DATA_SEGMENT_RELRO_END): Add.
* emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Handle
-z relro and -z norelro.
(gld${EMULATION_NAME}_list_options): Add it to usage.
(gld${EMULATION_NAME}_get_script): Return -z combreloc -z now
-z relro scripts when appropriate.
* scripttempl/elf.sc: Unset SEPARATE_GOTPLT if RELRO_NOW is set.
Create separate .got.plt section if SEPARATE_GOTPLT.
Move sections which are only written during relocation handling
to the beginning of RW segment.  If NO_SMALL_DATA, move .got
before .data.  Add DATA_SEGMENT_RELRO_END directive.
Include OTHER_RELRO_SECTIONS.
* ldgram.y (DATA_SEGMENT_RELRO_END): Add.
* ldexp.c (exp_print_token): Handle DATA_SEGMENT_RELRO_END.
(fold_unary): Likewise.
(fold_binary): Handle -z relro.
* ldexp.h (struct exp_data_seg): Add exp_dataseg_relro_seen and
exp_dataseg_relro_adjust phases.  Add relro_end field.
* ldmain.c (main): Initialize link_info.relro to FALSE.
* ldlang.c (lang_size_sections): Handle -z relro.
ld/testsuite/
* ld-i386/tlspic.rd: Adjust for section reordering changes
and removal of unneeded STT_SECTION symbols from .dynsym.
* ld-i386/tlspic.dd: Likewise.
* ld-i386/tlspic.sd: Likewise.
* ld-i386/tlsbin.rd: Likewise.
* ld-i386/tlsbinpic.s: Likewise.
* ld-i386/tlsbin.dd: Likewise.
* ld-i386/tlsbin.sd: Likewise.
* ld-i386/tlsnopic.rd: Likewise.
* ld-i386/tlsnopic1.s: Likewise.
* ld-i386/combreloc.d: Likewise.
* ld-i386/tlsnopic.dd: Likewise.
* ld-i386/tlsnopic.sd: Likewise.
* ld-x86-64/tlspic.rd: Likewise.
* ld-x86-64/tlspic.dd: Likewise.
* ld-x86-64/tlsbin.dd: Likewise.
* ld-x86-64/tlspic.sd: Likewise.
* ld-x86-64/tlsbin.sd: Likewise.
* ld-x86-64/tlspic.td: Likewise.
* ld-x86-64/tlsbin.td: Likewise.
* ld-x86-64/tlsbin.rd: Likewise.
* ld-s390/tlspic1.s: Likewise.
* ld-s390/tlsbinpic.s: Likewise.
* ld-s390/tlspic.rd: Likewise.
* ld-s390/tlsbin.rd: Likewise.
* ld-s390/tlspic.dd: Likewise.
* ld-s390/tlsbin.dd: Likewise.
* ld-s390/tlsbin.sd: Likewise.
* ld-s390/tlsbin.td: Likewise.
* ld-s390/tlspic.sd: Likewise.
* ld-s390/tlspic.td: Likewise.
* ld-s390/tlspic1_64.s: Likewise.
* ld-s390/tlsbinpic_64.s: Likewise.
* ld-s390/tlspic_64.rd: Likewise.
* ld-s390/tlsbin_64.rd: Likewise.
* ld-s390/tlspic_64.dd: Likewise.
* ld-s390/tlsbin_64.dd: Likewise.
* ld-s390/tlspic_64.sd: Likewise.
* ld-s390/tlspic_64.td: Likewise.
* ld-s390/tlsbin_64.td: Likewise.
* ld-s390/tlsbin_64.sd: Likewise.
* ld-powerpc/tlsexe32.r: Likewise.
* ld-powerpc/tlsso32.r: Likewise.
* ld-powerpc/tlsso32.d: Likewise.
* ld-powerpc/tlsso32.g: Likewise.
* ld-powerpc/tlsso32.t: Likewise.
* ld-powerpc/tlsexe.r: Likewise.
* ld-powerpc/tlsso.r: Likewise.
* ld-powerpc/tlsso.g: Likewise.
* ld-powerpc/tlsexetoc.r: Likewise.
* ld-powerpc/tlstocso.r: Likewise.
* ld-powerpc/tlstocso.g: Likewise.
* ld-ia64/tlspic.rd: Likewise.
* ld-ia64/tlspic.dd: Likewise.
* ld-ia64/tlspic.sd: Likewise.
* ld-ia64/tlspic.td: Likewise.
* ld-ia64/tlsbin.rd: Likewise.
* ld-ia64/tlsbin.sd: Likewise.
* ld-ia64/tlsbin.td: Likewise.
* ld-elfvsb/elfvsb.exp: XFAIL non-PIC load offset tests on s390x.
* ld-shared/shared.exp: Likewise.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elflink.c
include/ChangeLog
include/bfdlink.h
include/elf/common.h

index a9088e5..fc12cb4 100644 (file)
@@ -1,3 +1,33 @@
+2004-05-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * elflink.c (elf_bfd_final_link): Don't output STT_SECTION symbol
+       into .dynsym if elf_section_data (sec)->dynindx <= 0.
+       Adjust counting of last_local.
+       (_bfd_elf_link_renumber_dynsyms): Don't assign dynindx to sections
+       other than SHT_PROGBITS/SHT_NOBITS and neither for .got/.got.plt/.plt
+       created by the linker nor !SHF_ALLOC.
+
+       * elf32-i386.c (elf_i386_finish_dynamic_sections): Point
+       DT_PLTGOT to the start of the .got.plt section instead of the
+       .got output section.  Set sh_entsize for .got section in addition
+       to .got.plt.
+       (elf_i386_relocate_section): Don't assume _GLOBAL_OFFSET_TABLE_
+       is at sgot->output_section->vma.
+       * elf64-x86-64.c (elf64_x86_64_finish_dynamic_sections): Point
+       DT_PLTGOT to the start of the .got.plt section instead of the
+       .got output section.
+       (elf64_x86_64_relocate_section): Don't assume _GLOBAL_OFFSET_TABLE_
+       is at sgot->output_section->vma.  Set sh_entsize for .got section
+       in addition to .got.plt.
+       * elf.c (_bfd_elf_print_private_bfd_data): Handle PT_GNU_RELRO.
+       (bfd_section_from_phdr): Likewise.
+       (map_sections_to_segments): Likewise.
+       (assign_file_positions_for_segments): Likewise.
+       (get_program_header_size): Likewise.
+       * elflink.c (bfd_elf_size_dynamic_sections): Set
+       elf_tdata (output_bfd)->relro from info->relro.
+       * elf-bfd.h (struct elf_obj_tdata): Add relro field.
+
 2004-05-08  Alexandre Oliva  <aoliva@redhat.com>
 
        * elf32-frv.c (_frvfdpic_add_dyn_reloc): Don't warn when we get
index 9d0ec36..750cc1c 100644 (file)
@@ -1211,6 +1211,9 @@ struct elf_obj_tdata
   /* Segment flags for the PT_GNU_STACK segment.  */
   unsigned int stack_flags;  
 
+  /* Should the PT_GNU_RELRO segment be emitted?  */
+  bfd_boolean relro;
+
   /* Symbol version definitions in external objects.  */
   Elf_Internal_Verdef *verdef;
 
index 00443c2..8e208c2 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -974,6 +974,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
            case PT_TLS: pt = "TLS"; break;
            case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
            case PT_GNU_STACK: pt = "STACK"; break;
+           case PT_GNU_RELRO: pt = "RELRO"; break;
            default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
            }
          fprintf (f, "%8s off    0x", pt);
@@ -2300,6 +2301,9 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index)
     case PT_GNU_STACK:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
 
+    case PT_GNU_RELRO:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
+
     default:
       /* Check for any processor-specific program segment types.
          If no handler for them, default to making "segment" sections.  */
@@ -3547,6 +3551,21 @@ map_sections_to_segments (bfd *abfd)
       pm = &m->next;
     }
 
+  if (elf_tdata (abfd)->relro)
+    {
+      amt = sizeof (struct elf_segment_map);
+      m = bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_GNU_RELRO;
+      m->p_flags = PF_R;
+      m->p_flags_valid = 1;
+
+      *pm = m;
+      pm = &m->next;
+    }
+
   free (sections);
   sections = NULL;
 
@@ -4081,6 +4100,37 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
              if (! m->p_paddr_valid)
                p->p_paddr = phdrs_paddr;
            }
+         else if (p->p_type == PT_GNU_RELRO)
+           {
+             Elf_Internal_Phdr *lp;
+
+             for (lp = phdrs; lp < phdrs + count; ++lp)
+               {
+                 if (lp->p_type == PT_LOAD
+                     && lp->p_vaddr <= link_info->relro_end
+                     && lp->p_vaddr >= link_info->relro_start
+                     && lp->p_vaddr + lp->p_filesz
+                        >= link_info->relro_end)
+                   break;
+               }
+
+             if (lp < phdrs + count
+                 && link_info->relro_end > lp->p_vaddr)
+               {
+                 p->p_vaddr = lp->p_vaddr;
+                 p->p_paddr = lp->p_paddr;
+                 p->p_offset = lp->p_offset;
+                 p->p_filesz = link_info->relro_end - lp->p_vaddr;
+                 p->p_memsz = p->p_filesz;
+                 p->p_align = 1;
+                 p->p_flags = (lp->p_flags & ~PF_W);
+               }
+             else
+               {
+                 memset (p, 0, sizeof *p);
+                 p->p_type = PT_NULL;
+               }
+           }
        }
     }
 
@@ -4168,6 +4218,12 @@ get_program_header_size (bfd *abfd)
       ++segs;
     }
 
+  if (elf_tdata (abfd)->relro)
+    {
+      /* We need a PT_GNU_RELRO segment.  */
+      ++segs;
+    }
+
   for (s = abfd->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LOAD) != 0
index a53d93e..dee26a0 100644 (file)
@@ -2261,24 +2261,29 @@ elf_i386_relocate_section (bfd *output_bfd,
          if (off >= (bfd_vma) -2)
            abort ();
 
-         relocation = htab->sgot->output_offset + off;
+         relocation = htab->sgot->output_section->vma
+                      + htab->sgot->output_offset + off
+                      - htab->sgotplt->output_section->vma
+                      - htab->sgotplt->output_offset;
          break;
 
        case R_386_GOTOFF:
          /* Relocation is relative to the start of the global offset
             table.  */
 
-         /* Note that sgot->output_offset is not involved in this
-            calculation.  We always want the start of .got.  If we
-            defined _GLOBAL_OFFSET_TABLE in a different way, as is
+         /* Note that sgot is not involved in this
+            calculation.  We always want the start of .got.plt.  If we
+            defined _GLOBAL_OFFSET_TABLE_ in a different way, as is
             permitted by the ABI, we might have to change this
             calculation.  */
-         relocation -= htab->sgot->output_section->vma;
+         relocation -= htab->sgotplt->output_section->vma
+                       + htab->sgotplt->output_offset;
          break;
 
        case R_386_GOTPC:
          /* Use global offset table as symbol value.  */
-         relocation = htab->sgot->output_section->vma;
+         relocation = htab->sgotplt->output_section->vma
+                      + htab->sgotplt->output_offset;
          unresolved_reloc = FALSE;
          break;
 
@@ -2699,12 +2704,15 @@ elf_i386_relocate_section (bfd *output_bfd,
            abort ();
          if (r_type == ELF32_R_TYPE (rel->r_info))
            {
-             relocation = htab->sgot->output_offset + off;
+             bfd_vma g_o_t = htab->sgotplt->output_section->vma
+                             + htab->sgotplt->output_offset;
+             relocation = htab->sgot->output_section->vma
+                          + htab->sgot->output_offset + off - g_o_t;
              if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
                  && tls_type == GOT_TLS_IE_BOTH)
                relocation += 4;
              if (r_type == R_386_TLS_IE)
-               relocation += htab->sgot->output_section->vma;
+               relocation += g_o_t;
              unresolved_reloc = FALSE;
            }
          else
@@ -2761,7 +2769,11 @@ elf_i386_relocate_section (bfd *output_bfd,
                  if (tls_type == GOT_TLS_IE_BOTH)
                    off += 4;
                }
-             bfd_put_32 (output_bfd, htab->sgot->output_offset + off,
+             bfd_put_32 (output_bfd,
+                         htab->sgot->output_section->vma
+                         + htab->sgot->output_offset + off
+                         - htab->sgotplt->output_section->vma
+                         - htab->sgotplt->output_offset,
                          contents + roff + 8);
              /* Skip R_386_PLT32.  */
              rel++;
@@ -2823,7 +2835,10 @@ elf_i386_relocate_section (bfd *output_bfd,
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
              htab->tls_ldm_got.offset |= 1;
            }
-         relocation = htab->sgot->output_offset + off;
+         relocation = htab->sgot->output_section->vma
+                      + htab->sgot->output_offset + off
+                      - htab->sgotplt->output_section->vma
+                      - htab->sgotplt->output_offset;
          unresolved_reloc = FALSE;
          break;
 
@@ -3159,7 +3174,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
              continue;
 
            case DT_PLTGOT:
-             dyn.d_un.d_ptr = htab->sgot->output_section->vma;
+             s = htab->sgotplt;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_JMPREL:
@@ -3245,6 +3261,10 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 
       elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
     }
+
+  if (htab->sgot && htab->sgot->_raw_size > 0)
+    elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
+
   return TRUE;
 }
 
index ee1b14e..f9eb7db 100644 (file)
@@ -1911,9 +1911,11 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          if (off >= (bfd_vma) -2)
            abort ();
 
-         relocation = htab->sgot->output_offset + off;
-         if (r_type == R_X86_64_GOTPCREL)
-           relocation += htab->sgot->output_section->vma;
+         relocation = htab->sgot->output_section->vma
+                      + htab->sgot->output_offset + off;
+         if (r_type != R_X86_64_GOTPCREL)
+           relocation -= htab->sgotplt->output_section->vma
+                         - htab->sgotplt->output_offset;
 
          break;
 
@@ -2664,7 +2666,8 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
              continue;
 
            case DT_PLTGOT:
-             dyn.d_un.d_ptr = htab->sgot->output_section->vma;
+             s = htab->sgotplt;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_JMPREL:
@@ -2755,6 +2758,10 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
        GOT_ENTRY_SIZE;
     }
 
+  if (htab->sgot && htab->sgot->_raw_size > 0)
+    elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize
+      = GOT_ENTRY_SIZE;
+
   return TRUE;
 }
 
index 32f4264..cee5909 100644 (file)
@@ -622,8 +622,36 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *p;
       for (p = output_bfd->sections; p ; p = p->next)
-       if ((p->flags & SEC_EXCLUDE) == 0)
-         elf_section_data (p)->dynindx = ++dynsymcount;
+       if ((p->flags & SEC_EXCLUDE) == 0
+           && (p->flags & SEC_ALLOC) != 0)
+         switch (elf_section_data (p)->this_hdr.sh_type)
+           {
+           case SHT_PROGBITS:
+           case SHT_NOBITS:
+             /* If sh_type is yet undecided, assume it could be
+                SHT_PROGBITS/SHT_NOBITS.  */
+           case SHT_NULL:
+             if (strcmp (p->name, ".got") == 0
+                 || strcmp (p->name, ".got.plt") == 0
+                 || strcmp (p->name, ".plt") == 0)
+               {
+                 asection *ip;
+                 bfd *dynobj = elf_hash_table (info)->dynobj;
+
+                 if (dynobj != NULL
+                     && (ip = bfd_get_section_by_name (dynobj, p->name))
+                        != NULL
+                     && (ip->flags & SEC_LINKER_CREATED)
+                     && ip->output_section == p)
+                   continue;
+               }
+             elf_section_data (p)->dynindx = ++dynsymcount;
+             break;
+             /* There shouldn't be section relative relocations
+                against any other section.  */
+           default:
+             break;
+           }
     }
 
   if (elf_hash_table (info)->dynlocal)
@@ -4621,6 +4649,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   if (!is_elf_hash_table (info->hash))
     return TRUE;
 
+  elf_tdata (output_bfd)->relro = info->relro;
   if (info->execstack)
     elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
   else if (info->noexecstack)
@@ -7654,16 +7683,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              bfd_byte *dest;
              long dynindx;
 
-             indx = elf_section_data (s)->this_idx;
              dynindx = elf_section_data (s)->dynindx;
+             if (dynindx <= 0)
+               continue;
+             indx = elf_section_data (s)->this_idx;
              BFD_ASSERT (indx > 0);
              sym.st_shndx = indx;
              sym.st_value = s->vma;
              dest = dynsym + dynindx * bed->s->sizeof_sym;
+             if (last_local < dynindx)
+               last_local = dynindx;
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
-
-         last_local = bfd_count_sections (abfd);
        }
 
       /* Write out the local dynsyms.  */
index 4e92371..804d97f 100644 (file)
@@ -1,3 +1,10 @@
+2004-05-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * bfdlink.h (struct bfd_link_info): Add relro, relro_start and
+       relro_end fields.
+       * elf/common.h (PT_GNU_EH_FRAME, PT_GNU_STACK): Add comments.
+       (PT_GNU_RELRO): Define.
+
 2004-05-04  Andreas Jaeger  <aj@suse.de>
 
        * demangle.h: Do not use C++ reserved keyword typename as
index cc2043e..881d7d4 100644 (file)
@@ -302,6 +302,9 @@ struct bfd_link_info
      flags.  */
   unsigned int noexecstack: 1;
 
+  /* TRUE if PT_GNU_RELRO segment should be created.  */
+  unsigned int relro: 1;
+
   /* What to do with unresolved symbols in an object file.
      When producing executables the default is GENERATE_ERROR.
      When producing shared libraries the default is IGNORE.  The
@@ -391,6 +394,9 @@ struct bfd_link_info
 
   /* May be used to set DT_FLAGS_1 for ELF. */
   bfd_vma flags_1;
+
+  /* Start and end of RELRO region.  */
+  bfd_vma relro_start, relro_end;
 };
 
 /* This structures holds a set of callback functions.  These are
index 8ebc2cf..dbcb5d2 100644 (file)
 #define PT_LOPROC      0x70000000      /* Processor-specific */
 #define PT_HIPROC      0x7FFFFFFF      /* Processor-specific */
 
-#define PT_GNU_EH_FRAME        (PT_LOOS + 0x474e550)
-#define PT_GNU_STACK   (PT_LOOS + 0x474e551)
+#define PT_GNU_EH_FRAME        (PT_LOOS + 0x474e550) /* Frame unwind information */
+#define PT_GNU_STACK   (PT_LOOS + 0x474e551) /* Stack flags */
+#define PT_GNU_RELRO   (PT_LOOS + 0x474e552) /* Read-only after relocation */
 
 /* Program segment permissions, in program header p_flags field.  */