* PowerPC _GLOBAL_OFFSET_TABLE_
@ 2008-09-16 13:43 Alan Modra
2008-09-19 9:50 ` Alan Modra
0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2008-09-16 13:43 UTC (permalink / raw)
To: binutils
While I closed PR 6844 as invalid, due to a link script defining
_GLOBAL_OFFSET_TABLE_ outside of the .got section (and outside the
size of the .got section too), I figure that ld shouldn't segfault.
_GLOBAL_OFFSET_TABLE_ is special. It marks a header in the linker
generated .got section, so can't be defined somewhere else by a linker
script.
What's more, on checking uses of this symbol, I found a case where
we would generate a wrong relocation if the linker generated .got
section wasn't the first section in the output .got section. (You'd
need decidedly odd object files to trigger this.)
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.
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.244
diff -u -p -r1.244 elf32-ppc.c
--- bfd/elf32-ppc.c 15 Sep 2008 23:41:55 -0000 1.244
+++ bfd/elf32-ppc.c 16 Sep 2008 13:26:37 -0000
@@ -157,6 +157,12 @@ static const bfd_vma ppc_elf_vxworks_pic
/* 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)
\f
static reloc_howto_type *ppc_elf_howto_table[R_PPC_max];
@@ -6656,8 +6662,10 @@ ppc_elf_relocate_section (bfd *output_bf
}
}
- 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_bf
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_bf
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_bf
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_bf
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_bf
{
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_bf
&& (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 *outp
/* 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 *outp
+ 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 *outp
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 *ou
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 *ou
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 *ou
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);
-
- val = 0;
- if (sdyn != NULL)
- val = sdyn->output_section->vma + sdyn->output_offset;
- bfd_put_32 (output_bfd, val, p);
+ 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);
+ }
+ 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 *ou
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 *ou
}
}
- return TRUE;
+ return ret;
}
\f
#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: PowerPC _GLOBAL_OFFSET_TABLE_
2008-09-16 13:43 PowerPC _GLOBAL_OFFSET_TABLE_ Alan Modra
@ 2008-09-19 9:50 ` Alan Modra
0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2008-09-19 9:50 UTC (permalink / raw)
To: binutils
On Tue, Sep 16, 2008 at 11:12:48PM +0930, Alan Modra wrote:
> (ppc_elf_finish_dynamic_sections): Likewise. Error if
> htab->elf.hgot symbol is not defined in htab->got section.
My 2008-09-16 change resulted in "_GLOBAL_OFFSET_TABLE_ not defined
in linker created .got" errors on powerpc-vxworks, since in that case
the symbol is defined in .got.plt. However, I think the code setting
up the got header has been broken since the original vxworks commit.
Space for the header is allocated in .got.plt, but the .dynamic
address was being written to .got, overwriting the first .got entry.
I couldn't find details on what vxworks expects in the got header,
so don't really know if this is correct even now..
* elf32-ppc.c (ppc_elf_finish_dynamic_sections): Handle vxworks
_GLOBAL_OFFSET_TABLE_ in .got.plt section. Add BFD_ASSERTs.
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.245
diff -u -p -r1.245 elf32-ppc.c
--- bfd/elf32-ppc.c 16 Sep 2008 13:43:36 -0000 1.245
+++ bfd/elf32-ppc.c 19 Sep 2008 09:01:06 -0000
@@ -7727,29 +7727,38 @@ ppc_elf_finish_dynamic_sections (bfd *ou
}
}
- /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
- easily find the address of the _GLOBAL_OFFSET_TABLE_. */
if (htab->got != NULL)
{
- if (htab->elf.hgot->root.u.def.section == htab->got)
+ if (htab->elf.hgot->root.u.def.section == htab->got
+ || htab->elf.hgot->root.u.def.section == htab->sgotplt)
{
- unsigned char *p = htab->got->contents;
- bfd_vma val;
+ unsigned char *p = htab->elf.hgot->root.u.def.section->contents;
p += htab->elf.hgot->root.u.def.value;
if (htab->plt_type == PLT_OLD)
- bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+ {
+ /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4
+ so that a function can easily find the address of
+ _GLOBAL_OFFSET_TABLE_. */
+ BFD_ASSERT (htab->elf.hgot->root.u.def.value - 4
+ < htab->elf.hgot->root.u.def.section->size);
+ bfd_put_32 (output_bfd, 0x4e800021, p - 4);
+ }
- val = 0;
if (sdyn != NULL)
- val = sdyn->output_section->vma + sdyn->output_offset;
- bfd_put_32 (output_bfd, val, p);
+ {
+ bfd_vma val = sdyn->output_section->vma + sdyn->output_offset;
+ BFD_ASSERT (htab->elf.hgot->root.u.def.value
+ < htab->elf.hgot->root.u.def.section->size);
+ 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);
+ (htab->sgotplt != NULL
+ ? htab->sgotplt->name : htab->got->name));
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
}
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-09-19 9:50 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-09-16 13:43 PowerPC _GLOBAL_OFFSET_TABLE_ Alan Modra
2008-09-19 9:50 ` Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).