* elf32-sh.c (elf_sh_link_hash_entry): Replace
datalabel_got_offset with union of datalabel_got offset and refcount. (sh_elf_link_hash_newfunc): Initialize datalabel_got.refcount. (allocate_dynrelocs): Delete unnecessary code for STT_DATALABEL type. Create entry in got for datalabel version of symbol if datalabel_got.refcount > 0. (sh_elf_relocate_section): Use datalabel_got union. (sh_elf_gc_sweep_hook): Pull common code to initialize h and eh out of switch statement. Declare seen_stt_datalabel. Initialize it. Decrement datalabel_got.refcount for got relocs when seen_stt_datalabel is true. Decrement local_got_refcounts entry for datalabel got relocs of local symbols. (sh_elf_copy_indirect_symbol): Copy datalabel_got field over. (sh_elf_check_relocs): Declare seen_stt_datalabel. Initialize it. When seen_stt_datalabel is true, increment datalabel_got refcount rather than got.refcount. (sh_elf_finish_dynamic_symbol): Create relocs to initialize got entry for datalabel version of symbol.
This commit is contained in:
parent
24d1feef42
commit
396a608385
|
@ -1,3 +1,26 @@
|
|||
2002-10-14 Stephen Clarke <stephen.clarke@superh.com>
|
||||
|
||||
* elf32-sh.c (elf_sh_link_hash_entry): Replace
|
||||
datalabel_got_offset with union of datalabel_got
|
||||
offset and refcount.
|
||||
(sh_elf_link_hash_newfunc): Initialize datalabel_got.refcount.
|
||||
(allocate_dynrelocs): Delete unnecessary code for
|
||||
STT_DATALABEL type. Create entry in got for
|
||||
datalabel version of symbol if datalabel_got.refcount > 0.
|
||||
(sh_elf_relocate_section): Use datalabel_got union.
|
||||
(sh_elf_gc_sweep_hook): Pull common code to initialize
|
||||
h and eh out of switch statement. Declare seen_stt_datalabel.
|
||||
Initialize it. Decrement datalabel_got.refcount for
|
||||
got relocs when seen_stt_datalabel is true.
|
||||
Decrement local_got_refcounts entry for datalabel got relocs
|
||||
of local symbols.
|
||||
(sh_elf_copy_indirect_symbol): Copy datalabel_got field over.
|
||||
(sh_elf_check_relocs): Declare seen_stt_datalabel.
|
||||
Initialize it. When seen_stt_datalabel is true, increment
|
||||
datalabel_got refcount rather than got.refcount.
|
||||
(sh_elf_finish_dynamic_symbol): Create relocs to
|
||||
initialize got entry for datalabel version of symbol.
|
||||
|
||||
2002-10-14 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* Makefile.am: Run "make dep-am".
|
||||
|
|
423
bfd/elf32-sh.c
423
bfd/elf32-sh.c
|
@ -3505,7 +3505,11 @@ struct elf_sh_link_hash_entry
|
|||
struct elf_link_hash_entry root;
|
||||
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
bfd_vma datalabel_got_offset;
|
||||
union
|
||||
{
|
||||
bfd_signed_vma refcount;
|
||||
bfd_vma offset;
|
||||
} datalabel_got;
|
||||
#endif
|
||||
|
||||
/* Track dynamic relocs copied for this symbol. */
|
||||
|
@ -3616,13 +3620,10 @@ sh_elf_link_hash_newfunc (entry, table, string)
|
|||
table, string));
|
||||
if (ret != (struct elf_sh_link_hash_entry *) NULL)
|
||||
{
|
||||
struct elf_sh_link_hash_entry *eh;
|
||||
|
||||
eh = (struct elf_sh_link_hash_entry *) ret;
|
||||
eh->dyn_relocs = NULL;
|
||||
eh->gotplt_refcount = 0;
|
||||
ret->dyn_relocs = NULL;
|
||||
ret->gotplt_refcount = 0;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
ret->datalabel_got_offset = (bfd_vma) -1;
|
||||
ret->datalabel_got.refcount = ret->root.got.refcount;
|
||||
#endif
|
||||
ret->tls_type = GOT_UNKNOWN;
|
||||
ret->tls_tpoff32 = false;
|
||||
|
@ -4127,20 +4128,7 @@ allocate_dynrelocs (h, inf)
|
|||
}
|
||||
|
||||
s = htab->sgot;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
if (h->type == STT_DATALABEL)
|
||||
{
|
||||
struct elf_sh_link_hash_entry *hsh;
|
||||
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
hsh = (struct elf_sh_link_hash_entry *)h;
|
||||
hsh->datalabel_got_offset = s->_raw_size;
|
||||
}
|
||||
else
|
||||
h->got.offset = s->_raw_size;
|
||||
#else
|
||||
h->got.offset = s->_raw_size;
|
||||
#endif
|
||||
s->_raw_size += 4;
|
||||
/* R_SH_TLS_GD needs 2 consecutive GOT slots. */
|
||||
if (tls_type == GOT_TLS_GD)
|
||||
|
@ -4159,6 +4147,32 @@ allocate_dynrelocs (h, inf)
|
|||
else
|
||||
h->got.offset = (bfd_vma) -1;
|
||||
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
if (eh->datalabel_got.refcount > 0)
|
||||
{
|
||||
asection *s;
|
||||
boolean dyn;
|
||||
|
||||
/* Make sure this symbol is output as a dynamic symbol.
|
||||
Undefined weak syms won't yet be marked as dynamic. */
|
||||
if (h->dynindx == -1
|
||||
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
|
||||
{
|
||||
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
}
|
||||
|
||||
s = htab->sgot;
|
||||
eh->datalabel_got.offset = s->_raw_size;
|
||||
s->_raw_size += 4;
|
||||
dyn = htab->root.dynamic_sections_created;
|
||||
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
|
||||
htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
||||
}
|
||||
else
|
||||
eh->datalabel_got.offset = (bfd_vma) -1;
|
||||
#endif
|
||||
|
||||
if (eh->dyn_relocs == NULL)
|
||||
return true;
|
||||
|
||||
|
@ -4999,7 +5013,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
struct elf_sh_link_hash_entry *hsh;
|
||||
|
||||
hsh = (struct elf_sh_link_hash_entry *)h;
|
||||
off = hsh->datalabel_got_offset;
|
||||
off = hsh->datalabel_got.offset;
|
||||
}
|
||||
#endif
|
||||
BFD_ASSERT (off != (bfd_vma) -1);
|
||||
|
@ -5035,7 +5049,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
struct elf_sh_link_hash_entry *hsh;
|
||||
|
||||
hsh = (struct elf_sh_link_hash_entry *)h;
|
||||
hsh->datalabel_got_offset |= 1;
|
||||
hsh->datalabel_got.offset |= 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -5893,128 +5907,170 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs)
|
|||
|
||||
relend = relocs + sec->reloc_count;
|
||||
for (rel = relocs; rel < relend; rel++)
|
||||
switch (sh_elf_optimized_tls_reloc (info, ELF32_R_TYPE (rel->r_info),
|
||||
ELF32_R_SYM (rel->r_info)
|
||||
>= symtab_hdr->sh_info))
|
||||
{
|
||||
case R_SH_TLS_LD_32:
|
||||
if (sh_elf_hash_table (info)->tls_ldm_got.refcount > 0)
|
||||
sh_elf_hash_table (info)->tls_ldm_got.refcount -= 1;
|
||||
break;
|
||||
|
||||
case R_SH_GOT32:
|
||||
case R_SH_GOTOFF:
|
||||
case R_SH_GOTPC:
|
||||
{
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
case R_SH_GOT_LOW16:
|
||||
case R_SH_GOT_MEDLOW16:
|
||||
case R_SH_GOT_MEDHI16:
|
||||
case R_SH_GOT_HI16:
|
||||
case R_SH_GOT10BY4:
|
||||
case R_SH_GOT10BY8:
|
||||
case R_SH_GOTOFF_LOW16:
|
||||
case R_SH_GOTOFF_MEDLOW16:
|
||||
case R_SH_GOTOFF_MEDHI16:
|
||||
case R_SH_GOTOFF_HI16:
|
||||
case R_SH_GOTPC_LOW16:
|
||||
case R_SH_GOTPC_MEDLOW16:
|
||||
case R_SH_GOTPC_MEDHI16:
|
||||
case R_SH_GOTPC_HI16:
|
||||
int seen_stt_datalabel = 0;
|
||||
#endif
|
||||
case R_SH_TLS_GD_32:
|
||||
case R_SH_TLS_IE_32:
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx >= symtab_hdr->sh_info)
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
else if (local_got_refcounts != NULL)
|
||||
{
|
||||
if (local_got_refcounts[r_symndx] > 0)
|
||||
local_got_refcounts[r_symndx] -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_SH_DIR32:
|
||||
case R_SH_REL32:
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx >= symtab_hdr->sh_info)
|
||||
{
|
||||
struct elf_sh_link_hash_entry *eh;
|
||||
struct elf_sh_dyn_relocs **pp;
|
||||
struct elf_sh_dyn_relocs *p;
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = NULL;
|
||||
else
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
{
|
||||
seen_stt_datalabel |= h->type == STT_DATALABEL;
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
eh = (struct elf_sh_link_hash_entry *) h;
|
||||
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
switch (sh_elf_optimized_tls_reloc (info, ELF32_R_TYPE (rel->r_info),
|
||||
ELF32_R_SYM (rel->r_info)
|
||||
>= symtab_hdr->sh_info))
|
||||
{
|
||||
case R_SH_TLS_LD_32:
|
||||
if (sh_elf_hash_table (info)->tls_ldm_got.refcount > 0)
|
||||
sh_elf_hash_table (info)->tls_ldm_got.refcount -= 1;
|
||||
break;
|
||||
|
||||
if (!info->shared && h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
|
||||
eh = (struct elf_sh_link_hash_entry *) h;
|
||||
|
||||
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
|
||||
if (p->sec == sec)
|
||||
case R_SH_GOT32:
|
||||
case R_SH_GOTOFF:
|
||||
case R_SH_GOTPC:
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
case R_SH_GOT_LOW16:
|
||||
case R_SH_GOT_MEDLOW16:
|
||||
case R_SH_GOT_MEDHI16:
|
||||
case R_SH_GOT_HI16:
|
||||
case R_SH_GOT10BY4:
|
||||
case R_SH_GOT10BY8:
|
||||
case R_SH_GOTOFF_LOW16:
|
||||
case R_SH_GOTOFF_MEDLOW16:
|
||||
case R_SH_GOTOFF_MEDHI16:
|
||||
case R_SH_GOTOFF_HI16:
|
||||
case R_SH_GOTPC_LOW16:
|
||||
case R_SH_GOTPC_MEDLOW16:
|
||||
case R_SH_GOTPC_MEDHI16:
|
||||
case R_SH_GOTPC_HI16:
|
||||
#endif
|
||||
case R_SH_TLS_GD_32:
|
||||
case R_SH_TLS_IE_32:
|
||||
if (h != NULL)
|
||||
{
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
if (seen_stt_datalabel)
|
||||
{
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32)
|
||||
p->pc_count -= 1;
|
||||
p->count -= 1;
|
||||
if (p->count == 0)
|
||||
*pp = p->next;
|
||||
break;
|
||||
if (eh->datalabel_got.refcount > 0)
|
||||
eh->datalabel_got.refcount -= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case R_SH_PLT32:
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
case R_SH_PLT_LOW16:
|
||||
case R_SH_PLT_MEDLOW16:
|
||||
case R_SH_PLT_MEDHI16:
|
||||
case R_SH_PLT_HI16:
|
||||
else
|
||||
#endif
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx >= symtab_hdr->sh_info)
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
if (h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_SH_GOTPLT32:
|
||||
if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
else if (local_got_refcounts != NULL)
|
||||
{
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
case R_SH_GOTPLT_LOW16:
|
||||
case R_SH_GOTPLT_MEDLOW16:
|
||||
case R_SH_GOTPLT_MEDHI16:
|
||||
case R_SH_GOTPLT_HI16:
|
||||
case R_SH_GOTPLT10BY4:
|
||||
case R_SH_GOTPLT10BY8:
|
||||
if (rel->r_addend & 1)
|
||||
{
|
||||
if (local_got_refcounts[symtab_hdr->sh_info + r_symndx] > 0)
|
||||
local_got_refcounts[symtab_hdr->sh_info + r_symndx] -= 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx >= symtab_hdr->sh_info)
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
eh = (struct elf_sh_link_hash_entry *) h;
|
||||
if (eh->gotplt_refcount > 0)
|
||||
{
|
||||
eh->gotplt_refcount -= 1;
|
||||
if (h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
}
|
||||
else if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
else if (local_got_refcounts != NULL)
|
||||
{
|
||||
if (local_got_refcounts[r_symndx] > 0)
|
||||
local_got_refcounts[r_symndx] -= 1;
|
||||
}
|
||||
break;
|
||||
if (local_got_refcounts[r_symndx] > 0)
|
||||
local_got_refcounts[r_symndx] -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case R_SH_DIR32:
|
||||
case R_SH_REL32:
|
||||
if (h != NULL)
|
||||
{
|
||||
struct elf_sh_dyn_relocs **pp;
|
||||
struct elf_sh_dyn_relocs *p;
|
||||
|
||||
|
||||
if (!info->shared && h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
|
||||
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
|
||||
if (p->sec == sec)
|
||||
{
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32)
|
||||
p->pc_count -= 1;
|
||||
p->count -= 1;
|
||||
if (p->count == 0)
|
||||
*pp = p->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case R_SH_PLT32:
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
case R_SH_PLT_LOW16:
|
||||
case R_SH_PLT_MEDLOW16:
|
||||
case R_SH_PLT_MEDHI16:
|
||||
case R_SH_PLT_HI16:
|
||||
#endif
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_SH_GOTPLT32:
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
case R_SH_GOTPLT_LOW16:
|
||||
case R_SH_GOTPLT_MEDLOW16:
|
||||
case R_SH_GOTPLT_MEDHI16:
|
||||
case R_SH_GOTPLT_HI16:
|
||||
case R_SH_GOTPLT10BY4:
|
||||
case R_SH_GOTPLT10BY8:
|
||||
#endif
|
||||
if (h != NULL)
|
||||
{
|
||||
if (eh->gotplt_refcount > 0)
|
||||
{
|
||||
eh->gotplt_refcount -= 1;
|
||||
if (h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
}
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
else if (seen_stt_datalabel)
|
||||
{
|
||||
if (eh->datalabel_got.refcount > 0)
|
||||
eh->datalabel_got.refcount -= 1;
|
||||
}
|
||||
#endif
|
||||
else if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
else if (local_got_refcounts != NULL)
|
||||
{
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
if (rel->r_addend & 1)
|
||||
{
|
||||
if (local_got_refcounts[symtab_hdr->sh_info + r_symndx] > 0)
|
||||
local_got_refcounts[symtab_hdr->sh_info + r_symndx] -= 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (local_got_refcounts[r_symndx] > 0)
|
||||
local_got_refcounts[r_symndx] -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -6027,6 +6083,9 @@ sh_elf_copy_indirect_symbol (bed, dir, ind)
|
|||
struct elf_link_hash_entry *dir, *ind;
|
||||
{
|
||||
struct elf_sh_link_hash_entry *edir, *eind;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
bfd_signed_vma tmp;
|
||||
#endif
|
||||
|
||||
edir = (struct elf_sh_link_hash_entry *) dir;
|
||||
eind = (struct elf_sh_link_hash_entry *) ind;
|
||||
|
@ -6065,6 +6124,16 @@ sh_elf_copy_indirect_symbol (bed, dir, ind)
|
|||
}
|
||||
edir->gotplt_refcount = eind->gotplt_refcount;
|
||||
eind->gotplt_refcount = 0;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
tmp = edir->datalabel_got.refcount;
|
||||
if (tmp < 1)
|
||||
{
|
||||
edir->datalabel_got.refcount = eind->datalabel_got.refcount;
|
||||
eind->datalabel_got.refcount = tmp;
|
||||
}
|
||||
else
|
||||
BFD_ASSERT (eind->datalabel_got.refcount < 1);
|
||||
#endif
|
||||
|
||||
if (ind->root.type == bfd_link_hash_indirect
|
||||
&& dir->got.refcount <= 0)
|
||||
|
@ -6145,6 +6214,9 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
|
|||
{
|
||||
struct elf_link_hash_entry *h;
|
||||
unsigned long r_symndx;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
int seen_stt_datalabel = 0;
|
||||
#endif
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
|
@ -6152,7 +6224,17 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
|
|||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = NULL;
|
||||
else
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
{
|
||||
seen_stt_datalabel |= h->type == STT_DATALABEL;
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
r_type = sh_elf_optimized_tls_reloc (info, r_type, h == NULL);
|
||||
if (! info->shared
|
||||
|
@ -6256,7 +6338,17 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
|
|||
|
||||
if (h != NULL)
|
||||
{
|
||||
h->got.refcount += 1;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
if (seen_stt_datalabel)
|
||||
{
|
||||
struct elf_sh_link_hash_entry *eh =
|
||||
(struct elf_sh_link_hash_entry *)h;
|
||||
|
||||
eh->datalabel_got.refcount += 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
h->got.refcount += 1;
|
||||
old_tls_type = sh_elf_hash_entry (h)->tls_type;
|
||||
}
|
||||
else
|
||||
|
@ -6293,7 +6385,12 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
|
|||
= (char *) (local_got_refcounts + symtab_hdr->sh_info);
|
||||
#endif
|
||||
}
|
||||
local_got_refcounts[r_symndx] += 1;
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
if (rel->r_addend & 1)
|
||||
local_got_refcounts[symtab_hdr->sh_info + r_symndx] += 1;
|
||||
else
|
||||
#endif
|
||||
local_got_refcounts[r_symndx] += 1;
|
||||
old_tls_type = sh_elf_local_got_tls_type (abfd) [r_symndx];
|
||||
}
|
||||
|
||||
|
@ -6948,6 +7045,60 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
|||
++srel->reloc_count;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_SHMEDIA
|
||||
{
|
||||
struct elf_sh_link_hash_entry *eh;
|
||||
|
||||
eh = (struct elf_sh_link_hash_entry *) h;
|
||||
if (eh->datalabel_got.offset != (bfd_vma) -1)
|
||||
{
|
||||
asection *sgot;
|
||||
asection *srel;
|
||||
Elf_Internal_Rela rel;
|
||||
|
||||
/* This symbol has a datalabel entry in the global offset table.
|
||||
Set it up. */
|
||||
|
||||
sgot = htab->sgot;
|
||||
srel = htab->srelgot;
|
||||
BFD_ASSERT (sgot != NULL && srel != NULL);
|
||||
|
||||
rel.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ (eh->datalabel_got.offset &~ (bfd_vma) 1));
|
||||
|
||||
/* If this is a static link, or it is a -Bsymbolic link and the
|
||||
symbol is defined locally or was forced to be local because
|
||||
of a version file, we just want to emit a RELATIVE reloc.
|
||||
The entry in the global offset table will already have been
|
||||
initialized in the relocate_section function. */
|
||||
if (info->shared
|
||||
&& (info->symbolic
|
||||
|| h->dynindx == -1
|
||||
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
|
||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
|
||||
{
|
||||
rel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
|
||||
rel.r_addend = (h->root.u.def.value
|
||||
+ h->root.u.def.section->output_section->vma
|
||||
+ h->root.u.def.section->output_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents
|
||||
+ eh->datalabel_got.offset);
|
||||
rel.r_info = ELF32_R_INFO (h->dynindx, R_SH_GLOB_DAT);
|
||||
rel.r_addend = 0;
|
||||
}
|
||||
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rel,
|
||||
((Elf32_External_Rela *) srel->contents
|
||||
+ srel->reloc_count));
|
||||
++srel->reloc_count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
|
||||
{
|
||||
asection *s;
|
||||
|
|
Loading…
Reference in New Issue