diff options
author | Jakub Jelinek <jakub@redhat.com> | 2004-05-11 17:08:38 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2004-05-11 17:08:38 +0000 |
commit | 9f812b8f9265f579e5ee50279cf19d6fc2731194 (patch) | |
tree | 447b1853332860af9999b134826a174a0a95ee82 | |
parent | ee34322183a0de951597758aefd02e6599b1cb8a (diff) | |
download | gdb-9f812b8f9265f579e5ee50279cf19d6fc2731194.tar.gz |
bfd/
* 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.
-rw-r--r-- | bfd/ChangeLog | 30 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 3 | ||||
-rw-r--r-- | bfd/elf.c | 56 | ||||
-rw-r--r-- | bfd/elf32-i386.c | 42 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 15 | ||||
-rw-r--r-- | bfd/elflink.c | 41 | ||||
-rw-r--r-- | include/ChangeLog | 7 | ||||
-rw-r--r-- | include/bfdlink.h | 6 | ||||
-rw-r--r-- | include/elf/common.h | 5 |
9 files changed, 183 insertions, 22 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a9088e57c96..fc12cb43e30 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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 diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 9d0ec364b74..750cc1c675b 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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; diff --git a/bfd/elf.c b/bfd/elf.c index 00443c2cc83..8e208c22e60 100644 --- 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 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index a53d93ecc1d..dee26a025cd 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -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; } diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index ee1b14e193f..f9eb7db6434 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -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; } diff --git a/bfd/elflink.c b/bfd/elflink.c index 32f42641689..cee59096a52 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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. */ diff --git a/include/ChangeLog b/include/ChangeLog index 4e92371d1c2..804d97f7128 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -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 diff --git a/include/bfdlink.h b/include/bfdlink.h index cc2043e10ed..881d7d4796d 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -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 diff --git a/include/elf/common.h b/include/elf/common.h index 8ebc2cf4724..dbcb5d2795d 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -288,8 +288,9 @@ #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. */ |