From: rth Date: Tue, 23 May 2000 01:32:27 +0000 (+0000) Subject: * elf64-ia64.c (ia64_howto_table): Add PCREL60B, PCREL21BI, X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=aa3c85cac985c8316cd7995d0da76f60f5ea3883;p=pf3gnuchains%2Fsourceware.git * elf64-ia64.c (ia64_howto_table): Add PCREL60B, PCREL21BI, PCREL22, PCREL64I. Zero size of special relocs. (elf64_ia64_reloc_type_lookup): Likewise. (USE_BRL, oor_brl, oor_ip): New. (elf64_ia64_relax_section): New. (elf64_ia64_check_relocs): Handle PCREL60B, PCREL22, PCREL64I. (elf64_ia64_install_value): Likewise, plus PCREL21BI. (elf64_ia64_relocate_section): Likewise. (bfd_elf64_bfd_relax_section): New. * reloc.c (BFD_RELOC_IA64_PCREL21BI): New. (BFD_RELOC_IA64_{PCREL22,PCREL60B,PCREL64I}): New. * bfd-in2.h, libbfd.h: Regenerate. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8d8b8d9935..e5b040dcf6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2000-05-22 Richard Henderson + + * elf64-ia64.c (ia64_howto_table): Add PCREL60B, PCREL21BI, + PCREL22, PCREL64I. Zero size of special relocs. + (elf64_ia64_reloc_type_lookup): Likewise. + (USE_BRL, oor_brl, oor_ip): New. + (elf64_ia64_relax_section): New. + (elf64_ia64_check_relocs): Handle PCREL60B, PCREL22, PCREL64I. + (elf64_ia64_install_value): Likewise, plus PCREL21BI. + (elf64_ia64_relocate_section): Likewise. + (bfd_elf64_bfd_relax_section): New. + * reloc.c (BFD_RELOC_IA64_PCREL21BI): New. + (BFD_RELOC_IA64_{PCREL22,PCREL60B,PCREL64I}): New. + * bfd-in2.h, libbfd.h: Regenerate. + 2000-05-22 Nick Clifton * configure.in : Add peigen.lo to MIPS PE targets. @@ -6,7 +21,7 @@ 2000-05-22 Momchil Velikov * libbfd.c (_bfd_generic_verify_endian_match): Compare endianess - only if it is known for both input and output bfds. Separate + only if it is known for both input and output bfds. Separate error message strings as in some languages, it may be necessary to change more than one place in the string to change between 'big' and 'little'. @@ -689,10 +704,10 @@ Wed Apr 5 22:04:20 2000 J"orn Rennecke 2000-04-03 Kevin Buettner - * configure.in: Added corefile support for AIX 4.3. In particular, - AIX_CORE_DUMPX_CORE will be defined in addition to AIX_CORE when - compiling rs6000-core.c. - * configure: Regenerated. + * configure.in: Added corefile support for AIX 4.3. In particular, + AIX_CORE_DUMPX_CORE will be defined in addition to AIX_CORE when + compiling rs6000-core.c. + * configure: Regenerated. 2000-04-03 H.J. Lu @@ -779,7 +794,7 @@ Wed Mar 30 15:28:00 2000 Donald Lindsay 2000-03-14 Doug Evans - * elf32-m32r.c (m32r_elf_lo16_reloc): Rewrite. + * elf32-m32r.c (m32r_elf_lo16_reloc): Rewrite. 2000-03-14 Kazu Hirata @@ -892,7 +907,7 @@ Wed Mar 30 15:28:00 2000 Donald Lindsay * coffcode.h (styp_to_sec_flags): Initialise 'target_name'. * elf-m10300.c (mn10300_elf_relax_section): Initialise - 'sym_sec'. + 'sym_sec'. * elf32-i370.c: Add ATTRIBUTE_UNUSED to unused function parameters. @@ -1102,10 +1117,10 @@ Fri Feb 25 18:39:26 2000 Rodney Brown (RodneyBrown@pmsc.com) * elflink.h (elf_link_add_object_symbols): If a version symbol is not defined, don't add a second ELF_VER_CHR. - * elflink.h (elf_bfd_final_link): Call output_extsym for global + * elflink.h (elf_bfd_final_link): Call output_extsym for global symbols converted to local symbols even when stripping all symbols. - (elf_link_output_extsym): Process global symbols converted to + (elf_link_output_extsym): Process global symbols converted to local symbols even if they are being stripped. 2000-02-21 Alan Modra @@ -1303,25 +1318,25 @@ Thu Feb 10 20:07:50 GMT 2000 Toshiyasu Morita (toshi.morita@sega.com) 2000-01-27 Thomas de Lellis - * syms.c (bfd_decode_symclass) - Two new class characters were added - 'V' and 'v'. The - meaning of 'W' is now restricted to just weak non-object - symbols. This allows differentiation between, for example, - weak functions vs weak objects. nm for example now dumps: - 'W' = weak global - 'w' = weak unresolved - 'V' = weak global object - 'v' = weak unresolved object + * syms.c (bfd_decode_symclass) + Two new class characters were added - 'V' and 'v'. The + meaning of 'W' is now restricted to just weak non-object + symbols. This allows differentiation between, for example, + weak functions vs weak objects. nm for example now dumps: + 'W' = weak global + 'w' = weak unresolved + 'V' = weak global object + 'v' = weak unresolved object (bfd_is_undefined_symclass): New function. Return true if the given symbol class represents and undefined/unresolved symbol. - (bfd_symbol_info): Use bfd_is_undefined_symclass to check for + (bfd_symbol_info): Use bfd_is_undefined_symclass to check for unresolved symbols. * bfd-in2.h: Add prototype for bfd_is_undefined_symbol(). - * elf32-arm.h (elf32_arm_get_symbol_type): If a symbol has the + * elf32-arm.h (elf32_arm_get_symbol_type): If a symbol has the STT_ARM_16BIT flag set, but it is not attached to a data object return STT_ARM_16BIT so that it will be treated as code by the disassembler. @@ -1339,7 +1354,7 @@ Thu Feb 10 20:07:50 GMT 2000 Toshiyasu Morita (toshi.morita@sega.com) 2000-01-24 Robert Lipe (robertl@sco.com) - * coffcode.h (coff_write_object_contents): Get buff via bfd_malloc + * coffcode.h (coff_write_object_contents): Get buff via bfd_malloc instead of using GNU C extension. 2000-01-21 Nick Clifton @@ -1516,8 +1531,8 @@ Thu Feb 10 20:07:50 GMT 2000 Toshiyasu Morita (toshi.morita@sega.com) 1999-12-09 Nick Clifton * elflink.h (elf_link_add_archive_symbols): Add an archive - element even if contains a symbol which is currently only - considered to be a common. + element even if contains a symbol which is currently only + considered to be a common. * targets.c (struct bfd_target): Add new field _bfd_allow_commons_in_armap. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 01d735f250..a3f6d8cf67 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2479,8 +2479,12 @@ this offset in the reloc's section offset. */ BFD_RELOC_IA64_FPTR64MSB, BFD_RELOC_IA64_FPTR64LSB, BFD_RELOC_IA64_PCREL21B, + BFD_RELOC_IA64_PCREL21BI, BFD_RELOC_IA64_PCREL21M, BFD_RELOC_IA64_PCREL21F, + BFD_RELOC_IA64_PCREL22, + BFD_RELOC_IA64_PCREL60B, + BFD_RELOC_IA64_PCREL64I, BFD_RELOC_IA64_PCREL32MSB, BFD_RELOC_IA64_PCREL32LSB, BFD_RELOC_IA64_PCREL64MSB, diff --git a/bfd/elf64-ia64.c b/bfd/elf64-ia64.c index c24c91d8ec..ed9f8e3ec9 100644 --- a/bfd/elf64-ia64.c +++ b/bfd/elf64-ia64.c @@ -1,5 +1,5 @@ /* IA-64 support for 64-bit ELF - Copyright 1998, 1999 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000 Free Software Foundation, Inc. Contributed by David Mosberger-Tang This file is part of BFD, the Binary File Descriptor library. @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "opcode/ia64.h" #include "elf/ia64.h" + /* * THE RULES for all the stuff the linker creates -- * @@ -154,6 +155,9 @@ static reloc_howto_type *elf64_ia64_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code)); static void elf64_ia64_info_to_howto PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf64_Internal_Rela *elf_reloc)); +static boolean elf64_ia64_relax_section + PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, + boolean *again)); static boolean elf64_ia64_section_from_shdr PARAMS ((bfd *, Elf64_Internal_Shdr *, char *)); static boolean elf64_ia64_fake_sections @@ -329,12 +333,13 @@ static reloc_howto_type ia64_howto_table[] = IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, false, true), IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, false, true), - IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 4, false, true), + IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, false, true), IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, false, true), IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, false, true), IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, false, true), IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, false, true), + IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, true, true), IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, true, true), IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, true, true), IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, true, true), @@ -343,8 +348,8 @@ static reloc_howto_type ia64_howto_table[] = IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, true, true), IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, true, true), - IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 4, false, true), - IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 4, false, true), + IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, false, true), + IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, false, true), IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, false, true), IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, false, true), @@ -369,6 +374,10 @@ static reloc_howto_type ia64_howto_table[] = IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, false, true), IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, false, true), + IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, true, true), + IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, true, true), + IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, true, true), + IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, false, true), IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, false, true), IA64_HOWTO (R_IA64_EPLTMSB, "EPLTMSB", 4, false, true), @@ -377,10 +386,10 @@ static reloc_howto_type ia64_howto_table[] = IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, false, true), IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, false, true), - IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 4, false, false), + IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, false, false), IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, false, false), IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, false, false), - IA64_HOWTO (R_IA64_LTOFF_TP22, "LTOFF_TP22", 4, false, false), + IA64_HOWTO (R_IA64_LTOFF_TP22, "LTOFF_TP22", 0, false, false), }; static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1]; @@ -451,8 +460,12 @@ elf64_ia64_reloc_type_lookup (abfd, bfd_code) case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break; case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break; + case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break; case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break; case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break; + case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break; + case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break; + case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break; case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break; case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break; case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break; @@ -549,6 +562,353 @@ static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] = }; #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" + +/* Select out of range branch fixup type. Note that Itanium does + not support brl, and so it gets emulated by the kernel. */ +#undef USE_BRL + +static const bfd_byte oor_brl[16] = +{ + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */ + 0x00, 0x00, 0x00, 0xc0 +}; + +static const bfd_byte oor_ip[48] = +{ + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, /* movl r15=0 */ + 0x01, 0x00, 0x00, 0x60, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0 */ + 0x00, 0x01, 0x00, 0x60, 0x00, 0x00, /* mov r16=ip;; */ + 0xf2, 0x80, 0x00, 0x80, /* add r16=r15,r16;; */ + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */ + 0x60, 0x00, 0x80, 0x00 /* br b6;; */ +}; + +/* These functions do relaxation for IA-64 ELF. + + This is primarily to support branches to targets out of range; + relaxation of R_IA64_LTOFF22X and R_IA64_LDXMOV not yet supported. */ + +static boolean +elf64_ia64_relax_section (abfd, sec, link_info, again) + bfd *abfd; + asection *sec; + struct bfd_link_info *link_info; + boolean *again; +{ + struct one_fixup + { + struct one_fixup *next; + asection *tsec; + bfd_vma toff; + bfd_vma trampoff; + }; + + Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *free_relocs; + Elf_Internal_Rela *irel, *irelend; + bfd_byte *contents; + bfd_byte *free_contents; + Elf64_External_Sym *extsyms; + Elf64_External_Sym *free_extsyms; + struct elf64_ia64_link_hash_table *ia64_info; + struct one_fixup *fixups = NULL; + boolean changed_contents = false; + boolean changed_relocs = false; + + /* Assume we're not going to change any sizes, and we we'll only + need one pass. */ + *again = false; + + /* Nothing to do if there are no relocations. */ + if ((sec->flags & SEC_RELOC) == 0 + || sec->reloc_count == 0) + return true; + + /* If this is the first time we have been called for this section, + initialize the cooked size. */ + if (sec->_cooked_size == 0) + sec->_cooked_size = sec->_raw_size; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + /* Load the relocations for this section. */ + internal_relocs = (_bfd_elf64_link_read_relocs + (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, + link_info->keep_memory)); + if (internal_relocs == NULL) + goto error_return; + free_relocs = NULL; + if (! link_info->keep_memory) + free_relocs = internal_relocs; + + ia64_info = elf64_ia64_hash_table (link_info); + irelend = internal_relocs + sec->reloc_count; + + for (irel = internal_relocs; irel < irelend; irel++) + if (ELF64_R_TYPE (irel->r_info) == (int) R_IA64_PCREL21B) + break; + + /* No branch-type relocations. */ + if (irel == irelend) + { + if (free_relocs != NULL) + free (free_relocs); + return true; + } + + /* Get the section contents. */ + free_contents = NULL; + if (elf_section_data (sec)->this_hdr.contents != NULL) + contents = elf_section_data (sec)->this_hdr.contents; + else + { + contents = (bfd_byte *) bfd_malloc (sec->_raw_size); + if (contents == NULL) + goto error_return; + free_contents = contents; + + if (! bfd_get_section_contents (abfd, sec, contents, + (file_ptr) 0, sec->_raw_size)) + goto error_return; + } + + /* Read this BFD's symbols. */ + free_extsyms = NULL; + if (symtab_hdr->contents != NULL) + extsyms = (Elf64_External_Sym *) symtab_hdr->contents; + else + { + extsyms = (Elf64_External_Sym *) bfd_malloc (symtab_hdr->sh_size); + if (extsyms == NULL) + goto error_return; + free_extsyms = extsyms; + if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 + || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd) + != symtab_hdr->sh_size)) + goto error_return; + } + + for (; irel < irelend; irel++) + { + bfd_vma symaddr, reladdr, trampoff, toff, roff; + Elf_Internal_Sym isym; + asection *tsec; + struct one_fixup *f; + + if (ELF64_R_TYPE (irel->r_info) != (int) R_IA64_PCREL21B) + continue; + + /* Get the value of the symbol referred to by the reloc. */ + if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) + { + /* A local symbol. */ + bfd_elf64_swap_symbol_in (abfd, + extsyms + ELF64_R_SYM (irel->r_info), + &isym); + if (isym.st_shndx == SHN_UNDEF) + continue; /* We can't do anthing with undefined symbols. */ + else if (isym.st_shndx == SHN_ABS) + tsec = bfd_abs_section_ptr; + else if (isym.st_shndx == SHN_COMMON) + tsec = bfd_com_section_ptr; + else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) + tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + else + continue; /* who knows. */ + + toff = isym.st_value; + } + else + { + unsigned long indx; + struct elf_link_hash_entry *h; + struct elf64_ia64_dyn_sym_info *dyn_i; + + indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; + h = elf_sym_hashes (abfd)[indx]; + BFD_ASSERT (h != NULL); + + 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; + + dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, false); + + /* For branches to dynamic symbols, we're interested instead + in a branch to the PLT entry. */ + if (dyn_i && dyn_i->want_plt2) + { + tsec = ia64_info->plt_sec; + toff = dyn_i->plt2_offset; + } + else + { + /* We can't do anthing with undefined symbols. */ + if (h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak) + continue; + + tsec = h->root.u.def.section; + toff = h->root.u.def.value; + } + } + + symaddr = (tsec->output_section->vma + + tsec->output_offset + + toff + + irel->r_addend); + + roff = irel->r_offset; + reladdr = (sec->output_section->vma + + sec->output_offset + + roff) & -4; + + /* If the branch is in range, no need to do anything. */ + if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000 + && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0) + continue; + + /* If the branch and target are in the same section, you've + got one honking big section and we can't help you. You'll + get an error message later. */ + if (tsec == sec) + continue; + + /* Look for an existing fixup to this address. */ + for (f = fixups; f ; f = f->next) + if (f->tsec == tsec && f->toff == toff) + break; + + if (f == NULL) + { + /* Two alternatives: If it's a branch to a PLT entry, we can + make a copy of the FULL_PLT entry. Otherwise, we'll have + to use a `brl' insn to get where we're going. */ + + int size; + + if (tsec == ia64_info->plt_sec) + size = sizeof (plt_full_entry); + else + { +#ifdef USE_BRL + size = sizeof (oor_brl); +#else + size = sizeof (oor_ip); +#endif + } + + /* Resize the current section to make room for the new branch. */ + trampoff = (sec->_cooked_size + 15) & -16; + contents = (bfd_byte *) bfd_realloc (contents, trampoff + size); + if (contents == NULL) + goto error_return; + sec->_cooked_size = trampoff + size; + + if (tsec == ia64_info->plt_sec) + { + memcpy (contents + trampoff, plt_full_entry, size); + + /* Hijack the old relocation for use as the PLTOFF reloc. */ + irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), + R_IA64_PLTOFF22); + irel->r_offset = trampoff; + } + else + { +#ifdef USE_BRL + memcpy (contents + trampoff, oor_brl, size); + irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), + R_IA64_PCREL60B); + irel->r_offset = trampoff + 2; +#else + memcpy (contents + trampoff, oor_ip, size); + irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), + R_IA64_PCREL64I); + irel->r_addend -= 16; + irel->r_offset = trampoff + 2; +#endif + } + + /* Record the fixup so we don't do it again this section. */ + f = (struct one_fixup *) bfd_malloc (sizeof (*f)); + f->next = fixups; + f->tsec = tsec; + f->toff = toff; + f->trampoff = trampoff; + fixups = f; + } + else + { + /* Nop out the reloc, since we're finalizing things here. */ + irel->r_info = ELF64_R_INFO (0, R_IA64_NONE); + } + + /* Fix up the existing branch to hit the trampoline. Hope like + hell this doesn't overflow too. */ + if (elf64_ia64_install_value (abfd, contents + roff, + f->trampoff - (roff & -4), + R_IA64_PCREL21B) != bfd_reloc_ok) + goto error_return; + + changed_contents = true; + changed_relocs = true; + } + + /* Clean up and go home. */ + while (fixups) + { + struct one_fixup *f = fixups; + fixups = fixups->next; + free (f); + } + + if (changed_relocs) + elf_section_data (sec)->relocs = internal_relocs; + else if (free_relocs != NULL) + free (free_relocs); + + if (changed_contents) + elf_section_data (sec)->this_hdr.contents = contents; + else if (free_contents != NULL) + { + if (! link_info->keep_memory) + free (free_contents); + else + { + /* Cache the section contents for elf_link_input_bfd. */ + elf_section_data (sec)->this_hdr.contents = contents; + } + } + + if (free_extsyms != NULL) + { + if (! link_info->keep_memory) + free (free_extsyms); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = extsyms; + } + } + + *again = changed_contents || changed_relocs; + return true; + + error_return: + if (free_relocs != NULL) + free (free_relocs); + if (free_contents != NULL) + free (free_contents); + if (free_extsyms != NULL) + free (free_extsyms); + return false; +} /* Handle an IA-64 specific section when reading an object file. This is called when elfcode.h finds a section with an unknown type. */ @@ -1468,6 +1828,7 @@ elf64_ia64_check_relocs (abfd, info, sec, relocs) break; case R_IA64_PCREL21B: + case R_IA64_PCREL60B: /* Depending on where this symbol is defined, we may or may not need a full plt entry. Only skip if we know we'll not need the entry -- static or symbolic, and the symbol definition @@ -1489,6 +1850,8 @@ elf64_ia64_check_relocs (abfd, info, sec, relocs) dynrel_type = R_IA64_DIR64LSB; break; + case R_IA64_PCREL22: + case R_IA64_PCREL64I: case R_IA64_PCREL32MSB: case R_IA64_PCREL32LSB: case R_IA64_PCREL64MSB: @@ -2185,15 +2548,21 @@ elf64_ia64_install_value (abfd, hit_addr, val, r_type) /* Instruction relocations. */ case R_IA64_IMM14: opnd = IA64_OPND_IMM14; break; + case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break; case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break; - case R_IA64_PCREL21B: opnd = IA64_OPND_TGT25c; break; + case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break; + case R_IA64_PCREL21B: + case R_IA64_PCREL21BI: + opnd = IA64_OPND_TGT25c; + break; case R_IA64_IMM22: case R_IA64_GPREL22: case R_IA64_LTOFF22: case R_IA64_LTOFF22X: case R_IA64_PLTOFF22: + case R_IA64_PCREL22: case R_IA64_LTOFF_FPTR22: opnd = IA64_OPND_IMM22; break; @@ -2202,6 +2571,7 @@ elf64_ia64_install_value (abfd, hit_addr, val, r_type) case R_IA64_GPREL64I: case R_IA64_LTOFF64I: case R_IA64_PLTOFF64I: + case R_IA64_PCREL64I: case R_IA64_FPTR64I: case R_IA64_LTOFF_FPTR64I: opnd = IA64_OPND_IMMU64; @@ -2308,6 +2678,31 @@ elf64_ia64_install_value (abfd, hit_addr, val, r_type) bfd_put_64 (abfd, t1, hit_addr + 8); break; + case IA64_OPND_TGT64: + hit_addr -= (long) hit_addr & 0x3; + t0 = bfd_get_64 (abfd, hit_addr); + t1 = bfd_get_64 (abfd, hit_addr + 8); + + /* tmpl/s: bits 0.. 5 in t0 + slot 0: bits 5..45 in t0 + slot 1: bits 46..63 in t0, bits 0..22 in t1 + slot 2: bits 23..63 in t1 */ + + /* First, clear the bits that form the 64 bit constant. */ + t0 &= ~(0x3ffffLL << 46); + t1 &= ~(0x7fffffLL + | ((1LL << 36 | 0xfffffLL << 13) << 23)); + + val >>= 4; + t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */ + t1 |= ((val >> 36) & 0x7fffffLL) << 0; /* 23 msbs of imm39 */ + t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */ + | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */ + + bfd_put_64 (abfd, t0, hit_addr); + bfd_put_64 (abfd, t1, hit_addr + 8); + break; + default: switch ((long) hit_addr & 0x3) { @@ -3090,6 +3485,7 @@ elf64_ia64_relocate_section (output_bfd, info, input_bfd, input_section, } goto finish_pcrel; + case R_IA64_PCREL21BI: case R_IA64_PCREL21F: case R_IA64_PCREL21M: /* ??? These two are only used for speculation fixup code. @@ -3113,10 +3509,8 @@ elf64_ia64_relocate_section (output_bfd, info, input_bfd, input_section, goto finish_pcrel; case R_IA64_PCREL21B: + case R_IA64_PCREL60B: /* We should have created a PLT entry for any dynamic symbol. */ - /* ??? How to handle out of range branches, which are supposed - to be fixed up by a conforming linker. */ - dyn_i = NULL; if (h) dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, false); @@ -3145,6 +3539,8 @@ elf64_ia64_relocate_section (output_bfd, info, input_bfd, input_section, } goto finish_pcrel; + case R_IA64_PCREL22: + case R_IA64_PCREL64I: finish_pcrel: /* Make pc-relative. */ value -= (input_section->output_section->vma @@ -3650,6 +4046,8 @@ elf64_ia64_print_private_bfd_data (abfd, ptr) elf64_ia64_reloc_type_lookup #define bfd_elf64_bfd_is_local_label_name \ elf64_ia64_is_local_label_name +#define bfd_elf64_bfd_relax_section \ + elf64_ia64_relax_section /* Stuff for the BFD linker: */ #define bfd_elf64_bfd_link_hash_table_create \ diff --git a/bfd/libbfd.h b/bfd/libbfd.h index eed98f706d..effb0e819b 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -923,8 +923,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_IA64_FPTR64MSB", "BFD_RELOC_IA64_FPTR64LSB", "BFD_RELOC_IA64_PCREL21B", + "BFD_RELOC_IA64_PCREL21BI", "BFD_RELOC_IA64_PCREL21M", "BFD_RELOC_IA64_PCREL21F", + "BFD_RELOC_IA64_PCREL22", + "BFD_RELOC_IA64_PCREL60B", + "BFD_RELOC_IA64_PCREL64I", "BFD_RELOC_IA64_PCREL32MSB", "BFD_RELOC_IA64_PCREL32LSB", "BFD_RELOC_IA64_PCREL64MSB", diff --git a/bfd/reloc.c b/bfd/reloc.c index 77530a53e8..7b86e37be3 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2802,10 +2802,18 @@ ENUMX ENUMX BFD_RELOC_IA64_PCREL21B ENUMX + BFD_RELOC_IA64_PCREL21BI +ENUMX BFD_RELOC_IA64_PCREL21M ENUMX BFD_RELOC_IA64_PCREL21F ENUMX + BFD_RELOC_IA64_PCREL22 +ENUMX + BFD_RELOC_IA64_PCREL60B +ENUMX + BFD_RELOC_IA64_PCREL64I +ENUMX BFD_RELOC_IA64_PCREL32MSB ENUMX BFD_RELOC_IA64_PCREL32LSB