aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elf32-ppc.c110
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