| version 1.2.2.1, 2005/03/16 19:11:27 |
version 1.3, 2004/12/08 13:38:08 |
|
|
| /* SPARC-specific support for 64-bit ELF |
/* SPARC-specific support for 64-bit ELF |
| Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
| 2003 Free Software Foundation, Inc. |
2003, 2004 Free Software Foundation, Inc. |
| |
|
| This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
| |
|
| Line 61 static bfd_boolean sparc64_elf_size_dyna |
|
| Line 61 static bfd_boolean sparc64_elf_size_dyna |
|
| static int sparc64_elf_get_symbol_type |
static int sparc64_elf_get_symbol_type |
| PARAMS (( Elf_Internal_Sym *, int)); |
PARAMS (( Elf_Internal_Sym *, int)); |
| static bfd_boolean sparc64_elf_add_symbol_hook |
static bfd_boolean sparc64_elf_add_symbol_hook |
| PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, |
PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *, |
| const char **, flagword *, asection **, bfd_vma *)); |
const char **, flagword *, asection **, bfd_vma *)); |
| static bfd_boolean sparc64_elf_output_arch_syms |
static bfd_boolean sparc64_elf_output_arch_syms |
| PARAMS ((bfd *, struct bfd_link_info *, PTR, |
PARAMS ((bfd *, struct bfd_link_info *, PTR, |
| bfd_boolean (*) (PTR, const char *, Elf_Internal_Sym *, asection *))); |
bfd_boolean (*) (PTR, const char *, Elf_Internal_Sym *, |
| |
asection *, struct elf_link_hash_entry *))); |
| static void sparc64_elf_symbol_processing |
static void sparc64_elf_symbol_processing |
| PARAMS ((bfd *, asymbol *)); |
PARAMS ((bfd *, asymbol *)); |
| |
|
| Line 518 sparc64_elf_canonicalize_reloc (abfd, se |
|
| Line 519 sparc64_elf_canonicalize_reloc (abfd, se |
|
| { |
{ |
| arelent *tblptr; |
arelent *tblptr; |
| unsigned int i; |
unsigned int i; |
| struct elf_backend_data *bed = get_elf_backend_data (abfd); |
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
| |
|
| if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE)) |
if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE)) |
| return -1; |
return -1; |
| Line 1101 sparc64_elf_check_relocs (abfd, info, se |
|
| Line 1102 sparc64_elf_check_relocs (abfd, info, se |
|
| asection *srelgot; |
asection *srelgot; |
| asection *sreloc; |
asection *sreloc; |
| |
|
| if (info->relocateable || !(sec->flags & SEC_ALLOC)) |
if (info->relocatable || !(sec->flags & SEC_ALLOC)) |
| return TRUE; |
return TRUE; |
| |
|
| dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
| Line 1177 sparc64_elf_check_relocs (abfd, info, se |
|
| Line 1178 sparc64_elf_check_relocs (abfd, info, se |
|
| /* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
| if (h->dynindx == -1) |
if (h->dynindx == -1) |
| { |
{ |
| if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
| return FALSE; |
return FALSE; |
| } |
} |
| |
|
| Line 1260 sparc64_elf_check_relocs (abfd, info, se |
|
| Line 1261 sparc64_elf_check_relocs (abfd, info, se |
|
| /* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
| if (h->dynindx == -1) |
if (h->dynindx == -1) |
| { |
{ |
| if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
| return FALSE; |
return FALSE; |
| } |
} |
| |
|
| Line 1384 static bfd_boolean |
|
| Line 1385 static bfd_boolean |
|
| sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
| bfd *abfd; |
bfd *abfd; |
| struct bfd_link_info *info; |
struct bfd_link_info *info; |
| const Elf_Internal_Sym *sym; |
Elf_Internal_Sym *sym; |
| const char **namep; |
const char **namep; |
| flagword *flagsp ATTRIBUTE_UNUSED; |
flagword *flagsp ATTRIBUTE_UNUSED; |
| asection **secp ATTRIBUTE_UNUSED; |
asection **secp ATTRIBUTE_UNUSED; |
| Line 1502 sparc64_elf_add_symbol_hook (abfd, info, |
|
| Line 1503 sparc64_elf_add_symbol_hook (abfd, info, |
|
| return TRUE; |
return TRUE; |
| } |
} |
| |
|
| /* This function takes care of emiting STT_REGISTER symbols |
/* This function takes care of emitting STT_REGISTER symbols |
| which we cannot easily keep in the symbol hash table. */ |
which we cannot easily keep in the symbol hash table. */ |
| |
|
| static bfd_boolean |
static bfd_boolean |
| Line 1511 sparc64_elf_output_arch_syms (output_bfd |
|
| Line 1512 sparc64_elf_output_arch_syms (output_bfd |
|
| struct bfd_link_info *info; |
struct bfd_link_info *info; |
| PTR finfo; |
PTR finfo; |
| bfd_boolean (*func) |
bfd_boolean (*func) |
| PARAMS ((PTR, const char *, Elf_Internal_Sym *, asection *)); |
PARAMS ((PTR, const char *, Elf_Internal_Sym *, asection *, |
| |
struct elf_link_hash_entry *)); |
| { |
{ |
| int reg; |
int reg; |
| struct sparc64_elf_app_reg *app_regs = |
struct sparc64_elf_app_reg *app_regs = |
| Line 1557 sparc64_elf_output_arch_syms (output_bfd |
|
| Line 1559 sparc64_elf_output_arch_syms (output_bfd |
|
| sym.st_shndx = app_regs [reg].shndx; |
sym.st_shndx = app_regs [reg].shndx; |
| if (! (*func) (finfo, app_regs [reg].name, &sym, |
if (! (*func) (finfo, app_regs [reg].name, &sym, |
| sym.st_shndx == SHN_ABS |
sym.st_shndx == SHN_ABS |
| ? bfd_abs_section_ptr : bfd_und_section_ptr)) |
? bfd_abs_section_ptr : bfd_und_section_ptr, |
| |
NULL)) |
| return FALSE; |
return FALSE; |
| } |
} |
| |
|
| Line 1635 sparc64_elf_adjust_dynamic_symbol (info, |
|
| Line 1638 sparc64_elf_adjust_dynamic_symbol (info, |
|
| || h->root.type == bfd_link_hash_defweak) |
|| h->root.type == bfd_link_hash_defweak) |
| && (h->root.u.def.section->flags & SEC_CODE) != 0)) |
&& (h->root.u.def.section->flags & SEC_CODE) != 0)) |
| { |
{ |
| if (! info->shared |
if (! elf_hash_table (info)->dynamic_sections_created) |
| && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 |
|
| && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 |
|
| && h->root.type != bfd_link_hash_undefweak |
|
| && h->root.type != bfd_link_hash_undefined) |
|
| { |
{ |
| /* This case can occur if we saw a WPLT30 reloc in an input |
/* This case can occur if we saw a WPLT30 reloc in an input |
| file, but none of the input files were dynamic objects. |
file, but none of the input files were dynamic objects. |
| Line 1791 sparc64_elf_size_dynamic_sections (outpu |
|
| Line 1790 sparc64_elf_size_dynamic_sections (outpu |
|
| if (elf_hash_table (info)->dynamic_sections_created) |
if (elf_hash_table (info)->dynamic_sections_created) |
| { |
{ |
| /* Set the contents of the .interp section to the interpreter. */ |
/* Set the contents of the .interp section to the interpreter. */ |
| if (! info->shared) |
if (info->executable) |
| { |
{ |
| s = bfd_get_section_by_name (dynobj, ".interp"); |
s = bfd_get_section_by_name (dynobj, ".interp"); |
| BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
| Line 1883 sparc64_elf_size_dynamic_sections (outpu |
|
| Line 1882 sparc64_elf_size_dynamic_sections (outpu |
|
| the .dynamic section. The DT_DEBUG entry is filled in by the |
the .dynamic section. The DT_DEBUG entry is filled in by the |
| dynamic linker and used by the debugger. */ |
dynamic linker and used by the debugger. */ |
| #define add_dynamic_entry(TAG, VAL) \ |
#define add_dynamic_entry(TAG, VAL) \ |
| bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) |
_bfd_elf_add_dynamic_entry (info, TAG, VAL) |
| |
|
| int reg; |
int reg; |
| struct sparc64_elf_app_reg * app_regs; |
struct sparc64_elf_app_reg * app_regs; |
| struct elf_strtab_hash *dynstr; |
struct elf_strtab_hash *dynstr; |
| struct elf_link_hash_table *eht = elf_hash_table (info); |
struct elf_link_hash_table *eht = elf_hash_table (info); |
| |
|
| if (!info->shared) |
if (info->executable) |
| { |
{ |
| if (!add_dynamic_entry (DT_DEBUG, 0)) |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
| return FALSE; |
return FALSE; |
| Line 1996 sparc64_elf_relax_section (abfd, section |
|
| Line 1995 sparc64_elf_relax_section (abfd, section |
|
| return TRUE; |
return TRUE; |
| } |
} |
| |
|
| /* This is the condition under which finish_dynamic_symbol will be called |
|
| from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol |
|
| routine, we'll need to do something about initializing any .plt and |
|
| .got entries in relocate_section. */ |
|
| #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ |
|
| ((DYN) \ |
|
| && ((INFO)->shared \ |
|
| || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ |
|
| && ((H)->dynindx != -1 \ |
|
| || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) |
|
| |
|
| /* Relocate a SPARC64 ELF section. */ |
/* Relocate a SPARC64 ELF section. */ |
| |
|
| static bfd_boolean |
static bfd_boolean |
| Line 2032 sparc64_elf_relocate_section (output_bfd |
|
| Line 2020 sparc64_elf_relocate_section (output_bfd |
|
| Elf_Internal_Rela *rel; |
Elf_Internal_Rela *rel; |
| Elf_Internal_Rela *relend; |
Elf_Internal_Rela *relend; |
| |
|
| if (info->relocateable) |
if (info->relocatable) |
| return TRUE; |
return TRUE; |
| |
|
| dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
| Line 2046 sparc64_elf_relocate_section (output_bfd |
|
| Line 2034 sparc64_elf_relocate_section (output_bfd |
|
| got_base = elf_hash_table (info)->hgot->root.u.def.value; |
got_base = elf_hash_table (info)->hgot->root.u.def.value; |
| |
|
| sgot = splt = sreloc = NULL; |
sgot = splt = sreloc = NULL; |
| |
if (dynobj != NULL) |
| |
splt = bfd_get_section_by_name (dynobj, ".plt"); |
| |
|
| rel = relocs; |
rel = relocs; |
| relend = relocs + NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr); |
relend = relocs + NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr); |
| Line 2080 sparc64_elf_relocate_section (output_bfd |
|
| Line 2070 sparc64_elf_relocate_section (output_bfd |
|
| { |
{ |
| sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
| sec = local_sections[r_symndx]; |
sec = local_sections[r_symndx]; |
| relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
| } |
} |
| else |
else |
| { |
{ |
| h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
bfd_boolean warned; |
| while (h->root.type == bfd_link_hash_indirect |
|
| || h->root.type == bfd_link_hash_warning) |
|
| h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
| |
|
| relocation = 0; |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
| if (h->root.type == bfd_link_hash_defined |
r_symndx, symtab_hdr, sym_hashes, |
| || h->root.type == bfd_link_hash_defweak) |
h, sec, relocation, |
| |
unresolved_reloc, warned); |
| |
if (warned) |
| { |
{ |
| sec = h->root.u.def.section; |
|
| if (sec->output_section == NULL) |
|
| /* Set a flag that will be cleared later if we find a |
|
| relocation value for this symbol. output_section |
|
| is typically NULL for symbols satisfied by a shared |
|
| library. */ |
|
| unresolved_reloc = TRUE; |
|
| else |
|
| relocation = (h->root.u.def.value |
|
| + sec->output_section->vma |
|
| + sec->output_offset); |
|
| } |
|
| else if (h->root.type == bfd_link_hash_undefweak) |
|
| ; |
|
| else if (info->shared |
|
| && !info->no_undefined |
|
| && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) |
|
| ; |
|
| else |
|
| { |
|
| if (! ((*info->callbacks->undefined_symbol) |
|
| (info, h->root.root.string, input_bfd, |
|
| input_section, rel->r_offset, |
|
| (!info->shared || info->no_undefined |
|
| || ELF_ST_VISIBILITY (h->other))))) |
|
| return FALSE; |
|
| |
|
| /* To avoid generating warning messages about truncated |
/* To avoid generating warning messages about truncated |
| relocations, set the relocation's address to be the same as |
relocations, set the relocation's address to be the same as |
| the start of this section. */ |
the start of this section. */ |
| Line 2285 sparc64_elf_relocate_section (output_bfd |
|
| Line 2247 sparc64_elf_relocate_section (output_bfd |
|
| |
|
| if (is_plt) |
if (is_plt) |
| sec = splt; |
sec = splt; |
| else if (h == NULL) |
|
| sec = local_sections[r_symndx]; |
if (bfd_is_abs_section (sec)) |
| else |
|
| { |
|
| BFD_ASSERT (h->root.type == bfd_link_hash_defined |
|
| || (h->root.type |
|
| == bfd_link_hash_defweak)); |
|
| sec = h->root.u.def.section; |
|
| } |
|
| if (sec != NULL && bfd_is_abs_section (sec)) |
|
| indx = 0; |
indx = 0; |
| else if (sec == NULL || sec->owner == NULL) |
else if (sec == NULL || sec->owner == NULL) |
| { |
{ |
| Line 2370 sparc64_elf_relocate_section (output_bfd |
|
| Line 2324 sparc64_elf_relocate_section (output_bfd |
|
| BFD_ASSERT (off != (bfd_vma) -1); |
BFD_ASSERT (off != (bfd_vma) -1); |
| dyn = elf_hash_table (info)->dynamic_sections_created; |
dyn = elf_hash_table (info)->dynamic_sections_created; |
| |
|
| if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
| || (info->shared |
|| (info->shared |
| && (info->symbolic |
&& (info->symbolic |
| || h->dynindx == -1 |
|| h->dynindx == -1 |
| Line 2463 sparc64_elf_relocate_section (output_bfd |
|
| Line 2417 sparc64_elf_relocate_section (output_bfd |
|
| procedure linkage table. */ |
procedure linkage table. */ |
| BFD_ASSERT (h != NULL); |
BFD_ASSERT (h != NULL); |
| |
|
| if (h->plt.offset == (bfd_vma) -1) |
if (h->plt.offset == (bfd_vma) -1 || splt == NULL) |
| { |
{ |
| /* We didn't make a PLT entry for this symbol. This |
/* We didn't make a PLT entry for this symbol. This |
| happens when statically linking PIC code, or when |
happens when statically linking PIC code, or when |
| Line 2471 sparc64_elf_relocate_section (output_bfd |
|
| Line 2425 sparc64_elf_relocate_section (output_bfd |
|
| goto do_default; |
goto do_default; |
| } |
} |
| |
|
| if (splt == NULL) |
|
| { |
|
| splt = bfd_get_section_by_name (dynobj, ".plt"); |
|
| BFD_ASSERT (splt != NULL); |
|
| } |
|
| |
|
| relocation = (splt->output_section->vma |
relocation = (splt->output_section->vma |
| + splt->output_offset |
+ splt->output_offset |
| + sparc64_elf_plt_entry_offset (h->plt.offset)); |
+ sparc64_elf_plt_entry_offset (h->plt.offset)); |
| Line 2694 sparc64_elf_relocate_section (output_bfd |
|
| Line 2642 sparc64_elf_relocate_section (output_bfd |
|
| overflows. We don't, but this breaks stabs debugging |
overflows. We don't, but this breaks stabs debugging |
| info, whose relocations are only 32-bits wide. Ignore |
info, whose relocations are only 32-bits wide. Ignore |
| overflows for discarded entries. */ |
overflows for discarded entries. */ |
| if (r_type == R_SPARC_32 |
if ((r_type == R_SPARC_32 || r_type == R_SPARC_DISP32) |
| && _bfd_elf_section_offset (output_bfd, info, input_section, |
&& _bfd_elf_section_offset (output_bfd, info, input_section, |
| rel->r_offset) == (bfd_vma) -1) |
rel->r_offset) == (bfd_vma) -1) |
| break; |
break; |
| Line 3175 const struct elf_size_info sparc64_elf_s |
|
| Line 3123 const struct elf_size_info sparc64_elf_s |
|
| we use 2. */ |
we use 2. */ |
| 1, |
1, |
| 64, /* arch_size. */ |
64, /* arch_size. */ |
| 8, /* file_align. */ |
3, /* log_file_align. */ |
| ELFCLASS64, |
ELFCLASS64, |
| EV_CURRENT, |
EV_CURRENT, |
| bfd_elf64_write_out_phdrs, |
bfd_elf64_write_out_phdrs, |
| Line 3269 const struct elf_size_info sparc64_elf_s |
|
| Line 3217 const struct elf_size_info sparc64_elf_s |
|
| #define elf_backend_plt_alignment 8 |
#define elf_backend_plt_alignment 8 |
| |
|
| #define elf_backend_got_header_size 8 |
#define elf_backend_got_header_size 8 |
| #define elf_backend_plt_header_size PLT_HEADER_SIZE |
|
| |
|
| #include "elf64-target.h" |
#include "elf64-target.h" |