+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
/* 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;
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);
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. */
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;
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;
+ }
+ }
}
}
++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
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;
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
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++;
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;
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:
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;
}
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;
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:
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;
}
{
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)
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)
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. */
+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
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
/* 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
#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. */