aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2000-05-23 01:32:28 +0000
committerRichard Henderson <rth@redhat.com>2000-05-23 01:32:28 +0000
commit748abff62c2f576c8914568fc239406366bbf6a4 (patch)
tree7c67bef54e2a76d3042a561d7957072f1dabd8ee /bfd
parent40eb4f3424343491925157f61e6e9bb87c98b2f9 (diff)
downloadgdb-748abff62c2f576c8914568fc239406366bbf6a4.zip
gdb-748abff62c2f576c8914568fc239406366bbf6a4.tar.gz
gdb-748abff62c2f576c8914568fc239406366bbf6a4.tar.bz2
* 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog61
-rw-r--r--bfd/bfd-in2.h4
-rw-r--r--bfd/elf64-ia64.c418
-rw-r--r--bfd/libbfd.h4
-rw-r--r--bfd/reloc.c8
5 files changed, 462 insertions, 33 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 8d8b8d9..e5b040d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,18 @@
+2000-05-22 Richard Henderson <rth@cygnus.com>
+
+ * 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 <nickc@cygnus.com>
* configure.in : Add peigen.lo to MIPS PE targets.
@@ -6,7 +21,7 @@
2000-05-22 Momchil Velikov <velco@fadata.bg>
* 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 <amylaar@cygnus.co.uk>
2000-04-03 Kevin Buettner <kevinb@redhat.com>
- * 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 <hjl@gnu.org>
@@ -779,7 +794,7 @@ Wed Mar 30 15:28:00 2000 Donald Lindsay <dlindsay@cygnus.com>
2000-03-14 Doug Evans <dje@casey.transmeta.com>
- * elf32-m32r.c (m32r_elf_lo16_reloc): Rewrite.
+ * elf32-m32r.c (m32r_elf_lo16_reloc): Rewrite.
2000-03-14 Kazu Hirata <kazu@hxi.com>
@@ -892,7 +907,7 @@ Wed Mar 30 15:28:00 2000 Donald Lindsay <dlindsay@cygnus.com>
* 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 <alan@spri.levels.unisa.edu.au>
@@ -1303,25 +1318,25 @@ Thu Feb 10 20:07:50 GMT 2000 Toshiyasu Morita (toshi.morita@sega.com)
2000-01-27 Thomas de Lellis <tdel@windriver.com>
- * 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 <nickc@cygnus.com>
@@ -1516,8 +1531,8 @@ Thu Feb 10 20:07:50 GMT 2000 Toshiyasu Morita (toshi.morita@sega.com)
1999-12-09 Nick Clifton <nickc@cygnus.com>
* 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 01d735f..a3f6d8c 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 c24c91d..ed9f8e3 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 <davidm@hpl.hp.com>
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 eed98f7..effb0e8 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 77530a5..7b86e37 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