diff options
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 110 |
2 files changed, 57 insertions, 62 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c9cbe0c..6a2e8f3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,14 @@ 2008-09-16 Alan Modra <amodra@bigpond.net.au> + PR 6844 + * elf32-ppc.c (SYM_VAL): Define. Use throughout to find symbol vma. + (ppc_elf_relocate_section): Correct GOT offset calculation. + (ppc_elf_finish_dynamic_symbol): Use PPC_HA and PPC_LO. + (ppc_elf_finish_dynamic_sections): Likewise. Error if + htab->elf.hgot symbol is not defined in htab->got section. + +2008-09-16 Alan Modra <amodra@bigpond.net.au> + PR 6888 * elf32-ppc.c (ppc_elf_relocate_section): Handle NULL symbol section on R_PPC_TOC16, R_PPC_SDAREL16, R_PPC_EMB_SDA2REL, R_PPC_EMB_SDA21, diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 8720b0b..1082820 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -157,6 +157,12 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry /* Offset of tp and dtp pointers from start of TLS block. */ #define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 + +/* The value of a defined global symbol. */ +#define SYM_VAL(SYM) \ + ((SYM)->root.u.def.section->output_section->vma \ + + (SYM)->root.u.def.section->output_offset \ + + (SYM)->root.u.def.value) static reloc_howto_type *ppc_elf_howto_table[R_PPC_max]; @@ -6656,8 +6662,10 @@ ppc_elf_relocate_section (bfd *output_bfd, } } - relocation = htab->got->output_offset + off; - relocation -= htab->elf.hgot->root.u.def.value; + relocation = (htab->got->output_section->vma + + htab->got->output_offset + + off + - SYM_VAL (htab->elf.hgot)); /* Addends on got relocations don't make much sense. x+off@got is actually x@got+off, and since the got is @@ -7014,7 +7022,6 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_SDAREL16: { const char *name; - struct elf_link_hash_entry *sh; if (sec == NULL || sec->output_section == NULL) { @@ -7036,10 +7043,7 @@ ppc_elf_relocate_section (bfd *output_bfd, howto->name, name); } - sh = htab->sdata[0].sym; - addend -= (sh->root.u.def.value - + sh->root.u.def.section->output_offset - + sh->root.u.def.section->output_section->vma); + addend -= SYM_VAL (htab->sdata[0].sym); } break; @@ -7047,7 +7051,6 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_EMB_SDA2REL: { const char *name; - struct elf_link_hash_entry *sh; if (sec == NULL || sec->output_section == NULL) { @@ -7071,10 +7074,7 @@ ppc_elf_relocate_section (bfd *output_bfd, ret = FALSE; continue; } - sh = htab->sdata[1].sym; - addend -= (sh->root.u.def.value - + sh->root.u.def.section->output_offset - + sh->root.u.def.section->output_section->vma); + addend -= SYM_VAL (htab->sdata[1].sym); } break; @@ -7084,7 +7084,6 @@ ppc_elf_relocate_section (bfd *output_bfd, { const char *name; int reg; - struct elf_link_hash_entry *sh; if (sec == NULL || sec->output_section == NULL) { @@ -7099,19 +7098,13 @@ ppc_elf_relocate_section (bfd *output_bfd, && (name[5] == 0 || name[5] == '.')))) { reg = 13; - sh = htab->sdata[0].sym; - addend -= (sh->root.u.def.value - + sh->root.u.def.section->output_offset - + sh->root.u.def.section->output_section->vma); + addend -= SYM_VAL (htab->sdata[0].sym); } else if (CONST_STRNEQ (name, ".sdata2") || CONST_STRNEQ (name, ".sbss2")) { reg = 2; - sh = htab->sdata[1].sym; - addend -= (sh->root.u.def.value - + sh->root.u.def.section->output_offset - + sh->root.u.def.section->output_section->vma); + addend -= SYM_VAL (htab->sdata[1].sym); } else if (strcmp (name, ".PPC.EMB.sdata0") == 0 || strcmp (name, ".PPC.EMB.sbss0") == 0) @@ -7366,31 +7359,22 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, /* Fill in the .plt on VxWorks. */ if (info->shared) { - bfd_vma got_offset_hi = (got_offset >> 16) - + ((got_offset & 0x8000) >> 15); - bfd_put_32 (output_bfd, - plt_entry[0] | (got_offset_hi & 0xffff), + plt_entry[0] | PPC_HA (got_offset), htab->plt->contents + ent->plt.offset + 0); bfd_put_32 (output_bfd, - plt_entry[1] | (got_offset & 0xffff), + plt_entry[1] | PPC_LO (got_offset), htab->plt->contents + ent->plt.offset + 4); } else { - bfd_vma got_loc - = (got_offset - + htab->elf.hgot->root.u.def.value - + htab->elf.hgot->root.u.def.section->output_offset - + htab->elf.hgot->root.u.def.section->output_section->vma); - bfd_vma got_loc_hi = (got_loc >> 16) - + ((got_loc & 0x8000) >> 15); + bfd_vma got_loc = got_offset + SYM_VAL (htab->elf.hgot); bfd_put_32 (output_bfd, - plt_entry[0] | (got_loc_hi & 0xffff), + plt_entry[0] | PPC_HA (got_loc), htab->plt->contents + ent->plt.offset + 0); bfd_put_32 (output_bfd, - plt_entry[1] | (got_loc & 0xffff), + plt_entry[1] | PPC_LO (got_loc), htab->plt->contents + ent->plt.offset + 4); } @@ -7550,9 +7534,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, + ent->sec->output_section->vma + ent->sec->output_offset); else if (htab->elf.hgot != NULL) - got = (htab->elf.hgot->root.u.def.value - + htab->elf.hgot->root.u.def.section->output_section->vma - + htab->elf.hgot->root.u.def.section->output_offset); + got = SYM_VAL (htab->elf.hgot); plt -= got; @@ -7618,9 +7600,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, s = htab->relbss; BFD_ASSERT (s != NULL); - rela.r_offset = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); + rela.r_offset = SYM_VAL (h); rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); rela.r_addend = 0; loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); @@ -7670,7 +7650,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, asection *splt; struct ppc_elf_link_hash_table *htab; bfd_vma got; - bfd * dynobj; + bfd *dynobj; + bfd_boolean ret = TRUE; #ifdef DEBUG fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); @@ -7686,9 +7667,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, got = 0; if (htab->elf.hgot != NULL) - got = (htab->elf.hgot->root.u.def.value - + htab->elf.hgot->root.u.def.section->output_section->vma - + htab->elf.hgot->root.u.def.section->output_offset); + got = SYM_VAL (htab->elf.hgot); if (htab->elf.dynamic_sections_created) { @@ -7752,17 +7731,28 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, easily find the address of the _GLOBAL_OFFSET_TABLE_. */ if (htab->got != NULL) { - unsigned char *p = htab->got->contents; - bfd_vma val; + if (htab->elf.hgot->root.u.def.section == htab->got) + { + unsigned char *p = htab->got->contents; + bfd_vma val; - p += htab->elf.hgot->root.u.def.value; - if (htab->plt_type == PLT_OLD) - bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4); + p += htab->elf.hgot->root.u.def.value; + if (htab->plt_type == PLT_OLD) + bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4); - val = 0; - if (sdyn != NULL) - val = sdyn->output_section->vma + sdyn->output_offset; - bfd_put_32 (output_bfd, val, p); + val = 0; + if (sdyn != NULL) + val = sdyn->output_section->vma + sdyn->output_offset; + bfd_put_32 (output_bfd, val, p); + } + else + { + (*_bfd_error_handler) (_("%s not defined in linker created %s"), + htab->elf.hgot->root.root.string, + htab->got->name); + bfd_set_error (bfd_error_bad_value); + ret = FALSE; + } elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4; } @@ -7777,15 +7767,11 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, if (!info->shared) { - bfd_vma got_value = - (htab->elf.hgot->root.u.def.section->output_section->vma - + htab->elf.hgot->root.u.def.section->output_offset - + htab->elf.hgot->root.u.def.value); - bfd_vma got_hi = (got_value >> 16) + ((got_value & 0x8000) >> 15); + bfd_vma got_value = SYM_VAL (htab->elf.hgot); - bfd_put_32 (output_bfd, plt_entry[0] | (got_hi & 0xffff), + bfd_put_32 (output_bfd, plt_entry[0] | PPC_HA (got_value), splt->contents + 0); - bfd_put_32 (output_bfd, plt_entry[1] | (got_value & 0xffff), + bfd_put_32 (output_bfd, plt_entry[1] | PPC_LO (got_value), splt->contents + 4); } else @@ -8050,7 +8036,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, } } - return TRUE; + return ret; } #define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec |