This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
powerpc small data relocs
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sourceware dot org
- Date: Fri, 18 Sep 2009 22:07:21 +0930
- Subject: powerpc small data relocs
This patch started off as a fairly simple additional check that
_SDA_BASE_ and _SDA2_BASE_ were properly defined in relocate_section,
but grew somewhat when I found a number of untidy areas. Besides
error checking, this patch:
- removes the assumption that _SDA_BASE_ is at offset 0x8000 in
.sdata, which may not be true for custom linker scripts,
- allows SDAREL16 relocs in shared libs as per the ABI (*), and,
- downgrades an EMB_SDA2REL error to a warning.
*) Don't try to use this for -msecure-plt code. .got and .sdata will
likely be too far away.
PR ld/10406
* elf32-ppc.c (ppc_elf_howto_raw): Make R_PPC_EMB_SDAI16 and
R_PPC_EMB_SDA2I16 complain_overflow_signed.
(create_sdata_sym): Pass info rather than htab.
Update all callers. Ensure symbols are hidden.
(ppc_elf_check_relocs): Allow SDAREL16 when shared.
(ppc_elf_size_dynamic_sections): When shared, equate _SDA_BASE_ to
_GLOBAL_OFFSET_TABLE_.
(elf_finish_pointer_linker_section): Don't assume that sdata base
symbol is always at 0x8000 offset. Don't subtract the addend here.
(is_static_defined): New function.
(ppc_elf_relocate_section): Verify symbol base used in SDA relocs
is statically defined. Clear addend for EMB_SDAI16 and EMB_SDA2I16
relocs. Downgrade error on unexpected section for EMB_SDA2REL
reloc symbols to a warning.
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.267
diff -u -p -r1.267 elf32-ppc.c
--- bfd/elf32-ppc.c 10 Aug 2009 13:38:44 -0000 1.267
+++ bfd/elf32-ppc.c 18 Sep 2009 12:04:29 -0000
@@ -1300,7 +1300,7 @@ static reloc_howto_type ppc_elf_howto_ra
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_SDAI16", /* name */
FALSE, /* partial_inplace */
@@ -1317,7 +1317,7 @@ static reloc_howto_type ppc_elf_howto_ra
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_SDA2I16", /* name */
FALSE, /* partial_inplace */
@@ -3129,9 +3129,10 @@ ppc_elf_add_symbol_hook (bfd *abfd,
}
static bfd_boolean
-create_sdata_sym (struct ppc_elf_link_hash_table *htab,
- elf_linker_section_t *lsect)
+create_sdata_sym (struct bfd_link_info *info, elf_linker_section_t *lsect)
{
+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+
lsect->sym = elf_link_hash_lookup (&htab->elf, lsect->sym_name,
TRUE, FALSE, TRUE);
if (lsect->sym == NULL)
@@ -3139,6 +3140,7 @@ create_sdata_sym (struct ppc_elf_link_ha
if (lsect->sym->root.type == bfd_link_hash_new)
lsect->sym->non_elf = 0;
lsect->sym->ref_regular = 1;
+ _bfd_elf_link_hash_hide_symbol (info, lsect->sym, TRUE);
return TRUE;
}
@@ -3168,7 +3170,7 @@ ppc_elf_create_linker_section (bfd *abfd
return FALSE;
lsect->section = s;
- return create_sdata_sym (htab, lsect);
+ return create_sdata_sym (info, lsect);
}
/* Find a linker generated pointer with a given addend and type. */
@@ -3633,13 +3635,8 @@ ppc_elf_check_relocs (bfd *abfd,
break;
case R_PPC_SDAREL16:
- if (info->shared)
- {
- bad_shared_reloc (abfd, r_type);
- return FALSE;
- }
if (htab->sdata[0].sym == NULL
- && !create_sdata_sym (htab, &htab->sdata[0]))
+ && !create_sdata_sym (info, &htab->sdata[0]))
return FALSE;
if (h != NULL)
{
@@ -3655,7 +3652,7 @@ ppc_elf_check_relocs (bfd *abfd,
return FALSE;
}
if (htab->sdata[1].sym == NULL
- && !create_sdata_sym (htab, &htab->sdata[1]))
+ && !create_sdata_sym (info, &htab->sdata[1]))
return FALSE;
if (h != NULL)
{
@@ -3672,10 +3669,10 @@ ppc_elf_check_relocs (bfd *abfd,
return FALSE;
}
if (htab->sdata[0].sym == NULL
- && !create_sdata_sym (htab, &htab->sdata[0]))
+ && !create_sdata_sym (info, &htab->sdata[0]))
return FALSE;
if (htab->sdata[1].sym == NULL
- && !create_sdata_sym (htab, &htab->sdata[1]))
+ && !create_sdata_sym (info, &htab->sdata[1]))
return FALSE;
if (h != NULL)
{
@@ -5660,6 +5657,18 @@ ppc_elf_size_dynamic_sections (bfd *outp
htab->elf.hgot->root.u.def.value = g_o_t;
}
+ if (info->shared)
+ {
+ struct elf_link_hash_entry *sda = htab->sdata[0].sym;
+ if (sda != NULL
+ && !(sda->root.type == bfd_link_hash_defined
+ || sda->root.type == bfd_link_hash_defweak))
+ {
+ sda->root.type = bfd_link_hash_defined;
+ sda->root.u.def.section = htab->elf.hgot->root.u.def.section;
+ sda->root.u.def.value = htab->elf.hgot->root.u.def.value;
+ }
+ }
if (htab->glink != NULL
&& htab->glink->size != 0
@@ -6446,9 +6455,10 @@ elf_finish_pointer_linker_section (bfd *
linker_section_ptr->offset += 1;
}
- relocation = (lsect->section->output_offset
+ relocation = (lsect->section->output_section->vma
+ + lsect->section->output_offset
+ linker_section_ptr->offset - 1
- - 0x8000);
+ - SYM_VAL (lsect->sym));
#ifdef DEBUG
fprintf (stderr,
@@ -6456,9 +6466,7 @@ elf_finish_pointer_linker_section (bfd *
lsect->name, (long) relocation, (long) relocation);
#endif
- /* Subtract out the addend, because it will get added back in by the normal
- processing. */
- return relocation - linker_section_ptr->addend;
+ return relocation;
}
#define PPC_LO(v) ((v) & 0xffff)
@@ -6528,6 +6536,17 @@ write_glink_stub (struct plt_entry *ent,
}
}
+/* Return true if symbol is defined statically. */
+
+static bfd_boolean
+is_static_defined (struct elf_link_hash_entry *h)
+{
+ return ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section != NULL
+ && h->root.u.def.section->output_section != NULL);
+}
+
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.
@@ -7629,17 +7648,29 @@ ppc_elf_relocate_section (bfd *output_bf
/* Indirect .sdata relocation. */
case R_PPC_EMB_SDAI16:
BFD_ASSERT (htab->sdata[0].section != NULL);
+ if (!is_static_defined (htab->sdata[0].sym))
+ {
+ unresolved_reloc = TRUE;
+ break;
+ }
relocation
= elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0],
h, relocation, rel);
+ addend = 0;
break;
/* Indirect .sdata2 relocation. */
case R_PPC_EMB_SDA2I16:
BFD_ASSERT (htab->sdata[1].section != NULL);
+ if (!is_static_defined (htab->sdata[1].sym))
+ {
+ unresolved_reloc = TRUE;
+ break;
+ }
relocation
= elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1],
h, relocation, rel);
+ addend = 0;
break;
/* Handle the TOC16 reloc. We want to use the offset within the .got
@@ -7692,12 +7723,16 @@ ppc_elf_relocate_section (bfd *output_bf
case R_PPC_SDAREL16:
{
const char *name;
+ struct elf_link_hash_entry *sda = htab->sdata[0].sym;
- if (sec == NULL || sec->output_section == NULL)
+ if (sec == NULL
+ || sec->output_section == NULL
+ || !is_static_defined (sda))
{
unresolved_reloc = TRUE;
break;
}
+ addend -= SYM_VAL (sda);
name = bfd_get_section_name (abfd, sec->output_section);
if (! ((CONST_STRNEQ (name, ".sdata")
@@ -7713,7 +7748,6 @@ ppc_elf_relocate_section (bfd *output_bf
howto->name,
name);
}
- addend -= SYM_VAL (htab->sdata[0].sym);
}
break;
@@ -7721,12 +7755,16 @@ ppc_elf_relocate_section (bfd *output_bf
case R_PPC_EMB_SDA2REL:
{
const char *name;
+ struct elf_link_hash_entry *sda = htab->sdata[1].sym;
- if (sec == NULL || sec->output_section == NULL)
+ if (sec == NULL
+ || sec->output_section == NULL
+ || !is_static_defined (sda))
{
unresolved_reloc = TRUE;
break;
}
+ addend -= SYM_VAL (sda);
name = bfd_get_section_name (abfd, sec->output_section);
if (! (CONST_STRNEQ (name, ".sdata2")
@@ -7739,12 +7777,7 @@ ppc_elf_relocate_section (bfd *output_bf
sym_name,
howto->name,
name);
-
- bfd_set_error (bfd_error_bad_value);
- ret = FALSE;
- continue;
}
- addend -= SYM_VAL (htab->sdata[1].sym);
}
break;
@@ -7754,6 +7787,7 @@ ppc_elf_relocate_section (bfd *output_bf
{
const char *name;
int reg;
+ struct elf_link_hash_entry *sda = NULL;
if (sec == NULL || sec->output_section == NULL)
{
@@ -7768,13 +7802,13 @@ ppc_elf_relocate_section (bfd *output_bf
&& (name[5] == 0 || name[5] == '.'))))
{
reg = 13;
- addend -= SYM_VAL (htab->sdata[0].sym);
+ sda = htab->sdata[0].sym;
}
else if (CONST_STRNEQ (name, ".sdata2")
|| CONST_STRNEQ (name, ".sbss2"))
{
reg = 2;
- addend -= SYM_VAL (htab->sdata[1].sym);
+ sda = htab->sdata[1].sym;
}
else if (strcmp (name, ".PPC.EMB.sdata0") == 0
|| strcmp (name, ".PPC.EMB.sbss0") == 0)
@@ -7796,6 +7830,16 @@ ppc_elf_relocate_section (bfd *output_bf
continue;
}
+ if (sda != NULL)
+ {
+ if (!is_static_defined (sda))
+ {
+ unresolved_reloc = TRUE;
+ break;
+ }
+ addend -= SYM_VAL (sda);
+ }
+
if (r_type == R_PPC_EMB_SDA21)
{ /* fill in register field */
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
--
Alan Modra
Australia Development Lab, IBM