From bd6c6e2b809ed691984795a87afe7b64a9d0b47c Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 18 Sep 2009 12:41:52 +0000 Subject: [PATCH] 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. --- bfd/ChangeLog | 18 ++++++++++ bfd/elf32-ppc.c | 102 ++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 91 insertions(+), 29 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9a8e9bc..a009399 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,21 @@ +2009-09-18 Alan Modra + + 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. + 2009-09-18 Nick Clifton * po/es.po: Updated Spanish translation. diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index ae031df..bbe94db 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -1300,7 +1300,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 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_raw[] = { 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_hash_table *htab, 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 *output_bfd ATTRIBUTE_UNUSED, 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 *input_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 *input_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, asection *plt_sec, } } +/* 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_bfd, /* 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_bfd, 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_bfd, howto->name, name); } - addend -= SYM_VAL (htab->sdata[0].sym); } break; @@ -7721,12 +7755,16 @@ ppc_elf_relocate_section (bfd *output_bfd, 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_bfd, 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_bfd, { 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_bfd, && (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_bfd, 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); -- 2.7.4