| 1 |
/* CRIS-specific support for 32-bit ELF. |
/* CRIS-specific support for 32-bit ELF. |
| 2 |
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
| 3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
| 4 |
Contributed by Axis Communications AB. |
Contributed by Axis Communications AB. |
| 5 |
Written by Hans-Peter Nilsson, based on elf32-fr30.c |
Written by Hans-Peter Nilsson, based on elf32-fr30.c |
| 1528 |
rel->r_offset); |
rel->r_offset); |
| 1529 |
if (outrel.r_offset == (bfd_vma) -1) |
if (outrel.r_offset == (bfd_vma) -1) |
| 1530 |
skip = TRUE; |
skip = TRUE; |
| 1531 |
else if (outrel.r_offset == (bfd_vma) -2) |
else if (outrel.r_offset == (bfd_vma) -2 |
| 1532 |
|
/* For now, undefined weak symbols with non-default |
| 1533 |
|
visibility (yielding 0), like exception info for |
| 1534 |
|
discarded sections, will get a R_CRIS_NONE |
| 1535 |
|
relocation rather than no relocation, because we |
| 1536 |
|
notice too late that the symbol doesn't need a |
| 1537 |
|
relocation. */ |
| 1538 |
|
|| (h != NULL |
| 1539 |
|
&& h->root.type == bfd_link_hash_undefweak |
| 1540 |
|
&& ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)) |
| 1541 |
skip = TRUE, relocate = TRUE; |
skip = TRUE, relocate = TRUE; |
| 1542 |
outrel.r_offset += (input_section->output_section->vma |
outrel.r_offset += (input_section->output_section->vma |
| 1543 |
+ input_section->output_offset); |
+ input_section->output_offset); |
| 1615 |
case R_CRIS_16_DTPREL: |
case R_CRIS_16_DTPREL: |
| 1616 |
case R_CRIS_32_DTPREL: |
case R_CRIS_32_DTPREL: |
| 1617 |
/* This relocation must only be performed against local |
/* This relocation must only be performed against local |
| 1618 |
symbols. It's also ok when we link a program and the |
symbols, or to sections that are not loadable. It's also |
| 1619 |
symbol is defined in an ordinary (non-DSO) object (if |
ok when we link a program and the symbol is defined in an |
| 1620 |
it's undefined there, we've already seen an error). */ |
ordinary (non-DSO) object (if it's undefined there, we've |
| 1621 |
|
already seen an error). */ |
| 1622 |
if (h != NULL |
if (h != NULL |
| 1623 |
|
&& (input_section->flags & SEC_ALLOC) != 0 |
| 1624 |
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
| 1625 |
&& (info->shared |
&& (info->shared |
| 1626 |
|| (!h->def_regular |
|| (!h->def_regular |
| 1643 |
return FALSE; |
return FALSE; |
| 1644 |
} |
} |
| 1645 |
|
|
| 1646 |
BFD_ASSERT (elf_cris_hash_table (info)->dtpmod_refcount != 0); |
BFD_ASSERT ((input_section->flags & SEC_ALLOC) == 0 |
| 1647 |
|
|| elf_cris_hash_table (info)->dtpmod_refcount != 0); |
| 1648 |
|
|
| 1649 |
/* Fill in a R_CRIS_DTPMOD reloc at offset 3 if we haven't |
/* Fill in a R_CRIS_DTPMOD reloc at offset 3 if we haven't |
| 1650 |
already done so. Note that we do this in .got.plt, not |
already done so. Note that we do this in .got.plt, not |
| 1651 |
in .got, as .got.plt contains the first part, still the |
in .got, as .got.plt contains the first part, still the |
| 1652 |
reloc is against .got, because the linker script directs |
reloc is against .got, because the linker script directs |
| 1653 |
(is required to direct) them both into .got. */ |
(is required to direct) them both into .got. */ |
| 1654 |
if (elf_cris_hash_table (info)->dtpmod_refcount > 0) |
if (elf_cris_hash_table (info)->dtpmod_refcount > 0 |
| 1655 |
|
&& (input_section->flags & SEC_ALLOC) != 0) |
| 1656 |
{ |
{ |
| 1657 |
asection *sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); |
asection *sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); |
| 1658 |
BFD_ASSERT (sgotplt != NULL); |
BFD_ASSERT (sgotplt != NULL); |
| 1691 |
} |
} |
| 1692 |
|
|
| 1693 |
/* The thread-based offset to the local symbol is the |
/* The thread-based offset to the local symbol is the |
| 1694 |
relocation. */ |
relocation. |
| 1695 |
|
For the executable, TLS data begins at the thread pointer plus |
| 1696 |
|
the negative size of the TLS data. For a DSO, that's part of |
| 1697 |
|
the module TLS offset. */ |
| 1698 |
relocation -= elf_hash_table (info)->tls_sec == NULL |
relocation -= elf_hash_table (info)->tls_sec == NULL |
| 1699 |
? 0 : elf_hash_table (info)->tls_sec->vma; |
? 0 : (elf_hash_table (info)->tls_sec->vma |
| 1700 |
|
+ (info->shared |
| 1701 |
|
? 0 : elf_hash_table (info)->tls_size)); |
| 1702 |
break; |
break; |
| 1703 |
|
|
| 1704 |
case R_CRIS_32_GD: |
case R_CRIS_32_GD: |
| 1733 |
return FALSE; |
return FALSE; |
| 1734 |
} |
} |
| 1735 |
|
|
| 1736 |
if (!info->shared && (h == NULL || h->def_regular)) |
if (!info->shared |
| 1737 |
|
&& (h == NULL || h->def_regular || ELF_COMMON_DEF_P (h))) |
| 1738 |
{ |
{ |
| 1739 |
/* Known contents of the GOT. */ |
/* Known contents of the GOT. */ |
| 1740 |
bfd_vma off; |
bfd_vma off; |
| 1891 |
bfd_vma off; |
bfd_vma off; |
| 1892 |
|
|
| 1893 |
/* The symbol is defined in the program, so just write |
/* The symbol is defined in the program, so just write |
| 1894 |
the known_tpoffset into the GOT. */ |
the -prog_tls_size+known_tpoffset into the GOT. */ |
| 1895 |
relocation -= elf_hash_table (info)->tls_sec->vma; |
relocation -= elf_hash_table (info)->tls_sec->vma; |
| 1896 |
|
relocation -= elf_hash_table (info)->tls_size; |
| 1897 |
|
|
| 1898 |
if (h != NULL) |
if (h != NULL) |
| 1899 |
off = h->got.offset; |
off = h->got.offset; |
| 2001 |
|
|
| 2002 |
if (h != NULL |
if (h != NULL |
| 2003 |
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
| 2004 |
&& !h->def_regular |
&& !(h->def_regular || ELF_COMMON_DEF_P (h)) |
| 2005 |
/* If it's undefined, then an error message has already |
/* If it's undefined, then an error message has already |
| 2006 |
been emitted. */ |
been emitted. */ |
| 2007 |
&& h->root.type != bfd_link_hash_undefined) |
&& h->root.type != bfd_link_hash_undefined) |
| 2021 |
|
|
| 2022 |
/* NULL if we had an error. */ |
/* NULL if we had an error. */ |
| 2023 |
relocation -= elf_hash_table (info)->tls_sec == NULL |
relocation -= elf_hash_table (info)->tls_sec == NULL |
| 2024 |
? 0 : elf_hash_table (info)->tls_sec->vma; |
? 0 |
| 2025 |
|
: (elf_hash_table (info)->tls_sec->vma |
| 2026 |
|
+ elf_hash_table (info)->tls_size); |
| 2027 |
|
|
| 2028 |
/* The TLS-relative offset is the relocation. */ |
/* The TLS-relative offset is the relocation. */ |
| 2029 |
break; |
break; |
| 2168 |
bfd_byte *loc; |
bfd_byte *loc; |
| 2169 |
bfd_boolean has_gotplt = gotplt_offset != 0; |
bfd_boolean has_gotplt = gotplt_offset != 0; |
| 2170 |
|
|
| 2171 |
/* Get the index in the procedure linkage table which |
/* Get the index in the .rela.plt relocations for the .got.plt |
| 2172 |
corresponds to this symbol. This is the index of this symbol |
entry that corresponds to this symbol. |
| 2173 |
in all the symbols for which we are making plt entries. The |
We have to count backwards here, and the result is only valid |
| 2174 |
first entry in the procedure linkage table is reserved. */ |
as an index into .rela.plt. We also have to undo the effect |
| 2175 |
/* We have to count backwards here, and the result is only valid as |
of the R_CRIS_DTPMOD entry at .got index 3 (offset 12 into |
| 2176 |
an index into .got.plt and its relocations. FIXME: Constants... */ |
.got.plt) for which gotplt_offset is adjusted, because while |
| 2177 |
bfd_vma gotplt_index = gotplt_offset/4 - 3; |
that entry goes into .got.plt, its relocation goes into |
| 2178 |
|
.rela.got, not .rela.plt. (It's not PLT-specific; not to be |
| 2179 |
|
processed as part of the runtime lazy .rela.plt relocation). |
| 2180 |
|
FIXME: There be literal constants here... */ |
| 2181 |
|
bfd_vma rela_plt_index |
| 2182 |
|
= (elf_cris_hash_table (info)->dtpmod_refcount != 0 |
| 2183 |
|
? gotplt_offset/4 - 2 - 3 : gotplt_offset/4 - 3); |
| 2184 |
|
|
| 2185 |
/* Get the offset into the .got table of the entry that corresponds |
/* Get the offset into the .got table of the entry that corresponds |
| 2186 |
to this function. Note that we embed knowledge that "incoming" |
to this function. Note that we embed knowledge that "incoming" |
| 2230 |
{ |
{ |
| 2231 |
/* Fill in the offset to the reloc table. */ |
/* Fill in the offset to the reloc table. */ |
| 2232 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 2233 |
gotplt_index * sizeof (Elf32_External_Rela), |
rela_plt_index * sizeof (Elf32_External_Rela), |
| 2234 |
splt->contents + h->plt.offset + plt_off2); |
splt->contents + h->plt.offset + plt_off2); |
| 2235 |
|
|
| 2236 |
/* Fill in the offset to the first PLT entry, where to "jump". */ |
/* Fill in the offset to the first PLT entry, where to "jump". */ |
| 2253 |
+ got_offset); |
+ got_offset); |
| 2254 |
rela.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_JUMP_SLOT); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_JUMP_SLOT); |
| 2255 |
rela.r_addend = 0; |
rela.r_addend = 0; |
| 2256 |
loc = srela->contents + gotplt_index * sizeof (Elf32_External_Rela); |
loc = srela->contents + rela_plt_index * sizeof (Elf32_External_Rela); |
| 2257 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
| 2258 |
} |
} |
| 2259 |
|
|
| 2689 |
break; |
break; |
| 2690 |
|
|
| 2691 |
case R_CRIS_32_DTPREL: |
case R_CRIS_32_DTPREL: |
| 2692 |
|
/* This'd be a .dtpreld entry in e.g. debug info. */ |
| 2693 |
|
if ((sec->flags & SEC_ALLOC) == 0) |
| 2694 |
|
break; |
| 2695 |
|
/* Fall through. */ |
| 2696 |
case R_CRIS_16_DTPREL: |
case R_CRIS_16_DTPREL: |
| 2697 |
elf_cris_hash_table (info)->dtpmod_refcount--; |
elf_cris_hash_table (info)->dtpmod_refcount--; |
| 2698 |
if (elf_cris_hash_table (info)->dtpmod_refcount == 0) |
if (elf_cris_hash_table (info)->dtpmod_refcount == 0) |
| 3077 |
/* Only indirect symbols are replaced; we're not interested in |
/* Only indirect symbols are replaced; we're not interested in |
| 3078 |
updating any of EIND's fields for other symbols. */ |
updating any of EIND's fields for other symbols. */ |
| 3079 |
if (eind->root.root.type != bfd_link_hash_indirect) |
if (eind->root.root.type != bfd_link_hash_indirect) |
| 3080 |
return; |
{ |
| 3081 |
|
/* Still, we need to copy flags for e.g. weak definitions. */ |
| 3082 |
|
_bfd_elf_link_hash_copy_indirect (info, dir, ind); |
| 3083 |
|
return; |
| 3084 |
|
} |
| 3085 |
|
|
| 3086 |
BFD_ASSERT (edir->pcrel_relocs_copied == NULL); |
BFD_ASSERT (edir->pcrel_relocs_copied == NULL); |
| 3087 |
BFD_ASSERT (edir->gotplt_offset == 0 || eind->gotplt_offset == 0); |
BFD_ASSERT (edir->gotplt_offset == 0 || eind->gotplt_offset == 0); |
| 3160 |
on the first input bfd we found that contained dynamic relocs. */ |
on the first input bfd we found that contained dynamic relocs. */ |
| 3161 |
switch (r_type) |
switch (r_type) |
| 3162 |
{ |
{ |
|
case R_CRIS_16_DTPREL: |
|
| 3163 |
case R_CRIS_32_DTPREL: |
case R_CRIS_32_DTPREL: |
| 3164 |
|
if ((sec->flags & SEC_ALLOC) == 0) |
| 3165 |
|
/* This'd be a .dtpreld entry in e.g. debug info. We have |
| 3166 |
|
several different switch statements below, but none of |
| 3167 |
|
that is needed; we need no preparations for resolving |
| 3168 |
|
R_CRIS_32_DTPREL into a non-allocated section (debug |
| 3169 |
|
info), so let's just move on to the next |
| 3170 |
|
relocation. */ |
| 3171 |
|
continue; |
| 3172 |
|
/* Fall through. */ |
| 3173 |
|
case R_CRIS_16_DTPREL: |
| 3174 |
/* The first .got.plt entry is right after the R_CRIS_DTPMOD |
/* The first .got.plt entry is right after the R_CRIS_DTPMOD |
| 3175 |
entry at index 3. */ |
entry at index 3. */ |
| 3176 |
if (elf_cris_hash_table (info)->dtpmod_refcount == 0) |
if (elf_cris_hash_table (info)->dtpmod_refcount == 0) |