This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Fix IA-64 -pie support
- From: Jakub Jelinek <jakub at redhat dot com>
- To: David Mosberger <davidm at napali dot hpl dot hp dot com>, Jim Wilson <wilson at tuliptree dot org>, Richard Henderson <rth at redhat dot com>
- Cc: binutils at sources dot redhat dot com, drepper at redhat dot com
- Date: Wed, 2 Jul 2003 14:30:23 +0200
- Subject: [PATCH] Fix IA-64 -pie support
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Current IA-64 ld cannot link even trivial -pie applications, such as
int main () { } - it gets some assertion failures and finally segfaults.
This patch attempts to fix it.
While working on this, I've noticed that assembling and linking into shlib
of the following
addl r2 = @ltoff(@fptr(foobar)), gp
addl r3 = @ltoff(foobar), gp
creates only one .got entry, as if both relocations were @ltoff(@fptr()).
Is that on purpose? IMHO either linker should emit an error in this case,
or it should create 2 .got entries.
This patch also fixes (not just on ia64, but other arches as well) emitting
undefined symbol errors in -pie. Before ld would silently create e.g. a
PIE which did not have main function defined, which of course would segfault
when run.
2003-07-02 Jakub Jelinek <jakub@redhat.com>
bfd/
* elfxx-ia64.c (struct elfNN_ia64_link_hash_table): Add rel_fptr_sec.
(elfNN_ia64_dynamic_symbol_p): Change info->shared into
!info->executable.
(get_fptr): For -pie create .opd as writable section and create
.rela.opd as well.
(elfNN_ia64_check_relocs): Change info->shared into
!info->executable.
(allocate_fptr): Likewise.
(allocate_dynrel_entries): Account for a relative reloc for -pie
@fptr(). Don't account for a relative reloc if -pie want_ltoff_fptr
for undefweak symbol. Account for an IPLT reloc in .rela.opd
section if -pie.
(set_got_entry): Don't create a relative reloc if -pie
want_ltoff_fptr for undefweak symbol.
(set_fptr_entry): Emit an IPLT reloc in .rela.opd for -pie.
(elfNN_ia64_relocate_section): Emit a relative reloc for -pie
@fptr().
* elfxx-ia64.c (elfNN_ia64_relocate_section): Issue undefined_symbol
even if -pie.
* elf32-i386.c (elf_i386_relocate_section): Likewise.
* elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise.
* elf64-sparc.c (sparc64_elf_relocate_section): Likewise.
* elf64-s390.c (elf_s390_relocate_section): Likewise.
* elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
* elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
* elf32-s390.c (elf_s390_relocate_section): Likewise.
* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
ld/
* emulparams/elf64_ia64.sh (OTHER_READONLY_SECTIONS): Don't include
.opd if -pie.
(OTHER_READWRITE_SECTIONS): Include .opd if -pie.
* scripttempl/elf.sc: Use SHLIB_DATA_ADDR instead of DATA_ADDR
if -pie.
--- bfd/elfxx-ia64.c.jj 2003-07-01 07:14:13.000000000 -0400
+++ bfd/elfxx-ia64.c 2003-07-02 08:04:08.000000000 -0400
@@ -143,6 +143,7 @@ struct elfNN_ia64_link_hash_table
asection *got_sec; /* the linkage table section (or NULL) */
asection *rel_got_sec; /* dynamic relocation section for same */
asection *fptr_sec; /* function descriptor table (or NULL) */
+ asection *rel_fptr_sec; /* dynamic relocation section for same */
asection *plt_sec; /* the primary plt section (or NULL) */
asection *pltoff_sec; /* private descriptors for plt (or NULL) */
asection *rel_pltoff_sec; /* dynamic relocation section for same */
@@ -1652,7 +1653,7 @@ elfNN_ia64_dynamic_symbol_p (h, info)
|| h->root.type == bfd_link_hash_defweak)
return TRUE;
- if ((info->shared && (!info->symbolic || info->allow_shlib_undefined))
+ if ((!info->executable && (!info->symbolic || info->allow_shlib_undefined))
|| ((h->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
== (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
@@ -2063,7 +2064,7 @@ get_got (abfd, info, ia64_info)
static asection *
get_fptr (abfd, info, ia64_info)
bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ struct bfd_link_info *info;
struct elfNN_ia64_link_hash_table *ia64_info;
{
asection *fptr;
@@ -2083,7 +2084,7 @@ get_fptr (abfd, info, ia64_info)
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
- | SEC_READONLY
+ | (info->pie ? 0 : SEC_READONLY)
| SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, fptr, 4))
{
@@ -2092,6 +2093,26 @@ get_fptr (abfd, info, ia64_info)
}
ia64_info->fptr_sec = fptr;
+
+ if (info->pie)
+ {
+ asection *fptr_rel;
+ fptr_rel = bfd_make_section(abfd, ".rela.opd");
+ if (fptr_rel == NULL
+ || !bfd_set_section_flags (abfd, fptr_rel,
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY))
+ || !bfd_set_section_alignment (abfd, fptr_rel, 3))
+ {
+ BFD_ASSERT (0);
+ return NULL;
+ }
+
+ ia64_info->rel_fptr_sec = fptr_rel;
+ }
}
return fptr;
@@ -2278,7 +2299,7 @@ elfNN_ia64_check_relocs (abfd, info, sec
have yet been processed. Do something with what we know, as
this may help reduce memory usage and processing time later. */
maybe_dynamic = FALSE;
- if (h && ((info->shared
+ if (h && ((!info->executable
&& (!info->symbolic || info->allow_shlib_undefined))
|| ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
|| h->root.type == bfd_link_hash_defweak
@@ -2638,7 +2659,7 @@ allocate_fptr (dyn_i, data)
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if ((x->info->shared
+ if ((!x->info->executable
&& (!h
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
@@ -2788,10 +2809,11 @@ allocate_dynrel_entries (dyn_i, data)
switch (rent->type)
{
case R_IA64_FPTR64LSB:
- /* Allocate one iff !want_fptr, which by this point will
- be true only if we're actually allocating one statically
- in the main executable. */
- if (dyn_i->want_fptr)
+ /* Allocate one iff !want_fptr and not PIE, which by this point
+ will be true only if we're actually allocating one statically
+ in the main executable. Position independent executables
+ need a relative reloc. */
+ if (dyn_i->want_fptr && !x->info->pie)
continue;
break;
case R_IA64_PCREL64LSB:
@@ -2828,13 +2850,24 @@ allocate_dynrel_entries (dyn_i, data)
|| (dyn_i->want_ltoff_fptr
&& dyn_i->h
&& dyn_i->h->dynindx != -1))
- ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ {
+ if (!dyn_i->want_ltoff_fptr
+ || !x->info->pie
+ || dyn_i->h == NULL
+ || dyn_i->h->root.type != bfd_link_hash_undefweak)
+ ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ }
if ((dynamic_symbol || shared) && dyn_i->want_tprel)
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
if (dynamic_symbol && dyn_i->want_dtpmod)
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
if (dynamic_symbol && dyn_i->want_dtprel)
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
+ {
+ if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
+ ia64_info->rel_fptr_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ }
if (!resolved_zero && dyn_i->want_pltoff)
{
@@ -3444,14 +3477,18 @@ set_got_entry (abfd, info, dyn_i, dynind
bfd_put_64 (abfd, value, got_sec->contents + got_offset);
/* Install a dynamic relocation if needed. */
- if ((info->shared
- && (!dyn_i->h
- || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
- || dyn_i->h->root.type != bfd_link_hash_undefweak)
- && dyn_r_type != R_IA64_DTPREL64LSB)
- || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
- || elfNN_ia64_aix_vec (abfd->xvec)
- || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
+ if (((info->shared
+ && (!dyn_i->h
+ || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ || dyn_i->h->root.type != bfd_link_hash_undefweak)
+ && dyn_r_type != R_IA64_DTPREL64LSB)
+ || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
+ || elfNN_ia64_aix_vec (abfd->xvec)
+ || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
+ && (!dyn_i->want_ltoff_fptr
+ || !info->pie
+ || !dyn_i->h
+ || dyn_i->h->root.type != bfd_link_hash_undefweak))
{
if (dynindx == -1
&& dyn_r_type != R_IA64_TPREL64LSB
@@ -3530,6 +3567,24 @@ set_fptr_entry (abfd, info, dyn_i, value
bfd_put_64 (abfd, value, fptr_sec->contents + dyn_i->fptr_offset);
bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
fptr_sec->contents + dyn_i->fptr_offset + 8);
+ if (ia64_info->rel_fptr_sec)
+ {
+ Elf_Internal_Rela outrel;
+ bfd_byte *loc;
+
+ if (bfd_little_endian (abfd))
+ outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTLSB);
+ else
+ outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTMSB);
+ outrel.r_addend = value;
+ outrel.r_offset = (fptr_sec->output_section->vma
+ + fptr_sec->output_offset
+ + dyn_i->fptr_offset);
+ loc = ia64_info->rel_fptr_sec->contents;
+ loc += ia64_info->rel_fptr_sec->reloc_count++
+ * sizeof (ElfNN_External_Rela);
+ bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
+ }
}
/* Return the descriptor's address. */
@@ -3986,7 +4041,7 @@ elfNN_ia64_relocate_section (output_bfd,
}
else if (h->root.type == bfd_link_hash_undefweak)
undef_weak_ref = TRUE;
- else if (info->shared
+ else if (! info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
;
@@ -4146,14 +4201,36 @@ elfNN_ia64_relocate_section (output_bfd,
if (!undef_weak_ref)
value = set_fptr_entry (output_bfd, info, dyn_i, value);
}
- else
+ if (!dyn_i->want_fptr || info->pie)
{
long dynindx;
+ unsigned int dyn_r_type = r_type;
+ bfd_vma addend = rel->r_addend;
/* Otherwise, we expect the dynamic linker to create
the entry. */
- if (h)
+ if (dyn_i->want_fptr)
+ {
+ if (r_type == R_IA64_FPTR64I)
+ {
+ /* We can't represent this without a dynamic symbol.
+ Adjust the relocation to be against an output
+ section symbol, which are always present in the
+ dynamic symbol table. */
+ /* ??? People shouldn't be doing non-pic code in
+ shared libraries. Hork. */
+ (*_bfd_error_handler)
+ (_("%s: linking non-pic code in a position independent executable"),
+ bfd_archive_filename (input_bfd));
+ ret_val = FALSE;
+ continue;
+ }
+ dynindx = 0;
+ addend = value;
+ dyn_r_type = r_type + R_IA64_REL64LSB - R_IA64_FPTR64LSB;
+ }
+ else if (h)
{
if (h->dynindx != -1)
dynindx = h->dynindx;
@@ -4161,17 +4238,18 @@ elfNN_ia64_relocate_section (output_bfd,
dynindx = (_bfd_elf_link_lookup_local_dynindx
(info, h->root.u.def.section->owner,
global_sym_index (h)));
+ value = 0;
}
else
{
dynindx = (_bfd_elf_link_lookup_local_dynindx
(info, input_bfd, (long) r_symndx));
+ value = 0;
}
elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
- srel, rel->r_offset, r_type,
- dynindx, rel->r_addend);
- value = 0;
+ srel, rel->r_offset, dyn_r_type,
+ dynindx, addend);
}
r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
--- bfd/elf32-i386.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf32-i386.c 2003-07-02 08:04:34.000000000 -0400
@@ -2274,7 +2274,7 @@ elf_i386_relocate_section (output_bfd, i
}
else if (h->root.type == bfd_link_hash_undefweak)
;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
;
--- bfd/elf64-x86-64.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-x86-64.c 2003-07-02 08:04:56.000000000 -0400
@@ -1947,7 +1947,7 @@ elf64_x86_64_relocate_section (output_bf
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
--- bfd/elf64-sparc.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-sparc.c 2003-07-02 08:05:13.000000000 -0400
@@ -2097,7 +2097,7 @@ sparc64_elf_relocate_section (output_bfd
}
else if (h->root.type == bfd_link_hash_undefweak)
;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
;
--- bfd/elf64-s390.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-s390.c 2003-07-02 08:05:32.000000000 -0400
@@ -2244,7 +2244,7 @@ elf_s390_relocate_section (output_bfd, i
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
--- bfd/elf64-ppc.c.jj 2003-06-18 08:39:36.000000000 -0400
+++ bfd/elf64-ppc.c 2003-07-02 08:05:48.000000000 -0400
@@ -7347,7 +7347,7 @@ ppc64_elf_relocate_section (output_bfd,
}
else if (h->root.type == bfd_link_hash_undefweak)
;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
;
--- bfd/elf64-alpha.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-alpha.c 2003-07-02 08:06:09.000000000 -0400
@@ -4504,7 +4504,7 @@ elf64_alpha_relocate_section (output_bfd
}
else if (h->root.root.type == bfd_link_hash_undefweak)
undef_weak_ref = TRUE;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
;
--- bfd/elf32-sparc.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf32-sparc.c 2003-07-02 08:06:27.000000000 -0400
@@ -2206,7 +2206,7 @@ elf32_sparc_relocate_section (output_bfd
}
else if (h->root.type == bfd_link_hash_undefweak)
;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
;
--- bfd/elf32-s390.c.jj 2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf32-s390.c 2003-07-02 08:06:56.000000000 -0400
@@ -2273,7 +2273,7 @@ elf_s390_relocate_section (output_bfd, i
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
--- bfd/elf32-ppc.c.jj 2003-05-30 18:22:31.000000000 -0400
+++ bfd/elf32-ppc.c 2003-07-02 08:07:26.000000000 -0400
@@ -4387,7 +4387,7 @@ ppc_elf_relocate_section (output_bfd, in
}
else if (h->root.type == bfd_link_hash_undefweak)
;
- else if (info->shared
+ else if (!info->executable
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
;
--- ld/emulparams/elf64_ia64.sh.jj 2003-05-30 11:19:17.000000000 -0400
+++ ld/emulparams/elf64_ia64.sh 2003-07-01 14:16:16.000000000 -0400
@@ -22,7 +22,12 @@ OTHER_GOT_SECTIONS="
.IA_64.pltoff ${RELOCATING-0} : { *(.IA_64.pltoff) }"
OTHER_PLT_RELOC_SECTIONS="
.rela.IA_64.pltoff ${RELOCATING-0} : { *(.rela.IA_64.pltoff) }"
-OTHER_READONLY_SECTIONS="
- .opd ${RELOCATING-0} : { *(.opd) }
+OTHER_READONLY_SECTIONS=
+OTHER_READWRITE_SECTIONS=
+test -z "$CREATE_PIE" && OTHER_READONLY_SECTIONS="
+ .opd ${RELOCATING-0} : { *(.opd) }"
+test -n "$CREATE_PIE" && OTHER_READWRITE_SECTIONS="
+ .opd ${RELOCATING-0} : { *(.opd) }"
+OTHER_READONLY_SECTIONS="${OTHER_READONLY_SECTIONS}
.IA_64.unwind_info ${RELOCATING-0} : { *(.IA_64.unwind_info${RELOCATING+* .gnu.linkonce.ia64unwi.*}) }
.IA_64.unwind ${RELOCATING-0} : { *(.IA_64.unwind${RELOCATING+* .gnu.linkonce.ia64unw.*}) }"
--- ld/scripttempl/elf.sc.jj 2003-06-03 18:25:09.000000000 -0400
+++ ld/scripttempl/elf.sc 2003-07-01 12:17:12.000000000 -0400
@@ -72,8 +72,8 @@ if [ -z "$MACHINE" ]; then OUTPUT_ARCH=$
test -z "${ELFSIZE}" && ELFSIZE=32
test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
test "$LD_FLAG" = "N" && DATA_ADDR=.
-test -n "$CREATE_SHLIB" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
-test -z "$CREATE_SHLIB" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
+test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
+test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
DATA_SEGMENT_END=""
if test -n "${COMMONPAGESIZE}"; then
@@ -285,8 +285,9 @@ cat <<EOF
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
- ${CREATE_SHLIB-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
+ ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
+ ${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
Jakub