This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
alpha relocation fixes
- From: rth at redhat dot com
- To: binutils at sources dot redhat dot com
- Date: Sat, 1 Jun 2002 23:26:08 -0700
- Subject: alpha relocation fixes
The testing that succeeded on a rh 7.0 system failed on a 7.2 system.
I guess differences in libc twig different code paths. :-/
r~
* elf64-alpha.c (elf64_alpha_relax_with_lituse): Don't test for
undefined symbols here.
(elf64_alpha_relax_section): Do it here. Also test for not
defined in the current module.
(elf64_alpha_relocate_section_r): Split out of ...
(elf64_alpha_relocate_section): ... here. Don't dereference
NULL when looking up local got entries.
Index: elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.68
diff -c -p -d -r1.68 elf64-alpha.c
*** elf64-alpha.c 2 Jun 2002 03:58:40 -0000 1.68
--- elf64-alpha.c 2 Jun 2002 06:18:30 -0000
*************** static boolean elf64_alpha_adjust_dynami
*** 134,139 ****
--- 134,142 ----
PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
static boolean elf64_alpha_size_dynamic_sections
PARAMS((bfd *, struct bfd_link_info *));
+ static boolean elf64_alpha_relocate_section_r
+ PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static boolean elf64_alpha_relocate_section
PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
*************** elf64_alpha_relax_with_lituse (info, sym
*** 1399,1413 ****
bfd_vma optdest, org;
bfd_signed_vma odisp;
- /* If this symbol is undefined, we can't relax it to a branch. */
- if (info->h
- && (info->h->root.root.type == bfd_link_hash_undefweak
- || info->h->root.root.type == bfd_link_hash_undefined))
- {
- all_optimized = false;
- break;
- }
-
/* If not zero, place to jump without needing pv. */
optdest = elf64_alpha_relax_opt_call (info, symval);
org = (info->sec->output_section->vma
--- 1402,1407 ----
*************** elf64_alpha_relax_section (abfd, sec, li
*** 2181,2187 ****
shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0);
bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym);
if (isym.st_shndx == SHN_UNDEF)
! info.tsec = bfd_und_section_ptr;
else if (isym.st_shndx == SHN_ABS)
info.tsec = bfd_abs_section_ptr;
else if (isym.st_shndx == SHN_COMMON)
--- 2175,2181 ----
shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0);
bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym);
if (isym.st_shndx == SHN_UNDEF)
! continue;
else if (isym.st_shndx == SHN_ABS)
info.tsec = bfd_abs_section_ptr;
else if (isym.st_shndx == SHN_COMMON)
*************** elf64_alpha_relax_section (abfd, sec, li
*** 2207,2212 ****
--- 2201,2216 ----
|| h->root.root.type == bfd_link_hash_warning)
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
+ /* If the symbol is undefined, we can't do anything with it. */
+ if (h->root.root.type == bfd_link_hash_undefweak
+ || h->root.root.type == bfd_link_hash_undefined)
+ continue;
+
+ /* If the symbol isn't defined in the current module, again
+ we can't do anything. */
+ if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+ continue;
+
info.h = h;
info.tsec = h->root.root.u.def.section;
info.other = h->root.other;
*************** elf64_alpha_size_dynamic_sections (outpu
*** 4173,4178 ****
--- 4177,4247 ----
return true;
}
+ /* Relocate an Alpha ELF section for a relocatable link.
+
+ We don't have to change anything unless the reloc is against a section
+ symbol, in which case we have to adjust according to where the section
+ symbol winds up in the output section. */
+
+ static boolean
+ elf64_alpha_relocate_section_r (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ bfd *output_bfd ATTRIBUTE_UNUSED;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents ATTRIBUTE_UNUSED;
+ Elf_Internal_Rela *relocs;
+ Elf_Internal_Sym *local_syms;
+ asection **local_sections;
+ {
+ unsigned long symtab_hdr_sh_info;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+ boolean ret_val = true;
+
+ symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info;
+
+ relend = relocs + input_section->reloc_count;
+ for (rel = relocs; rel < relend; rel++)
+ {
+ unsigned long r_symndx;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ unsigned long r_type;
+
+ r_type = ELF64_R_TYPE(rel->r_info);
+ if (r_type >= R_ALPHA_max)
+ {
+ (*_bfd_error_handler)
+ (_("%s: unknown relocation type %d"),
+ bfd_archive_filename (input_bfd), (int)r_type);
+ bfd_set_error (bfd_error_bad_value);
+ ret_val = false;
+ continue;
+ }
+
+ r_symndx = ELF64_R_SYM(rel->r_info);
+
+ /* The symbol associated with GPDISP and LITUSE is
+ immaterial. Only the addend is significant. */
+ if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
+ continue;
+
+ if (r_symndx < symtab_hdr_sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
+ {
+ sec = local_sections[r_symndx];
+ rel->r_addend += sec->output_offset + sym->st_value;
+ }
+ }
+ }
+
+ return ret_val;
+ }
+
/* Relocate an Alpha ELF section. */
static boolean
*************** elf64_alpha_relocate_section (output_bfd
*** 4187,4253 ****
Elf_Internal_Sym *local_syms;
asection **local_sections;
{
! Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
! struct elf_link_tls_segment *tls_segment = NULL;
! asection *sgot = NULL, *srel = NULL, *srelgot = NULL;
! bfd *dynobj = NULL, *gotobj = NULL;
! bfd_vma gp = 0, tp_base = 0, dtp_base = 0;
! boolean ret_val = true;
! if (!info->relocateable)
! {
! const char *name;
! dynobj = elf_hash_table (info)->dynobj;
! if (dynobj)
! srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
! name = (bfd_elf_string_from_elf_section
! (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
! elf_section_data(input_section)->rel_hdr.sh_name));
! BFD_ASSERT(name != NULL);
! srel = bfd_get_section_by_name (dynobj, name);
! /* Find the gp value for this input bfd. */
! gotobj = alpha_elf_tdata (input_bfd)->gotobj;
! if (gotobj)
{
! sgot = alpha_elf_tdata (gotobj)->got;
! gp = _bfd_get_gp_value (gotobj);
! if (gp == 0)
! {
! gp = (sgot->output_section->vma
! + sgot->output_offset
! + 0x8000);
! _bfd_set_gp_value (gotobj, gp);
! }
! }
! tls_segment = elf_hash_table (info)->tls_segment;
! if (tls_segment)
! {
! dtp_base = alpha_get_dtprel_base (tls_segment);
! tp_base = alpha_get_tprel_base (tls_segment);
! }
}
- rel = relocs;
relend = relocs + input_section->reloc_count;
! for (; rel < relend; rel++)
{
! struct alpha_elf_link_hash_entry *h;
struct alpha_elf_got_entry *gotent;
bfd_reloc_status_type r;
reloc_howto_type *howto;
unsigned long r_symndx;
! Elf_Internal_Sym *sym;
! asection *sec;
bfd_vma value;
bfd_vma addend;
boolean dynamic_symbol_p;
! boolean undef_weak_ref;
unsigned long r_type;
r_type = ELF64_R_TYPE(rel->r_info);
--- 4256,4341 ----
Elf_Internal_Sym *local_syms;
asection **local_sections;
{
! Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
! struct elf_link_tls_segment *tls_segment;
! asection *sgot, *srel, *srelgot;
! bfd *dynobj, *gotobj;
! bfd_vma gp, tp_base, dtp_base;
! struct alpha_elf_got_entry **local_got_entries;
! boolean ret_val;
! const char *section_name;
! /* Handle relocatable links with a smaller loop. */
! if (info->relocateable)
! return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
! input_section, contents, relocs,
! local_syms, local_sections);
! /* This is a final link. */
! ret_val = true;
! symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
!
! dynobj = elf_hash_table (info)->dynobj;
! if (dynobj)
! srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
! else
! srelgot = NULL;
!
! section_name = (bfd_elf_string_from_elf_section
! (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
! elf_section_data(input_section)->rel_hdr.sh_name));
! BFD_ASSERT(section_name != NULL);
! srel = bfd_get_section_by_name (dynobj, section_name);
!
! /* Find the gp value for this input bfd. */
! gotobj = alpha_elf_tdata (input_bfd)->gotobj;
! if (gotobj)
! {
! sgot = alpha_elf_tdata (gotobj)->got;
! gp = _bfd_get_gp_value (gotobj);
! if (gp == 0)
{
! gp = (sgot->output_section->vma
! + sgot->output_offset
! + 0x8000);
! _bfd_set_gp_value (gotobj, gp);
! }
! }
! else
! {
! sgot = NULL;
! gp = 0;
! }
! local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
!
! tls_segment = elf_hash_table (info)->tls_segment;
! if (tls_segment)
! {
! dtp_base = alpha_get_dtprel_base (tls_segment);
! tp_base = alpha_get_tprel_base (tls_segment);
}
+ else
+ dtp_base = tp_base = 0;
relend = relocs + input_section->reloc_count;
! for (rel = relocs; rel < relend; rel++)
{
! struct alpha_elf_link_hash_entry *h = NULL;
struct alpha_elf_got_entry *gotent;
bfd_reloc_status_type r;
reloc_howto_type *howto;
unsigned long r_symndx;
! Elf_Internal_Sym *sym = NULL;
! asection *sec = NULL;
bfd_vma value;
bfd_vma addend;
boolean dynamic_symbol_p;
! boolean undef_weak_ref = false;
unsigned long r_type;
r_type = ELF64_R_TYPE(rel->r_info);
*************** elf64_alpha_relocate_section (output_bfd
*** 4264,4308 ****
howto = elf64_alpha_howto_table + r_type;
r_symndx = ELF64_R_SYM(rel->r_info);
- if (info->relocateable)
- {
- /* This is a relocateable link. We don't have to change
- anything, unless the reloc is against a section symbol,
- in which case we have to adjust according to where the
- section symbol winds up in the output section. */
-
- /* The symbol associated with GPDISP and LITUSE is
- immaterial. Only the addend is significant. */
- if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
- continue;
-
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
- {
- sec = local_sections[r_symndx];
- rel->r_addend += sec->output_offset + sym->st_value;
- }
- }
-
- continue;
- }
-
- /* This is a final link. */
-
- h = NULL;
- sym = NULL;
- sec = NULL;
- undef_weak_ref = false;
-
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
! gotent = alpha_elf_tdata(input_bfd)->local_got_entries[r_symndx];
/* Need to adjust local GOT entries' addends for SEC_MERGE
unless it has been done already. */
--- 4352,4367 ----
howto = elf64_alpha_howto_table + r_type;
r_symndx = ELF64_R_SYM(rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
! if (local_got_entries)
! gotent = local_got_entries[r_symndx];
! else
! gotent = NULL;
/* Need to adjust local GOT entries' addends for SEC_MERGE
unless it has been done already. */