2002-04-17 H.J. Lu (hjl@gnu.org) * elf-bfd.h (elf_rela_adjust_local_addend): New. * elf.c (_bfd_elf_rela_local_sym): Use it. * elf64-alpha.c (elf64_alpha_relocate_section): Likewise. * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise. * elf64-alpha.c (elf64_alpha_relocate_section): Call _bfd_elf_rela_local_sym to adjust addend. * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise. * elf64-alpha.c (alpha_elf_link_hash_entry): Add orig_addend. (elf64_alpha_check_relocs): Initialize orig_addend. (elf64_alpha_relocate_section): Check orig_addend instead of addend for match. --- bfd/elf-bfd.h.merge Thu Apr 4 09:25:13 2002 +++ bfd/elf-bfd.h Wed Apr 17 11:38:31 2002 @@ -913,6 +913,12 @@ struct bfd_elf_section_data && bfd_is_abs_section((sec)->output_section) \ && elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE) +/* Return true if need to adjust addend for local RELA relocation. */ +#define elf_rela_adjust_local_addend(sec,sym) \ + (((sec)->flags & SEC_MERGE) \ + && ELF_ST_TYPE ((sym)->st_info) == STT_SECTION \ + && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE) + #define get_elf_backend_data(abfd) \ ((struct elf_backend_data *) (abfd)->xvec->backend_data) --- bfd/elf.c.merge Thu Apr 4 23:06:35 2002 +++ bfd/elf.c Wed Apr 17 11:33:49 2002 @@ -6905,9 +6905,7 @@ _bfd_elf_rela_local_sym (abfd, sym, sec, relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); - if ((sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION - && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE) + if (elf_rela_adjust_local_addend (sec, sym)) { asection *msec; --- bfd/elf64-alpha.c.merge Tue Apr 16 12:04:32 2002 +++ bfd/elf64-alpha.c Wed Apr 17 11:34:27 2002 @@ -165,6 +165,9 @@ struct alpha_elf_link_hash_entry /* the addend in effect for this entry. */ bfd_vma addend; + /* the orignal addend in effect for this entry. */ + bfd_vma orig_addend; + /* the .got offset for this entry. */ int got_offset; @@ -2335,6 +2338,7 @@ elf64_alpha_check_relocs (abfd, info, se gotent->gotobj = abfd; gotent->addend = rel->r_addend; + gotent->orig_addend = rel->r_addend; gotent->got_offset = -1; gotent->flags = 0; gotent->use_count = 1; @@ -2380,6 +2384,7 @@ elf64_alpha_check_relocs (abfd, info, se gotent->gotobj = abfd; gotent->addend = rel->r_addend; + gotent->orig_addend = rel->r_addend; gotent->got_offset = -1; gotent->flags = 0; gotent->use_count = 1; @@ -3321,7 +3326,7 @@ elf64_alpha_relocate_section (output_bfd struct alpha_elf_link_hash_entry *h; Elf_Internal_Sym *sym; bfd_vma relocation; - bfd_vma addend; + bfd_vma addend, orig_addend; bfd_reloc_status_type r; r_type = ELF64_R_TYPE(rel->r_info); @@ -3365,6 +3370,7 @@ elf64_alpha_relocate_section (output_bfd sym = NULL; sec = NULL; + orig_addend = rel->r_addend; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -3411,8 +3417,8 @@ elf64_alpha_relocate_section (output_bfd relocation = 0; } } - addend = rel->r_addend; + addend = rel->r_addend; switch (r_type) { case R_ALPHA_GPDISP: @@ -3454,40 +3460,29 @@ elf64_alpha_relocate_section (output_bfd /* Need to adjust local GOT entries' addends for SEC_MERGE unless it has been done already. */ - if ((sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION - && (elf_section_data (sec)->sec_info_type - == ELF_INFO_TYPE_MERGE) + if (elf_rela_adjust_local_addend (sec, sym) && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0) { struct alpha_elf_got_entry *ent; - asection *msec; + Elf_Internal_Rela rela; for (ent = gotent; ent; ent = ent->next) { ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED; if (ent->use_count == 0) continue; - msec = sec; - ent->addend = - _bfd_merged_section_offset (output_bfd, &msec, - elf_section_data (sec)-> - sec_info, - sym->st_value - + ent->addend, - (bfd_vma) 0); - ent->addend -= sym->st_value; - ent->addend += msec->output_section->vma - + msec->output_offset - - sec->output_section->vma - - sec->output_offset; + rela.r_addend = ent->addend; + _bfd_elf_rela_local_sym (output_bfd, sym, sec, + &rela); + ent->addend = rela.r_addend; } } } BFD_ASSERT(gotent != NULL); - while (gotent->gotobj != gotobj || gotent->addend != addend) + while (gotent->gotobj != gotobj + || gotent->orig_addend != orig_addend) gotent = gotent->next; BFD_ASSERT(gotent->use_count >= 1); --- bfd/elfxx-ia64.c.merge Wed Apr 3 09:39:30 2002 +++ bfd/elfxx-ia64.c Wed Apr 17 11:42:13 2002 @@ -3568,10 +3568,7 @@ elfNN_ia64_relocate_section (output_bfd, sym = local_syms + r_symndx; sym_sec = local_sections[r_symndx]; value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel); - if ((sym_sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION - && (elf_section_data (sym_sec)->sec_info_type - == ELF_INFO_TYPE_MERGE)) + if (elf_rela_adjust_local_addend (sym_sec, sym)) { struct elfNN_ia64_local_hash_entry *loc_h; @@ -3579,23 +3576,14 @@ elfNN_ia64_relocate_section (output_bfd, if (loc_h && ! loc_h->sec_merge_done) { struct elfNN_ia64_dyn_sym_info *dynent; - asection *msec; + Elf_Internal_Rela rela; for (dynent = loc_h->info; dynent; dynent = dynent->next) { - msec = sym_sec; - dynent->addend = - _bfd_merged_section_offset (output_bfd, &msec, - elf_section_data (msec)-> - sec_info, - sym->st_value - + dynent->addend, - (bfd_vma) 0); - dynent->addend -= sym->st_value; - dynent->addend += msec->output_section->vma - + msec->output_offset - - sym_sec->output_section->vma - - sym_sec->output_offset; + rela.r_addend = dynent->addend; + _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, + &rela); + dynent->addend = rela.r_addend; } loc_h->sec_merge_done = 1; }