* 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.
This commit is contained in:
parent
40eb4f3424
commit
748abff62c
@ -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.
|
||||
|
@ -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,
|
||||
|
418
bfd/elf64-ia64.c
418
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 \
|
||||
|
@ -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",
|
||||
|
@ -2801,10 +2801,18 @@ ENUMX
|
||||
BFD_RELOC_IA64_FPTR64LSB
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user