* 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.
This commit is contained in:
Alan Modra 2008-09-16 13:43:36 +00:00
parent 9fa33bee6a
commit e87d403811
2 changed files with 57 additions and 62 deletions

View File

@ -1,3 +1,12 @@
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

View File

@ -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