aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-10-26 23:03:34 +0000
committerIan Lance Taylor <ian@airs.com>1995-10-26 23:03:34 +0000
commit230de6b86821d6558fc9af2ed7d89aaaee8175f6 (patch)
tree9c7a0d75c6858454104ba26cb173931198ddf941 /bfd
parent972821a346258eb36d7a30f1d1571d974ea15baa (diff)
downloadfsf-binutils-gdb-230de6b86821d6558fc9af2ed7d89aaaee8175f6.zip
fsf-binutils-gdb-230de6b86821d6558fc9af2ed7d89aaaee8175f6.tar.gz
fsf-binutils-gdb-230de6b86821d6558fc9af2ed7d89aaaee8175f6.tar.bz2
get symndx right for TOC relative relocs
Diffstat (limited to 'bfd')
-rw-r--r--bfd/xcofflink.c75
1 files changed, 60 insertions, 15 deletions
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 33251b1..290643b 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -242,9 +242,15 @@ struct xcoff_link_hash_entry
section which holds it. */
asection *toc_section;
- /* If we have created a TOC entry, this is the offset in
- toc_section. */
- bfd_vma toc_offset;
+ union
+ {
+ /* If we have created a TOC entry (the XCOFF_SET_TOC flag is
+ set), this is the offset in toc_section. */
+ bfd_vma toc_offset;
+ /* If the TOC entry comes from an input file, this is set to the
+ symbo lindex of the C_HIDEXT XMC_TC symbol. */
+ long toc_indx;
+ } u;
/* If this symbol is a function entry point which is called, this
field holds a pointer to the function descriptor. */
@@ -505,7 +511,7 @@ xcoff_link_hash_newfunc (entry, table, string)
/* Set local fields. */
ret->indx = -1;
ret->toc_section = NULL;
- ret->toc_offset = 0;
+ ret->u.toc_indx = -1;
ret->descriptor = NULL;
ret->ldsym = NULL;
ret->ldindx = -1;
@@ -1385,10 +1391,7 @@ xcoff_link_add_symbols (abfd, info)
/* If this is a TOC section for a symbol, record it. */
if (set_toc != NULL)
- {
- set_toc->toc_section = csect;
- set_toc->toc_offset = 0;
- }
+ set_toc->toc_section = csect;
}
break;
@@ -2562,7 +2565,7 @@ xcoff_build_ldsyms (h, p)
if (hds->toc_section == NULL)
{
hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
- hds->toc_offset = hds->toc_section->_raw_size;
+ hds->u.toc_offset = hds->toc_section->_raw_size;
hds->toc_section->_raw_size += 4;
++xcoff_hash_table (ldinfo->info)->ldrel_count;
++hds->toc_section->reloc_count;
@@ -3658,6 +3661,18 @@ xcoff_link_input_bfd (finfo, input_bfd)
h->indx = output_index;
}
+ /* If this is a symbol in the TOC which we may have merged
+ (class XMC_TC), remember the symbol index of the TOC
+ symbol. */
+ if (isym.n_sclass == C_HIDEXT
+ && aux.x_csect.x_smclas == XMC_TC
+ && *sym_hash != NULL)
+ {
+ BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
+ BFD_ASSERT ((*sym_hash)->toc_section != NULL);
+ (*sym_hash)->u.toc_indx = output_index;
+ }
+
output_index += add;
outsym += add * osymesz;
}
@@ -4044,7 +4059,34 @@ xcoff_link_input_bfd (finfo, input_bfd)
if (r_symndx != -1)
{
h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
- if (h != NULL)
+ if (h != NULL
+ && (irel->r_type == R_TOC
+ || irel->r_type == R_GL
+ || irel->r_type == R_TCL
+ || irel->r_type == R_TRL
+ || irel->r_type == R_TRLA))
+ {
+ /* This is a TOC relative reloc with a symbol
+ attached. The symbol should be the one which
+ this reloc is for. We want to make this
+ reloc against the TOC address of the symbol,
+ not the symbol itself. */
+ BFD_ASSERT (h->toc_section != NULL);
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ if (h->u.toc_indx == -1)
+ {
+ /* We could handle this case if we had to,
+ but I don't think it can arise. */
+ (*_bfd_error_handler)
+ ("%s: unattached TOC reloc against `%s'",
+ bfd_get_filename (input_bfd),
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ irel->r_symndx = h->u.toc_indx;
+ }
+ else if (h != NULL)
{
/* This is a global symbol. */
if (h->indx >= 0)
@@ -4344,8 +4386,9 @@ xcoff_write_global_symbol (h, p)
specific TOC element. */
tocoff = (h->descriptor->toc_section->output_section->vma
+ h->descriptor->toc_section->output_offset
- + h->descriptor->toc_offset
- xcoff_data (output_bfd)->toc);
+ if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
+ tocoff += h->descriptor->u.toc_offset;
bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | tocoff, p);
for (i = 0, p += 4;
i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
@@ -4369,7 +4412,7 @@ xcoff_write_global_symbol (h, p)
irel = finfo->section_info[oindx].relocs + osec->reloc_count;
irel->r_vaddr = (osec->vma
+ tocsec->output_offset
- + h->toc_offset);
+ + h->u.toc_offset);
if (h->indx >= 0)
irel->r_symndx = h->indx;
else
@@ -4838,9 +4881,11 @@ _bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
return false;
}
if (h != NULL)
- val = (h->toc_section->output_section->vma
- + h->toc_section->output_offset
- + h->toc_offset);
+ {
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ val = (h->toc_section->output_section->vma
+ + h->toc_section->output_offset);
+ }
val = ((val - xcoff_data (output_bfd)->toc)
- (sym->n_value - xcoff_data (input_bfd)->toc));
addend = 0;