summaryrefslogtreecommitdiffstats
path: root/contrib/binutils
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2003-03-02 19:01:31 +0000
committerobrien <obrien@FreeBSD.org>2003-03-02 19:01:31 +0000
commitecae3c4f95ba7c7ee8f027517f4bda25518ed2cf (patch)
tree8b4a32e377f7ae2d2c44c77552f417099b87069d /contrib/binutils
parent4f4b0b5073010ff850cc95a6bd074066eeb7dccb (diff)
downloadFreeBSD-src-ecae3c4f95ba7c7ee8f027517f4bda25518ed2cf.zip
FreeBSD-src-ecae3c4f95ba7c7ee8f027517f4bda25518ed2cf.tar.gz
Junk that never should have gotten imported.
Diffstat (limited to 'contrib/binutils')
-rw-r--r--contrib/binutils/bfd/VERSION1
-rw-r--r--contrib/binutils/bfd/acconfig.h34
-rw-r--r--contrib/binutils/bfd/aout-tic30.c1098
-rw-r--r--contrib/binutils/bfd/coff-mips.c2736
-rw-r--r--contrib/binutils/bfd/coff-sh.c3343
-rw-r--r--contrib/binutils/bfd/coff-tic30.c210
-rw-r--r--contrib/binutils/bfd/coff-z8k.c338
-rw-r--r--contrib/binutils/bfd/cpu-mips.c120
-rw-r--r--contrib/binutils/bfd/cpu-sh.c168
-rw-r--r--contrib/binutils/bfd/cpu-tic30.c39
-rw-r--r--contrib/binutils/bfd/cpu-v850.c100
-rw-r--r--contrib/binutils/bfd/cpu-z8k.c193
-rw-r--r--contrib/binutils/bfd/elf32-mips.c10405
-rw-r--r--contrib/binutils/bfd/elf32-sh.c6285
-rw-r--r--contrib/binutils/bfd/elf32-v850.c2220
-rw-r--r--contrib/binutils/bfd/elf64-mips.c7092
-rw-r--r--contrib/binutils/bfd/filemode.c194
-rw-r--r--contrib/binutils/bfd/mipsbsd.c487
-rw-r--r--contrib/binutils/bfd/pe-mips.c998
19 files changed, 0 insertions, 36061 deletions
diff --git a/contrib/binutils/bfd/VERSION b/contrib/binutils/bfd/VERSION
deleted file mode 100644
index dbe5900..0000000
--- a/contrib/binutils/bfd/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-2.8.1
diff --git a/contrib/binutils/bfd/acconfig.h b/contrib/binutils/bfd/acconfig.h
deleted file mode 100644
index 1d5e819..0000000
--- a/contrib/binutils/bfd/acconfig.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-/* Name of package. */
-#undef PACKAGE
-
-/* Version of package. */
-#undef VERSION
-
-/* Whether strstr must be declared even if <string.h> is included. */
-#undef NEED_DECLARATION_STRSTR
-
-/* Whether malloc must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_MALLOC
-
-/* Whether realloc must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_REALLOC
-
-/* Whether free must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_FREE
-
-/* Whether getenv must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_GETENV
-@TOP@
-
-/* Do we need to use the b modifier when opening binary files? */
-#undef USE_BINARY_FOPEN
-
-/* Name of host specific header file to include in trad-core.c. */
-#undef TRAD_HEADER
-
-/* Define only if <sys/procfs.h> is available *and* it defines prstatus_t. */
-#undef HAVE_SYS_PROCFS_H
-
-/* Do we really want to use mmap if it's available? */
-#undef USE_MMAP
diff --git a/contrib/binutils/bfd/aout-tic30.c b/contrib/binutils/bfd/aout-tic30.c
deleted file mode 100644
index a39a5b1..0000000
--- a/contrib/binutils/bfd/aout-tic30.c
+++ /dev/null
@@ -1,1098 +0,0 @@
-/* BFD back-end for TMS320C30 a.out binaries.
- Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
- Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
-
- This file is part of BFD, the Binary File Descriptor library.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#define TARGET_IS_BIG_ENDIAN_P
-#define N_HEADER_IN_TEXT(x) 1
-#define BYTES_IN_WORD 4
-#define TEXT_START_ADDR 1024
-#define TARGET_PAGE_SIZE 128
-#define SEGMENT_SIZE TARGET_PAGE_SIZE
-#define DEFAULT_ARCH bfd_arch_tic30
-#define ARCH_SIZE 32
-
-/* Do not "beautify" the CONCAT* macro args. Traditional C will not
- remove whitespace added here, and thus will fail to concatenate
- the tokens. */
-#define MY(OP) CONCAT2 (tic30_aout_,OP)
-#define TARGETNAME "a.out-tic30"
-#define NAME(x,y) CONCAT3 (tic30_aout,_32_,y)
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libaout.h"
-
-#include "aout/aout64.h"
-#include "aout/stab_gnu.h"
-#include "aout/ar.h"
-
-static bfd_reloc_status_type tic30_aout_fix_16
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type tic30_aout_fix_32
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type tic30_aout_fix_pcrel_16
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static reloc_howto_type *tic30_aout_reloc_howto
- PARAMS ((bfd *, struct reloc_std_external *, int *, int *, int *));
-static bfd_reloc_status_type tic30_aout_relocate_contents
- PARAMS ((reloc_howto_type *, bfd *, bfd_vma, bfd_byte *));
-static bfd_reloc_status_type tic30_aout_final_link_relocate
- PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, bfd_vma,
- bfd_vma, bfd_vma));
-static const bfd_target *tic30_aout_object_p PARAMS ((bfd *));
-static boolean tic30_aout_write_object_contents PARAMS ((bfd *));
-static boolean tic30_aout_set_sizes PARAMS ((bfd *));
-static const bfd_target * tic30_aout_callback PARAMS ((bfd *));
-static boolean MY_bfd_copy_private_section_data
- PARAMS ((bfd *, asection *, bfd *, asection *));
-static boolean MY_bfd_final_link PARAMS ((bfd *, struct bfd_link_info *));
-reloc_howto_type * tic30_aout_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-enum machine_type tic30_aout_machine_type
- PARAMS ((enum bfd_architecture, unsigned long, boolean *));
-boolean tic30_aout_set_arch_mach
- PARAMS ((bfd *, enum bfd_architecture, unsigned long));
-
-#define MY_reloc_howto(BFD, REL, IN, EX, PC) \
- tic30_aout_reloc_howto(BFD, REL, &IN, &EX, &PC)
-#define MY_final_link_relocate tic30_aout_final_link_relocate
-#define MY_object_p tic30_aout_object_p
-#define MY_mkobject NAME(aout,mkobject)
-#define MY_write_object_contents tic30_aout_write_object_contents
-#define MY_set_sizes tic30_aout_set_sizes
-
-#ifndef MY_exec_hdr_flags
-#define MY_exec_hdr_flags 1
-#endif
-
-#ifndef MY_backend_data
-
-#ifndef MY_zmagic_contiguous
-#define MY_zmagic_contiguous 0
-#endif
-#ifndef MY_text_includes_header
-#define MY_text_includes_header 0
-#endif
-#ifndef MY_entry_is_text_address
-#define MY_entry_is_text_address 0
-#endif
-#ifndef MY_exec_header_not_counted
-#define MY_exec_header_not_counted 1
-#endif
-#ifndef MY_add_dynamic_symbols
-#define MY_add_dynamic_symbols 0
-#endif
-#ifndef MY_add_one_symbol
-#define MY_add_one_symbol 0
-#endif
-#ifndef MY_link_dynamic_object
-#define MY_link_dynamic_object 0
-#endif
-#ifndef MY_write_dynamic_symbol
-#define MY_write_dynamic_symbol 0
-#endif
-#ifndef MY_check_dynamic_reloc
-#define MY_check_dynamic_reloc 0
-#endif
-#ifndef MY_finish_dynamic_link
-#define MY_finish_dynamic_link 0
-#endif
-
-static const struct aout_backend_data tic30_aout_backend_data =
-{
- MY_zmagic_contiguous,
- MY_text_includes_header,
- MY_entry_is_text_address,
- MY_exec_hdr_flags,
- 0, /* text vma? */
- MY_set_sizes,
- MY_exec_header_not_counted,
- MY_add_dynamic_symbols,
- MY_add_one_symbol,
- MY_link_dynamic_object,
- MY_write_dynamic_symbol,
- MY_check_dynamic_reloc,
- MY_finish_dynamic_link
-};
-#define MY_backend_data &tic30_aout_backend_data
-#endif
-
-/* FIXME: This is wrong. aoutx.h should really only be included by
- aout32.c. */
-
-#include "aoutx.h"
-
-/* This table lists the relocation types for the TMS320C30. There are
- only a few relocations required, and all must be divided by 4 (>>
- 2) to get the 32-bit addresses in the format the TMS320C30 likes
- it. */
-reloc_howto_type tic30_aout_howto_table[] =
- {
- EMPTY_HOWTO (-1),
- HOWTO (1, 2, 1, 16, false, 0, 0, tic30_aout_fix_16,
- "16", false, 0x0000FFFF, 0x0000FFFF, false),
- HOWTO (2, 2, 2, 24, false, 0, complain_overflow_bitfield, NULL,
- "24", false, 0x00FFFFFF, 0x00FFFFFF, false),
- HOWTO (3, 18, 3, 24, false, 0, complain_overflow_bitfield, NULL,
- "LDP", false, 0x00FF0000, 0x000000FF, false),
- HOWTO (4, 2, 4, 32, false, 0, complain_overflow_bitfield, tic30_aout_fix_32,
- "32", false, 0xFFFFFFFF, 0xFFFFFFFF, false),
- HOWTO (5, 2, 1, 16, true, 0, complain_overflow_signed,
- tic30_aout_fix_pcrel_16, "PCREL", true, 0x0000FFFF, 0x0000FFFF, true),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1)
- };
-
-extern reloc_howto_type *NAME (aout, reloc_type_lookup)
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-
-reloc_howto_type *
-tic30_aout_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- switch (code)
- {
- case BFD_RELOC_8:
- case BFD_RELOC_TIC30_LDP:
- return &tic30_aout_howto_table[3];
- case BFD_RELOC_16:
- return &tic30_aout_howto_table[1];
- case BFD_RELOC_24:
- return &tic30_aout_howto_table[2];
- case BFD_RELOC_16_PCREL:
- return &tic30_aout_howto_table[5];
- case BFD_RELOC_32:
- return &tic30_aout_howto_table[4];
- default:
- return (reloc_howto_type *) NULL;
- }
-}
-
-static reloc_howto_type *
-tic30_aout_reloc_howto (abfd, relocs, r_index, r_extern, r_pcrel)
- bfd *abfd;
- struct reloc_std_external *relocs;
- int *r_index;
- int *r_extern;
- int *r_pcrel;
-{
- unsigned int r_length;
- unsigned int r_pcrel_done;
- int index;
-
- *r_pcrel = 0;
- if (bfd_header_big_endian (abfd))
- {
- *r_index = ((relocs->r_index[0] << 16) | (relocs->r_index[1] << 8) | relocs->r_index[2]);
- *r_extern = (0 != (relocs->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
- r_pcrel_done = (0 != (relocs->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
- r_length = ((relocs->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) >> RELOC_STD_BITS_LENGTH_SH_BIG);
- }
- else
- {
- *r_index = ((relocs->r_index[2] << 16) | (relocs->r_index[1] << 8) | relocs->r_index[0]);
- *r_extern = (0 != (relocs->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
- r_pcrel_done = (0 != (relocs->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
- r_length = ((relocs->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
- }
- index = r_length + 4 * r_pcrel_done;
- return tic30_aout_howto_table + index;
-}
-
-/* This function is used as a callback for 16-bit relocs. This is
- required for relocations between segments. A line in aoutx.h
- requires that any relocations for the data section should point to
- the end of the aligned text section, plus an offset. By default,
- this does not happen, therefore this function takes care of
- that. */
-
-static bfd_reloc_status_type
-tic30_aout_fix_16 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_vma relocation;
-
- /* Make sure that the symbol's section is defined. */
- if (symbol->section == &bfd_und_section && (symbol->flags & BSF_WEAK) == 0)
- return output_bfd ? bfd_reloc_ok : bfd_reloc_undefined;
- /* Get the size of the input section and turn it into the TMS320C30
- 32-bit address format. */
- relocation = (symbol->section->vma >> 2);
- relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
- bfd_put_16 (abfd, relocation, (bfd_byte *) data + reloc_entry->address);
- return bfd_reloc_ok;
-}
-
-/* This function does the same thing as tic30_aout_fix_16 except for 32
- bit relocations. */
-
-static bfd_reloc_status_type
-tic30_aout_fix_32 (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_vma relocation;
-
- /* Make sure that the symbol's section is defined. */
- if (symbol->section == &bfd_und_section && (symbol->flags & BSF_WEAK) == 0)
- return output_bfd ? bfd_reloc_ok : bfd_reloc_undefined;
- /* Get the size of the input section and turn it into the TMS320C30
- 32-bit address format. */
- relocation = (symbol->section->vma >> 2);
- relocation += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
- bfd_put_32 (abfd, relocation, (bfd_byte *) data + reloc_entry->address);
- return bfd_reloc_ok;
-}
-
-/* This function is used to work out pc-relative offsets for the
- TMS320C30. The data already placed by md_pcrel_from within gas is
- useless for a relocation, so we just get the offset value and place
- a version of this within the object code.
- tic30_aout_final_link_relocate will then calculate the required
- relocation to add on to the value in the object code. */
-
-static bfd_reloc_status_type
-tic30_aout_fix_pcrel_16 (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol ATTRIBUTE_UNUSED;
- PTR data;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd ATTRIBUTE_UNUSED;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_vma relocation = 1;
- bfd_byte offset_data = bfd_get_8 (abfd, (bfd_byte *) data + reloc_entry->address - 1);
-
- /* The byte before the location of the fix contains bits 23-16 of
- the pcrel instruction. Bit 21 is set for a delayed instruction
- which requires on offset of 3 instead of 1. */
- if (offset_data & 0x20)
- relocation -= 3;
- else
- relocation -= 1;
- bfd_put_16 (abfd, relocation, (bfd_byte *) data + reloc_entry->address);
- return bfd_reloc_ok;
-}
-
-/* These macros will get 24-bit values from the bfd definition.
- Big-endian only. */
-#define bfd_getb_24(BFD,ADDR) \
- (bfd_get_8 (BFD, ADDR ) << 16) | \
- (bfd_get_8 (BFD, ADDR + 1) << 8) | \
- (bfd_get_8 (BFD, ADDR + 2) )
-
-#define bfd_putb_24(BFD,DATA,ADDR) \
- bfd_put_8 (BFD, (bfd_byte) ((DATA >> 16) & 0xFF), ADDR ); \
- bfd_put_8 (BFD, (bfd_byte) ((DATA >> 8) & 0xFF), ADDR + 1); \
- bfd_put_8 (BFD, (bfd_byte) ( DATA & 0xFF), ADDR + 2)
-
-/* Set parameters about this a.out file that are machine-dependent.
- This routine is called from some_aout_object_p just before it returns. */
-
-static const bfd_target *
-tic30_aout_callback (abfd)
- bfd *abfd;
-{
- struct internal_exec *execp = exec_hdr (abfd);
- unsigned int arch_align_power;
- unsigned long arch_align;
-
- /* Calculate the file positions of the parts of a newly read aout header. */
- obj_textsec (abfd)->_raw_size = N_TXTSIZE (*execp);
-
- /* The virtual memory addresses of the sections. */
- obj_textsec (abfd)->vma = N_TXTADDR (*execp);
- obj_datasec (abfd)->vma = N_DATADDR (*execp);
- obj_bsssec (abfd)->vma = N_BSSADDR (*execp);
-
- obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
- obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
- obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
-
- /* The file offsets of the sections. */
- obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
- obj_datasec (abfd)->filepos = N_DATOFF (*execp);
-
- /* The file offsets of the relocation info. */
- obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
- obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);
-
- /* The file offsets of the string table and symbol table. */
- obj_sym_filepos (abfd) = N_SYMOFF (*execp);
- obj_str_filepos (abfd) = N_STROFF (*execp);
-
- /* Determine the architecture and machine type of the object file. */
-#ifdef SET_ARCH_MACH
- SET_ARCH_MACH (abfd, *execp);
-#else
- bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0L);
-#endif
-
- /* Now that we know the architecture, set the alignments of the
- sections. This is normally done by NAME(aout,new_section_hook),
- but when the initial sections were created the architecture had
- not yet been set. However, for backward compatibility, we don't
- set the alignment power any higher than as required by the size
- of the section. */
- arch_align_power = bfd_get_arch_info (abfd)->section_align_power;
- arch_align = 1 << arch_align_power;
- if ((BFD_ALIGN (obj_textsec (abfd)->_raw_size, arch_align)
- == obj_textsec (abfd)->_raw_size)
- && (BFD_ALIGN (obj_datasec (abfd)->_raw_size, arch_align)
- == obj_datasec (abfd)->_raw_size)
- && (BFD_ALIGN (obj_bsssec (abfd)->_raw_size, arch_align)
- == obj_bsssec (abfd)->_raw_size))
- {
- obj_textsec (abfd)->alignment_power = arch_align_power;
- obj_datasec (abfd)->alignment_power = arch_align_power;
- obj_bsssec (abfd)->alignment_power = arch_align_power;
- }
- return abfd->xvec;
-}
-
-static bfd_reloc_status_type
-tic30_aout_final_link_relocate (howto, input_bfd, input_section, contents,
- address, value, addend)
- reloc_howto_type *howto;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- bfd_vma address;
- bfd_vma value;
- bfd_vma addend;
-{
- bfd_vma relocation;
-
- if (address > input_section->_raw_size)
- return bfd_reloc_outofrange;
-
- relocation = value + addend;
- if (howto->pc_relative)
- {
- relocation -= (input_section->output_section->vma + input_section->output_offset);
- if (howto->pcrel_offset)
- relocation -= address;
- }
- return tic30_aout_relocate_contents (howto, input_bfd, relocation,
- contents + address);
-}
-
-bfd_reloc_status_type
-tic30_aout_relocate_contents (howto, input_bfd, relocation, location)
- reloc_howto_type *howto;
- bfd *input_bfd;
- bfd_vma relocation;
- bfd_byte *location;
-{
- bfd_vma x;
- boolean overflow;
-
- if (howto->size < 0)
- relocation = -relocation;
-
- switch (howto->size)
- {
- default:
- case 0:
- abort ();
- break;
- case 1:
- x = bfd_get_16 (input_bfd, location);
- break;
- case 2:
- x = bfd_getb_24 (input_bfd, location);
- break;
- case 3:
- x = bfd_get_8 (input_bfd, location);
- break;
- case 4:
- x = bfd_get_32 (input_bfd, location);
- break;
- }
-
- overflow = false;
-
- if (howto->complain_on_overflow != complain_overflow_dont)
- {
- bfd_vma check;
- bfd_signed_vma signed_check;
- bfd_vma add;
- bfd_signed_vma signed_add;
-
- if (howto->rightshift == 0)
- {
- check = relocation;
- signed_check = (bfd_signed_vma) relocation;
- }
- else
- {
- check = relocation >> howto->rightshift;
- if ((bfd_signed_vma) relocation >= 0)
- signed_check = check;
- else
- signed_check = (check | ((bfd_vma) - 1 & ~((bfd_vma) - 1 >> howto->rightshift)));
- }
- add = x & howto->src_mask;
- signed_add = add;
- if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
- signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
- if (howto->bitpos == 0)
- {
- check += add;
- signed_check += signed_add;
- }
- else
- {
- check += add >> howto->bitpos;
- if (signed_add >= 0)
- signed_check += add >> howto->bitpos;
- else
- signed_check += ((add >> howto->bitpos) | ((bfd_vma) - 1 & ~((bfd_vma) - 1 >> howto->bitpos)));
- }
- switch (howto->complain_on_overflow)
- {
- case complain_overflow_signed:
- {
- bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
- bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
- if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
- overflow = true;
- }
- break;
- case complain_overflow_unsigned:
- {
- bfd_vma reloc_unsigned_max = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
- if (check > reloc_unsigned_max)
- overflow = true;
- }
- break;
- case complain_overflow_bitfield:
- {
- bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
- if ((check & ~reloc_bits) != 0
- && (((bfd_vma) signed_check & ~reloc_bits)
- != ((bfd_vma) -1 & ~reloc_bits)))
- overflow = true;
- }
- break;
- default:
- abort ();
- }
- }
- relocation >>= (bfd_vma) howto->rightshift;
- relocation <<= (bfd_vma) howto->bitpos;
- x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask));
- switch (howto->size)
- {
- default:
- case 0:
- abort ();
- break;
- case 1:
- bfd_put_16 (input_bfd, x, location);
- break;
- case 2:
- bfd_putb_24 (input_bfd, x, location);
- break;
- case 3:
- bfd_put_8 (input_bfd, x, location);
- break;
- case 4:
- bfd_put_32 (input_bfd, x, location);
- break;
- }
- return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
-}
-
-/* Finish up the reading of an a.out file header. */
-
-static const bfd_target *
-tic30_aout_object_p (abfd)
- bfd *abfd;
-{
- struct external_exec exec_bytes; /* Raw exec header from file. */
- struct internal_exec exec; /* Cleaned-up exec header. */
- const bfd_target *target;
- bfd_size_type amt = EXEC_BYTES_SIZE;
-
- if (bfd_bread ((PTR) &exec_bytes, amt, abfd) != amt)
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_wrong_format);
- return 0;
- }
-
-#ifdef SWAP_MAGIC
- exec.a_info = SWAP_MAGIC (exec_bytes.e_info);
-#else
- exec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
-#endif /* SWAP_MAGIC */
-
- if (N_BADMAG (exec))
- return 0;
-#ifdef MACHTYPE_OK
- if (!(MACHTYPE_OK (N_MACHTYPE (exec))))
- return 0;
-#endif
-
- NAME (aout, swap_exec_header_in) (abfd, &exec_bytes, &exec);
-
-#ifdef SWAP_MAGIC
- /* swap_exec_header_in read in a_info with the wrong byte order */
- exec.a_info = SWAP_MAGIC (exec_bytes.e_info);
-#endif /* SWAP_MAGIC */
-
- target = NAME (aout, some_aout_object_p) (abfd, &exec, tic30_aout_callback);
-
-#ifdef ENTRY_CAN_BE_ZERO
- /* The NEWSOS3 entry-point is/was 0, which (amongst other lossage)
- means that it isn't obvious if EXEC_P should be set.
- All of the following must be true for an executable:
- There must be no relocations, the bfd can be neither an
- archive nor an archive element, and the file must be executable. */
-
- if (exec.a_trsize + exec.a_drsize == 0
- && bfd_get_format (abfd) == bfd_object && abfd->my_archive == NULL)
- {
- struct stat buf;
-#ifndef S_IXUSR
-#define S_IXUSR 0100 /* Execute by owner. */
-#endif
- if (stat (abfd->filename, &buf) == 0 && (buf.st_mode & S_IXUSR))
- abfd->flags |= EXEC_P;
- }
-#endif /* ENTRY_CAN_BE_ZERO */
-
- return target;
-}
-
-/* Copy private section data. This actually does nothing with the
- sections. It copies the subformat field. We copy it here, because
- we need to know whether this is a QMAGIC file before we set the
- section contents, and copy_private_bfd_data is not called until
- after the section contents have been set. */
-
-static boolean
-MY_bfd_copy_private_section_data (ibfd, isec, obfd, osec)
- bfd *ibfd;
- asection *isec ATTRIBUTE_UNUSED;
- bfd *obfd;
- asection *osec ATTRIBUTE_UNUSED;
-{
- if (bfd_get_flavour (obfd) == bfd_target_aout_flavour)
- obj_aout_subformat (obfd) = obj_aout_subformat (ibfd);
- return true;
-}
-
-/* Write an object file.
- Section contents have already been written. We write the
- file header, symbols, and relocation. */
-
-static boolean
-tic30_aout_write_object_contents (abfd)
- bfd *abfd;
-{
- struct external_exec exec_bytes;
- struct internal_exec *execp = exec_hdr (abfd);
-
- obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
-
- {
- bfd_size_type text_size; /* Dummy vars. */
- file_ptr text_end;
-
- if (adata (abfd).magic == undecided_magic)
- NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
-
- execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;
- execp->a_entry = bfd_get_start_address (abfd);
-
- execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * obj_reloc_entry_size (abfd));
- execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * obj_reloc_entry_size (abfd));
- NAME (aout, swap_exec_header_out) (abfd, execp, &exec_bytes);
-
- if (adata (abfd).exec_bytes_size > 0)
- {
- bfd_size_type amt;
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
- return false;
- amt = adata (abfd).exec_bytes_size;
- if (bfd_bwrite ((PTR) &exec_bytes, amt, abfd) != amt)
- return false;
- }
-
- /* Now write out reloc info, followed by syms and strings. */
- if (bfd_get_outsymbols (abfd) != (asymbol **) NULL
- && bfd_get_symcount (abfd) != 0)
- {
- if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*execp)), SEEK_SET) != 0)
- return false;
-
- if (!NAME (aout, write_syms) (abfd))
- return false;
- }
-
- if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*execp)), SEEK_SET) != 0)
- return false;
- if (!NAME (aout, squirt_out_relocs) (abfd, obj_textsec (abfd)))
- return false;
-
- if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp)), SEEK_SET) != 0)
- return false;
- if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))
- return false;
- }
-
- return true;
-}
-
-static boolean
-tic30_aout_set_sizes (abfd)
- bfd *abfd;
-{
- adata (abfd).page_size = TARGET_PAGE_SIZE;
-
-#ifdef SEGMENT_SIZE
- adata (abfd).segment_size = SEGMENT_SIZE;
-#else
- adata (abfd).segment_size = TARGET_PAGE_SIZE;
-#endif
-
-#ifdef ZMAGIC_DISK_BLOCK_SIZE
- adata (abfd).zmagic_disk_block_size = ZMAGIC_DISK_BLOCK_SIZE;
-#else
- adata (abfd).zmagic_disk_block_size = TARGET_PAGE_SIZE;
-#endif
-
- adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
-
- return true;
-}
-
-#ifndef MY_final_link_callback
-
-/* Callback for the final_link routine to set the section offsets. */
-
-static void MY_final_link_callback
- PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
-
-static void
-MY_final_link_callback (abfd, ptreloff, pdreloff, psymoff)
- bfd *abfd;
- file_ptr *ptreloff;
- file_ptr *pdreloff;
- file_ptr *psymoff;
-{
- struct internal_exec *execp = exec_hdr (abfd);
-
- *ptreloff = obj_datasec (abfd)->filepos + execp->a_data;
- *pdreloff = *ptreloff + execp->a_trsize;
- *psymoff = *pdreloff + execp->a_drsize;;
-}
-
-#endif
-
-#ifndef MY_bfd_final_link
-
-/* Final link routine. We need to use a call back to get the correct
- offsets in the output file. */
-
-static boolean
-MY_bfd_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- struct internal_exec *execp = exec_hdr (abfd);
- file_ptr pos;
- bfd_vma vma = 0;
- int pad;
-
- /* Set the executable header size to 0, as we don't want one for an
- output. */
- adata (abfd).exec_bytes_size = 0;
- pos = adata (abfd).exec_bytes_size;
- /* Text. */
- vma = info->create_object_symbols_section->vma;
- pos += vma;
- obj_textsec (abfd)->filepos = pos;
- obj_textsec (abfd)->vma = vma;
- obj_textsec (abfd)->user_set_vma = 1;
- pos += obj_textsec (abfd)->_raw_size;
- vma += obj_textsec (abfd)->_raw_size;
-
- /* Data. */
- if (abfd->flags & D_PAGED)
- {
- if (info->create_object_symbols_section->next->vma > 0)
- obj_datasec (abfd)->vma = info->create_object_symbols_section->next->vma;
- else
- obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size);
- }
- else
- {
- obj_datasec (abfd)->vma = BFD_ALIGN (vma, 4);
- }
-
- if (obj_datasec (abfd)->vma < vma)
- obj_datasec (abfd)->vma = BFD_ALIGN (vma, 4);
-
- obj_datasec (abfd)->user_set_vma = 1;
- vma = obj_datasec (abfd)->vma;
- obj_datasec (abfd)->filepos = vma + adata (abfd).exec_bytes_size;
- execp->a_text = vma - obj_textsec (abfd)->vma;
- obj_textsec (abfd)->_raw_size = execp->a_text;
-
- /* Since BSS follows data immediately, see if it needs alignment. */
- vma += obj_datasec (abfd)->_raw_size;
- pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma;
- obj_datasec (abfd)->_raw_size += pad;
- pos += obj_datasec (abfd)->_raw_size;
- execp->a_data = obj_datasec (abfd)->_raw_size;
-
- /* BSS. */
- obj_bsssec (abfd)->vma = vma;
- obj_bsssec (abfd)->user_set_vma = 1;
-
- /* We are fully resized, so don't readjust in final_link. */
- adata (abfd).magic = z_magic;
-
- return NAME (aout, final_link) (abfd, info, MY_final_link_callback);
-}
-
-#endif
-
-enum machine_type
-tic30_aout_machine_type (arch, machine, unknown)
- enum bfd_architecture arch;
- unsigned long machine ATTRIBUTE_UNUSED;
- boolean *unknown;
-{
- enum machine_type arch_flags;
-
- arch_flags = M_UNKNOWN;
- *unknown = true;
-
- switch (arch)
- {
- case bfd_arch_tic30:
- *unknown = false;
- break;
- default:
- arch_flags = M_UNKNOWN;
- }
- if (arch_flags != M_UNKNOWN)
- *unknown = false;
- return arch_flags;
-}
-
-boolean
-tic30_aout_set_arch_mach (abfd, arch, machine)
- bfd *abfd;
- enum bfd_architecture arch;
- unsigned long machine;
-{
- if (!bfd_default_set_arch_mach (abfd, arch, machine))
- return false;
- if (arch != bfd_arch_unknown)
- {
- boolean unknown;
- tic30_aout_machine_type (arch, machine, &unknown);
- if (unknown)
- return false;
- }
- obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
- return (*aout_backend_info (abfd)->set_sizes) (abfd);
-}
-
-/* We assume BFD generic archive files. */
-#ifndef MY_openr_next_archived_file
-#define MY_openr_next_archived_file bfd_generic_openr_next_archived_file
-#endif
-#ifndef MY_get_elt_at_index
-#define MY_get_elt_at_index _bfd_generic_get_elt_at_index
-#endif
-#ifndef MY_generic_stat_arch_elt
-#define MY_generic_stat_arch_elt bfd_generic_stat_arch_elt
-#endif
-#ifndef MY_slurp_armap
-#define MY_slurp_armap bfd_slurp_bsd_armap
-#endif
-#ifndef MY_slurp_extended_name_table
-#define MY_slurp_extended_name_table _bfd_slurp_extended_name_table
-#endif
-#ifndef MY_construct_extended_name_table
-#define MY_construct_extended_name_table \
- _bfd_archive_bsd_construct_extended_name_table
-#endif
-#ifndef MY_write_armap
-#define MY_write_armap bsd_write_armap
-#endif
-#ifndef MY_read_ar_hdr
-#define MY_read_ar_hdr _bfd_generic_read_ar_hdr
-#endif
-#ifndef MY_truncate_arname
-#define MY_truncate_arname bfd_bsd_truncate_arname
-#endif
-#ifndef MY_update_armap_timestamp
-#define MY_update_armap_timestamp _bfd_archive_bsd_update_armap_timestamp
-#endif
-
-/* No core file defined here -- configure in trad-core.c separately. */
-#ifndef MY_core_file_failing_command
-#define MY_core_file_failing_command _bfd_nocore_core_file_failing_command
-#endif
-#ifndef MY_core_file_failing_signal
-#define MY_core_file_failing_signal _bfd_nocore_core_file_failing_signal
-#endif
-#ifndef MY_core_file_matches_executable_p
-#define MY_core_file_matches_executable_p \
- _bfd_nocore_core_file_matches_executable_p
-#endif
-#ifndef MY_core_file_p
-#define MY_core_file_p _bfd_dummy_target
-#endif
-
-#ifndef MY_bfd_debug_info_start
-#define MY_bfd_debug_info_start bfd_void
-#endif
-#ifndef MY_bfd_debug_info_end
-#define MY_bfd_debug_info_end bfd_void
-#endif
-#ifndef MY_bfd_debug_info_accumulate
-#define MY_bfd_debug_info_accumulate \
- (void (*) PARAMS ((bfd*, struct sec *))) bfd_void
-#endif
-
-#ifndef MY_core_file_failing_command
-#define MY_core_file_failing_command NAME(aout,core_file_failing_command)
-#endif
-#ifndef MY_core_file_failing_signal
-#define MY_core_file_failing_signal NAME(aout,core_file_failing_signal)
-#endif
-#ifndef MY_core_file_matches_executable_p
-#define MY_core_file_matches_executable_p NAME(aout,core_file_matches_executable_p)
-#endif
-#ifndef MY_set_section_contents
-#define MY_set_section_contents NAME(aout,set_section_contents)
-#endif
-#ifndef MY_get_section_contents
-#define MY_get_section_contents aout_32_get_section_contents
-#endif
-#ifndef MY_get_section_contents_in_window
-#define MY_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
-#endif
-#ifndef MY_new_section_hook
-#define MY_new_section_hook NAME(aout,new_section_hook)
-#endif
-#ifndef MY_get_symtab_upper_bound
-#define MY_get_symtab_upper_bound NAME(aout,get_symtab_upper_bound)
-#endif
-#ifndef MY_get_symtab
-#define MY_get_symtab NAME(aout,get_symtab)
-#endif
-#ifndef MY_get_reloc_upper_bound
-#define MY_get_reloc_upper_bound NAME(aout,get_reloc_upper_bound)
-#endif
-#ifndef MY_canonicalize_reloc
-#define MY_canonicalize_reloc NAME(aout,canonicalize_reloc)
-#endif
-#ifndef MY_make_empty_symbol
-#define MY_make_empty_symbol NAME(aout,make_empty_symbol)
-#endif
-#ifndef MY_print_symbol
-#define MY_print_symbol NAME(aout,print_symbol)
-#endif
-#ifndef MY_get_symbol_info
-#define MY_get_symbol_info NAME(aout,get_symbol_info)
-#endif
-#ifndef MY_get_lineno
-#define MY_get_lineno NAME(aout,get_lineno)
-#endif
-#ifndef MY_set_arch_mach
-#define MY_set_arch_mach tic30_aout_set_arch_mach
-#endif
-#ifndef MY_find_nearest_line
-#define MY_find_nearest_line NAME(aout,find_nearest_line)
-#endif
-#ifndef MY_sizeof_headers
-#define MY_sizeof_headers NAME(aout,sizeof_headers)
-#endif
-#ifndef MY_bfd_get_relocated_section_contents
-#define MY_bfd_get_relocated_section_contents \
- bfd_generic_get_relocated_section_contents
-#endif
-#ifndef MY_bfd_relax_section
-#define MY_bfd_relax_section bfd_generic_relax_section
-#endif
-#ifndef MY_bfd_gc_sections
-#define MY_bfd_gc_sections bfd_generic_gc_sections
-#endif
-#ifndef MY_bfd_merge_sections
-#define MY_bfd_merge_sections bfd_generic_merge_sections
-#endif
-#ifndef MY_bfd_discard_group
-#define MY_bfd_discard_group bfd_generic_discard_group
-#endif
-#ifndef MY_bfd_reloc_type_lookup
-#define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
-#endif
-#ifndef MY_bfd_make_debug_symbol
-#define MY_bfd_make_debug_symbol 0
-#endif
-#ifndef MY_read_minisymbols
-#define MY_read_minisymbols NAME(aout,read_minisymbols)
-#endif
-#ifndef MY_minisymbol_to_symbol
-#define MY_minisymbol_to_symbol NAME(aout,minisymbol_to_symbol)
-#endif
-#ifndef MY_bfd_link_hash_table_create
-#define MY_bfd_link_hash_table_create NAME(aout,link_hash_table_create)
-#endif
-#ifndef MY_bfd_link_hash_table_free
-#define MY_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
-#endif
-#ifndef MY_bfd_link_add_symbols
-#define MY_bfd_link_add_symbols NAME(aout,link_add_symbols)
-#endif
-#ifndef MY_bfd_link_just_syms
-#define MY_bfd_link_just_syms _bfd_generic_link_just_syms
-#endif
-#ifndef MY_bfd_link_split_section
-#define MY_bfd_link_split_section _bfd_generic_link_split_section
-#endif
-
-#ifndef MY_bfd_copy_private_bfd_data
-#define MY_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
-#endif
-
-#ifndef MY_bfd_merge_private_bfd_data
-#define MY_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
-#endif
-
-#ifndef MY_bfd_copy_private_symbol_data
-#define MY_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
-#endif
-
-#ifndef MY_bfd_print_private_bfd_data
-#define MY_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
-#endif
-
-#ifndef MY_bfd_set_private_flags
-#define MY_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
-#endif
-
-#ifndef MY_bfd_is_local_label_name
-#define MY_bfd_is_local_label_name bfd_generic_is_local_label_name
-#endif
-
-#ifndef MY_bfd_free_cached_info
-#define MY_bfd_free_cached_info NAME(aout,bfd_free_cached_info)
-#endif
-
-#ifndef MY_close_and_cleanup
-#define MY_close_and_cleanup MY_bfd_free_cached_info
-#endif
-
-#ifndef MY_get_dynamic_symtab_upper_bound
-#define MY_get_dynamic_symtab_upper_bound \
- _bfd_nodynamic_get_dynamic_symtab_upper_bound
-#endif
-#ifndef MY_canonicalize_dynamic_symtab
-#define MY_canonicalize_dynamic_symtab \
- _bfd_nodynamic_canonicalize_dynamic_symtab
-#endif
-#ifndef MY_get_dynamic_reloc_upper_bound
-#define MY_get_dynamic_reloc_upper_bound \
- _bfd_nodynamic_get_dynamic_reloc_upper_bound
-#endif
-#ifndef MY_canonicalize_dynamic_reloc
-#define MY_canonicalize_dynamic_reloc \
- _bfd_nodynamic_canonicalize_dynamic_reloc
-#endif
-
-/* Aout symbols normally have leading underscores */
-#ifndef MY_symbol_leading_char
-#define MY_symbol_leading_char '_'
-#endif
-
-/* Aout archives normally use spaces for padding */
-#ifndef AR_PAD_CHAR
-#define AR_PAD_CHAR ' '
-#endif
-
-#ifndef MY_BFD_TARGET
-const bfd_target tic30_aout_vec =
-{
- TARGETNAME, /* name */
- bfd_target_aout_flavour,
- BFD_ENDIAN_BIG, /* target byte order (big) */
- BFD_ENDIAN_BIG, /* target headers byte order (big) */
- (HAS_RELOC | /* object flags */
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
- MY_symbol_leading_char,
- AR_PAD_CHAR, /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
- {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
- bfd_generic_archive_p, MY_core_file_p},
- {bfd_false, MY_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, MY_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (MY),
- BFD_JUMP_TABLE_COPY (MY),
- BFD_JUMP_TABLE_CORE (MY),
- BFD_JUMP_TABLE_ARCHIVE (MY),
- BFD_JUMP_TABLE_SYMBOLS (MY),
- BFD_JUMP_TABLE_RELOCS (MY),
- BFD_JUMP_TABLE_WRITE (MY),
- BFD_JUMP_TABLE_LINK (MY),
- BFD_JUMP_TABLE_DYNAMIC (MY),
-
- NULL,
-
- (PTR) MY_backend_data
-};
-#endif /* MY_BFD_TARGET */
diff --git a/contrib/binutils/bfd/coff-mips.c b/contrib/binutils/bfd/coff-mips.c
deleted file mode 100644
index 672b07f..0000000
--- a/contrib/binutils/bfd/coff-mips.c
+++ /dev/null
@@ -1,2736 +0,0 @@
-/* BFD back-end for MIPS Extended-Coff files.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001
- Free Software Foundation, Inc.
- Original version by Per Bothner.
- Full support added by Ian Lance Taylor, ian@cygnus.com.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "bfdlink.h"
-#include "libbfd.h"
-#include "coff/internal.h"
-#include "coff/sym.h"
-#include "coff/symconst.h"
-#include "coff/ecoff.h"
-#include "coff/mips.h"
-#include "libcoff.h"
-#include "libecoff.h"
-
-/* Prototypes for static functions. */
-
-static boolean mips_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
-static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
- struct internal_reloc *));
-static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
- const struct internal_reloc *,
- PTR));
-static void mips_adjust_reloc_in PARAMS ((bfd *,
- const struct internal_reloc *,
- arelent *));
-static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
- struct internal_reloc *));
-static bfd_reloc_status_type mips_generic_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static bfd_reloc_status_type mips_refhi_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static bfd_reloc_status_type mips_reflo_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static bfd_reloc_status_type mips_gprel_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static bfd_reloc_status_type mips_relhi_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static bfd_reloc_status_type mips_rello_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static bfd_reloc_status_type mips_switch_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd,
- char **error));
-static void mips_relocate_hi PARAMS ((struct internal_reloc *refhi,
- struct internal_reloc *reflo,
- bfd *input_bfd,
- asection *input_section,
- bfd_byte *contents,
- size_t adjust,
- bfd_vma relocation,
- boolean pcrel));
-static boolean mips_relocate_section PARAMS ((bfd *, struct bfd_link_info *,
- bfd *, asection *,
- bfd_byte *, PTR));
-static boolean mips_read_relocs PARAMS ((bfd *, asection *));
-static boolean mips_relax_section PARAMS ((bfd *, asection *,
- struct bfd_link_info *,
- boolean *));
-static boolean mips_relax_pcrel16 PARAMS ((struct bfd_link_info *, bfd *,
- asection *,
- struct ecoff_link_hash_entry *,
- bfd_byte *, bfd_vma));
-static reloc_howto_type *mips_bfd_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-
-/* ECOFF has COFF sections, but the debugging information is stored in
- a completely different format. ECOFF targets use some of the
- swapping routines from coffswap.h, and some of the generic COFF
- routines in coffgen.c, but, unlike the real COFF targets, do not
- use coffcode.h itself.
-
- Get the generic COFF swapping routines, except for the reloc,
- symbol, and lineno ones. Give them ECOFF names. */
-#define MIPSECOFF
-#define NO_COFF_RELOCS
-#define NO_COFF_SYMBOLS
-#define NO_COFF_LINENOS
-#define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
-#define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
-#define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
-#define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
-#define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
-#define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
-#include "coffswap.h"
-
-/* Get the ECOFF swapping routines. */
-#define ECOFF_32
-#include "ecoffswap.h"
-
-/* How to process the various relocs types. */
-
-static reloc_howto_type mips_howto_table[] =
-{
- /* Reloc type 0 is ignored. The reloc reading code ensures that
- this is a reference to the .abs section, which will cause
- bfd_perform_relocation to do nothing. */
- HOWTO (MIPS_R_IGNORE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- 0, /* special_function */
- "IGNORE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 16 bit reference to a symbol, normally from a data section. */
- HOWTO (MIPS_R_REFHALF, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- mips_generic_reloc, /* special_function */
- "REFHALF", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 32 bit reference to a symbol, normally from a data section. */
- HOWTO (MIPS_R_REFWORD, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- mips_generic_reloc, /* special_function */
- "REFWORD", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 26 bit absolute jump address. */
- HOWTO (MIPS_R_JMPADDR, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper four
- bits must match the PC. */
- mips_generic_reloc, /* special_function */
- "JMPADDR", /* name */
- true, /* partial_inplace */
- 0x3ffffff, /* src_mask */
- 0x3ffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* The high 16 bits of a symbol value. Handled by the function
- mips_refhi_reloc. */
- HOWTO (MIPS_R_REFHI, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- mips_refhi_reloc, /* special_function */
- "REFHI", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* The low 16 bits of a symbol value. */
- HOWTO (MIPS_R_REFLO, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_reflo_reloc, /* special_function */
- "REFLO", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A reference to an offset from the gp register. Handled by the
- function mips_gprel_reloc. */
- HOWTO (MIPS_R_GPREL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_gprel_reloc, /* special_function */
- "GPREL", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A reference to a literal using an offset from the gp register.
- Handled by the function mips_gprel_reloc. */
- HOWTO (MIPS_R_LITERAL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_gprel_reloc, /* special_function */
- "LITERAL", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- EMPTY_HOWTO (8),
- EMPTY_HOWTO (9),
- EMPTY_HOWTO (10),
- EMPTY_HOWTO (11),
-
- /* This reloc is a Cygnus extension used when generating position
- independent code for embedded systems. It represents a 16 bit PC
- relative reloc rightshifted twice as used in the MIPS branch
- instructions. */
- HOWTO (MIPS_R_PCREL16, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_generic_reloc, /* special_function */
- "PCREL16", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* This reloc is a Cygnus extension used when generating position
- independent code for embedded systems. It represents the high 16
- bits of a PC relative reloc. The next reloc must be
- MIPS_R_RELLO, and the addend is formed from the addends of the
- two instructions, just as in MIPS_R_REFHI and MIPS_R_REFLO. The
- final value is actually PC relative to the location of the
- MIPS_R_RELLO reloc, not the MIPS_R_RELHI reloc. */
- HOWTO (MIPS_R_RELHI, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- mips_relhi_reloc, /* special_function */
- "RELHI", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* This reloc is a Cygnus extension used when generating position
- independent code for embedded systems. It represents the low 16
- bits of a PC relative reloc. */
- HOWTO (MIPS_R_RELLO, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_rello_reloc, /* special_function */
- "RELLO", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- true), /* pcrel_offset */
-
- EMPTY_HOWTO (15),
- EMPTY_HOWTO (16),
- EMPTY_HOWTO (17),
- EMPTY_HOWTO (18),
- EMPTY_HOWTO (19),
- EMPTY_HOWTO (20),
- EMPTY_HOWTO (21),
-
- /* This reloc is a Cygnus extension used when generating position
- independent code for embedded systems. It represents an entry in
- a switch table, which is the difference between two symbols in
- the .text section. The symndx is actually the offset from the
- reloc address to the subtrahend. See include/coff/mips.h for
- more details. */
- HOWTO (MIPS_R_SWITCH, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_switch_reloc, /* special_function */
- "SWITCH", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- true) /* pcrel_offset */
-};
-
-#define MIPS_HOWTO_COUNT \
- (sizeof mips_howto_table / sizeof mips_howto_table[0])
-
-/* When the linker is doing relaxing, it may change an external PCREL16
- reloc. This typically represents an instruction like
- bal foo
- We change it to
- .set noreorder
- bal $L1
- lui $at,%hi(foo - $L1)
- $L1:
- addiu $at,%lo(foo - $L1)
- addu $at,$at,$31
- jalr $at
- PCREL16_EXPANSION_ADJUSTMENT is the number of bytes this changes the
- instruction by. */
-
-#define PCREL16_EXPANSION_ADJUSTMENT (4 * 4)
-
-/* See whether the magic number matches. */
-
-static boolean
-mips_ecoff_bad_format_hook (abfd, filehdr)
- bfd *abfd;
- PTR filehdr;
-{
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
-
- switch (internal_f->f_magic)
- {
- case MIPS_MAGIC_1:
- /* I don't know what endianness this implies. */
- return true;
-
- case MIPS_MAGIC_BIG:
- case MIPS_MAGIC_BIG2:
- case MIPS_MAGIC_BIG3:
- return bfd_big_endian (abfd);
-
- case MIPS_MAGIC_LITTLE:
- case MIPS_MAGIC_LITTLE2:
- case MIPS_MAGIC_LITTLE3:
- return bfd_little_endian (abfd);
-
- default:
- return false;
- }
-}
-
-/* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in
- external form. They use a bit which indicates whether the symbol
- is external. */
-
-/* Swap a reloc in. */
-
-static void
-mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
- bfd *abfd;
- PTR ext_ptr;
- struct internal_reloc *intern;
-{
- const RELOC *ext = (RELOC *) ext_ptr;
-
- intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
- if (bfd_header_big_endian (abfd))
- {
- intern->r_symndx = (((int) ext->r_bits[0]
- << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
- | ((int) ext->r_bits[1]
- << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
- | ((int) ext->r_bits[2]
- << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
- intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
- >> RELOC_BITS3_TYPE_SH_BIG);
- intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
- }
- else
- {
- intern->r_symndx = (((int) ext->r_bits[0]
- << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
- | ((int) ext->r_bits[1]
- << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
- | ((int) ext->r_bits[2]
- << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
- intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
- >> RELOC_BITS3_TYPE_SH_LITTLE)
- | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
- << RELOC_BITS3_TYPEHI_SH_LITTLE));
- intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
- }
-
- /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
- MIPS_R_RELLO reloc, r_symndx is actually the offset from the
- reloc address to the base of the difference (see
- include/coff/mips.h for more details). We copy symndx into the
- r_offset field so as not to confuse ecoff_slurp_reloc_table in
- ecoff.c. In adjust_reloc_in we then copy r_offset into the reloc
- addend. */
- if (intern->r_type == MIPS_R_SWITCH
- || (! intern->r_extern
- && (intern->r_type == MIPS_R_RELLO
- || intern->r_type == MIPS_R_RELHI)))
- {
- BFD_ASSERT (! intern->r_extern);
- intern->r_offset = intern->r_symndx;
- if (intern->r_offset & 0x800000)
- intern->r_offset -= 0x1000000;
- intern->r_symndx = RELOC_SECTION_TEXT;
- }
-}
-
-/* Swap a reloc out. */
-
-static void
-mips_ecoff_swap_reloc_out (abfd, intern, dst)
- bfd *abfd;
- const struct internal_reloc *intern;
- PTR dst;
-{
- RELOC *ext = (RELOC *) dst;
- long r_symndx;
-
- BFD_ASSERT (intern->r_extern
- || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
-
- /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELLO or
- MIPS_R_RELHI reloc, we actually want to write the contents of
- r_offset out as the symbol index. This undoes the change made by
- mips_ecoff_swap_reloc_in. */
- if (intern->r_type != MIPS_R_SWITCH
- && (intern->r_extern
- || (intern->r_type != MIPS_R_RELHI
- && intern->r_type != MIPS_R_RELLO)))
- r_symndx = intern->r_symndx;
- else
- {
- BFD_ASSERT (intern->r_symndx == RELOC_SECTION_TEXT);
- r_symndx = intern->r_offset & 0xffffff;
- }
-
- H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
- if (bfd_header_big_endian (abfd))
- {
- ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
- ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
- ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
- ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
- & RELOC_BITS3_TYPE_BIG)
- | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
- }
- else
- {
- ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
- ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
- ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
- ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
- & RELOC_BITS3_TYPE_LITTLE)
- | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
- & RELOC_BITS3_TYPEHI_LITTLE))
- | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
- }
-}
-
-/* Finish canonicalizing a reloc. Part of this is generic to all
- ECOFF targets, and that part is in ecoff.c. The rest is done in
- this backend routine. It must fill in the howto field. */
-
-static void
-mips_adjust_reloc_in (abfd, intern, rptr)
- bfd *abfd;
- const struct internal_reloc *intern;
- arelent *rptr;
-{
- if (intern->r_type > MIPS_R_SWITCH)
- abort ();
-
- if (! intern->r_extern
- && (intern->r_type == MIPS_R_GPREL
- || intern->r_type == MIPS_R_LITERAL))
- rptr->addend += ecoff_data (abfd)->gp;
-
- /* If the type is MIPS_R_IGNORE, make sure this is a reference to
- the absolute section so that the reloc is ignored. */
- if (intern->r_type == MIPS_R_IGNORE)
- rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
-
- /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
- MIPS_R_RELLO reloc, we want the addend field of the BFD relocto
- hold the value which was originally in the symndx field of the
- internal MIPS ECOFF reloc. This value was copied into
- intern->r_offset by mips_swap_reloc_in, and here we copy it into
- the addend field. */
- if (intern->r_type == MIPS_R_SWITCH
- || (! intern->r_extern
- && (intern->r_type == MIPS_R_RELHI
- || intern->r_type == MIPS_R_RELLO)))
- rptr->addend = intern->r_offset;
-
- rptr->howto = &mips_howto_table[intern->r_type];
-}
-
-/* Make any adjustments needed to a reloc before writing it out. None
- are needed for MIPS. */
-
-static void
-mips_adjust_reloc_out (abfd, rel, intern)
- bfd *abfd ATTRIBUTE_UNUSED;
- const arelent *rel;
- struct internal_reloc *intern;
-{
- /* For a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
- MIPS_R_RELLO reloc, we must copy rel->addend into
- intern->r_offset. This will then be written out as the symbol
- index by mips_ecoff_swap_reloc_out. This operation parallels the
- action of mips_adjust_reloc_in. */
- if (intern->r_type == MIPS_R_SWITCH
- || (! intern->r_extern
- && (intern->r_type == MIPS_R_RELHI
- || intern->r_type == MIPS_R_RELLO)))
- intern->r_offset = rel->addend;
-}
-
-/* ECOFF relocs are either against external symbols, or against
- sections. If we are producing relocateable output, and the reloc
- is against an external symbol, and nothing has given us any
- additional addend, the resulting reloc will also be against the
- same symbol. In such a case, we don't want to change anything
- about the way the reloc is handled, since it will all be done at
- final link time. Rather than put special case code into
- bfd_perform_relocation, all the reloc types use this howto
- function. It just short circuits the reloc if producing
- relocateable output against an external symbol. */
-
-static bfd_reloc_status_type
-mips_generic_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- return bfd_reloc_continue;
-}
-
-/* Do a REFHI relocation. This has to be done in combination with a
- REFLO reloc, because there is a carry from the REFLO to the REFHI.
- Here we just save the information we need; we do the actual
- relocation when we see the REFLO. MIPS ECOFF requires that the
- REFLO immediately follow the REFHI. As a GNU extension, we permit
- an arbitrary number of HI relocs to be associated with a single LO
- reloc. This extension permits gcc to output the HI and LO relocs
- itself. */
-
-struct mips_hi
-{
- struct mips_hi *next;
- bfd_byte *addr;
- bfd_vma addend;
-};
-
-/* FIXME: This should not be a static variable. */
-
-static struct mips_hi *mips_refhi_list;
-
-static bfd_reloc_status_type
-mips_refhi_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct mips_hi *n;
-
- /* If we're relocating, and this an external symbol, we don't want
- to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- ret = bfd_reloc_ok;
- if (bfd_is_und_section (symbol->section)
- && output_bfd == (bfd *) NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Save the information, and let REFLO do the actual relocation. */
- n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
- if (n == NULL)
- return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = mips_refhi_list;
- mips_refhi_list = n;
-
- if (output_bfd != (bfd *) NULL)
- reloc_entry->address += input_section->output_offset;
-
- return ret;
-}
-
-/* Do a REFLO relocation. This is a straightforward 16 bit inplace
- relocation; this function exists in order to do the REFHI
- relocation described above. */
-
-static bfd_reloc_status_type
-mips_reflo_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- if (mips_refhi_list != NULL)
- {
- struct mips_hi *l;
-
- l = mips_refhi_list;
- while (l != NULL)
- {
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
- struct mips_hi *next;
-
- /* Do the REFHI relocation. Note that we actually don't
- need to know anything about the REFLO itself, except
- where to find the low 16 bits of the addend needed by the
- REFHI. */
- insn = bfd_get_32 (abfd, l->addr);
- vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
- & 0xffff);
- val = ((insn & 0xffff) << 16) + vallo;
- val += l->addend;
-
- /* The low order 16 bits are always treated as a signed
- value. Therefore, a negative value in the low order bits
- requires an adjustment in the high order bits. We need
- to make this adjustment in two ways: once for the bits we
- took from the data, and once for the bits we are putting
- back in to the data. */
- if ((vallo & 0x8000) != 0)
- val -= 0x10000;
- if ((val & 0x8000) != 0)
- val += 0x10000;
-
- insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
- bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
-
- next = l->next;
- free (l);
- l = next;
- }
-
- mips_refhi_list = NULL;
- }
-
- /* Now do the REFLO reloc in the usual way. */
- return mips_generic_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
-}
-
-/* Do a GPREL relocation. This is a 16 bit value which must become
- the offset from the gp register. */
-
-static bfd_reloc_status_type
-mips_gprel_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_vma gp;
- bfd_vma relocation;
- unsigned long val;
- unsigned long insn;
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ECOFF
- file. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (output_bfd != (bfd *) NULL)
- relocateable = true;
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
- }
-
- if (bfd_is_und_section (symbol->section)
- && relocateable == false)
- return bfd_reloc_undefined;
-
- /* We have to figure out the gp value, so that we can adjust the
- symbol value correctly. We look up the symbol _gp in the output
- BFD. If we can't find it, we're stuck. We cache it in the ECOFF
- target data. We don't need to adjust the symbol value for an
- external symbol if we are producing relocateable output. */
- gp = _bfd_get_gp_value (output_bfd);
- if (gp == 0
- && (relocateable == false
- || (symbol->flags & BSF_SECTION_SYM) != 0))
- {
- if (relocateable != false)
- {
- /* Make up a value. */
- gp = symbol->section->output_section->vma + 0x4000;
- _bfd_set_gp_value (output_bfd, gp);
- }
- else
- {
- unsigned int count;
- asymbol **sym;
- unsigned int i;
-
- count = bfd_get_symcount (output_bfd);
- sym = bfd_get_outsymbols (output_bfd);
-
- if (sym == (asymbol **) NULL)
- i = count;
- else
- {
- for (i = 0; i < count; i++, sym++)
- {
- register const char *name;
-
- name = bfd_asymbol_name (*sym);
- if (*name == '_' && strcmp (name, "_gp") == 0)
- {
- gp = bfd_asymbol_value (*sym);
- _bfd_set_gp_value (output_bfd, gp);
- break;
- }
- }
- }
-
- if (i >= count)
- {
- /* Only get the error once. */
- gp = 4;
- _bfd_set_gp_value (output_bfd, gp);
- *error_message =
- (char *) _("GP relative relocation when _gp not defined");
- return bfd_reloc_dangerous;
- }
- }
- }
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* Set val to the offset into the section or symbol. */
- val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
- if (val & 0x8000)
- val -= 0x10000;
-
- /* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
- an external symbol. */
- if (relocateable == false
- || (symbol->flags & BSF_SECTION_SYM) != 0)
- val += relocation - gp;
-
- insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
- bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
-
- if (relocateable != false)
- reloc_entry->address += input_section->output_offset;
-
- /* Make sure it fit in 16 bits. */
- if ((long) val >= 0x8000 || (long) val < -0x8000)
- return bfd_reloc_overflow;
-
- return bfd_reloc_ok;
-}
-
-/* Do a RELHI relocation. We do this in conjunction with a RELLO
- reloc, just as REFHI and REFLO are done together. RELHI and RELLO
- are Cygnus extensions used when generating position independent
- code for embedded systems. */
-
-/* FIXME: This should not be a static variable. */
-
-static struct mips_hi *mips_relhi_list;
-
-static bfd_reloc_status_type
-mips_relhi_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct mips_hi *n;
-
- /* If this is a reloc against a section symbol, then it is correct
- in the object file. The only time we want to change this case is
- when we are relaxing, and that is handled entirely by
- mips_relocate_section and never calls this function. */
- if ((symbol->flags & BSF_SECTION_SYM) != 0)
- {
- if (output_bfd != (bfd *) NULL)
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* This is an external symbol. If we're relocating, we don't want
- to change anything. */
- if (output_bfd != (bfd *) NULL)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- ret = bfd_reloc_ok;
- if (bfd_is_und_section (symbol->section)
- && output_bfd == (bfd *) NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Save the information, and let RELLO do the actual relocation. */
- n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
- if (n == NULL)
- return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = mips_relhi_list;
- mips_relhi_list = n;
-
- if (output_bfd != (bfd *) NULL)
- reloc_entry->address += input_section->output_offset;
-
- return ret;
-}
-
-/* Do a RELLO relocation. This is a straightforward 16 bit PC
- relative relocation; this function exists in order to do the RELHI
- relocation described above. */
-
-static bfd_reloc_status_type
-mips_rello_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- if (mips_relhi_list != NULL)
- {
- struct mips_hi *l;
-
- l = mips_relhi_list;
- while (l != NULL)
- {
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
- struct mips_hi *next;
-
- /* Do the RELHI relocation. Note that we actually don't
- need to know anything about the RELLO itself, except
- where to find the low 16 bits of the addend needed by the
- RELHI. */
- insn = bfd_get_32 (abfd, l->addr);
- vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
- & 0xffff);
- val = ((insn & 0xffff) << 16) + vallo;
- val += l->addend;
-
- /* If the symbol is defined, make val PC relative. If the
- symbol is not defined we don't want to do this, because
- we don't want the value in the object file to incorporate
- the address of the reloc. */
- if (! bfd_is_und_section (bfd_get_section (symbol))
- && ! bfd_is_com_section (bfd_get_section (symbol)))
- val -= (input_section->output_section->vma
- + input_section->output_offset
- + reloc_entry->address);
-
- /* The low order 16 bits are always treated as a signed
- value. Therefore, a negative value in the low order bits
- requires an adjustment in the high order bits. We need
- to make this adjustment in two ways: once for the bits we
- took from the data, and once for the bits we are putting
- back in to the data. */
- if ((vallo & 0x8000) != 0)
- val -= 0x10000;
- if ((val & 0x8000) != 0)
- val += 0x10000;
-
- insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
- bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
-
- next = l->next;
- free (l);
- l = next;
- }
-
- mips_relhi_list = NULL;
- }
-
- /* If this is a reloc against a section symbol, then it is correct
- in the object file. The only time we want to change this case is
- when we are relaxing, and that is handled entirely by
- mips_relocate_section and never calls this function. */
- if ((symbol->flags & BSF_SECTION_SYM) != 0)
- {
- if (output_bfd != (bfd *) NULL)
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* bfd_perform_relocation does not handle pcrel_offset relocations
- correctly when generating a relocateable file, so handle them
- directly here. */
- if (output_bfd != (bfd *) NULL)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* Now do the RELLO reloc in the usual way. */
- return mips_generic_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
-}
-
-/* This is the special function for the MIPS_R_SWITCH reloc. This
- special reloc is normally correct in the object file, and only
- requires special handling when relaxing. We don't want
- bfd_perform_relocation to tamper with it at all. */
-
-static bfd_reloc_status_type
-mips_switch_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry ATTRIBUTE_UNUSED;
- asymbol *symbol ATTRIBUTE_UNUSED;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd ATTRIBUTE_UNUSED;
- char **error_message ATTRIBUTE_UNUSED;
-{
- return bfd_reloc_ok;
-}
-
-/* Get the howto structure for a generic reloc type. */
-
-static reloc_howto_type *
-mips_bfd_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- int mips_type;
-
- switch (code)
- {
- case BFD_RELOC_16:
- mips_type = MIPS_R_REFHALF;
- break;
- case BFD_RELOC_32:
- case BFD_RELOC_CTOR:
- mips_type = MIPS_R_REFWORD;
- break;
- case BFD_RELOC_MIPS_JMP:
- mips_type = MIPS_R_JMPADDR;
- break;
- case BFD_RELOC_HI16_S:
- mips_type = MIPS_R_REFHI;
- break;
- case BFD_RELOC_LO16:
- mips_type = MIPS_R_REFLO;
- break;
- case BFD_RELOC_GPREL16:
- mips_type = MIPS_R_GPREL;
- break;
- case BFD_RELOC_MIPS_LITERAL:
- mips_type = MIPS_R_LITERAL;
- break;
- case BFD_RELOC_16_PCREL_S2:
- mips_type = MIPS_R_PCREL16;
- break;
- case BFD_RELOC_PCREL_HI16_S:
- mips_type = MIPS_R_RELHI;
- break;
- case BFD_RELOC_PCREL_LO16:
- mips_type = MIPS_R_RELLO;
- break;
- case BFD_RELOC_GPREL32:
- mips_type = MIPS_R_SWITCH;
- break;
- default:
- return (reloc_howto_type *) NULL;
- }
-
- return &mips_howto_table[mips_type];
-}
-
-/* A helper routine for mips_relocate_section which handles the REFHI
- and RELHI relocations. The REFHI relocation must be followed by a
- REFLO relocation (and RELHI by a RELLO), and the addend used is
- formed from the addends of both instructions. */
-
-static void
-mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents, adjust,
- relocation, pcrel)
- struct internal_reloc *refhi;
- struct internal_reloc *reflo;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- size_t adjust;
- bfd_vma relocation;
- boolean pcrel;
-{
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
-
- if (refhi == NULL)
- return;
-
- insn = bfd_get_32 (input_bfd,
- contents + adjust + refhi->r_vaddr - input_section->vma);
- if (reflo == NULL)
- vallo = 0;
- else
- vallo = (bfd_get_32 (input_bfd,
- contents + adjust + reflo->r_vaddr - input_section->vma)
- & 0xffff);
-
- val = ((insn & 0xffff) << 16) + vallo;
- val += relocation;
-
- /* The low order 16 bits are always treated as a signed value.
- Therefore, a negative value in the low order bits requires an
- adjustment in the high order bits. We need to make this
- adjustment in two ways: once for the bits we took from the data,
- and once for the bits we are putting back in to the data. */
- if ((vallo & 0x8000) != 0)
- val -= 0x10000;
-
- if (pcrel)
- val -= (input_section->output_section->vma
- + input_section->output_offset
- + (reflo->r_vaddr - input_section->vma + adjust));
-
- if ((val & 0x8000) != 0)
- val += 0x10000;
-
- insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
- bfd_put_32 (input_bfd, (bfd_vma) insn,
- contents + adjust + refhi->r_vaddr - input_section->vma);
-}
-
-/* Relocate a section while linking a MIPS ECOFF file. */
-
-static boolean
-mips_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, external_relocs)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- PTR external_relocs;
-{
- asection **symndx_to_section;
- struct ecoff_link_hash_entry **sym_hashes;
- bfd_vma gp;
- boolean gp_undefined;
- size_t adjust;
- long *offsets;
- struct external_reloc *ext_rel;
- struct external_reloc *ext_rel_end;
- unsigned int i;
- boolean got_lo;
- struct internal_reloc lo_int_rel;
- bfd_size_type amt;
-
- BFD_ASSERT (input_bfd->xvec->byteorder
- == output_bfd->xvec->byteorder);
-
- /* We keep a table mapping the symndx found in an internal reloc to
- the appropriate section. This is faster than looking up the
- section by name each time. */
- symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
- if (symndx_to_section == (asection **) NULL)
- {
- amt = NUM_RELOC_SECTIONS * sizeof (asection *);
- symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
- if (!symndx_to_section)
- return false;
-
- symndx_to_section[RELOC_SECTION_NONE] = NULL;
- symndx_to_section[RELOC_SECTION_TEXT] =
- bfd_get_section_by_name (input_bfd, ".text");
- symndx_to_section[RELOC_SECTION_RDATA] =
- bfd_get_section_by_name (input_bfd, ".rdata");
- symndx_to_section[RELOC_SECTION_DATA] =
- bfd_get_section_by_name (input_bfd, ".data");
- symndx_to_section[RELOC_SECTION_SDATA] =
- bfd_get_section_by_name (input_bfd, ".sdata");
- symndx_to_section[RELOC_SECTION_SBSS] =
- bfd_get_section_by_name (input_bfd, ".sbss");
- symndx_to_section[RELOC_SECTION_BSS] =
- bfd_get_section_by_name (input_bfd, ".bss");
- symndx_to_section[RELOC_SECTION_INIT] =
- bfd_get_section_by_name (input_bfd, ".init");
- symndx_to_section[RELOC_SECTION_LIT8] =
- bfd_get_section_by_name (input_bfd, ".lit8");
- symndx_to_section[RELOC_SECTION_LIT4] =
- bfd_get_section_by_name (input_bfd, ".lit4");
- symndx_to_section[RELOC_SECTION_XDATA] = NULL;
- symndx_to_section[RELOC_SECTION_PDATA] = NULL;
- symndx_to_section[RELOC_SECTION_FINI] =
- bfd_get_section_by_name (input_bfd, ".fini");
- symndx_to_section[RELOC_SECTION_LITA] = NULL;
- symndx_to_section[RELOC_SECTION_ABS] = NULL;
-
- ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
- }
-
- sym_hashes = ecoff_data (input_bfd)->sym_hashes;
-
- gp = _bfd_get_gp_value (output_bfd);
- if (gp == 0)
- gp_undefined = true;
- else
- gp_undefined = false;
-
- got_lo = false;
-
- adjust = 0;
-
- if (ecoff_section_data (input_bfd, input_section) == NULL)
- offsets = NULL;
- else
- offsets = ecoff_section_data (input_bfd, input_section)->offsets;
-
- ext_rel = (struct external_reloc *) external_relocs;
- ext_rel_end = ext_rel + input_section->reloc_count;
- for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
- {
- struct internal_reloc int_rel;
- boolean use_lo = false;
- bfd_vma addend;
- reloc_howto_type *howto;
- struct ecoff_link_hash_entry *h = NULL;
- asection *s = NULL;
- bfd_vma relocation;
- bfd_reloc_status_type r;
-
- if (! got_lo)
- mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
- else
- {
- int_rel = lo_int_rel;
- got_lo = false;
- }
-
- BFD_ASSERT (int_rel.r_type
- < sizeof mips_howto_table / sizeof mips_howto_table[0]);
-
- /* The REFHI and RELHI relocs requires special handling. they
- must be followed by a REFLO or RELLO reloc, respectively, and
- the addend is formed from both relocs. */
- if (int_rel.r_type == MIPS_R_REFHI
- || int_rel.r_type == MIPS_R_RELHI)
- {
- struct external_reloc *lo_ext_rel;
-
- /* As a GNU extension, permit an arbitrary number of REFHI
- or RELHI relocs before the REFLO or RELLO reloc. This
- permits gcc to emit the HI and LO relocs itself. */
- for (lo_ext_rel = ext_rel + 1;
- lo_ext_rel < ext_rel_end;
- lo_ext_rel++)
- {
- mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,
- &lo_int_rel);
- if (lo_int_rel.r_type != int_rel.r_type)
- break;
- }
-
- if (lo_ext_rel < ext_rel_end
- && (lo_int_rel.r_type
- == (int_rel.r_type == MIPS_R_REFHI
- ? MIPS_R_REFLO
- : MIPS_R_RELLO))
- && int_rel.r_extern == lo_int_rel.r_extern
- && int_rel.r_symndx == lo_int_rel.r_symndx)
- {
- use_lo = true;
- if (lo_ext_rel == ext_rel + 1)
- got_lo = true;
- }
- }
-
- howto = &mips_howto_table[int_rel.r_type];
-
- /* The SWITCH reloc must be handled specially. This reloc is
- marks the location of a difference between two portions of an
- object file. The symbol index does not reference a symbol,
- but is actually the offset from the reloc to the subtrahend
- of the difference. This reloc is correct in the object file,
- and needs no further adjustment, unless we are relaxing. If
- we are relaxing, we may have to add in an offset. Since no
- symbols are involved in this reloc, we handle it completely
- here. */
- if (int_rel.r_type == MIPS_R_SWITCH)
- {
- if (offsets != NULL
- && offsets[i] != 0)
- {
- r = _bfd_relocate_contents (howto, input_bfd,
- (bfd_vma) offsets[i],
- (contents
- + adjust
- + int_rel.r_vaddr
- - input_section->vma));
- BFD_ASSERT (r == bfd_reloc_ok);
- }
-
- continue;
- }
-
- if (int_rel.r_extern)
- {
- h = sym_hashes[int_rel.r_symndx];
- /* If h is NULL, that means that there is a reloc against an
- external symbol which we thought was just a debugging
- symbol. This should not happen. */
- if (h == (struct ecoff_link_hash_entry *) NULL)
- abort ();
- }
- else
- {
- if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
- s = NULL;
- else
- s = symndx_to_section[int_rel.r_symndx];
-
- if (s == (asection *) NULL)
- abort ();
- }
-
- /* The GPREL reloc uses an addend: the difference in the GP
- values. */
- if (int_rel.r_type != MIPS_R_GPREL
- && int_rel.r_type != MIPS_R_LITERAL)
- addend = 0;
- else
- {
- if (gp_undefined)
- {
- if (! ((*info->callbacks->reloc_dangerous)
- (info, _("GP relative relocation used when GP not defined"),
- input_bfd, input_section,
- int_rel.r_vaddr - input_section->vma)))
- return false;
- /* Only give the error once per link. */
- gp = 4;
- _bfd_set_gp_value (output_bfd, gp);
- gp_undefined = false;
- }
- if (! int_rel.r_extern)
- {
- /* This is a relocation against a section. The current
- addend in the instruction is the difference between
- INPUT_SECTION->vma and the GP value of INPUT_BFD. We
- must change this to be the difference between the
- final definition (which will end up in RELOCATION)
- and the GP value of OUTPUT_BFD (which is in GP). */
- addend = ecoff_data (input_bfd)->gp - gp;
- }
- else if (! info->relocateable
- || h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- /* This is a relocation against a defined symbol. The
- current addend in the instruction is simply the
- desired offset into the symbol (normally zero). We
- are going to change this into a relocation against a
- defined symbol, so we want the instruction to hold
- the difference between the final definition of the
- symbol (which will end up in RELOCATION) and the GP
- value of OUTPUT_BFD (which is in GP). */
- addend = - gp;
- }
- else
- {
- /* This is a relocation against an undefined or common
- symbol. The current addend in the instruction is
- simply the desired offset into the symbol (normally
- zero). We are generating relocateable output, and we
- aren't going to define this symbol, so we just leave
- the instruction alone. */
- addend = 0;
- }
- }
-
- /* If we are relaxing, mips_relax_section may have set
- offsets[i] to some value. A value of 1 means we must expand
- a PC relative branch into a multi-instruction of sequence,
- and any other value is an addend. */
- if (offsets != NULL
- && offsets[i] != 0)
- {
- BFD_ASSERT (! info->relocateable);
- BFD_ASSERT (int_rel.r_type == MIPS_R_PCREL16
- || int_rel.r_type == MIPS_R_RELHI
- || int_rel.r_type == MIPS_R_RELLO);
- if (offsets[i] != 1)
- addend += offsets[i];
- else
- {
- bfd_byte *here;
-
- BFD_ASSERT (int_rel.r_extern
- && int_rel.r_type == MIPS_R_PCREL16);
-
- /* Move the rest of the instructions up. */
- here = (contents
- + adjust
- + int_rel.r_vaddr
- - input_section->vma);
- memmove (here + PCREL16_EXPANSION_ADJUSTMENT, here,
- (size_t) (input_section->_raw_size
- - (int_rel.r_vaddr - input_section->vma)));
-
- /* Generate the new instructions. */
- if (! mips_relax_pcrel16 (info, input_bfd, input_section,
- h, here,
- (input_section->output_section->vma
- + input_section->output_offset
- + (int_rel.r_vaddr
- - input_section->vma)
- + adjust)))
- return false;
-
- /* We must adjust everything else up a notch. */
- adjust += PCREL16_EXPANSION_ADJUSTMENT;
-
- /* mips_relax_pcrel16 handles all the details of this
- relocation. */
- continue;
- }
- }
-
- /* If we are relaxing, and this is a reloc against the .text
- segment, we may need to adjust it if some branches have been
- expanded. The reloc types which are likely to occur in the
- .text section are handled efficiently by mips_relax_section,
- and thus do not need to be handled here. */
- if (ecoff_data (input_bfd)->debug_info.adjust != NULL
- && ! int_rel.r_extern
- && int_rel.r_symndx == RELOC_SECTION_TEXT
- && (strcmp (bfd_get_section_name (input_bfd, input_section),
- ".text") != 0
- || (int_rel.r_type != MIPS_R_PCREL16
- && int_rel.r_type != MIPS_R_SWITCH
- && int_rel.r_type != MIPS_R_RELHI
- && int_rel.r_type != MIPS_R_RELLO)))
- {
- bfd_vma adr;
- struct ecoff_value_adjust *a;
-
- /* We need to get the addend so that we know whether we need
- to adjust the address. */
- BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);
-
- adr = bfd_get_32 (input_bfd,
- (contents
- + adjust
- + int_rel.r_vaddr
- - input_section->vma));
-
- for (a = ecoff_data (input_bfd)->debug_info.adjust;
- a != (struct ecoff_value_adjust *) NULL;
- a = a->next)
- {
- if (adr >= a->start && adr < a->end)
- addend += a->adjust;
- }
- }
-
- if (info->relocateable)
- {
- /* We are generating relocateable output, and must convert
- the existing reloc. */
- if (int_rel.r_extern)
- {
- if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && ! bfd_is_abs_section (h->root.u.def.section))
- {
- const char *name;
-
- /* This symbol is defined in the output. Convert
- the reloc from being against the symbol to being
- against the section. */
-
- /* Clear the r_extern bit. */
- int_rel.r_extern = 0;
-
- /* Compute a new r_symndx value. */
- s = h->root.u.def.section;
- name = bfd_get_section_name (output_bfd,
- s->output_section);
-
- int_rel.r_symndx = -1;
- switch (name[1])
- {
- case 'b':
- if (strcmp (name, ".bss") == 0)
- int_rel.r_symndx = RELOC_SECTION_BSS;
- break;
- case 'd':
- if (strcmp (name, ".data") == 0)
- int_rel.r_symndx = RELOC_SECTION_DATA;
- break;
- case 'f':
- if (strcmp (name, ".fini") == 0)
- int_rel.r_symndx = RELOC_SECTION_FINI;
- break;
- case 'i':
- if (strcmp (name, ".init") == 0)
- int_rel.r_symndx = RELOC_SECTION_INIT;
- break;
- case 'l':
- if (strcmp (name, ".lit8") == 0)
- int_rel.r_symndx = RELOC_SECTION_LIT8;
- else if (strcmp (name, ".lit4") == 0)
- int_rel.r_symndx = RELOC_SECTION_LIT4;
- break;
- case 'r':
- if (strcmp (name, ".rdata") == 0)
- int_rel.r_symndx = RELOC_SECTION_RDATA;
- break;
- case 's':
- if (strcmp (name, ".sdata") == 0)
- int_rel.r_symndx = RELOC_SECTION_SDATA;
- else if (strcmp (name, ".sbss") == 0)
- int_rel.r_symndx = RELOC_SECTION_SBSS;
- break;
- case 't':
- if (strcmp (name, ".text") == 0)
- int_rel.r_symndx = RELOC_SECTION_TEXT;
- break;
- }
-
- if (int_rel.r_symndx == -1)
- abort ();
-
- /* Add the section VMA and the symbol value. */
- relocation = (h->root.u.def.value
- + s->output_section->vma
- + s->output_offset);
-
- /* For a PC relative relocation, the object file
- currently holds just the addend. We must adjust
- by the address to get the right value. */
- if (howto->pc_relative)
- {
- relocation -= int_rel.r_vaddr - input_section->vma;
-
- /* If we are converting a RELHI or RELLO reloc
- from being against an external symbol to
- being against a section, we must put a
- special value into the r_offset field. This
- value is the old addend. The r_offset for
- both the RELHI and RELLO relocs are the same,
- and we set both when we see RELHI. */
- if (int_rel.r_type == MIPS_R_RELHI)
- {
- long addhi, addlo;
-
- addhi = bfd_get_32 (input_bfd,
- (contents
- + adjust
- + int_rel.r_vaddr
- - input_section->vma));
- addhi &= 0xffff;
- if (addhi & 0x8000)
- addhi -= 0x10000;
- addhi <<= 16;
-
- if (! use_lo)
- addlo = 0;
- else
- {
- addlo = bfd_get_32 (input_bfd,
- (contents
- + adjust
- + lo_int_rel.r_vaddr
- - input_section->vma));
- addlo &= 0xffff;
- if (addlo & 0x8000)
- addlo -= 0x10000;
-
- lo_int_rel.r_offset = addhi + addlo;
- }
-
- int_rel.r_offset = addhi + addlo;
- }
- }
-
- h = NULL;
- }
- else
- {
- /* Change the symndx value to the right one for the
- output BFD. */
- int_rel.r_symndx = h->indx;
- if (int_rel.r_symndx == -1)
- {
- /* This symbol is not being written out. */
- if (! ((*info->callbacks->unattached_reloc)
- (info, h->root.root.string, input_bfd,
- input_section,
- int_rel.r_vaddr - input_section->vma)))
- return false;
- int_rel.r_symndx = 0;
- }
- relocation = 0;
- }
- }
- else
- {
- /* This is a relocation against a section. Adjust the
- value by the amount the section moved. */
- relocation = (s->output_section->vma
- + s->output_offset
- - s->vma);
- }
-
- relocation += addend;
- addend = 0;
-
- /* Adjust a PC relative relocation by removing the reference
- to the original address in the section and including the
- reference to the new address. However, external RELHI
- and RELLO relocs are PC relative, but don't include any
- reference to the address. The addend is merely an
- addend. */
- if (howto->pc_relative
- && (! int_rel.r_extern
- || (int_rel.r_type != MIPS_R_RELHI
- && int_rel.r_type != MIPS_R_RELLO)))
- relocation -= (input_section->output_section->vma
- + input_section->output_offset
- - input_section->vma);
-
- /* Adjust the contents. */
- if (relocation == 0)
- r = bfd_reloc_ok;
- else
- {
- if (int_rel.r_type != MIPS_R_REFHI
- && int_rel.r_type != MIPS_R_RELHI)
- r = _bfd_relocate_contents (howto, input_bfd, relocation,
- (contents
- + adjust
- + int_rel.r_vaddr
- - input_section->vma));
- else
- {
- mips_relocate_hi (&int_rel,
- use_lo ? &lo_int_rel : NULL,
- input_bfd, input_section, contents,
- adjust, relocation,
- int_rel.r_type == MIPS_R_RELHI);
- r = bfd_reloc_ok;
- }
- }
-
- /* Adjust the reloc address. */
- int_rel.r_vaddr += (input_section->output_section->vma
- + input_section->output_offset
- - input_section->vma);
-
- /* Save the changed reloc information. */
- mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
- }
- else
- {
- /* We are producing a final executable. */
- if (int_rel.r_extern)
- {
- /* This is a reloc against a symbol. */
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- asection *hsec;
-
- hsec = h->root.u.def.section;
- relocation = (h->root.u.def.value
- + hsec->output_section->vma
- + hsec->output_offset);
- }
- else
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd,
- input_section,
- int_rel.r_vaddr - input_section->vma, true)))
- return false;
- relocation = 0;
- }
- }
- else
- {
- /* This is a reloc against a section. */
- relocation = (s->output_section->vma
- + s->output_offset
- - s->vma);
-
- /* A PC relative reloc is already correct in the object
- file. Make it look like a pcrel_offset relocation by
- adding in the start address. */
- if (howto->pc_relative)
- {
- if (int_rel.r_type != MIPS_R_RELHI || ! use_lo)
- relocation += int_rel.r_vaddr + adjust;
- else
- relocation += lo_int_rel.r_vaddr + adjust;
- }
- }
-
- if (int_rel.r_type != MIPS_R_REFHI
- && int_rel.r_type != MIPS_R_RELHI)
- r = _bfd_final_link_relocate (howto,
- input_bfd,
- input_section,
- contents,
- (int_rel.r_vaddr
- - input_section->vma
- + adjust),
- relocation,
- addend);
- else
- {
- mips_relocate_hi (&int_rel,
- use_lo ? &lo_int_rel : NULL,
- input_bfd, input_section, contents, adjust,
- relocation,
- int_rel.r_type == MIPS_R_RELHI);
- r = bfd_reloc_ok;
- }
- }
-
- /* MIPS_R_JMPADDR requires peculiar overflow detection. The
- instruction provides a 28 bit address (the two lower bits are
- implicit zeroes) which is combined with the upper four bits
- of the instruction address. */
- if (r == bfd_reloc_ok
- && int_rel.r_type == MIPS_R_JMPADDR
- && (((relocation
- + addend
- + (int_rel.r_extern ? 0 : s->vma))
- & 0xf0000000)
- != ((input_section->output_section->vma
- + input_section->output_offset
- + (int_rel.r_vaddr - input_section->vma)
- + adjust)
- & 0xf0000000)))
- r = bfd_reloc_overflow;
-
- if (r != bfd_reloc_ok)
- {
- switch (r)
- {
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
- {
- const char *name;
-
- if (int_rel.r_extern)
- name = h->root.root.string;
- else
- name = bfd_section_name (input_bfd, s);
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section,
- int_rel.r_vaddr - input_section->vma)))
- return false;
- }
- break;
- }
- }
- }
-
- return true;
-}
-
-/* Read in the relocs for a section. */
-
-static boolean
-mips_read_relocs (abfd, sec)
- bfd *abfd;
- asection *sec;
-{
- struct ecoff_section_tdata *section_tdata;
- bfd_size_type amt;
-
- section_tdata = ecoff_section_data (abfd, sec);
- if (section_tdata == (struct ecoff_section_tdata *) NULL)
- {
- amt = sizeof (struct ecoff_section_tdata);
- sec->used_by_bfd = (PTR) bfd_alloc (abfd, amt);
- if (sec->used_by_bfd == NULL)
- return false;
-
- section_tdata = ecoff_section_data (abfd, sec);
- section_tdata->external_relocs = NULL;
- section_tdata->contents = NULL;
- section_tdata->offsets = NULL;
- }
-
- if (section_tdata->external_relocs == NULL)
- {
- amt = ecoff_backend (abfd)->external_reloc_size;
- amt *= sec->reloc_count;
- section_tdata->external_relocs = (PTR) bfd_alloc (abfd, amt);
- if (section_tdata->external_relocs == NULL && amt != 0)
- return false;
-
- if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
- || bfd_bread (section_tdata->external_relocs, amt, abfd) != amt)
- return false;
- }
-
- return true;
-}
-
-/* Relax a section when linking a MIPS ECOFF file. This is used for
- embedded PIC code, which always uses PC relative branches which
- only have an 18 bit range on MIPS. If a branch is not in range, we
- generate a long instruction sequence to compensate. Each time we
- find a branch to expand, we have to check all the others again to
- make sure they are still in range. This is slow, but it only has
- to be done when -relax is passed to the linker.
-
- This routine figures out which branches need to expand; the actual
- expansion is done in mips_relocate_section when the section
- contents are relocated. The information is stored in the offsets
- field of the ecoff_section_tdata structure. An offset of 1 means
- that the branch must be expanded into a multi-instruction PC
- relative branch (such an offset will only occur for a PC relative
- branch to an external symbol). Any other offset must be a multiple
- of four, and is the amount to change the branch by (such an offset
- will only occur for a PC relative branch within the same section).
-
- We do not modify the section relocs or contents themselves so that
- if memory usage becomes an issue we can discard them and read them
- again. The only information we must save in memory between this
- routine and the mips_relocate_section routine is the table of
- offsets. */
-
-static boolean
-mips_relax_section (abfd, sec, info, again)
- bfd *abfd;
- asection *sec;
- struct bfd_link_info *info;
- boolean *again;
-{
- struct ecoff_section_tdata *section_tdata;
- bfd_byte *contents = NULL;
- long *offsets;
- struct external_reloc *ext_rel;
- struct external_reloc *ext_rel_end;
- unsigned int i;
-
- /* Assume we are not going to need another pass. */
- *again = false;
-
- /* If we are not generating an ECOFF file, this is much too
- confusing to deal with. */
- if (info->hash->creator->flavour != bfd_get_flavour (abfd))
- return true;
-
- /* If there are no relocs, there is nothing to do. */
- if (sec->reloc_count == 0)
- return true;
-
- /* We are only interested in PC relative relocs, and why would there
- ever be one from anything but the .text section? */
- if (strcmp (bfd_get_section_name (abfd, sec), ".text") != 0)
- return true;
-
- /* Read in the relocs, if we haven't already got them. */
- section_tdata = ecoff_section_data (abfd, sec);
- if (section_tdata == (struct ecoff_section_tdata *) NULL
- || section_tdata->external_relocs == NULL)
- {
- if (! mips_read_relocs (abfd, sec))
- goto error_return;
- section_tdata = ecoff_section_data (abfd, sec);
- }
-
- if (sec->_cooked_size == 0)
- {
- /* We must initialize _cooked_size only the first time we are
- called. */
- sec->_cooked_size = sec->_raw_size;
- }
-
- contents = section_tdata->contents;
- offsets = section_tdata->offsets;
-
- /* Look for any external PC relative relocs. Internal PC relative
- relocs are already correct in the object file, so they certainly
- can not overflow. */
- ext_rel = (struct external_reloc *) section_tdata->external_relocs;
- ext_rel_end = ext_rel + sec->reloc_count;
- for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
- {
- struct internal_reloc int_rel;
- struct ecoff_link_hash_entry *h;
- asection *hsec;
- bfd_signed_vma relocation;
- struct external_reloc *adj_ext_rel;
- unsigned int adj_i;
- unsigned long ext_count;
- struct ecoff_link_hash_entry **adj_h_ptr;
- struct ecoff_link_hash_entry **adj_h_ptr_end;
- struct ecoff_value_adjust *adjust;
- bfd_size_type amt;
-
- /* If we have already expanded this reloc, we certainly don't
- need to do it again. */
- if (offsets != (long *) NULL && offsets[i] == 1)
- continue;
-
- /* Quickly check that this reloc is external PCREL16. */
- if (bfd_header_big_endian (abfd))
- {
- if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) == 0
- || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)
- >> RELOC_BITS3_TYPE_SH_BIG)
- != MIPS_R_PCREL16))
- continue;
- }
- else
- {
- if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) == 0
- || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
- >> RELOC_BITS3_TYPE_SH_LITTLE)
- != MIPS_R_PCREL16))
- continue;
- }
-
- mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
-
- h = ecoff_data (abfd)->sym_hashes[int_rel.r_symndx];
- if (h == (struct ecoff_link_hash_entry *) NULL)
- abort ();
-
- if (h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak)
- {
- /* Just ignore undefined symbols. These will presumably
- generate an error later in the link. */
- continue;
- }
-
- /* Get the value of the symbol. */
- hsec = h->root.u.def.section;
- relocation = (h->root.u.def.value
- + hsec->output_section->vma
- + hsec->output_offset);
-
- /* Subtract out the current address. */
- relocation -= (sec->output_section->vma
- + sec->output_offset
- + (int_rel.r_vaddr - sec->vma));
-
- /* The addend is stored in the object file. In the normal case
- of ``bal symbol'', the addend will be -4. It will only be
- different in the case of ``bal symbol+constant''. To avoid
- always reading in the section contents, we don't check the
- addend in the object file (we could easily check the contents
- if we happen to have already read them in, but I fear that
- this could be confusing). This means we will screw up if
- there is a branch to a symbol that is in range, but added to
- a constant which puts it out of range; in such a case the
- link will fail with a reloc overflow error. Since the
- compiler will never generate such code, it should be easy
- enough to work around it by changing the assembly code in the
- source file. */
- relocation -= 4;
-
- /* Now RELOCATION is the number we want to put in the object
- file. See whether it fits. */
- if (relocation >= -0x20000 && relocation < 0x20000)
- continue;
-
- /* Now that we know this reloc needs work, which will rarely
- happen, go ahead and grab the section contents. */
- if (contents == (bfd_byte *) NULL)
- {
- if (info->keep_memory)
- contents = (bfd_byte *) bfd_alloc (abfd, sec->_raw_size);
- else
- contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
- if (contents == (bfd_byte *) NULL)
- goto error_return;
- if (! bfd_get_section_contents (abfd, sec, (PTR) contents,
- (file_ptr) 0, sec->_raw_size))
- goto error_return;
- if (info->keep_memory)
- section_tdata->contents = contents;
- }
-
- /* We only support changing the bal instruction. It would be
- possible to handle other PC relative branches, but some of
- them (the conditional branches) would require a different
- length instruction sequence which would complicate both this
- routine and mips_relax_pcrel16. It could be written if
- somebody felt it were important. Ignoring this reloc will
- presumably cause a reloc overflow error later on. */
- if (bfd_get_32 (abfd, contents + int_rel.r_vaddr - sec->vma)
- != 0x0411ffff) /* bgezal $0,. == bal . */
- continue;
-
- /* Bother. We need to expand this reloc, and we will need to
- make another relaxation pass since this change may put other
- relocs out of range. We need to examine the local branches
- and we need to allocate memory to hold the offsets we must
- add to them. We also need to adjust the values of all
- symbols in the object file following this location. */
-
- sec->_cooked_size += PCREL16_EXPANSION_ADJUSTMENT;
- *again = true;
-
- if (offsets == (long *) NULL)
- {
- bfd_size_type size;
-
- size = (bfd_size_type) sec->reloc_count * sizeof (long);
- offsets = (long *) bfd_alloc (abfd, size);
- if (offsets == (long *) NULL)
- goto error_return;
- memset (offsets, 0, (size_t) size);
- section_tdata->offsets = offsets;
- }
-
- offsets[i] = 1;
-
- /* Now look for all PC relative references that cross this reloc
- and adjust their offsets. */
- adj_ext_rel = (struct external_reloc *) section_tdata->external_relocs;
- for (adj_i = 0; adj_ext_rel < ext_rel_end; adj_ext_rel++, adj_i++)
- {
- struct internal_reloc adj_int_rel;
- bfd_vma start, stop;
- int change;
-
- mips_ecoff_swap_reloc_in (abfd, (PTR) adj_ext_rel, &adj_int_rel);
-
- if (adj_int_rel.r_type == MIPS_R_PCREL16)
- {
- unsigned long insn;
-
- /* We only care about local references. External ones
- will be relocated correctly anyhow. */
- if (adj_int_rel.r_extern)
- continue;
-
- /* We are only interested in a PC relative reloc within
- this section. FIXME: Cross section PC relative
- relocs may not be handled correctly; does anybody
- care? */
- if (adj_int_rel.r_symndx != RELOC_SECTION_TEXT)
- continue;
-
- start = adj_int_rel.r_vaddr;
-
- insn = bfd_get_32 (abfd,
- contents + adj_int_rel.r_vaddr - sec->vma);
-
- stop = (insn & 0xffff) << 2;
- if ((stop & 0x20000) != 0)
- stop -= 0x40000;
- stop += adj_int_rel.r_vaddr + 4;
- }
- else if (adj_int_rel.r_type == MIPS_R_RELHI)
- {
- struct internal_reloc rello;
- long addhi, addlo;
-
- /* The next reloc must be MIPS_R_RELLO, and we handle
- them together. */
- BFD_ASSERT (adj_ext_rel + 1 < ext_rel_end);
-
- mips_ecoff_swap_reloc_in (abfd, (PTR) (adj_ext_rel + 1), &rello);
-
- BFD_ASSERT (rello.r_type == MIPS_R_RELLO);
-
- addhi = bfd_get_32 (abfd,
- contents + adj_int_rel.r_vaddr - sec->vma);
- addhi &= 0xffff;
- if (addhi & 0x8000)
- addhi -= 0x10000;
- addhi <<= 16;
-
- addlo = bfd_get_32 (abfd, contents + rello.r_vaddr - sec->vma);
- addlo &= 0xffff;
- if (addlo & 0x8000)
- addlo -= 0x10000;
-
- if (adj_int_rel.r_extern)
- {
- /* The value we want here is
- sym - RELLOaddr + addend
- which we can express as
- sym - (RELLOaddr - addend)
- Therefore if we are expanding the area between
- RELLOaddr and RELLOaddr - addend we must adjust
- the addend. This is admittedly ambiguous, since
- we might mean (sym + addend) - RELLOaddr, but in
- practice we don't, and there is no way to handle
- that case correctly since at this point we have
- no idea whether any reloc is being expanded
- between sym and sym + addend. */
- start = rello.r_vaddr - (addhi + addlo);
- stop = rello.r_vaddr;
- }
- else
- {
- /* An internal RELHI/RELLO pair represents the
- difference between two addresses, $LC0 - foo.
- The symndx value is actually the difference
- between the reloc address and $LC0. This lets us
- compute $LC0, and, by considering the addend,
- foo. If the reloc we are expanding falls between
- those two relocs, we must adjust the addend. At
- this point, the symndx value is actually in the
- r_offset field, where it was put by
- mips_ecoff_swap_reloc_in. */
- start = rello.r_vaddr - adj_int_rel.r_offset;
- stop = start + addhi + addlo;
- }
- }
- else if (adj_int_rel.r_type == MIPS_R_SWITCH)
- {
- /* A MIPS_R_SWITCH reloc represents a word of the form
- .word $L3-$LS12
- The value in the object file is correct, assuming the
- original value of $L3. The symndx value is actually
- the difference between the reloc address and $LS12.
- This lets us compute the original value of $LS12 as
- vaddr - symndx
- and the original value of $L3 as
- vaddr - symndx + addend
- where addend is the value from the object file. At
- this point, the symndx value is actually found in the
- r_offset field, since it was moved by
- mips_ecoff_swap_reloc_in. */
- start = adj_int_rel.r_vaddr - adj_int_rel.r_offset;
- stop = start + bfd_get_32 (abfd,
- (contents
- + adj_int_rel.r_vaddr
- - sec->vma));
- }
- else
- continue;
-
- /* If the range expressed by this reloc, which is the
- distance between START and STOP crosses the reloc we are
- expanding, we must adjust the offset. The sign of the
- adjustment depends upon the direction in which the range
- crosses the reloc being expanded. */
- if (start <= int_rel.r_vaddr && stop > int_rel.r_vaddr)
- change = PCREL16_EXPANSION_ADJUSTMENT;
- else if (start > int_rel.r_vaddr && stop <= int_rel.r_vaddr)
- change = - PCREL16_EXPANSION_ADJUSTMENT;
- else
- change = 0;
-
- offsets[adj_i] += change;
-
- if (adj_int_rel.r_type == MIPS_R_RELHI)
- {
- adj_ext_rel++;
- adj_i++;
- offsets[adj_i] += change;
- }
- }
-
- /* Find all symbols in this section defined by this object file
- and adjust their values. Note that we decide whether to
- adjust the value based on the value stored in the ECOFF EXTR
- structure, because the value stored in the hash table may
- have been changed by an earlier expanded reloc and thus may
- no longer correctly indicate whether the symbol is before or
- after the expanded reloc. */
- ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
- adj_h_ptr = ecoff_data (abfd)->sym_hashes;
- adj_h_ptr_end = adj_h_ptr + ext_count;
- for (; adj_h_ptr < adj_h_ptr_end; adj_h_ptr++)
- {
- struct ecoff_link_hash_entry *adj_h;
-
- adj_h = *adj_h_ptr;
- if (adj_h != (struct ecoff_link_hash_entry *) NULL
- && (adj_h->root.type == bfd_link_hash_defined
- || adj_h->root.type == bfd_link_hash_defweak)
- && adj_h->root.u.def.section == sec
- && adj_h->esym.asym.value > int_rel.r_vaddr)
- adj_h->root.u.def.value += PCREL16_EXPANSION_ADJUSTMENT;
- }
-
- /* Add an entry to the symbol value adjust list. This is used
- by bfd_ecoff_debug_accumulate to adjust the values of
- internal symbols and FDR's. */
- amt = sizeof (struct ecoff_value_adjust);
- adjust = (struct ecoff_value_adjust *) bfd_alloc (abfd, amt);
- if (adjust == (struct ecoff_value_adjust *) NULL)
- goto error_return;
-
- adjust->start = int_rel.r_vaddr;
- adjust->end = sec->vma + sec->_raw_size;
- adjust->adjust = PCREL16_EXPANSION_ADJUSTMENT;
-
- adjust->next = ecoff_data (abfd)->debug_info.adjust;
- ecoff_data (abfd)->debug_info.adjust = adjust;
- }
-
- if (contents != (bfd_byte *) NULL && ! info->keep_memory)
- free (contents);
-
- return true;
-
- error_return:
- if (contents != (bfd_byte *) NULL && ! info->keep_memory)
- free (contents);
- return false;
-}
-
-/* This routine is called from mips_relocate_section when a PC
- relative reloc must be expanded into the five instruction sequence.
- It handles all the details of the expansion, including resolving
- the reloc. */
-
-static boolean
-mips_relax_pcrel16 (info, input_bfd, input_section, h, location, address)
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- bfd *input_bfd;
- asection *input_section ATTRIBUTE_UNUSED;
- struct ecoff_link_hash_entry *h;
- bfd_byte *location;
- bfd_vma address;
-{
- bfd_vma relocation;
-
- /* 0x0411ffff is bgezal $0,. == bal . */
- BFD_ASSERT (bfd_get_32 (input_bfd, location) == 0x0411ffff);
-
- /* We need to compute the distance between the symbol and the
- current address plus eight. */
- relocation = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- relocation -= address + 8;
-
- /* If the lower half is negative, increment the upper 16 half. */
- if ((relocation & 0x8000) != 0)
- relocation += 0x10000;
-
- bfd_put_32 (input_bfd, (bfd_vma) 0x04110001, location); /* bal .+8 */
- bfd_put_32 (input_bfd,
- 0x3c010000 | ((relocation >> 16) & 0xffff), /* lui $at,XX */
- location + 4);
- bfd_put_32 (input_bfd,
- 0x24210000 | (relocation & 0xffff), /* addiu $at,$at,XX */
- location + 8);
- bfd_put_32 (input_bfd,
- (bfd_vma) 0x003f0821, location + 12); /* addu $at,$at,$ra */
- bfd_put_32 (input_bfd,
- (bfd_vma) 0x0020f809, location + 16); /* jalr $at */
-
- return true;
-}
-
-/* Given a .sdata section and a .rel.sdata in-memory section, store
- relocation information into the .rel.sdata section which can be
- used at runtime to relocate the section. This is called by the
- linker when the --embedded-relocs switch is used. This is called
- after the add_symbols entry point has been called for all the
- objects, and before the final_link entry point is called. This
- function presumes that the object was compiled using
- -membedded-pic. */
-
-boolean
-bfd_mips_ecoff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *datasec;
- asection *relsec;
- char **errmsg;
-{
- struct ecoff_link_hash_entry **sym_hashes;
- struct ecoff_section_tdata *section_tdata;
- struct external_reloc *ext_rel;
- struct external_reloc *ext_rel_end;
- bfd_byte *p;
- bfd_size_type amt;
-
- BFD_ASSERT (! info->relocateable);
-
- *errmsg = NULL;
-
- if (datasec->reloc_count == 0)
- return true;
-
- sym_hashes = ecoff_data (abfd)->sym_hashes;
-
- if (! mips_read_relocs (abfd, datasec))
- return false;
-
- amt = (bfd_size_type) datasec->reloc_count * 4;
- relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
- if (relsec->contents == NULL)
- return false;
-
- p = relsec->contents;
-
- section_tdata = ecoff_section_data (abfd, datasec);
- ext_rel = (struct external_reloc *) section_tdata->external_relocs;
- ext_rel_end = ext_rel + datasec->reloc_count;
- for (; ext_rel < ext_rel_end; ext_rel++, p += 4)
- {
- struct internal_reloc int_rel;
- boolean text_relative;
-
- mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
-
- /* We are going to write a four byte word into the runtime reloc
- section. The word will be the address in the data section
- which must be relocated. This must be on a word boundary,
- which means the lower two bits must be zero. We use the
- least significant bit to indicate how the value in the data
- section must be relocated. A 0 means that the value is
- relative to the text section, while a 1 indicates that the
- value is relative to the data section. Given that we are
- assuming the code was compiled using -membedded-pic, there
- should not be any other possibilities. */
-
- /* We can only relocate REFWORD relocs at run time. */
- if (int_rel.r_type != MIPS_R_REFWORD)
- {
- *errmsg = _("unsupported reloc type");
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- if (int_rel.r_extern)
- {
- struct ecoff_link_hash_entry *h;
-
- h = sym_hashes[int_rel.r_symndx];
- /* If h is NULL, that means that there is a reloc against an
- external symbol which we thought was just a debugging
- symbol. This should not happen. */
- if (h == (struct ecoff_link_hash_entry *) NULL)
- abort ();
- if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && (h->root.u.def.section->flags & SEC_CODE) != 0)
- text_relative = true;
- else
- text_relative = false;
- }
- else
- {
- switch (int_rel.r_symndx)
- {
- case RELOC_SECTION_TEXT:
- text_relative = true;
- break;
- case RELOC_SECTION_SDATA:
- case RELOC_SECTION_SBSS:
- case RELOC_SECTION_LIT8:
- text_relative = false;
- break;
- default:
- /* No other sections should appear in -membedded-pic
- code. */
- *errmsg = _("reloc against unsupported section");
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
-
- if ((int_rel.r_offset & 3) != 0)
- {
- *errmsg = _("reloc not properly aligned");
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- bfd_put_32 (abfd,
- (int_rel.r_vaddr - datasec->vma + datasec->output_offset
- + (text_relative ? 0 : 1)),
- p);
- }
-
- return true;
-}
-
-/* This is the ECOFF backend structure. The backend field of the
- target vector points to this. */
-
-static const struct ecoff_backend_data mips_ecoff_backend_data =
-{
- /* COFF backend structure. */
- {
- (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
- (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
- (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
- (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
- (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
- (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
- (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
- mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
- mips_ecoff_swap_scnhdr_out,
- FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, true, false, 4, false, 2,
- mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
- mips_ecoff_swap_scnhdr_in, NULL,
- mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
- _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
- _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL
- },
- /* Supported architecture. */
- bfd_arch_mips,
- /* Initial portion of armap string. */
- "__________",
- /* The page boundary used to align sections in a demand-paged
- executable file. E.g., 0x1000. */
- 0x1000,
- /* True if the .rdata section is part of the text segment, as on the
- Alpha. False if .rdata is part of the data segment, as on the
- MIPS. */
- false,
- /* Bitsize of constructor entries. */
- 32,
- /* Reloc to use for constructor entries. */
- &mips_howto_table[MIPS_R_REFWORD],
- {
- /* Symbol table magic number. */
- magicSym,
- /* Alignment of debugging information. E.g., 4. */
- 4,
- /* Sizes of external symbolic information. */
- sizeof (struct hdr_ext),
- sizeof (struct dnr_ext),
- sizeof (struct pdr_ext),
- sizeof (struct sym_ext),
- sizeof (struct opt_ext),
- sizeof (struct fdr_ext),
- sizeof (struct rfd_ext),
- sizeof (struct ext_ext),
- /* Functions to swap in external symbolic data. */
- ecoff_swap_hdr_in,
- ecoff_swap_dnr_in,
- ecoff_swap_pdr_in,
- ecoff_swap_sym_in,
- ecoff_swap_opt_in,
- ecoff_swap_fdr_in,
- ecoff_swap_rfd_in,
- ecoff_swap_ext_in,
- _bfd_ecoff_swap_tir_in,
- _bfd_ecoff_swap_rndx_in,
- /* Functions to swap out external symbolic data. */
- ecoff_swap_hdr_out,
- ecoff_swap_dnr_out,
- ecoff_swap_pdr_out,
- ecoff_swap_sym_out,
- ecoff_swap_opt_out,
- ecoff_swap_fdr_out,
- ecoff_swap_rfd_out,
- ecoff_swap_ext_out,
- _bfd_ecoff_swap_tir_out,
- _bfd_ecoff_swap_rndx_out,
- /* Function to read in symbolic data. */
- _bfd_ecoff_slurp_symbolic_info
- },
- /* External reloc size. */
- RELSZ,
- /* Reloc swapping functions. */
- mips_ecoff_swap_reloc_in,
- mips_ecoff_swap_reloc_out,
- /* Backend reloc tweaking. */
- mips_adjust_reloc_in,
- mips_adjust_reloc_out,
- /* Relocate section contents while linking. */
- mips_relocate_section,
- /* Do final adjustments to filehdr and aouthdr. */
- NULL,
- /* Read an element from an archive at a given file position. */
- _bfd_get_elt_at_filepos
-};
-
-/* Looking up a reloc type is MIPS specific. */
-#define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
-
-/* Getting relocated section contents is generic. */
-#define _bfd_ecoff_bfd_get_relocated_section_contents \
- bfd_generic_get_relocated_section_contents
-
-/* Handling file windows is generic. */
-#define _bfd_ecoff_get_section_contents_in_window \
- _bfd_generic_get_section_contents_in_window
-
-/* Relaxing sections is MIPS specific. */
-#define _bfd_ecoff_bfd_relax_section mips_relax_section
-
-/* GC of sections is not done. */
-#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
-
-/* Merging of sections is not done. */
-#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
-
-extern const bfd_target ecoff_big_vec;
-
-const bfd_target ecoff_little_vec =
-{
- "ecoff-littlemips", /* name */
- bfd_target_ecoff_flavour,
- BFD_ENDIAN_LITTLE, /* data byte order is little */
- BFD_ENDIAN_LITTLE, /* header byte order is little */
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
-
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
- 0, /* leading underscore */
- ' ', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
-
- {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- _bfd_ecoff_archive_p, _bfd_dummy_target},
- {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
- BFD_JUMP_TABLE_COPY (_bfd_ecoff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
- BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
- BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
- BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
- BFD_JUMP_TABLE_LINK (_bfd_ecoff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- & ecoff_big_vec,
-
- (PTR) &mips_ecoff_backend_data
-};
-
-const bfd_target ecoff_big_vec =
-{
- "ecoff-bigmips", /* name */
- bfd_target_ecoff_flavour,
- BFD_ENDIAN_BIG, /* data byte order is big */
- BFD_ENDIAN_BIG, /* header byte order is big */
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
-
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
- 0, /* leading underscore */
- ' ', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16,
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16,
- {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- _bfd_ecoff_archive_p, _bfd_dummy_target},
- {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
- BFD_JUMP_TABLE_COPY (_bfd_ecoff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
- BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
- BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
- BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
- BFD_JUMP_TABLE_LINK (_bfd_ecoff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- & ecoff_little_vec,
-
- (PTR) &mips_ecoff_backend_data
-};
-
-const bfd_target ecoff_biglittle_vec =
-{
- "ecoff-biglittlemips", /* name */
- bfd_target_ecoff_flavour,
- BFD_ENDIAN_LITTLE, /* data byte order is little */
- BFD_ENDIAN_BIG, /* header byte order is big */
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
-
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
- 0, /* leading underscore */
- ' ', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
-
- {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- _bfd_ecoff_archive_p, _bfd_dummy_target},
- {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
- BFD_JUMP_TABLE_COPY (_bfd_ecoff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
- BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
- BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
- BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
- BFD_JUMP_TABLE_LINK (_bfd_ecoff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- NULL,
-
- (PTR) &mips_ecoff_backend_data
-};
diff --git a/contrib/binutils/bfd/coff-sh.c b/contrib/binutils/bfd/coff-sh.c
deleted file mode 100644
index d1dc4fd..0000000
--- a/contrib/binutils/bfd/coff-sh.c
+++ /dev/null
@@ -1,3343 +0,0 @@
-/* BFD back-end for Hitachi Super-H COFF binaries.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
- Contributed by Cygnus Support.
- Written by Steve Chamberlain, <sac@cygnus.com>.
- Relaxing code written by Ian Lance Taylor, <ian@cygnus.com>.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libiberty.h"
-#include "libbfd.h"
-#include "bfdlink.h"
-#include "coff/sh.h"
-#include "coff/internal.h"
-
-#ifdef COFF_WITH_PE
-#include "coff/pe.h"
-
-#ifndef COFF_IMAGE_WITH_PE
-static boolean sh_align_load_span
- PARAMS ((bfd *, asection *, bfd_byte *,
- boolean (*) (bfd *, asection *, PTR, bfd_byte *, bfd_vma),
- PTR, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, boolean *));
-
-#define _bfd_sh_align_load_span sh_align_load_span
-#endif
-#endif
-
-#include "libcoff.h"
-
-/* Internal functions. */
-static bfd_reloc_status_type sh_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static long get_symbol_value PARAMS ((asymbol *));
-static boolean sh_relax_section
- PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
-static boolean sh_relax_delete_bytes
- PARAMS ((bfd *, asection *, bfd_vma, int));
-#ifndef COFF_IMAGE_WITH_PE
-static const struct sh_opcode *sh_insn_info PARAMS ((unsigned int));
-#endif
-static boolean sh_align_loads
- PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *, boolean *));
-static boolean sh_swap_insns
- PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
-static boolean sh_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- struct internal_reloc *, struct internal_syment *, asection **));
-static bfd_byte *sh_coff_get_relocated_section_contents
- PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
- bfd_byte *, boolean, asymbol **));
-static reloc_howto_type * sh_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
-
-#ifdef COFF_WITH_PE
-/* Can't build import tables with 2**4 alignment. */
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
-#else
-/* Default section alignment to 2**4. */
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 4
-#endif
-
-#ifdef COFF_IMAGE_WITH_PE
-/* Align PE executables. */
-#define COFF_PAGE_SIZE 0x1000
-#endif
-
-/* Generate long file names. */
-#define COFF_LONG_FILENAMES
-
-#ifdef COFF_WITH_PE
-static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
-/* Return true if this relocation should
- appear in the output .reloc section. */
-static boolean in_reloc_p (abfd, howto)
- bfd * abfd ATTRIBUTE_UNUSED;
- reloc_howto_type * howto;
-{
- return ! howto->pc_relative && howto->type != R_SH_IMAGEBASE;
-}
-#endif
-
-/* The supported relocations. There are a lot of relocations defined
- in coff/internal.h which we do not expect to ever see. */
-static reloc_howto_type sh_coff_howtos[] =
-{
- EMPTY_HOWTO (0),
- EMPTY_HOWTO (1),
-#ifdef COFF_WITH_PE
- /* Windows CE */
- HOWTO (R_SH_IMM32CE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_imm32ce", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-#else
- EMPTY_HOWTO (2),
-#endif
- EMPTY_HOWTO (3), /* R_SH_PCREL8 */
- EMPTY_HOWTO (4), /* R_SH_PCREL16 */
- EMPTY_HOWTO (5), /* R_SH_HIGH8 */
- EMPTY_HOWTO (6), /* R_SH_IMM24 */
- EMPTY_HOWTO (7), /* R_SH_LOW16 */
- EMPTY_HOWTO (8),
- EMPTY_HOWTO (9), /* R_SH_PCDISP8BY4 */
-
- HOWTO (R_SH_PCDISP8BY2, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_pcdisp8by2", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- EMPTY_HOWTO (11), /* R_SH_PCDISP8 */
-
- HOWTO (R_SH_PCDISP, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 12, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_pcdisp12by2", /* name */
- true, /* partial_inplace */
- 0xfff, /* src_mask */
- 0xfff, /* dst_mask */
- true), /* pcrel_offset */
-
- EMPTY_HOWTO (13),
-
- HOWTO (R_SH_IMM32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_imm32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- EMPTY_HOWTO (15),
-#ifdef COFF_WITH_PE
- HOWTO (R_SH_IMAGEBASE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "rva32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-#else
- EMPTY_HOWTO (16), /* R_SH_IMM8 */
-#endif
- EMPTY_HOWTO (17), /* R_SH_IMM8BY2 */
- EMPTY_HOWTO (18), /* R_SH_IMM8BY4 */
- EMPTY_HOWTO (19), /* R_SH_IMM4 */
- EMPTY_HOWTO (20), /* R_SH_IMM4BY2 */
- EMPTY_HOWTO (21), /* R_SH_IMM4BY4 */
-
- HOWTO (R_SH_PCRELIMM8BY2, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_pcrelimm8by2", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- HOWTO (R_SH_PCRELIMM8BY4, /* type */
- 2, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_pcrelimm8by4", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- HOWTO (R_SH_IMM16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_imm16", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_SWITCH16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_switch16", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_SWITCH32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_switch32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_USES, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_uses", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_COUNT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_count", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_ALIGN, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_align", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_CODE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_code", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_DATA, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_data", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_LABEL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_label", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_SWITCH8, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_reloc, /* special_function */
- "r_switch8", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- false) /* pcrel_offset */
-};
-
-#define SH_COFF_HOWTO_COUNT (sizeof sh_coff_howtos / sizeof sh_coff_howtos[0])
-
-/* Check for a bad magic number. */
-#define BADMAG(x) SHBADMAG(x)
-
-/* Customize coffcode.h (this is not currently used). */
-#define SH 1
-
-/* FIXME: This should not be set here. */
-#define __A_MAGIC_SET__
-
-#ifndef COFF_WITH_PE
-/* Swap the r_offset field in and out. */
-#define SWAP_IN_RELOC_OFFSET H_GET_32
-#define SWAP_OUT_RELOC_OFFSET H_PUT_32
-
-/* Swap out extra information in the reloc structure. */
-#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
- do \
- { \
- dst->r_stuff[0] = 'S'; \
- dst->r_stuff[1] = 'C'; \
- } \
- while (0)
-#endif
-
-/* Get the value of a symbol, when performing a relocation. */
-
-static long
-get_symbol_value (symbol)
- asymbol *symbol;
-{
- bfd_vma relocation;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = (symbol->value +
- symbol->section->output_section->vma +
- symbol->section->output_offset);
-
- return relocation;
-}
-
-#ifdef COFF_WITH_PE
-/* Convert an rtype to howto for the COFF backend linker.
- Copied from coff-i386. */
-#define coff_rtype_to_howto coff_sh_rtype_to_howto
-static reloc_howto_type * coff_sh_rtype_to_howto PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
-
-static reloc_howto_type *
-coff_sh_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
- bfd * abfd ATTRIBUTE_UNUSED;
- asection * sec;
- struct internal_reloc * rel;
- struct coff_link_hash_entry * h;
- struct internal_syment * sym;
- bfd_vma * addendp;
-{
- reloc_howto_type * howto;
-
- howto = sh_coff_howtos + rel->r_type;
-
- *addendp = 0;
-
- if (howto->pc_relative)
- *addendp += sec->vma;
-
- if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
- {
- /* This is a common symbol. The section contents include the
- size (sym->n_value) as an addend. The relocate_section
- function will be adding in the final value of the symbol. We
- need to subtract out the current size in order to get the
- correct result. */
- BFD_ASSERT (h != NULL);
- }
-
- if (howto->pc_relative)
- {
- *addendp -= 4;
-
- /* If the symbol is defined, then the generic code is going to
- add back the symbol value in order to cancel out an
- adjustment it made to the addend. However, we set the addend
- to 0 at the start of this function. We need to adjust here,
- to avoid the adjustment the generic code will make. FIXME:
- This is getting a bit hackish. */
- if (sym != NULL && sym->n_scnum != 0)
- *addendp -= sym->n_value;
- }
-
- if (rel->r_type == R_SH_IMAGEBASE)
- *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
-
- return howto;
-}
-
-#endif /* COFF_WITH_PE */
-
-/* This structure is used to map BFD reloc codes to SH PE relocs. */
-struct shcoff_reloc_map
-{
- bfd_reloc_code_real_type bfd_reloc_val;
- unsigned char shcoff_reloc_val;
-};
-
-#ifdef COFF_WITH_PE
-/* An array mapping BFD reloc codes to SH PE relocs. */
-static const struct shcoff_reloc_map sh_reloc_map[] =
-{
- { BFD_RELOC_32, R_SH_IMM32CE },
- { BFD_RELOC_RVA, R_SH_IMAGEBASE },
- { BFD_RELOC_CTOR, R_SH_IMM32CE },
-};
-#else
-/* An array mapping BFD reloc codes to SH PE relocs. */
-static const struct shcoff_reloc_map sh_reloc_map[] =
-{
- { BFD_RELOC_32, R_SH_IMM32 },
- { BFD_RELOC_CTOR, R_SH_IMM32 },
-};
-#endif
-
-/* Given a BFD reloc code, return the howto structure for the
- corresponding SH PE reloc. */
-#define coff_bfd_reloc_type_lookup sh_coff_reloc_type_lookup
-
-static reloc_howto_type *
-sh_coff_reloc_type_lookup (abfd, code)
- bfd * abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- unsigned int i;
-
- for (i = ARRAY_SIZE (sh_reloc_map); i--;)
- if (sh_reloc_map[i].bfd_reloc_val == code)
- return &sh_coff_howtos[(int) sh_reloc_map[i].shcoff_reloc_val];
-
- fprintf (stderr, "SH Error: unknown reloc type %d\n", code);
- return NULL;
-}
-
-/* This macro is used in coffcode.h to get the howto corresponding to
- an internal reloc. */
-
-#define RTYPE2HOWTO(relent, internal) \
- ((relent)->howto = \
- ((internal)->r_type < SH_COFF_HOWTO_COUNT \
- ? &sh_coff_howtos[(internal)->r_type] \
- : (reloc_howto_type *) NULL))
-
-/* This is the same as the macro in coffcode.h, except that it copies
- r_offset into reloc_entry->addend for some relocs. */
-#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
- { \
- coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
- if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
- coffsym = (obj_symbols (abfd) \
- + (cache_ptr->sym_ptr_ptr - symbols)); \
- else if (ptr) \
- coffsym = coff_symbol_from (abfd, ptr); \
- if (coffsym != (coff_symbol_type *) NULL \
- && coffsym->native->u.syment.n_scnum == 0) \
- cache_ptr->addend = 0; \
- else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
- && ptr->section != (asection *) NULL) \
- cache_ptr->addend = - (ptr->section->vma + ptr->value); \
- else \
- cache_ptr->addend = 0; \
- if ((reloc).r_type == R_SH_SWITCH8 \
- || (reloc).r_type == R_SH_SWITCH16 \
- || (reloc).r_type == R_SH_SWITCH32 \
- || (reloc).r_type == R_SH_USES \
- || (reloc).r_type == R_SH_COUNT \
- || (reloc).r_type == R_SH_ALIGN) \
- cache_ptr->addend = (reloc).r_offset; \
- }
-
-/* This is the howto function for the SH relocations. */
-
-static bfd_reloc_status_type
-sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol_in;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- unsigned long insn;
- bfd_vma sym_value;
- unsigned short r_type;
- bfd_vma addr = reloc_entry->address;
- bfd_byte *hit_data = addr + (bfd_byte *) data;
-
- r_type = reloc_entry->howto->type;
-
- if (output_bfd != NULL)
- {
- /* Partial linking--do nothing. */
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* Almost all relocs have to do with relaxing. If any work must be
- done for them, it has been done in sh_relax_section. */
- if (r_type != R_SH_IMM32
-#ifdef COFF_WITH_PE
- && r_type != R_SH_IMM32CE
- && r_type != R_SH_IMAGEBASE
-#endif
- && (r_type != R_SH_PCDISP
- || (symbol_in->flags & BSF_LOCAL) != 0))
- return bfd_reloc_ok;
-
- if (symbol_in != NULL
- && bfd_is_und_section (symbol_in->section))
- return bfd_reloc_undefined;
-
- sym_value = get_symbol_value (symbol_in);
-
- switch (r_type)
- {
- case R_SH_IMM32:
-#ifdef COFF_WITH_PE
- case R_SH_IMM32CE:
-#endif
- insn = bfd_get_32 (abfd, hit_data);
- insn += sym_value + reloc_entry->addend;
- bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
- break;
-#ifdef COFF_WITH_PE
- case R_SH_IMAGEBASE:
- insn = bfd_get_32 (abfd, hit_data);
- insn += sym_value + reloc_entry->addend;
- insn -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
- bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
- break;
-#endif
- case R_SH_PCDISP:
- insn = bfd_get_16 (abfd, hit_data);
- sym_value += reloc_entry->addend;
- sym_value -= (input_section->output_section->vma
- + input_section->output_offset
- + addr
- + 4);
- sym_value += (insn & 0xfff) << 1;
- if (insn & 0x800)
- sym_value -= 0x1000;
- insn = (insn & 0xf000) | (sym_value & 0xfff);
- bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
- if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
- return bfd_reloc_overflow;
- break;
- default:
- abort ();
- break;
- }
-
- return bfd_reloc_ok;
-}
-
-#define coff_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
-
-/* We can do relaxing. */
-#define coff_bfd_relax_section sh_relax_section
-
-/* We use the special COFF backend linker. */
-#define coff_relocate_section sh_relocate_section
-
-/* When relaxing, we need to use special code to get the relocated
- section contents. */
-#define coff_bfd_get_relocated_section_contents \
- sh_coff_get_relocated_section_contents
-
-#include "coffcode.h"
-
-/* This function handles relaxing on the SH.
-
- Function calls on the SH look like this:
-
- movl L1,r0
- ...
- jsr @r0
- ...
- L1:
- .long function
-
- The compiler and assembler will cooperate to create R_SH_USES
- relocs on the jsr instructions. The r_offset field of the
- R_SH_USES reloc is the PC relative offset to the instruction which
- loads the register (the r_offset field is computed as though it
- were a jump instruction, so the offset value is actually from four
- bytes past the instruction). The linker can use this reloc to
- determine just which function is being called, and thus decide
- whether it is possible to replace the jsr with a bsr.
-
- If multiple function calls are all based on a single register load
- (i.e., the same function is called multiple times), the compiler
- guarantees that each function call will have an R_SH_USES reloc.
- Therefore, if the linker is able to convert each R_SH_USES reloc
- which refers to that address, it can safely eliminate the register
- load.
-
- When the assembler creates an R_SH_USES reloc, it examines it to
- determine which address is being loaded (L1 in the above example).
- It then counts the number of references to that address, and
- creates an R_SH_COUNT reloc at that address. The r_offset field of
- the R_SH_COUNT reloc will be the number of references. If the
- linker is able to eliminate a register load, it can use the
- R_SH_COUNT reloc to see whether it can also eliminate the function
- address.
-
- SH relaxing also handles another, unrelated, matter. On the SH, if
- a load or store instruction is not aligned on a four byte boundary,
- the memory cycle interferes with the 32 bit instruction fetch,
- causing a one cycle bubble in the pipeline. Therefore, we try to
- align load and store instructions on four byte boundaries if we
- can, by swapping them with one of the adjacent instructions. */
-
-static boolean
-sh_relax_section (abfd, sec, link_info, again)
- bfd *abfd;
- asection *sec;
- struct bfd_link_info *link_info;
- boolean *again;
-{
- struct internal_reloc *internal_relocs;
- struct internal_reloc *free_relocs = NULL;
- boolean have_code;
- struct internal_reloc *irel, *irelend;
- bfd_byte *contents = NULL;
- bfd_byte *free_contents = NULL;
-
- *again = false;
-
- if (link_info->relocateable
- || (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;
-
- internal_relocs = (_bfd_coff_read_internal_relocs
- (abfd, sec, link_info->keep_memory,
- (bfd_byte *) NULL, false,
- (struct internal_reloc *) NULL));
- if (internal_relocs == NULL)
- goto error_return;
- if (! link_info->keep_memory)
- free_relocs = internal_relocs;
-
- have_code = false;
-
- irelend = internal_relocs + sec->reloc_count;
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- bfd_vma laddr, paddr, symval;
- unsigned short insn;
- struct internal_reloc *irelfn, *irelscan, *irelcount;
- struct internal_syment sym;
- bfd_signed_vma foff;
-
- if (irel->r_type == R_SH_CODE)
- have_code = true;
-
- if (irel->r_type != R_SH_USES)
- continue;
-
- /* Get the section contents. */
- if (contents == NULL)
- {
- if (coff_section_data (abfd, sec) != NULL
- && coff_section_data (abfd, sec)->contents != NULL)
- contents = coff_section_data (abfd, sec)->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;
- }
- }
-
- /* The r_offset field of the R_SH_USES reloc will point us to
- the register load. The 4 is because the r_offset field is
- computed as though it were a jump offset, which are based
- from 4 bytes after the jump instruction. */
- laddr = irel->r_vaddr - sec->vma + 4;
- /* Careful to sign extend the 32-bit offset. */
- laddr += ((irel->r_offset & 0xffffffff) ^ 0x80000000) - 0x80000000;
- if (laddr >= sec->_raw_size)
- {
- (*_bfd_error_handler) ("%s: 0x%lx: warning: bad R_SH_USES offset",
- bfd_archive_filename (abfd),
- (unsigned long) irel->r_vaddr);
- continue;
- }
- insn = bfd_get_16 (abfd, contents + laddr);
-
- /* If the instruction is not mov.l NN,rN, we don't know what to do. */
- if ((insn & 0xf000) != 0xd000)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x",
- bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr, insn));
- continue;
- }
-
- /* Get the address from which the register is being loaded. The
- displacement in the mov.l instruction is quadrupled. It is a
- displacement from four bytes after the movl instruction, but,
- before adding in the PC address, two least significant bits
- of the PC are cleared. We assume that the section is aligned
- on a four byte boundary. */
- paddr = insn & 0xff;
- paddr *= 4;
- paddr += (laddr + 4) &~ (bfd_vma) 3;
- if (paddr >= sec->_raw_size)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: warning: bad R_SH_USES load offset",
- bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr));
- continue;
- }
-
- /* Get the reloc for the address from which the register is
- being loaded. This reloc will tell us which function is
- actually being called. */
- paddr += sec->vma;
- for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
- if (irelfn->r_vaddr == paddr
-#ifdef COFF_WITH_PE
- && (irelfn->r_type == R_SH_IMM32
- || irelfn->r_type == R_SH_IMM32CE
- || irelfn->r_type == R_SH_IMAGEBASE))
-
-#else
- && irelfn->r_type == R_SH_IMM32)
-#endif
- break;
- if (irelfn >= irelend)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: warning: could not find expected reloc",
- bfd_archive_filename (abfd), (unsigned long) paddr));
- continue;
- }
-
- /* Get the value of the symbol referred to by the reloc. */
- if (! _bfd_coff_get_external_symbols (abfd))
- goto error_return;
- bfd_coff_swap_sym_in (abfd,
- ((bfd_byte *) obj_coff_external_syms (abfd)
- + (irelfn->r_symndx
- * bfd_coff_symesz (abfd))),
- &sym);
- if (sym.n_scnum != 0 && sym.n_scnum != sec->target_index)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: warning: symbol in unexpected section",
- bfd_archive_filename (abfd), (unsigned long) paddr));
- continue;
- }
-
- if (sym.n_sclass != C_EXT)
- {
- symval = (sym.n_value
- - sec->vma
- + sec->output_section->vma
- + sec->output_offset);
- }
- else
- {
- struct coff_link_hash_entry *h;
-
- h = obj_coff_sym_hashes (abfd)[irelfn->r_symndx];
- BFD_ASSERT (h != NULL);
- if (h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak)
- {
- /* This appears to be a reference to an undefined
- symbol. Just ignore it--it will be caught by the
- regular reloc processing. */
- continue;
- }
-
- symval = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
-
- symval += bfd_get_32 (abfd, contents + paddr - sec->vma);
-
- /* See if this function call can be shortened. */
- foff = (symval
- - (irel->r_vaddr
- - sec->vma
- + sec->output_section->vma
- + sec->output_offset
- + 4));
- if (foff < -0x1000 || foff >= 0x1000)
- {
- /* After all that work, we can't shorten this function call. */
- continue;
- }
-
- /* Shorten the function call. */
-
- /* For simplicity of coding, we are going to modify the section
- contents, the section relocs, and the BFD symbol table. We
- must tell the rest of the code not to free up this
- information. It would be possible to instead create a table
- of changes which have to be made, as is done in coff-mips.c;
- that would be more work, but would require less memory when
- the linker is run. */
-
- if (coff_section_data (abfd, sec) == NULL)
- {
- bfd_size_type amt = sizeof (struct coff_section_tdata);
- sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
- if (sec->used_by_bfd == NULL)
- goto error_return;
- }
-
- coff_section_data (abfd, sec)->relocs = internal_relocs;
- coff_section_data (abfd, sec)->keep_relocs = true;
- free_relocs = NULL;
-
- coff_section_data (abfd, sec)->contents = contents;
- coff_section_data (abfd, sec)->keep_contents = true;
- free_contents = NULL;
-
- obj_coff_keep_syms (abfd) = true;
-
- /* Replace the jsr with a bsr. */
-
- /* Change the R_SH_USES reloc into an R_SH_PCDISP reloc, and
- replace the jsr with a bsr. */
- irel->r_type = R_SH_PCDISP;
- irel->r_symndx = irelfn->r_symndx;
- if (sym.n_sclass != C_EXT)
- {
- /* If this needs to be changed because of future relaxing,
- it will be handled here like other internal PCDISP
- relocs. */
- bfd_put_16 (abfd,
- (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff),
- contents + irel->r_vaddr - sec->vma);
- }
- else
- {
- /* We can't fully resolve this yet, because the external
- symbol value may be changed by future relaxing. We let
- the final link phase handle it. */
- bfd_put_16 (abfd, (bfd_vma) 0xb000,
- contents + irel->r_vaddr - sec->vma);
- }
-
- /* See if there is another R_SH_USES reloc referring to the same
- register load. */
- for (irelscan = internal_relocs; irelscan < irelend; irelscan++)
- if (irelscan->r_type == R_SH_USES
- && laddr == irelscan->r_vaddr - sec->vma + 4 + irelscan->r_offset)
- break;
- if (irelscan < irelend)
- {
- /* Some other function call depends upon this register load,
- and we have not yet converted that function call.
- Indeed, we may never be able to convert it. There is
- nothing else we can do at this point. */
- continue;
- }
-
- /* Look for a R_SH_COUNT reloc on the location where the
- function address is stored. Do this before deleting any
- bytes, to avoid confusion about the address. */
- for (irelcount = internal_relocs; irelcount < irelend; irelcount++)
- if (irelcount->r_vaddr == paddr
- && irelcount->r_type == R_SH_COUNT)
- break;
-
- /* Delete the register load. */
- if (! sh_relax_delete_bytes (abfd, sec, laddr, 2))
- goto error_return;
-
- /* That will change things, so, just in case it permits some
- other function call to come within range, we should relax
- again. Note that this is not required, and it may be slow. */
- *again = true;
-
- /* Now check whether we got a COUNT reloc. */
- if (irelcount >= irelend)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: warning: could not find expected COUNT reloc",
- bfd_archive_filename (abfd), (unsigned long) paddr));
- continue;
- }
-
- /* The number of uses is stored in the r_offset field. We've
- just deleted one. */
- if (irelcount->r_offset == 0)
- {
- ((*_bfd_error_handler) ("%s: 0x%lx: warning: bad count",
- bfd_archive_filename (abfd),
- (unsigned long) paddr));
- continue;
- }
-
- --irelcount->r_offset;
-
- /* If there are no more uses, we can delete the address. Reload
- the address from irelfn, in case it was changed by the
- previous call to sh_relax_delete_bytes. */
- if (irelcount->r_offset == 0)
- {
- if (! sh_relax_delete_bytes (abfd, sec,
- irelfn->r_vaddr - sec->vma, 4))
- goto error_return;
- }
-
- /* We've done all we can with that function call. */
- }
-
- /* Look for load and store instructions that we can align on four
- byte boundaries. */
- if (have_code)
- {
- boolean swapped;
-
- /* Get the section contents. */
- if (contents == NULL)
- {
- if (coff_section_data (abfd, sec) != NULL
- && coff_section_data (abfd, sec)->contents != NULL)
- contents = coff_section_data (abfd, sec)->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;
- }
- }
-
- if (! sh_align_loads (abfd, sec, internal_relocs, contents, &swapped))
- goto error_return;
-
- if (swapped)
- {
- if (coff_section_data (abfd, sec) == NULL)
- {
- bfd_size_type amt = sizeof (struct coff_section_tdata);
- sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
- if (sec->used_by_bfd == NULL)
- goto error_return;
- }
-
- coff_section_data (abfd, sec)->relocs = internal_relocs;
- coff_section_data (abfd, sec)->keep_relocs = true;
- free_relocs = NULL;
-
- coff_section_data (abfd, sec)->contents = contents;
- coff_section_data (abfd, sec)->keep_contents = true;
- free_contents = NULL;
-
- obj_coff_keep_syms (abfd) = true;
- }
- }
-
- if (free_relocs != NULL)
- {
- free (free_relocs);
- free_relocs = NULL;
- }
-
- if (free_contents != NULL)
- {
- if (! link_info->keep_memory)
- free (free_contents);
- else
- {
- /* Cache the section contents for coff_link_input_bfd. */
- if (coff_section_data (abfd, sec) == NULL)
- {
- bfd_size_type amt = sizeof (struct coff_section_tdata);
- sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
- if (sec->used_by_bfd == NULL)
- goto error_return;
- coff_section_data (abfd, sec)->relocs = NULL;
- }
- coff_section_data (abfd, sec)->contents = contents;
- }
- }
-
- return true;
-
- error_return:
- if (free_relocs != NULL)
- free (free_relocs);
- if (free_contents != NULL)
- free (free_contents);
- return false;
-}
-
-/* Delete some bytes from a section while relaxing. */
-
-static boolean
-sh_relax_delete_bytes (abfd, sec, addr, count)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
- int count;
-{
- bfd_byte *contents;
- struct internal_reloc *irel, *irelend;
- struct internal_reloc *irelalign;
- bfd_vma toaddr;
- bfd_byte *esym, *esymend;
- bfd_size_type symesz;
- struct coff_link_hash_entry **sym_hash;
- asection *o;
-
- contents = coff_section_data (abfd, sec)->contents;
-
- /* The deletion must stop at the next ALIGN reloc for an aligment
- power larger than the number of bytes we are deleting. */
-
- irelalign = NULL;
- toaddr = sec->_cooked_size;
-
- irel = coff_section_data (abfd, sec)->relocs;
- irelend = irel + sec->reloc_count;
- for (; irel < irelend; irel++)
- {
- if (irel->r_type == R_SH_ALIGN
- && irel->r_vaddr - sec->vma > addr
- && count < (1 << irel->r_offset))
- {
- irelalign = irel;
- toaddr = irel->r_vaddr - sec->vma;
- break;
- }
- }
-
- /* Actually delete the bytes. */
- memmove (contents + addr, contents + addr + count,
- (size_t) (toaddr - addr - count));
- if (irelalign == NULL)
- sec->_cooked_size -= count;
- else
- {
- int i;
-
-#define NOP_OPCODE (0x0009)
-
- BFD_ASSERT ((count & 1) == 0);
- for (i = 0; i < count; i += 2)
- bfd_put_16 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
- }
-
- /* Adjust all the relocs. */
- for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
- {
- bfd_vma nraddr, stop;
- bfd_vma start = 0;
- int insn = 0;
- struct internal_syment sym;
- int off, adjust, oinsn;
- bfd_signed_vma voff = 0;
- boolean overflow;
-
- /* Get the new reloc address. */
- nraddr = irel->r_vaddr - sec->vma;
- if ((irel->r_vaddr - sec->vma > addr
- && irel->r_vaddr - sec->vma < toaddr)
- || (irel->r_type == R_SH_ALIGN
- && irel->r_vaddr - sec->vma == toaddr))
- nraddr -= count;
-
- /* See if this reloc was for the bytes we have deleted, in which
- case we no longer care about it. Don't delete relocs which
- represent addresses, though. */
- if (irel->r_vaddr - sec->vma >= addr
- && irel->r_vaddr - sec->vma < addr + count
- && irel->r_type != R_SH_ALIGN
- && irel->r_type != R_SH_CODE
- && irel->r_type != R_SH_DATA
- && irel->r_type != R_SH_LABEL)
- irel->r_type = R_SH_UNUSED;
-
- /* If this is a PC relative reloc, see if the range it covers
- includes the bytes we have deleted. */
- switch (irel->r_type)
- {
- default:
- break;
-
- case R_SH_PCDISP8BY2:
- case R_SH_PCDISP:
- case R_SH_PCRELIMM8BY2:
- case R_SH_PCRELIMM8BY4:
- start = irel->r_vaddr - sec->vma;
- insn = bfd_get_16 (abfd, contents + nraddr);
- break;
- }
-
- switch (irel->r_type)
- {
- default:
- start = stop = addr;
- break;
-
- case R_SH_IMM32:
-#ifdef COFF_WITH_PE
- case R_SH_IMM32CE:
- case R_SH_IMAGEBASE:
-#endif
- /* If this reloc is against a symbol defined in this
- section, and the symbol will not be adjusted below, we
- must check the addend to see it will put the value in
- range to be adjusted, and hence must be changed. */
- bfd_coff_swap_sym_in (abfd,
- ((bfd_byte *) obj_coff_external_syms (abfd)
- + (irel->r_symndx
- * bfd_coff_symesz (abfd))),
- &sym);
- if (sym.n_sclass != C_EXT
- && sym.n_scnum == sec->target_index
- && ((bfd_vma) sym.n_value <= addr
- || (bfd_vma) sym.n_value >= toaddr))
- {
- bfd_vma val;
-
- val = bfd_get_32 (abfd, contents + nraddr);
- val += sym.n_value;
- if (val > addr && val < toaddr)
- bfd_put_32 (abfd, val - count, contents + nraddr);
- }
- start = stop = addr;
- break;
-
- case R_SH_PCDISP8BY2:
- off = insn & 0xff;
- if (off & 0x80)
- off -= 0x100;
- stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
- break;
-
- case R_SH_PCDISP:
- bfd_coff_swap_sym_in (abfd,
- ((bfd_byte *) obj_coff_external_syms (abfd)
- + (irel->r_symndx
- * bfd_coff_symesz (abfd))),
- &sym);
- if (sym.n_sclass == C_EXT)
- start = stop = addr;
- else
- {
- off = insn & 0xfff;
- if (off & 0x800)
- off -= 0x1000;
- stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
- }
- break;
-
- case R_SH_PCRELIMM8BY2:
- off = insn & 0xff;
- stop = start + 4 + off * 2;
- break;
-
- case R_SH_PCRELIMM8BY4:
- off = insn & 0xff;
- stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
- break;
-
- case R_SH_SWITCH8:
- case R_SH_SWITCH16:
- case R_SH_SWITCH32:
- /* These relocs types represent
- .word L2-L1
- The r_offset field holds the difference between the reloc
- address and L1. That is the start of the reloc, and
- adding in the contents gives us the top. We must adjust
- both the r_offset field and the section contents. */
-
- start = irel->r_vaddr - sec->vma;
- stop = (bfd_vma) ((bfd_signed_vma) start - (long) irel->r_offset);
-
- if (start > addr
- && start < toaddr
- && (stop <= addr || stop >= toaddr))
- irel->r_offset += count;
- else if (stop > addr
- && stop < toaddr
- && (start <= addr || start >= toaddr))
- irel->r_offset -= count;
-
- start = stop;
-
- if (irel->r_type == R_SH_SWITCH16)
- voff = bfd_get_signed_16 (abfd, contents + nraddr);
- else if (irel->r_type == R_SH_SWITCH8)
- voff = bfd_get_8 (abfd, contents + nraddr);
- else
- voff = bfd_get_signed_32 (abfd, contents + nraddr);
- stop = (bfd_vma) ((bfd_signed_vma) start + voff);
-
- break;
-
- case R_SH_USES:
- start = irel->r_vaddr - sec->vma;
- stop = (bfd_vma) ((bfd_signed_vma) start
- + (long) irel->r_offset
- + 4);
- break;
- }
-
- if (start > addr
- && start < toaddr
- && (stop <= addr || stop >= toaddr))
- adjust = count;
- else if (stop > addr
- && stop < toaddr
- && (start <= addr || start >= toaddr))
- adjust = - count;
- else
- adjust = 0;
-
- if (adjust != 0)
- {
- oinsn = insn;
- overflow = false;
- switch (irel->r_type)
- {
- default:
- abort ();
- break;
-
- case R_SH_PCDISP8BY2:
- case R_SH_PCRELIMM8BY2:
- insn += adjust / 2;
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
- break;
-
- case R_SH_PCDISP:
- insn += adjust / 2;
- if ((oinsn & 0xf000) != (insn & 0xf000))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
- break;
-
- case R_SH_PCRELIMM8BY4:
- BFD_ASSERT (adjust == count || count >= 4);
- if (count >= 4)
- insn += adjust / 4;
- else
- {
- if ((irel->r_vaddr & 3) == 0)
- ++insn;
- }
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
- break;
-
- case R_SH_SWITCH8:
- voff += adjust;
- if (voff < 0 || voff >= 0xff)
- overflow = true;
- bfd_put_8 (abfd, (bfd_vma) voff, contents + nraddr);
- break;
-
- case R_SH_SWITCH16:
- voff += adjust;
- if (voff < - 0x8000 || voff >= 0x8000)
- overflow = true;
- bfd_put_signed_16 (abfd, (bfd_vma) voff, contents + nraddr);
- break;
-
- case R_SH_SWITCH32:
- voff += adjust;
- bfd_put_signed_32 (abfd, (bfd_vma) voff, contents + nraddr);
- break;
-
- case R_SH_USES:
- irel->r_offset += adjust;
- break;
- }
-
- if (overflow)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: fatal: reloc overflow while relaxing",
- bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
-
- irel->r_vaddr = nraddr + sec->vma;
- }
-
- /* Look through all the other sections. If there contain any IMM32
- relocs against internal symbols which we are not going to adjust
- below, we may need to adjust the addends. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- struct internal_reloc *internal_relocs;
- struct internal_reloc *irelscan, *irelscanend;
- bfd_byte *ocontents;
-
- if (o == sec
- || (o->flags & SEC_RELOC) == 0
- || o->reloc_count == 0)
- continue;
-
- /* We always cache the relocs. Perhaps, if info->keep_memory is
- false, we should free them, if we are permitted to, when we
- leave sh_coff_relax_section. */
- internal_relocs = (_bfd_coff_read_internal_relocs
- (abfd, o, true, (bfd_byte *) NULL, false,
- (struct internal_reloc *) NULL));
- if (internal_relocs == NULL)
- return false;
-
- ocontents = NULL;
- irelscanend = internal_relocs + o->reloc_count;
- for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
- {
- struct internal_syment sym;
-
-#ifdef COFF_WITH_PE
- if (irelscan->r_type != R_SH_IMM32
- && irelscan->r_type != R_SH_IMAGEBASE
- && irelscan->r_type != R_SH_IMM32CE)
-#else
- if (irelscan->r_type != R_SH_IMM32)
-#endif
- continue;
-
- bfd_coff_swap_sym_in (abfd,
- ((bfd_byte *) obj_coff_external_syms (abfd)
- + (irelscan->r_symndx
- * bfd_coff_symesz (abfd))),
- &sym);
- if (sym.n_sclass != C_EXT
- && sym.n_scnum == sec->target_index
- && ((bfd_vma) sym.n_value <= addr
- || (bfd_vma) sym.n_value >= toaddr))
- {
- bfd_vma val;
-
- if (ocontents == NULL)
- {
- if (coff_section_data (abfd, o)->contents != NULL)
- ocontents = coff_section_data (abfd, o)->contents;
- else
- {
- /* We always cache the section contents.
- Perhaps, if info->keep_memory is false, we
- should free them, if we are permitted to,
- when we leave sh_coff_relax_section. */
- ocontents = (bfd_byte *) bfd_malloc (o->_raw_size);
- if (ocontents == NULL)
- return false;
- if (! bfd_get_section_contents (abfd, o, ocontents,
- (file_ptr) 0,
- o->_raw_size))
- return false;
- coff_section_data (abfd, o)->contents = ocontents;
- }
- }
-
- val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
- val += sym.n_value;
- if (val > addr && val < toaddr)
- bfd_put_32 (abfd, val - count,
- ocontents + irelscan->r_vaddr - o->vma);
-
- coff_section_data (abfd, o)->keep_contents = true;
- }
- }
- }
-
- /* Adjusting the internal symbols will not work if something has
- already retrieved the generic symbols. It would be possible to
- make this work by adjusting the generic symbols at the same time.
- However, this case should not arise in normal usage. */
- if (obj_symbols (abfd) != NULL
- || obj_raw_syments (abfd) != NULL)
- {
- ((*_bfd_error_handler)
- ("%s: fatal: generic symbols retrieved before relaxing",
- bfd_archive_filename (abfd)));
- bfd_set_error (bfd_error_invalid_operation);
- return false;
- }
-
- /* Adjust all the symbols. */
- sym_hash = obj_coff_sym_hashes (abfd);
- symesz = bfd_coff_symesz (abfd);
- esym = (bfd_byte *) obj_coff_external_syms (abfd);
- esymend = esym + obj_raw_syment_count (abfd) * symesz;
- while (esym < esymend)
- {
- struct internal_syment isym;
-
- bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &isym);
-
- if (isym.n_scnum == sec->target_index
- && (bfd_vma) isym.n_value > addr
- && (bfd_vma) isym.n_value < toaddr)
- {
- isym.n_value -= count;
-
- bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
-
- if (*sym_hash != NULL)
- {
- BFD_ASSERT ((*sym_hash)->root.type == bfd_link_hash_defined
- || (*sym_hash)->root.type == bfd_link_hash_defweak);
- BFD_ASSERT ((*sym_hash)->root.u.def.value >= addr
- && (*sym_hash)->root.u.def.value < toaddr);
- (*sym_hash)->root.u.def.value -= count;
- }
- }
-
- esym += (isym.n_numaux + 1) * symesz;
- sym_hash += isym.n_numaux + 1;
- }
-
- /* See if we can move the ALIGN reloc forward. We have adjusted
- r_vaddr for it already. */
- if (irelalign != NULL)
- {
- bfd_vma alignto, alignaddr;
-
- alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_offset);
- alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
- 1 << irelalign->r_offset);
- if (alignto != alignaddr)
- {
- /* Tail recursion. */
- return sh_relax_delete_bytes (abfd, sec, alignaddr,
- (int) (alignto - alignaddr));
- }
- }
-
- return true;
-}
-
-/* This is yet another version of the SH opcode table, used to rapidly
- get information about a particular instruction. */
-
-/* The opcode map is represented by an array of these structures. The
- array is indexed by the high order four bits in the instruction. */
-
-struct sh_major_opcode
-{
- /* A pointer to the instruction list. This is an array which
- contains all the instructions with this major opcode. */
- const struct sh_minor_opcode *minor_opcodes;
- /* The number of elements in minor_opcodes. */
- unsigned short count;
-};
-
-/* This structure holds information for a set of SH opcodes. The
- instruction code is anded with the mask value, and the resulting
- value is used to search the order opcode list. */
-
-struct sh_minor_opcode
-{
- /* The sorted opcode list. */
- const struct sh_opcode *opcodes;
- /* The number of elements in opcodes. */
- unsigned short count;
- /* The mask value to use when searching the opcode list. */
- unsigned short mask;
-};
-
-/* This structure holds information for an SH instruction. An array
- of these structures is sorted in order by opcode. */
-
-struct sh_opcode
-{
- /* The code for this instruction, after it has been anded with the
- mask value in the sh_major_opcode structure. */
- unsigned short opcode;
- /* Flags for this instruction. */
- unsigned long flags;
-};
-
-/* Flag which appear in the sh_opcode structure. */
-
-/* This instruction loads a value from memory. */
-#define LOAD (0x1)
-
-/* This instruction stores a value to memory. */
-#define STORE (0x2)
-
-/* This instruction is a branch. */
-#define BRANCH (0x4)
-
-/* This instruction has a delay slot. */
-#define DELAY (0x8)
-
-/* This instruction uses the value in the register in the field at
- mask 0x0f00 of the instruction. */
-#define USES1 (0x10)
-#define USES1_REG(x) ((x & 0x0f00) >> 8)
-
-/* This instruction uses the value in the register in the field at
- mask 0x00f0 of the instruction. */
-#define USES2 (0x20)
-#define USES2_REG(x) ((x & 0x00f0) >> 4)
-
-/* This instruction uses the value in register 0. */
-#define USESR0 (0x40)
-
-/* This instruction sets the value in the register in the field at
- mask 0x0f00 of the instruction. */
-#define SETS1 (0x80)
-#define SETS1_REG(x) ((x & 0x0f00) >> 8)
-
-/* This instruction sets the value in the register in the field at
- mask 0x00f0 of the instruction. */
-#define SETS2 (0x100)
-#define SETS2_REG(x) ((x & 0x00f0) >> 4)
-
-/* This instruction sets register 0. */
-#define SETSR0 (0x200)
-
-/* This instruction sets a special register. */
-#define SETSSP (0x400)
-
-/* This instruction uses a special register. */
-#define USESSP (0x800)
-
-/* This instruction uses the floating point register in the field at
- mask 0x0f00 of the instruction. */
-#define USESF1 (0x1000)
-#define USESF1_REG(x) ((x & 0x0f00) >> 8)
-
-/* This instruction uses the floating point register in the field at
- mask 0x00f0 of the instruction. */
-#define USESF2 (0x2000)
-#define USESF2_REG(x) ((x & 0x00f0) >> 4)
-
-/* This instruction uses floating point register 0. */
-#define USESF0 (0x4000)
-
-/* This instruction sets the floating point register in the field at
- mask 0x0f00 of the instruction. */
-#define SETSF1 (0x8000)
-#define SETSF1_REG(x) ((x & 0x0f00) >> 8)
-
-#define USESAS (0x10000)
-#define USESAS_REG(x) (((((x) >> 8) - 2) & 3) + 2)
-#define USESR8 (0x20000)
-#define SETSAS (0x40000)
-#define SETSAS_REG(x) USESAS_REG (x)
-
-#ifndef COFF_IMAGE_WITH_PE
-static boolean sh_insn_uses_reg
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
-static boolean sh_insn_sets_reg
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
-static boolean sh_insn_uses_or_sets_reg
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
-static boolean sh_insn_uses_freg
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
-static boolean sh_insn_sets_freg
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
-static boolean sh_insn_uses_or_sets_freg
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
-static boolean sh_insns_conflict
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
- const struct sh_opcode *));
-static boolean sh_load_use
- PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
- const struct sh_opcode *));
-#endif
-/* The opcode maps. */
-
-#define MAP(a) a, sizeof a / sizeof a[0]
-
-static const struct sh_opcode sh_opcode00[] =
-{
- { 0x0008, SETSSP }, /* clrt */
- { 0x0009, 0 }, /* nop */
- { 0x000b, BRANCH | DELAY | USESSP }, /* rts */
- { 0x0018, SETSSP }, /* sett */
- { 0x0019, SETSSP }, /* div0u */
- { 0x001b, 0 }, /* sleep */
- { 0x0028, SETSSP }, /* clrmac */
- { 0x002b, BRANCH | DELAY | SETSSP }, /* rte */
- { 0x0038, USESSP | SETSSP }, /* ldtlb */
- { 0x0048, SETSSP }, /* clrs */
- { 0x0058, SETSSP } /* sets */
-};
-
-static const struct sh_opcode sh_opcode01[] =
-{
- { 0x0003, BRANCH | DELAY | USES1 | SETSSP }, /* bsrf rn */
- { 0x000a, SETS1 | USESSP }, /* sts mach,rn */
- { 0x001a, SETS1 | USESSP }, /* sts macl,rn */
- { 0x0023, BRANCH | DELAY | USES1 }, /* braf rn */
- { 0x0029, SETS1 | USESSP }, /* movt rn */
- { 0x002a, SETS1 | USESSP }, /* sts pr,rn */
- { 0x005a, SETS1 | USESSP }, /* sts fpul,rn */
- { 0x006a, SETS1 | USESSP }, /* sts fpscr,rn / sts dsr,rn */
- { 0x0083, LOAD | USES1 }, /* pref @rn */
- { 0x007a, SETS1 | USESSP }, /* sts a0,rn */
- { 0x008a, SETS1 | USESSP }, /* sts x0,rn */
- { 0x009a, SETS1 | USESSP }, /* sts x1,rn */
- { 0x00aa, SETS1 | USESSP }, /* sts y0,rn */
- { 0x00ba, SETS1 | USESSP } /* sts y1,rn */
-};
-
-/* These sixteen instructions can be handled with one table entry below. */
-#if 0
- { 0x0002, SETS1 | USESSP }, /* stc sr,rn */
- { 0x0012, SETS1 | USESSP }, /* stc gbr,rn */
- { 0x0022, SETS1 | USESSP }, /* stc vbr,rn */
- { 0x0032, SETS1 | USESSP }, /* stc ssr,rn */
- { 0x0042, SETS1 | USESSP }, /* stc spc,rn */
- { 0x0052, SETS1 | USESSP }, /* stc mod,rn */
- { 0x0062, SETS1 | USESSP }, /* stc rs,rn */
- { 0x0072, SETS1 | USESSP }, /* stc re,rn */
- { 0x0082, SETS1 | USESSP }, /* stc r0_bank,rn */
- { 0x0092, SETS1 | USESSP }, /* stc r1_bank,rn */
- { 0x00a2, SETS1 | USESSP }, /* stc r2_bank,rn */
- { 0x00b2, SETS1 | USESSP }, /* stc r3_bank,rn */
- { 0x00c2, SETS1 | USESSP }, /* stc r4_bank,rn */
- { 0x00d2, SETS1 | USESSP }, /* stc r5_bank,rn */
- { 0x00e2, SETS1 | USESSP }, /* stc r6_bank,rn */
- { 0x00f2, SETS1 | USESSP } /* stc r7_bank,rn */
-#endif
-
-static const struct sh_opcode sh_opcode02[] =
-{
- { 0x0002, SETS1 | USESSP }, /* stc <special_reg>,rn */
- { 0x0004, STORE | USES1 | USES2 | USESR0 }, /* mov.b rm,@(r0,rn) */
- { 0x0005, STORE | USES1 | USES2 | USESR0 }, /* mov.w rm,@(r0,rn) */
- { 0x0006, STORE | USES1 | USES2 | USESR0 }, /* mov.l rm,@(r0,rn) */
- { 0x0007, SETSSP | USES1 | USES2 }, /* mul.l rm,rn */
- { 0x000c, LOAD | SETS1 | USES2 | USESR0 }, /* mov.b @(r0,rm),rn */
- { 0x000d, LOAD | SETS1 | USES2 | USESR0 }, /* mov.w @(r0,rm),rn */
- { 0x000e, LOAD | SETS1 | USES2 | USESR0 }, /* mov.l @(r0,rm),rn */
- { 0x000f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP }, /* mac.l @rm+,@rn+ */
-};
-
-static const struct sh_minor_opcode sh_opcode0[] =
-{
- { MAP (sh_opcode00), 0xffff },
- { MAP (sh_opcode01), 0xf0ff },
- { MAP (sh_opcode02), 0xf00f }
-};
-
-static const struct sh_opcode sh_opcode10[] =
-{
- { 0x1000, STORE | USES1 | USES2 } /* mov.l rm,@(disp,rn) */
-};
-
-static const struct sh_minor_opcode sh_opcode1[] =
-{
- { MAP (sh_opcode10), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcode20[] =
-{
- { 0x2000, STORE | USES1 | USES2 }, /* mov.b rm,@rn */
- { 0x2001, STORE | USES1 | USES2 }, /* mov.w rm,@rn */
- { 0x2002, STORE | USES1 | USES2 }, /* mov.l rm,@rn */
- { 0x2004, STORE | SETS1 | USES1 | USES2 }, /* mov.b rm,@-rn */
- { 0x2005, STORE | SETS1 | USES1 | USES2 }, /* mov.w rm,@-rn */
- { 0x2006, STORE | SETS1 | USES1 | USES2 }, /* mov.l rm,@-rn */
- { 0x2007, SETSSP | USES1 | USES2 | USESSP }, /* div0s */
- { 0x2008, SETSSP | USES1 | USES2 }, /* tst rm,rn */
- { 0x2009, SETS1 | USES1 | USES2 }, /* and rm,rn */
- { 0x200a, SETS1 | USES1 | USES2 }, /* xor rm,rn */
- { 0x200b, SETS1 | USES1 | USES2 }, /* or rm,rn */
- { 0x200c, SETSSP | USES1 | USES2 }, /* cmp/str rm,rn */
- { 0x200d, SETS1 | USES1 | USES2 }, /* xtrct rm,rn */
- { 0x200e, SETSSP | USES1 | USES2 }, /* mulu.w rm,rn */
- { 0x200f, SETSSP | USES1 | USES2 } /* muls.w rm,rn */
-};
-
-static const struct sh_minor_opcode sh_opcode2[] =
-{
- { MAP (sh_opcode20), 0xf00f }
-};
-
-static const struct sh_opcode sh_opcode30[] =
-{
- { 0x3000, SETSSP | USES1 | USES2 }, /* cmp/eq rm,rn */
- { 0x3002, SETSSP | USES1 | USES2 }, /* cmp/hs rm,rn */
- { 0x3003, SETSSP | USES1 | USES2 }, /* cmp/ge rm,rn */
- { 0x3004, SETSSP | USESSP | USES1 | USES2 }, /* div1 rm,rn */
- { 0x3005, SETSSP | USES1 | USES2 }, /* dmulu.l rm,rn */
- { 0x3006, SETSSP | USES1 | USES2 }, /* cmp/hi rm,rn */
- { 0x3007, SETSSP | USES1 | USES2 }, /* cmp/gt rm,rn */
- { 0x3008, SETS1 | USES1 | USES2 }, /* sub rm,rn */
- { 0x300a, SETS1 | SETSSP | USES1 | USES2 | USESSP }, /* subc rm,rn */
- { 0x300b, SETS1 | SETSSP | USES1 | USES2 }, /* subv rm,rn */
- { 0x300c, SETS1 | USES1 | USES2 }, /* add rm,rn */
- { 0x300d, SETSSP | USES1 | USES2 }, /* dmuls.l rm,rn */
- { 0x300e, SETS1 | SETSSP | USES1 | USES2 | USESSP }, /* addc rm,rn */
- { 0x300f, SETS1 | SETSSP | USES1 | USES2 } /* addv rm,rn */
-};
-
-static const struct sh_minor_opcode sh_opcode3[] =
-{
- { MAP (sh_opcode30), 0xf00f }
-};
-
-static const struct sh_opcode sh_opcode40[] =
-{
- { 0x4000, SETS1 | SETSSP | USES1 }, /* shll rn */
- { 0x4001, SETS1 | SETSSP | USES1 }, /* shlr rn */
- { 0x4002, STORE | SETS1 | USES1 | USESSP }, /* sts.l mach,@-rn */
- { 0x4004, SETS1 | SETSSP | USES1 }, /* rotl rn */
- { 0x4005, SETS1 | SETSSP | USES1 }, /* rotr rn */
- { 0x4006, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,mach */
- { 0x4008, SETS1 | USES1 }, /* shll2 rn */
- { 0x4009, SETS1 | USES1 }, /* shlr2 rn */
- { 0x400a, SETSSP | USES1 }, /* lds rm,mach */
- { 0x400b, BRANCH | DELAY | USES1 }, /* jsr @rn */
- { 0x4010, SETS1 | SETSSP | USES1 }, /* dt rn */
- { 0x4011, SETSSP | USES1 }, /* cmp/pz rn */
- { 0x4012, STORE | SETS1 | USES1 | USESSP }, /* sts.l macl,@-rn */
- { 0x4014, SETSSP | USES1 }, /* setrc rm */
- { 0x4015, SETSSP | USES1 }, /* cmp/pl rn */
- { 0x4016, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,macl */
- { 0x4018, SETS1 | USES1 }, /* shll8 rn */
- { 0x4019, SETS1 | USES1 }, /* shlr8 rn */
- { 0x401a, SETSSP | USES1 }, /* lds rm,macl */
- { 0x401b, LOAD | SETSSP | USES1 }, /* tas.b @rn */
- { 0x4020, SETS1 | SETSSP | USES1 }, /* shal rn */
- { 0x4021, SETS1 | SETSSP | USES1 }, /* shar rn */
- { 0x4022, STORE | SETS1 | USES1 | USESSP }, /* sts.l pr,@-rn */
- { 0x4024, SETS1 | SETSSP | USES1 | USESSP }, /* rotcl rn */
- { 0x4025, SETS1 | SETSSP | USES1 | USESSP }, /* rotcr rn */
- { 0x4026, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,pr */
- { 0x4028, SETS1 | USES1 }, /* shll16 rn */
- { 0x4029, SETS1 | USES1 }, /* shlr16 rn */
- { 0x402a, SETSSP | USES1 }, /* lds rm,pr */
- { 0x402b, BRANCH | DELAY | USES1 }, /* jmp @rn */
- { 0x4052, STORE | SETS1 | USES1 | USESSP }, /* sts.l fpul,@-rn */
- { 0x4056, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,fpul */
- { 0x405a, SETSSP | USES1 }, /* lds.l rm,fpul */
- { 0x4062, STORE | SETS1 | USES1 | USESSP }, /* sts.l fpscr / dsr,@-rn */
- { 0x4066, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,fpscr / dsr */
- { 0x406a, SETSSP | USES1 }, /* lds rm,fpscr / lds rm,dsr */
- { 0x4072, STORE | SETS1 | USES1 | USESSP }, /* sts.l a0,@-rn */
- { 0x4076, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,a0 */
- { 0x407a, SETSSP | USES1 }, /* lds.l rm,a0 */
- { 0x4082, STORE | SETS1 | USES1 | USESSP }, /* sts.l x0,@-rn */
- { 0x4086, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,x0 */
- { 0x408a, SETSSP | USES1 }, /* lds.l rm,x0 */
- { 0x4092, STORE | SETS1 | USES1 | USESSP }, /* sts.l x1,@-rn */
- { 0x4096, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,x1 */
- { 0x409a, SETSSP | USES1 }, /* lds.l rm,x1 */
- { 0x40a2, STORE | SETS1 | USES1 | USESSP }, /* sts.l y0,@-rn */
- { 0x40a6, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,y0 */
- { 0x40aa, SETSSP | USES1 }, /* lds.l rm,y0 */
- { 0x40b2, STORE | SETS1 | USES1 | USESSP }, /* sts.l y1,@-rn */
- { 0x40b6, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,y1 */
- { 0x40ba, SETSSP | USES1 } /* lds.l rm,y1 */
-#if 0 /* These groups sixteen insns can be
- handled with one table entry each below. */
- { 0x4003, STORE | SETS1 | USES1 | USESSP }, /* stc.l sr,@-rn */
- { 0x4013, STORE | SETS1 | USES1 | USESSP }, /* stc.l gbr,@-rn */
- { 0x4023, STORE | SETS1 | USES1 | USESSP }, /* stc.l vbr,@-rn */
- { 0x4033, STORE | SETS1 | USES1 | USESSP }, /* stc.l ssr,@-rn */
- { 0x4043, STORE | SETS1 | USES1 | USESSP }, /* stc.l spc,@-rn */
- { 0x4053, STORE | SETS1 | USES1 | USESSP }, /* stc.l mod,@-rn */
- { 0x4063, STORE | SETS1 | USES1 | USESSP }, /* stc.l rs,@-rn */
- { 0x4073, STORE | SETS1 | USES1 | USESSP }, /* stc.l re,@-rn */
- { 0x4083, STORE | SETS1 | USES1 | USESSP }, /* stc.l r0_bank,@-rn */
- ..
- { 0x40f3, STORE | SETS1 | USES1 | USESSP }, /* stc.l r7_bank,@-rn */
-
- { 0x4007, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,sr */
- { 0x4017, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,gbr */
- { 0x4027, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,vbr */
- { 0x4037, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,ssr */
- { 0x4047, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,spc */
- { 0x4057, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,mod */
- { 0x4067, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,rs */
- { 0x4077, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,re */
- { 0x4087, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,r0_bank */
- ..
- { 0x40f7, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,r7_bank */
-
- { 0x400e, SETSSP | USES1 }, /* ldc rm,sr */
- { 0x401e, SETSSP | USES1 }, /* ldc rm,gbr */
- { 0x402e, SETSSP | USES1 }, /* ldc rm,vbr */
- { 0x403e, SETSSP | USES1 }, /* ldc rm,ssr */
- { 0x404e, SETSSP | USES1 }, /* ldc rm,spc */
- { 0x405e, SETSSP | USES1 }, /* ldc rm,mod */
- { 0x406e, SETSSP | USES1 }, /* ldc rm,rs */
- { 0x407e, SETSSP | USES1 } /* ldc rm,re */
- { 0x408e, SETSSP | USES1 } /* ldc rm,r0_bank */
- ..
- { 0x40fe, SETSSP | USES1 } /* ldc rm,r7_bank */
-#endif
-};
-
-static const struct sh_opcode sh_opcode41[] =
-{
- { 0x4003, STORE | SETS1 | USES1 | USESSP }, /* stc.l <special_reg>,@-rn */
- { 0x4007, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,<special_reg> */
- { 0x400c, SETS1 | USES1 | USES2 }, /* shad rm,rn */
- { 0x400d, SETS1 | USES1 | USES2 }, /* shld rm,rn */
- { 0x400e, SETSSP | USES1 }, /* ldc rm,<special_reg> */
- { 0x400f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP }, /* mac.w @rm+,@rn+ */
-};
-
-static const struct sh_minor_opcode sh_opcode4[] =
-{
- { MAP (sh_opcode40), 0xf0ff },
- { MAP (sh_opcode41), 0xf00f }
-};
-
-static const struct sh_opcode sh_opcode50[] =
-{
- { 0x5000, LOAD | SETS1 | USES2 } /* mov.l @(disp,rm),rn */
-};
-
-static const struct sh_minor_opcode sh_opcode5[] =
-{
- { MAP (sh_opcode50), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcode60[] =
-{
- { 0x6000, LOAD | SETS1 | USES2 }, /* mov.b @rm,rn */
- { 0x6001, LOAD | SETS1 | USES2 }, /* mov.w @rm,rn */
- { 0x6002, LOAD | SETS1 | USES2 }, /* mov.l @rm,rn */
- { 0x6003, SETS1 | USES2 }, /* mov rm,rn */
- { 0x6004, LOAD | SETS1 | SETS2 | USES2 }, /* mov.b @rm+,rn */
- { 0x6005, LOAD | SETS1 | SETS2 | USES2 }, /* mov.w @rm+,rn */
- { 0x6006, LOAD | SETS1 | SETS2 | USES2 }, /* mov.l @rm+,rn */
- { 0x6007, SETS1 | USES2 }, /* not rm,rn */
- { 0x6008, SETS1 | USES2 }, /* swap.b rm,rn */
- { 0x6009, SETS1 | USES2 }, /* swap.w rm,rn */
- { 0x600a, SETS1 | SETSSP | USES2 | USESSP }, /* negc rm,rn */
- { 0x600b, SETS1 | USES2 }, /* neg rm,rn */
- { 0x600c, SETS1 | USES2 }, /* extu.b rm,rn */
- { 0x600d, SETS1 | USES2 }, /* extu.w rm,rn */
- { 0x600e, SETS1 | USES2 }, /* exts.b rm,rn */
- { 0x600f, SETS1 | USES2 } /* exts.w rm,rn */
-};
-
-static const struct sh_minor_opcode sh_opcode6[] =
-{
- { MAP (sh_opcode60), 0xf00f }
-};
-
-static const struct sh_opcode sh_opcode70[] =
-{
- { 0x7000, SETS1 | USES1 } /* add #imm,rn */
-};
-
-static const struct sh_minor_opcode sh_opcode7[] =
-{
- { MAP (sh_opcode70), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcode80[] =
-{
- { 0x8000, STORE | USES2 | USESR0 }, /* mov.b r0,@(disp,rn) */
- { 0x8100, STORE | USES2 | USESR0 }, /* mov.w r0,@(disp,rn) */
- { 0x8200, SETSSP }, /* setrc #imm */
- { 0x8400, LOAD | SETSR0 | USES2 }, /* mov.b @(disp,rm),r0 */
- { 0x8500, LOAD | SETSR0 | USES2 }, /* mov.w @(disp,rn),r0 */
- { 0x8800, SETSSP | USESR0 }, /* cmp/eq #imm,r0 */
- { 0x8900, BRANCH | USESSP }, /* bt label */
- { 0x8b00, BRANCH | USESSP }, /* bf label */
- { 0x8c00, SETSSP }, /* ldrs @(disp,pc) */
- { 0x8d00, BRANCH | DELAY | USESSP }, /* bt/s label */
- { 0x8e00, SETSSP }, /* ldre @(disp,pc) */
- { 0x8f00, BRANCH | DELAY | USESSP } /* bf/s label */
-};
-
-static const struct sh_minor_opcode sh_opcode8[] =
-{
- { MAP (sh_opcode80), 0xff00 }
-};
-
-static const struct sh_opcode sh_opcode90[] =
-{
- { 0x9000, LOAD | SETS1 } /* mov.w @(disp,pc),rn */
-};
-
-static const struct sh_minor_opcode sh_opcode9[] =
-{
- { MAP (sh_opcode90), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcodea0[] =
-{
- { 0xa000, BRANCH | DELAY } /* bra label */
-};
-
-static const struct sh_minor_opcode sh_opcodea[] =
-{
- { MAP (sh_opcodea0), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcodeb0[] =
-{
- { 0xb000, BRANCH | DELAY } /* bsr label */
-};
-
-static const struct sh_minor_opcode sh_opcodeb[] =
-{
- { MAP (sh_opcodeb0), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcodec0[] =
-{
- { 0xc000, STORE | USESR0 | USESSP }, /* mov.b r0,@(disp,gbr) */
- { 0xc100, STORE | USESR0 | USESSP }, /* mov.w r0,@(disp,gbr) */
- { 0xc200, STORE | USESR0 | USESSP }, /* mov.l r0,@(disp,gbr) */
- { 0xc300, BRANCH | USESSP }, /* trapa #imm */
- { 0xc400, LOAD | SETSR0 | USESSP }, /* mov.b @(disp,gbr),r0 */
- { 0xc500, LOAD | SETSR0 | USESSP }, /* mov.w @(disp,gbr),r0 */
- { 0xc600, LOAD | SETSR0 | USESSP }, /* mov.l @(disp,gbr),r0 */
- { 0xc700, SETSR0 }, /* mova @(disp,pc),r0 */
- { 0xc800, SETSSP | USESR0 }, /* tst #imm,r0 */
- { 0xc900, SETSR0 | USESR0 }, /* and #imm,r0 */
- { 0xca00, SETSR0 | USESR0 }, /* xor #imm,r0 */
- { 0xcb00, SETSR0 | USESR0 }, /* or #imm,r0 */
- { 0xcc00, LOAD | SETSSP | USESR0 | USESSP }, /* tst.b #imm,@(r0,gbr) */
- { 0xcd00, LOAD | STORE | USESR0 | USESSP }, /* and.b #imm,@(r0,gbr) */
- { 0xce00, LOAD | STORE | USESR0 | USESSP }, /* xor.b #imm,@(r0,gbr) */
- { 0xcf00, LOAD | STORE | USESR0 | USESSP } /* or.b #imm,@(r0,gbr) */
-};
-
-static const struct sh_minor_opcode sh_opcodec[] =
-{
- { MAP (sh_opcodec0), 0xff00 }
-};
-
-static const struct sh_opcode sh_opcoded0[] =
-{
- { 0xd000, LOAD | SETS1 } /* mov.l @(disp,pc),rn */
-};
-
-static const struct sh_minor_opcode sh_opcoded[] =
-{
- { MAP (sh_opcoded0), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcodee0[] =
-{
- { 0xe000, SETS1 } /* mov #imm,rn */
-};
-
-static const struct sh_minor_opcode sh_opcodee[] =
-{
- { MAP (sh_opcodee0), 0xf000 }
-};
-
-static const struct sh_opcode sh_opcodef0[] =
-{
- { 0xf000, SETSF1 | USESF1 | USESF2 }, /* fadd fm,fn */
- { 0xf001, SETSF1 | USESF1 | USESF2 }, /* fsub fm,fn */
- { 0xf002, SETSF1 | USESF1 | USESF2 }, /* fmul fm,fn */
- { 0xf003, SETSF1 | USESF1 | USESF2 }, /* fdiv fm,fn */
- { 0xf004, SETSSP | USESF1 | USESF2 }, /* fcmp/eq fm,fn */
- { 0xf005, SETSSP | USESF1 | USESF2 }, /* fcmp/gt fm,fn */
- { 0xf006, LOAD | SETSF1 | USES2 | USESR0 }, /* fmov.s @(r0,rm),fn */
- { 0xf007, STORE | USES1 | USESF2 | USESR0 }, /* fmov.s fm,@(r0,rn) */
- { 0xf008, LOAD | SETSF1 | USES2 }, /* fmov.s @rm,fn */
- { 0xf009, LOAD | SETS2 | SETSF1 | USES2 }, /* fmov.s @rm+,fn */
- { 0xf00a, STORE | USES1 | USESF2 }, /* fmov.s fm,@rn */
- { 0xf00b, STORE | SETS1 | USES1 | USESF2 }, /* fmov.s fm,@-rn */
- { 0xf00c, SETSF1 | USESF2 }, /* fmov fm,fn */
- { 0xf00e, SETSF1 | USESF1 | USESF2 | USESF0 } /* fmac f0,fm,fn */
-};
-
-static const struct sh_opcode sh_opcodef1[] =
-{
- { 0xf00d, SETSF1 | USESSP }, /* fsts fpul,fn */
- { 0xf01d, SETSSP | USESF1 }, /* flds fn,fpul */
- { 0xf02d, SETSF1 | USESSP }, /* float fpul,fn */
- { 0xf03d, SETSSP | USESF1 }, /* ftrc fn,fpul */
- { 0xf04d, SETSF1 | USESF1 }, /* fneg fn */
- { 0xf05d, SETSF1 | USESF1 }, /* fabs fn */
- { 0xf06d, SETSF1 | USESF1 }, /* fsqrt fn */
- { 0xf07d, SETSSP | USESF1 }, /* ftst/nan fn */
- { 0xf08d, SETSF1 }, /* fldi0 fn */
- { 0xf09d, SETSF1 } /* fldi1 fn */
-};
-
-static const struct sh_minor_opcode sh_opcodef[] =
-{
- { MAP (sh_opcodef0), 0xf00f },
- { MAP (sh_opcodef1), 0xf0ff }
-};
-
-#ifndef COFF_IMAGE_WITH_PE
-static struct sh_major_opcode sh_opcodes[] =
-{
- { MAP (sh_opcode0) },
- { MAP (sh_opcode1) },
- { MAP (sh_opcode2) },
- { MAP (sh_opcode3) },
- { MAP (sh_opcode4) },
- { MAP (sh_opcode5) },
- { MAP (sh_opcode6) },
- { MAP (sh_opcode7) },
- { MAP (sh_opcode8) },
- { MAP (sh_opcode9) },
- { MAP (sh_opcodea) },
- { MAP (sh_opcodeb) },
- { MAP (sh_opcodec) },
- { MAP (sh_opcoded) },
- { MAP (sh_opcodee) },
- { MAP (sh_opcodef) }
-};
-#endif
-
-/* The double data transfer / parallel processing insns are not
- described here. This will cause sh_align_load_span to leave them alone. */
-
-static const struct sh_opcode sh_dsp_opcodef0[] =
-{
- { 0xf400, USESAS | SETSAS | LOAD | SETSSP }, /* movs.x @-as,ds */
- { 0xf401, USESAS | SETSAS | STORE | USESSP }, /* movs.x ds,@-as */
- { 0xf404, USESAS | LOAD | SETSSP }, /* movs.x @as,ds */
- { 0xf405, USESAS | STORE | USESSP }, /* movs.x ds,@as */
- { 0xf408, USESAS | SETSAS | LOAD | SETSSP }, /* movs.x @as+,ds */
- { 0xf409, USESAS | SETSAS | STORE | USESSP }, /* movs.x ds,@as+ */
- { 0xf40c, USESAS | SETSAS | LOAD | SETSSP | USESR8 }, /* movs.x @as+r8,ds */
- { 0xf40d, USESAS | SETSAS | STORE | USESSP | USESR8 } /* movs.x ds,@as+r8 */
-};
-
-static const struct sh_minor_opcode sh_dsp_opcodef[] =
-{
- { MAP (sh_dsp_opcodef0), 0xfc0d }
-};
-
-#ifndef COFF_IMAGE_WITH_PE
-/* Given an instruction, return a pointer to the corresponding
- sh_opcode structure. Return NULL if the instruction is not
- recognized. */
-
-static const struct sh_opcode *
-sh_insn_info (insn)
- unsigned int insn;
-{
- const struct sh_major_opcode *maj;
- const struct sh_minor_opcode *min, *minend;
-
- maj = &sh_opcodes[(insn & 0xf000) >> 12];
- min = maj->minor_opcodes;
- minend = min + maj->count;
- for (; min < minend; min++)
- {
- unsigned int l;
- const struct sh_opcode *op, *opend;
-
- l = insn & min->mask;
- op = min->opcodes;
- opend = op + min->count;
-
- /* Since the opcodes tables are sorted, we could use a binary
- search here if the count were above some cutoff value. */
- for (; op < opend; op++)
- if (op->opcode == l)
- return op;
- }
-
- return NULL;
-}
-
-/* See whether an instruction uses or sets a general purpose register */
-
-static boolean
-sh_insn_uses_or_sets_reg (insn, op, reg)
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int reg;
-{
- if (sh_insn_uses_reg (insn, op, reg))
- return true;
-
- return sh_insn_sets_reg (insn, op, reg);
-}
-
-/* See whether an instruction uses a general purpose register. */
-
-static boolean
-sh_insn_uses_reg (insn, op, reg)
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int reg;
-{
- unsigned int f;
-
- f = op->flags;
-
- if ((f & USES1) != 0
- && USES1_REG (insn) == reg)
- return true;
- if ((f & USES2) != 0
- && USES2_REG (insn) == reg)
- return true;
- if ((f & USESR0) != 0
- && reg == 0)
- return true;
- if ((f & USESAS) && reg == USESAS_REG (insn))
- return true;
- if ((f & USESR8) && reg == 8)
- return true;
-
- return false;
-}
-
-/* See whether an instruction sets a general purpose register. */
-
-static boolean
-sh_insn_sets_reg (insn, op, reg)
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int reg;
-{
- unsigned int f;
-
- f = op->flags;
-
- if ((f & SETS1) != 0
- && SETS1_REG (insn) == reg)
- return true;
- if ((f & SETS2) != 0
- && SETS2_REG (insn) == reg)
- return true;
- if ((f & SETSR0) != 0
- && reg == 0)
- return true;
- if ((f & SETSAS) && reg == SETSAS_REG (insn))
- return true;
-
- return false;
-}
-
-/* See whether an instruction uses or sets a floating point register */
-
-static boolean
-sh_insn_uses_or_sets_freg (insn, op, reg)
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int reg;
-{
- if (sh_insn_uses_freg (insn, op, reg))
- return true;
-
- return sh_insn_sets_freg (insn, op, reg);
-}
-
-/* See whether an instruction uses a floating point register. */
-
-static boolean
-sh_insn_uses_freg (insn, op, freg)
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int freg;
-{
- unsigned int f;
-
- f = op->flags;
-
- /* We can't tell if this is a double-precision insn, so just play safe
- and assume that it might be. So not only have we test FREG against
- itself, but also even FREG against FREG+1 - if the using insn uses
- just the low part of a double precision value - but also an odd
- FREG against FREG-1 - if the setting insn sets just the low part
- of a double precision value.
- So what this all boils down to is that we have to ignore the lowest
- bit of the register number. */
-
- if ((f & USESF1) != 0
- && (USESF1_REG (insn) & 0xe) == (freg & 0xe))
- return true;
- if ((f & USESF2) != 0
- && (USESF2_REG (insn) & 0xe) == (freg & 0xe))
- return true;
- if ((f & USESF0) != 0
- && freg == 0)
- return true;
-
- return false;
-}
-
-/* See whether an instruction sets a floating point register. */
-
-static boolean
-sh_insn_sets_freg (insn, op, freg)
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int freg;
-{
- unsigned int f;
-
- f = op->flags;
-
- /* We can't tell if this is a double-precision insn, so just play safe
- and assume that it might be. So not only have we test FREG against
- itself, but also even FREG against FREG+1 - if the using insn uses
- just the low part of a double precision value - but also an odd
- FREG against FREG-1 - if the setting insn sets just the low part
- of a double precision value.
- So what this all boils down to is that we have to ignore the lowest
- bit of the register number. */
-
- if ((f & SETSF1) != 0
- && (SETSF1_REG (insn) & 0xe) == (freg & 0xe))
- return true;
-
- return false;
-}
-
-/* See whether instructions I1 and I2 conflict, assuming I1 comes
- before I2. OP1 and OP2 are the corresponding sh_opcode structures.
- This should return true if there is a conflict, or false if the
- instructions can be swapped safely. */
-
-static boolean
-sh_insns_conflict (i1, op1, i2, op2)
- unsigned int i1;
- const struct sh_opcode *op1;
- unsigned int i2;
- const struct sh_opcode *op2;
-{
- unsigned int f1, f2;
-
- f1 = op1->flags;
- f2 = op2->flags;
-
- /* Load of fpscr conflicts with floating point operations.
- FIXME: shouldn't test raw opcodes here. */
- if (((i1 & 0xf0ff) == 0x4066 && (i2 & 0xf000) == 0xf000)
- || ((i2 & 0xf0ff) == 0x4066 && (i1 & 0xf000) == 0xf000))
- return true;
-
- if ((f1 & (BRANCH | DELAY)) != 0
- || (f2 & (BRANCH | DELAY)) != 0)
- return true;
-
- if (((f1 | f2) & SETSSP)
- && (f1 & (SETSSP | USESSP))
- && (f2 & (SETSSP | USESSP)))
- return true;
-
- if ((f1 & SETS1) != 0
- && sh_insn_uses_or_sets_reg (i2, op2, SETS1_REG (i1)))
- return true;
- if ((f1 & SETS2) != 0
- && sh_insn_uses_or_sets_reg (i2, op2, SETS2_REG (i1)))
- return true;
- if ((f1 & SETSR0) != 0
- && sh_insn_uses_or_sets_reg (i2, op2, 0))
- return true;
- if ((f1 & SETSAS)
- && sh_insn_uses_or_sets_reg (i2, op2, SETSAS_REG (i1)))
- return true;
- if ((f1 & SETSF1) != 0
- && sh_insn_uses_or_sets_freg (i2, op2, SETSF1_REG (i1)))
- return true;
-
- if ((f2 & SETS1) != 0
- && sh_insn_uses_or_sets_reg (i1, op1, SETS1_REG (i2)))
- return true;
- if ((f2 & SETS2) != 0
- && sh_insn_uses_or_sets_reg (i1, op1, SETS2_REG (i2)))
- return true;
- if ((f2 & SETSR0) != 0
- && sh_insn_uses_or_sets_reg (i1, op1, 0))
- return true;
- if ((f2 & SETSAS)
- && sh_insn_uses_or_sets_reg (i1, op1, SETSAS_REG (i2)))
- return true;
- if ((f2 & SETSF1) != 0
- && sh_insn_uses_or_sets_freg (i1, op1, SETSF1_REG (i2)))
- return true;
-
- /* The instructions do not conflict. */
- return false;
-}
-
-/* I1 is a load instruction, and I2 is some other instruction. Return
- true if I1 loads a register which I2 uses. */
-
-static boolean
-sh_load_use (i1, op1, i2, op2)
- unsigned int i1;
- const struct sh_opcode *op1;
- unsigned int i2;
- const struct sh_opcode *op2;
-{
- unsigned int f1;
-
- f1 = op1->flags;
-
- if ((f1 & LOAD) == 0)
- return false;
-
- /* If both SETS1 and SETSSP are set, that means a load to a special
- register using postincrement addressing mode, which we don't care
- about here. */
- if ((f1 & SETS1) != 0
- && (f1 & SETSSP) == 0
- && sh_insn_uses_reg (i2, op2, (i1 & 0x0f00) >> 8))
- return true;
-
- if ((f1 & SETSR0) != 0
- && sh_insn_uses_reg (i2, op2, 0))
- return true;
-
- if ((f1 & SETSF1) != 0
- && sh_insn_uses_freg (i2, op2, (i1 & 0x0f00) >> 8))
- return true;
-
- return false;
-}
-
-/* Try to align loads and stores within a span of memory. This is
- called by both the ELF and the COFF sh targets. ABFD and SEC are
- the BFD and section we are examining. CONTENTS is the contents of
- the section. SWAP is the routine to call to swap two instructions.
- RELOCS is a pointer to the internal relocation information, to be
- passed to SWAP. PLABEL is a pointer to the current label in a
- sorted list of labels; LABEL_END is the end of the list. START and
- STOP are the range of memory to examine. If a swap is made,
- *PSWAPPED is set to true. */
-
-#ifdef COFF_WITH_PE
-static
-#endif
-boolean
-_bfd_sh_align_load_span (abfd, sec, contents, swap, relocs,
- plabel, label_end, start, stop, pswapped)
- bfd *abfd;
- asection *sec;
- bfd_byte *contents;
- boolean (*swap) PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
- PTR relocs;
- bfd_vma **plabel;
- bfd_vma *label_end;
- bfd_vma start;
- bfd_vma stop;
- boolean *pswapped;
-{
- int dsp = (abfd->arch_info->mach == bfd_mach_sh_dsp
- || abfd->arch_info->mach == bfd_mach_sh3_dsp);
- bfd_vma i;
-
- /* The SH4 has a Harvard architecture, hence aligning loads is not
- desirable. In fact, it is counter-productive, since it interferes
- with the schedules generated by the compiler. */
- if (abfd->arch_info->mach == bfd_mach_sh4)
- return true;
-
- /* If we are linking sh[3]-dsp code, swap the FPU instructions for DSP
- instructions. */
- if (dsp)
- {
- sh_opcodes[0xf].minor_opcodes = sh_dsp_opcodef;
- sh_opcodes[0xf].count = sizeof sh_dsp_opcodef / sizeof sh_dsp_opcodef;
- }
-
- /* Instructions should be aligned on 2 byte boundaries. */
- if ((start & 1) == 1)
- ++start;
-
- /* Now look through the unaligned addresses. */
- i = start;
- if ((i & 2) == 0)
- i += 2;
- for (; i < stop; i += 4)
- {
- unsigned int insn;
- const struct sh_opcode *op;
- unsigned int prev_insn = 0;
- const struct sh_opcode *prev_op = NULL;
-
- insn = bfd_get_16 (abfd, contents + i);
- op = sh_insn_info (insn);
- if (op == NULL
- || (op->flags & (LOAD | STORE)) == 0)
- continue;
-
- /* This is a load or store which is not on a four byte boundary. */
-
- while (*plabel < label_end && **plabel < i)
- ++*plabel;
-
- if (i > start)
- {
- prev_insn = bfd_get_16 (abfd, contents + i - 2);
- /* If INSN is the field b of a parallel processing insn, it is not
- a load / store after all. Note that the test here might mistake
- the field_b of a pcopy insn for the starting code of a parallel
- processing insn; this might miss a swapping opportunity, but at
- least we're on the safe side. */
- if (dsp && (prev_insn & 0xfc00) == 0xf800)
- continue;
-
- /* Check if prev_insn is actually the field b of a parallel
- processing insn. Again, this can give a spurious match
- after a pcopy. */
- if (dsp && i - 2 > start)
- {
- unsigned pprev_insn = bfd_get_16 (abfd, contents + i - 4);
-
- if ((pprev_insn & 0xfc00) == 0xf800)
- prev_op = NULL;
- else
- prev_op = sh_insn_info (prev_insn);
- }
- else
- prev_op = sh_insn_info (prev_insn);
-
- /* If the load/store instruction is in a delay slot, we
- can't swap. */
- if (prev_op == NULL
- || (prev_op->flags & DELAY) != 0)
- continue;
- }
- if (i > start
- && (*plabel >= label_end || **plabel != i)
- && prev_op != NULL
- && (prev_op->flags & (LOAD | STORE)) == 0
- && ! sh_insns_conflict (prev_insn, prev_op, insn, op))
- {
- boolean ok;
-
- /* The load/store instruction does not have a label, and
- there is a previous instruction; PREV_INSN is not
- itself a load/store instruction, and PREV_INSN and
- INSN do not conflict. */
-
- ok = true;
-
- if (i >= start + 4)
- {
- unsigned int prev2_insn;
- const struct sh_opcode *prev2_op;
-
- prev2_insn = bfd_get_16 (abfd, contents + i - 4);
- prev2_op = sh_insn_info (prev2_insn);
-
- /* If the instruction before PREV_INSN has a delay
- slot--that is, PREV_INSN is in a delay slot--we
- can not swap. */
- if (prev2_op == NULL
- || (prev2_op->flags & DELAY) != 0)
- ok = false;
-
- /* If the instruction before PREV_INSN is a load,
- and it sets a register which INSN uses, then
- putting INSN immediately after PREV_INSN will
- cause a pipeline bubble, so there is no point to
- making the swap. */
- if (ok
- && (prev2_op->flags & LOAD) != 0
- && sh_load_use (prev2_insn, prev2_op, insn, op))
- ok = false;
- }
-
- if (ok)
- {
- if (! (*swap) (abfd, sec, relocs, contents, i - 2))
- return false;
- *pswapped = true;
- continue;
- }
- }
-
- while (*plabel < label_end && **plabel < i + 2)
- ++*plabel;
-
- if (i + 2 < stop
- && (*plabel >= label_end || **plabel != i + 2))
- {
- unsigned int next_insn;
- const struct sh_opcode *next_op;
-
- /* There is an instruction after the load/store
- instruction, and it does not have a label. */
- next_insn = bfd_get_16 (abfd, contents + i + 2);
- next_op = sh_insn_info (next_insn);
- if (next_op != NULL
- && (next_op->flags & (LOAD | STORE)) == 0
- && ! sh_insns_conflict (insn, op, next_insn, next_op))
- {
- boolean ok;
-
- /* NEXT_INSN is not itself a load/store instruction,
- and it does not conflict with INSN. */
-
- ok = true;
-
- /* If PREV_INSN is a load, and it sets a register
- which NEXT_INSN uses, then putting NEXT_INSN
- immediately after PREV_INSN will cause a pipeline
- bubble, so there is no reason to make this swap. */
- if (prev_op != NULL
- && (prev_op->flags & LOAD) != 0
- && sh_load_use (prev_insn, prev_op, next_insn, next_op))
- ok = false;
-
- /* If INSN is a load, and it sets a register which
- the insn after NEXT_INSN uses, then doing the
- swap will cause a pipeline bubble, so there is no
- reason to make the swap. However, if the insn
- after NEXT_INSN is itself a load or store
- instruction, then it is misaligned, so
- optimistically hope that it will be swapped
- itself, and just live with the pipeline bubble if
- it isn't. */
- if (ok
- && i + 4 < stop
- && (op->flags & LOAD) != 0)
- {
- unsigned int next2_insn;
- const struct sh_opcode *next2_op;
-
- next2_insn = bfd_get_16 (abfd, contents + i + 4);
- next2_op = sh_insn_info (next2_insn);
- if ((next2_op->flags & (LOAD | STORE)) == 0
- && sh_load_use (insn, op, next2_insn, next2_op))
- ok = false;
- }
-
- if (ok)
- {
- if (! (*swap) (abfd, sec, relocs, contents, i))
- return false;
- *pswapped = true;
- continue;
- }
- }
- }
- }
-
- return true;
-}
-#endif /* not COFF_IMAGE_WITH_PE */
-
-/* Look for loads and stores which we can align to four byte
- boundaries. See the longer comment above sh_relax_section for why
- this is desirable. This sets *PSWAPPED if some instruction was
- swapped. */
-
-static boolean
-sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
- bfd *abfd;
- asection *sec;
- struct internal_reloc *internal_relocs;
- bfd_byte *contents;
- boolean *pswapped;
-{
- struct internal_reloc *irel, *irelend;
- bfd_vma *labels = NULL;
- bfd_vma *label, *label_end;
- bfd_size_type amt;
-
- *pswapped = false;
-
- irelend = internal_relocs + sec->reloc_count;
-
- /* Get all the addresses with labels on them. */
- amt = (bfd_size_type) sec->reloc_count * sizeof (bfd_vma);
- labels = (bfd_vma *) bfd_malloc (amt);
- if (labels == NULL)
- goto error_return;
- label_end = labels;
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- if (irel->r_type == R_SH_LABEL)
- {
- *label_end = irel->r_vaddr - sec->vma;
- ++label_end;
- }
- }
-
- /* Note that the assembler currently always outputs relocs in
- address order. If that ever changes, this code will need to sort
- the label values and the relocs. */
-
- label = labels;
-
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- bfd_vma start, stop;
-
- if (irel->r_type != R_SH_CODE)
- continue;
-
- start = irel->r_vaddr - sec->vma;
-
- for (irel++; irel < irelend; irel++)
- if (irel->r_type == R_SH_DATA)
- break;
- if (irel < irelend)
- stop = irel->r_vaddr - sec->vma;
- else
- stop = sec->_cooked_size;
-
- if (! _bfd_sh_align_load_span (abfd, sec, contents, sh_swap_insns,
- (PTR) internal_relocs, &label,
- label_end, start, stop, pswapped))
- goto error_return;
- }
-
- free (labels);
-
- return true;
-
- error_return:
- if (labels != NULL)
- free (labels);
- return false;
-}
-
-/* Swap two SH instructions. */
-
-static boolean
-sh_swap_insns (abfd, sec, relocs, contents, addr)
- bfd *abfd;
- asection *sec;
- PTR relocs;
- bfd_byte *contents;
- bfd_vma addr;
-{
- struct internal_reloc *internal_relocs = (struct internal_reloc *) relocs;
- unsigned short i1, i2;
- struct internal_reloc *irel, *irelend;
-
- /* Swap the instructions themselves. */
- i1 = bfd_get_16 (abfd, contents + addr);
- i2 = bfd_get_16 (abfd, contents + addr + 2);
- bfd_put_16 (abfd, (bfd_vma) i2, contents + addr);
- bfd_put_16 (abfd, (bfd_vma) i1, contents + addr + 2);
-
- /* Adjust all reloc addresses. */
- irelend = internal_relocs + sec->reloc_count;
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- int type, add;
-
- /* There are a few special types of relocs that we don't want to
- adjust. These relocs do not apply to the instruction itself,
- but are only associated with the address. */
- type = irel->r_type;
- if (type == R_SH_ALIGN
- || type == R_SH_CODE
- || type == R_SH_DATA
- || type == R_SH_LABEL)
- continue;
-
- /* If an R_SH_USES reloc points to one of the addresses being
- swapped, we must adjust it. It would be incorrect to do this
- for a jump, though, since we want to execute both
- instructions after the jump. (We have avoided swapping
- around a label, so the jump will not wind up executing an
- instruction it shouldn't). */
- if (type == R_SH_USES)
- {
- bfd_vma off;
-
- off = irel->r_vaddr - sec->vma + 4 + irel->r_offset;
- if (off == addr)
- irel->r_offset += 2;
- else if (off == addr + 2)
- irel->r_offset -= 2;
- }
-
- if (irel->r_vaddr - sec->vma == addr)
- {
- irel->r_vaddr += 2;
- add = -2;
- }
- else if (irel->r_vaddr - sec->vma == addr + 2)
- {
- irel->r_vaddr -= 2;
- add = 2;
- }
- else
- add = 0;
-
- if (add != 0)
- {
- bfd_byte *loc;
- unsigned short insn, oinsn;
- boolean overflow;
-
- loc = contents + irel->r_vaddr - sec->vma;
- overflow = false;
- switch (type)
- {
- default:
- break;
-
- case R_SH_PCDISP8BY2:
- case R_SH_PCRELIMM8BY2:
- insn = bfd_get_16 (abfd, loc);
- oinsn = insn;
- insn += add / 2;
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, loc);
- break;
-
- case R_SH_PCDISP:
- insn = bfd_get_16 (abfd, loc);
- oinsn = insn;
- insn += add / 2;
- if ((oinsn & 0xf000) != (insn & 0xf000))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, loc);
- break;
-
- case R_SH_PCRELIMM8BY4:
- /* This reloc ignores the least significant 3 bits of
- the program counter before adding in the offset.
- This means that if ADDR is at an even address, the
- swap will not affect the offset. If ADDR is an at an
- odd address, then the instruction will be crossing a
- four byte boundary, and must be adjusted. */
- if ((addr & 3) != 0)
- {
- insn = bfd_get_16 (abfd, loc);
- oinsn = insn;
- insn += add / 2;
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, loc);
- }
-
- break;
- }
-
- if (overflow)
- {
- ((*_bfd_error_handler)
- ("%s: 0x%lx: fatal: reloc overflow while relaxing",
- bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
- }
-
- return true;
-}
-
-/* This is a modification of _bfd_coff_generic_relocate_section, which
- will handle SH relaxing. */
-
-static boolean
-sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
- relocs, syms, sections)
- bfd *output_bfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- struct internal_reloc *relocs;
- struct internal_syment *syms;
- asection **sections;
-{
- struct internal_reloc *rel;
- struct internal_reloc *relend;
-
- rel = relocs;
- relend = rel + input_section->reloc_count;
- for (; rel < relend; rel++)
- {
- long symndx;
- struct coff_link_hash_entry *h;
- struct internal_syment *sym;
- bfd_vma addend;
- bfd_vma val;
- reloc_howto_type *howto;
- bfd_reloc_status_type rstat;
-
- /* Almost all relocs have to do with relaxing. If any work must
- be done for them, it has been done in sh_relax_section. */
- if (rel->r_type != R_SH_IMM32
-#ifdef COFF_WITH_PE
- && rel->r_type != R_SH_IMM32CE
- && rel->r_type != R_SH_IMAGEBASE
-#endif
- && rel->r_type != R_SH_PCDISP)
- continue;
-
- symndx = rel->r_symndx;
-
- if (symndx == -1)
- {
- h = NULL;
- sym = NULL;
- }
- else
- {
- if (symndx < 0
- || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
- {
- (*_bfd_error_handler)
- ("%s: illegal symbol index %ld in relocs",
- bfd_archive_filename (input_bfd), symndx);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- h = obj_coff_sym_hashes (input_bfd)[symndx];
- sym = syms + symndx;
- }
-
- if (sym != NULL && sym->n_scnum != 0)
- addend = - sym->n_value;
- else
- addend = 0;
-
- if (rel->r_type == R_SH_PCDISP)
- addend -= 4;
-
- if (rel->r_type >= SH_COFF_HOWTO_COUNT)
- howto = NULL;
- else
- howto = &sh_coff_howtos[rel->r_type];
-
- if (howto == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
-#ifdef COFF_WITH_PE
- if (rel->r_type == R_SH_IMAGEBASE)
- addend -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
-#endif
-
- val = 0;
-
- if (h == NULL)
- {
- asection *sec;
-
- /* There is nothing to do for an internal PCDISP reloc. */
- if (rel->r_type == R_SH_PCDISP)
- continue;
-
- if (symndx == -1)
- {
- sec = bfd_abs_section_ptr;
- val = 0;
- }
- else
- {
- sec = sections[symndx];
- val = (sec->output_section->vma
- + sec->output_offset
- + sym->n_value
- - sec->vma);
- }
- }
- else
- {
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- asection *sec;
-
- sec = h->root.u.def.section;
- val = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
- else if (! info->relocateable)
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma, true)))
- return false;
- }
- }
-
- rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents,
- rel->r_vaddr - input_section->vma,
- val, addend);
-
- switch (rstat)
- {
- default:
- abort ();
- case bfd_reloc_ok:
- break;
- case bfd_reloc_overflow:
- {
- const char *name;
- char buf[SYMNMLEN + 1];
-
- if (symndx == -1)
- name = "*ABS*";
- else if (h != NULL)
- name = h->root.root.string;
- else if (sym->_n._n_n._n_zeroes == 0
- && sym->_n._n_n._n_offset != 0)
- name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
- else
- {
- strncpy (buf, sym->_n._n_name, SYMNMLEN);
- buf[SYMNMLEN] = '\0';
- name = buf;
- }
-
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0, input_bfd,
- input_section, rel->r_vaddr - input_section->vma)))
- return false;
- }
- }
- }
-
- return true;
-}
-
-/* This is a version of bfd_generic_get_relocated_section_contents
- which uses sh_relocate_section. */
-
-static bfd_byte *
-sh_coff_get_relocated_section_contents (output_bfd, link_info, link_order,
- data, relocateable, symbols)
- bfd *output_bfd;
- struct bfd_link_info *link_info;
- struct bfd_link_order *link_order;
- bfd_byte *data;
- boolean relocateable;
- asymbol **symbols;
-{
- asection *input_section = link_order->u.indirect.section;
- bfd *input_bfd = input_section->owner;
- asection **sections = NULL;
- struct internal_reloc *internal_relocs = NULL;
- struct internal_syment *internal_syms = NULL;
-
- /* We only need to handle the case of relaxing, or of having a
- particular set of section contents, specially. */
- if (relocateable
- || coff_section_data (input_bfd, input_section) == NULL
- || coff_section_data (input_bfd, input_section)->contents == NULL)
- return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
- link_order, data,
- relocateable,
- symbols);
-
- memcpy (data, coff_section_data (input_bfd, input_section)->contents,
- (size_t) input_section->_raw_size);
-
- if ((input_section->flags & SEC_RELOC) != 0
- && input_section->reloc_count > 0)
- {
- bfd_size_type symesz = bfd_coff_symesz (input_bfd);
- bfd_byte *esym, *esymend;
- struct internal_syment *isymp;
- asection **secpp;
- bfd_size_type amt;
-
- if (! _bfd_coff_get_external_symbols (input_bfd))
- goto error_return;
-
- internal_relocs = (_bfd_coff_read_internal_relocs
- (input_bfd, input_section, false, (bfd_byte *) NULL,
- false, (struct internal_reloc *) NULL));
- if (internal_relocs == NULL)
- goto error_return;
-
- amt = obj_raw_syment_count (input_bfd);
- amt *= sizeof (struct internal_syment);
- internal_syms = (struct internal_syment *) bfd_malloc (amt);
- if (internal_syms == NULL)
- goto error_return;
-
- amt = obj_raw_syment_count (input_bfd);
- amt *= sizeof (asection *);
- sections = (asection **) bfd_malloc (amt);
- if (sections == NULL)
- goto error_return;
-
- isymp = internal_syms;
- secpp = sections;
- esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
- esymend = esym + obj_raw_syment_count (input_bfd) * symesz;
- while (esym < esymend)
- {
- bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
-
- if (isymp->n_scnum != 0)
- *secpp = coff_section_from_bfd_index (input_bfd, isymp->n_scnum);
- else
- {
- if (isymp->n_value == 0)
- *secpp = bfd_und_section_ptr;
- else
- *secpp = bfd_com_section_ptr;
- }
-
- esym += (isymp->n_numaux + 1) * symesz;
- secpp += isymp->n_numaux + 1;
- isymp += isymp->n_numaux + 1;
- }
-
- if (! sh_relocate_section (output_bfd, link_info, input_bfd,
- input_section, data, internal_relocs,
- internal_syms, sections))
- goto error_return;
-
- free (sections);
- sections = NULL;
- free (internal_syms);
- internal_syms = NULL;
- free (internal_relocs);
- internal_relocs = NULL;
- }
-
- return data;
-
- error_return:
- if (internal_relocs != NULL)
- free (internal_relocs);
- if (internal_syms != NULL)
- free (internal_syms);
- if (sections != NULL)
- free (sections);
- return NULL;
-}
-
-/* The target vectors. */
-
-#ifndef TARGET_SHL_SYM
-CREATE_BIG_COFF_TARGET_VEC (shcoff_vec, "coff-sh", BFD_IS_RELAXABLE, 0, '_', NULL)
-#endif
-
-#ifdef TARGET_SHL_SYM
-#define TARGET_SYM TARGET_SHL_SYM
-#else
-#define TARGET_SYM shlcoff_vec
-#endif
-
-#ifndef TARGET_SHL_NAME
-#define TARGET_SHL_NAME "coff-shl"
-#endif
-
-#ifdef COFF_WITH_PE
-CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
- SEC_CODE | SEC_DATA, '_', NULL);
-#else
-CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
- 0, '_', NULL)
-#endif
-
-#ifndef TARGET_SHL_SYM
-static const bfd_target * coff_small_object_p PARAMS ((bfd *));
-static boolean coff_small_new_section_hook PARAMS ((bfd *, asection *));
-/* Some people want versions of the SH COFF target which do not align
- to 16 byte boundaries. We implement that by adding a couple of new
- target vectors. These are just like the ones above, but they
- change the default section alignment. To generate them in the
- assembler, use -small. To use them in the linker, use -b
- coff-sh{l}-small and -oformat coff-sh{l}-small.
-
- Yes, this is a horrible hack. A general solution for setting
- section alignment in COFF is rather complex. ELF handles this
- correctly. */
-
-/* Only recognize the small versions if the target was not defaulted.
- Otherwise we won't recognize the non default endianness. */
-
-static const bfd_target *
-coff_small_object_p (abfd)
- bfd *abfd;
-{
- if (abfd->target_defaulted)
- {
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
- }
- return coff_object_p (abfd);
-}
-
-/* Set the section alignment for the small versions. */
-
-static boolean
-coff_small_new_section_hook (abfd, section)
- bfd *abfd;
- asection *section;
-{
- if (! coff_new_section_hook (abfd, section))
- return false;
-
- /* We must align to at least a four byte boundary, because longword
- accesses must be on a four byte boundary. */
- if (section->alignment_power == COFF_DEFAULT_SECTION_ALIGNMENT_POWER)
- section->alignment_power = 2;
-
- return true;
-}
-
-/* This is copied from bfd_coff_std_swap_table so that we can change
- the default section alignment power. */
-
-static const bfd_coff_backend_data bfd_coff_small_swap_table =
-{
- coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
- coff_swap_aux_out, coff_swap_sym_out,
- coff_swap_lineno_out, coff_swap_reloc_out,
- coff_swap_filehdr_out, coff_swap_aouthdr_out,
- coff_swap_scnhdr_out,
- FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ, FILNMLEN,
-#ifdef COFF_LONG_FILENAMES
- true,
-#else
- false,
-#endif
-#ifdef COFF_LONG_SECTION_NAMES
- true,
-#else
- false,
-#endif
- 2,
-#ifdef COFF_FORCE_SYMBOLS_IN_STRINGS
- true,
-#else
- false,
-#endif
-#ifdef COFF_DEBUG_STRING_WIDE_PREFIX
- 4,
-#else
- 2,
-#endif
- coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
- coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
- coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
- coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
- coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
- coff_classify_symbol, coff_compute_section_file_positions,
- coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
- coff_adjust_symndx, coff_link_add_one_symbol,
- coff_link_output_has_begun, coff_final_link_postscript
-};
-
-#define coff_small_close_and_cleanup \
- coff_close_and_cleanup
-#define coff_small_bfd_free_cached_info \
- coff_bfd_free_cached_info
-#define coff_small_get_section_contents \
- coff_get_section_contents
-#define coff_small_get_section_contents_in_window \
- coff_get_section_contents_in_window
-
-extern const bfd_target shlcoff_small_vec;
-
-const bfd_target shcoff_small_vec =
-{
- "coff-sh-small", /* name */
- bfd_target_coff_flavour,
- BFD_ENDIAN_BIG, /* data byte order is big */
- BFD_ENDIAN_BIG, /* header byte order is big */
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
-
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
- '_', /* leading symbol underscore */
- '/', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
-
- {_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
- bfd_generic_archive_p, _bfd_dummy_target},
- {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
- bfd_false},
- {bfd_false, coff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (coff_small),
- BFD_JUMP_TABLE_COPY (coff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
- BFD_JUMP_TABLE_SYMBOLS (coff),
- BFD_JUMP_TABLE_RELOCS (coff),
- BFD_JUMP_TABLE_WRITE (coff),
- BFD_JUMP_TABLE_LINK (coff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- & shlcoff_small_vec,
-
- (PTR) &bfd_coff_small_swap_table
-};
-
-const bfd_target shlcoff_small_vec =
-{
- "coff-shl-small", /* name */
- bfd_target_coff_flavour,
- BFD_ENDIAN_LITTLE, /* data byte order is little */
- BFD_ENDIAN_LITTLE, /* header byte order is little endian too*/
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
-
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
- '_', /* leading symbol underscore */
- '/', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
-
- {_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
- bfd_generic_archive_p, _bfd_dummy_target},
- {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
- bfd_false},
- {bfd_false, coff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (coff_small),
- BFD_JUMP_TABLE_COPY (coff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
- BFD_JUMP_TABLE_SYMBOLS (coff),
- BFD_JUMP_TABLE_RELOCS (coff),
- BFD_JUMP_TABLE_WRITE (coff),
- BFD_JUMP_TABLE_LINK (coff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- & shcoff_small_vec,
-
- (PTR) &bfd_coff_small_swap_table
-};
-#endif
diff --git a/contrib/binutils/bfd/coff-tic30.c b/contrib/binutils/bfd/coff-tic30.c
deleted file mode 100644
index a3bbc4c..0000000
--- a/contrib/binutils/bfd/coff-tic30.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/* BFD back-end for TMS320C30 coff binaries.
- Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
-
- This file is part of BFD, the Binary File Descriptor library.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-#include "bfdlink.h"
-#include "coff/tic30.h"
-#include "coff/internal.h"
-#include "libcoff.h"
-
-static int coff_tic30_select_reloc PARAMS ((reloc_howto_type *));
-static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
-static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
-
-reloc_howto_type * tic30_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
-
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
-
-reloc_howto_type tic30_coff_howto_table[] =
- {
- HOWTO (R_TIC30_ABS16, 2, 1, 16, false, 0, 0, NULL,
- "16", false, 0x0000FFFF, 0x0000FFFF, false),
- HOWTO (R_TIC30_ABS24, 2, 2, 24, false, 8, complain_overflow_bitfield, NULL,
- "24", false, 0xFFFFFF00, 0xFFFFFF00, false),
- HOWTO (R_TIC30_LDP, 18, 0, 24, false, 0, complain_overflow_bitfield, NULL,
- "LDP", false, 0x00FF0000, 0x000000FF, false),
- HOWTO (R_TIC30_ABS32, 2, 2, 32, false, 0, complain_overflow_bitfield, NULL,
- "32", false, 0xFFFFFFFF, 0xFFFFFFFF, false),
- HOWTO (R_TIC30_PC16, 2, 1, 16, true, 0, complain_overflow_signed, NULL,
- "PCREL", false, 0x0000FFFF, 0x0000FFFF, false),
- EMPTY_HOWTO (-1)
- };
-
-#ifndef coff_bfd_reloc_type_lookup
-#define coff_bfd_reloc_type_lookup tic30_coff_reloc_type_lookup
-
-/* For the case statement use the code values used in tc_gen_reloc to
- map to the howto table entries that match those in both the aout
- and coff implementations. */
-
-reloc_howto_type *
-tic30_coff_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- switch (code)
- {
- case BFD_RELOC_8:
- case BFD_RELOC_TIC30_LDP:
- return &tic30_coff_howto_table[2];
- case BFD_RELOC_16:
- return &tic30_coff_howto_table[0];
- case BFD_RELOC_24:
- return &tic30_coff_howto_table[1];
- case BFD_RELOC_16_PCREL:
- return &tic30_coff_howto_table[4];
- case BFD_RELOC_32:
- return &tic30_coff_howto_table[3];
- default:
- return (reloc_howto_type *) NULL;
- }
-}
-
-#endif
-
-/* Turn a howto into a reloc number. */
-
-static int
-coff_tic30_select_reloc (howto)
- reloc_howto_type *howto;
-{
- return howto->type;
-}
-
-#define SELECT_RELOC(x,howto) x.r_type = coff_tic30_select_reloc(howto)
-
-#define BADMAG(x) TIC30BADMAG(x)
-#define TIC30 1 /* Customize coffcode.h */
-#define __A_MAGIC_SET__
-
-/* Code to swap in the reloc */
-#define SWAP_IN_RELOC_OFFSET H_GET_32
-#define SWAP_OUT_RELOC_OFFSET H_PUT_32
-#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) dst->r_stuff[0] = 'S'; \
-dst->r_stuff[1] = 'C';
-
-/* Code to turn a r_type into a howto ptr, uses the above howto table. */
-
-static void
-rtype2howto (internal, dst)
- arelent *internal;
- struct internal_reloc *dst;
-{
- switch (dst->r_type)
- {
- case R_TIC30_ABS16:
- internal->howto = &tic30_coff_howto_table[0];
- break;
- case R_TIC30_ABS24:
- internal->howto = &tic30_coff_howto_table[1];
- break;
- case R_TIC30_ABS32:
- internal->howto = &tic30_coff_howto_table[3];
- break;
- case R_TIC30_LDP:
- internal->howto = &tic30_coff_howto_table[2];
- break;
- case R_TIC30_PC16:
- internal->howto = &tic30_coff_howto_table[4];
- break;
- default:
- abort ();
- break;
- }
-}
-
-#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
-
-/* Perform any necessary magic to the addend in a reloc entry */
-
-#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
- cache_ptr->addend = ext_reloc.r_offset;
-
-#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
- reloc_processing(relent, reloc, symbols, abfd, section)
-
-static void
-reloc_processing (relent, reloc, symbols, abfd, section)
- arelent *relent;
- struct internal_reloc *reloc;
- asymbol **symbols;
- bfd *abfd;
- asection *section;
-{
- relent->address = reloc->r_vaddr;
- rtype2howto (relent, reloc);
-
- if (reloc->r_symndx > 0)
- relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
- else
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
-
- relent->addend = reloc->r_offset;
- relent->address -= section->vma;
-}
-
-#include "coffcode.h"
-
-const bfd_target tic30_coff_vec =
-{
- "coff-tic30", /* name */
- bfd_target_coff_flavour,
- BFD_ENDIAN_BIG, /* data byte order is big */
- BFD_ENDIAN_LITTLE, /* header byte order is little */
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT),
-
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
- '_', /* leading symbol underscore */
- '/', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
-
- {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- bfd_generic_archive_p, _bfd_dummy_target},
- {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
- bfd_false},
- {bfd_false, coff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (coff),
- BFD_JUMP_TABLE_COPY (coff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
- BFD_JUMP_TABLE_SYMBOLS (coff),
- BFD_JUMP_TABLE_RELOCS (coff),
- BFD_JUMP_TABLE_WRITE (coff),
- BFD_JUMP_TABLE_LINK (coff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- NULL,
-
- COFF_SWAP_TABLE
-};
diff --git a/contrib/binutils/bfd/coff-z8k.c b/contrib/binutils/bfd/coff-z8k.c
deleted file mode 100644
index c626cd7..0000000
--- a/contrib/binutils/bfd/coff-z8k.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/* BFD back-end for Zilog Z800n COFF binaries.
- Copyright 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001
- Free Software Foundation, Inc.
- Contributed by Cygnus Support.
- Written by Steve Chamberlain, <sac@cygnus.com>.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-#include "bfdlink.h"
-#include "coff/z8k.h"
-#include "coff/internal.h"
-#include "libcoff.h"
-
-static void extra_case PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
-static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
-static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
-static int coff_z8k_select_reloc PARAMS ((reloc_howto_type *));
-
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
-
-static reloc_howto_type r_imm32 =
-HOWTO (R_IMM32, 0, 2, 32, false, 0,
- complain_overflow_bitfield, 0, "r_imm32", true, 0xffffffff,
- 0xffffffff, false);
-
-static reloc_howto_type r_imm4l =
-HOWTO (R_IMM4L, 0, 0, 4, false, 0,
- complain_overflow_bitfield, 0, "r_imm4l", true, 0xf, 0xf, false);
-
-static reloc_howto_type r_da =
-HOWTO (R_IMM16, 0, 1, 16, false, 0,
- complain_overflow_bitfield, 0, "r_da", true, 0x0000ffff, 0x0000ffff,
- false);
-
-static reloc_howto_type r_imm8 =
-HOWTO (R_IMM8, 0, 0, 8, false, 0,
- complain_overflow_bitfield, 0, "r_imm8", true, 0x000000ff, 0x000000ff,
- false);
-
-static reloc_howto_type r_rel16 =
-HOWTO (R_REL16, 0, 1, 16, false, 0,
- complain_overflow_bitfield, 0, "r_rel16", true, 0x0000ffff, 0x0000ffff,
- true);
-
-static reloc_howto_type r_jr =
-HOWTO (R_JR, 0, 0, 8, true, 0, complain_overflow_signed, 0,
- "r_jr", true, 0, 0, true);
-
-static reloc_howto_type r_disp7 =
-HOWTO (R_DISP7, 0, 0, 7, true, 0, complain_overflow_bitfield, 0,
- "r_disp7", true, 0, 0, true);
-
-static reloc_howto_type r_callr =
-HOWTO (R_CALLR, 0, 1, 12, true, 0, complain_overflow_signed, 0,
- "r_callr", true, 0xfff, 0xfff, true);
-
-/* Turn a howto into a reloc number */
-
-static int
-coff_z8k_select_reloc (howto)
- reloc_howto_type *howto;
-{
- return howto->type;
-}
-
-#define SELECT_RELOC(x,howto) x.r_type = coff_z8k_select_reloc(howto)
-
-#define BADMAG(x) Z8KBADMAG(x)
-#define Z8K 1 /* Customize coffcode.h */
-#define __A_MAGIC_SET__
-
-/* Code to swap in the reloc. */
-#define SWAP_IN_RELOC_OFFSET H_GET_32
-#define SWAP_OUT_RELOC_OFFSET H_PUT_32
-#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
- dst->r_stuff[0] = 'S'; \
- dst->r_stuff[1] = 'C';
-
-/* Code to turn a r_type into a howto ptr, uses the above howto table. */
-
-static void
-rtype2howto (internal, dst)
- arelent * internal;
- struct internal_reloc *dst;
-{
- switch (dst->r_type)
- {
- default:
- abort ();
- break;
- case R_IMM8:
- internal->howto = &r_imm8;
- break;
- case R_IMM16:
- internal->howto = &r_da;
- break;
- case R_JR:
- internal->howto = &r_jr;
- break;
- case R_DISP7:
- internal->howto = &r_disp7;
- break;
- case R_CALLR:
- internal->howto = &r_callr;
- break;
- case R_REL16:
- internal->howto = &r_rel16;
- break;
- case R_IMM32:
- internal->howto = &r_imm32;
- break;
- case R_IMM4L:
- internal->howto = &r_imm4l;
- break;
- }
-}
-
-#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
-
-/* Perform any necessary magic to the addend in a reloc entry. */
-
-#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
- cache_ptr->addend = ext_reloc.r_offset;
-
-#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
- reloc_processing(relent, reloc, symbols, abfd, section)
-
-static void
-reloc_processing (relent, reloc, symbols, abfd, section)
- arelent * relent;
- struct internal_reloc * reloc;
- asymbol ** symbols;
- bfd * abfd;
- asection * section;
-{
- relent->address = reloc->r_vaddr;
- rtype2howto (relent, reloc);
-
- if (reloc->r_symndx > 0)
- relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
- else
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
-
- relent->addend = reloc->r_offset;
- relent->address -= section->vma;
-}
-
-static void
-extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
- bfd * in_abfd;
- struct bfd_link_info * link_info;
- struct bfd_link_order * link_order;
- arelent * reloc;
- bfd_byte * data;
- unsigned int * src_ptr;
- unsigned int * dst_ptr;
-{
- asection * input_section = link_order->u.indirect.section;
-
- switch (reloc->howto->type)
- {
- case R_IMM8:
- bfd_put_8 (in_abfd,
- bfd_coff_reloc16_get_value (reloc, link_info, input_section),
- data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
- break;
-
- case R_IMM32:
- bfd_put_32 (in_abfd,
- /* 0x80000000 indicates a long segmented address. */
- bfd_coff_reloc16_get_value (reloc, link_info, input_section) | 0x80000000,
- data + *dst_ptr);
- (*dst_ptr) += 4;
- (*src_ptr) += 4;
- break;
-
- case R_IMM4L:
- bfd_put_8 (in_abfd,
- ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
- | (0x0f
- & bfd_coff_reloc16_get_value (reloc, link_info,
- input_section))),
- data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
- break;
-
- case R_IMM16:
- bfd_put_16 (in_abfd,
- bfd_coff_reloc16_get_value (reloc, link_info, input_section),
- data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
- break;
-
- case R_JR:
- {
- bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
- input_section);
- bfd_vma dot = (link_order->offset
- + *dst_ptr
- + input_section->output_section->vma);
- int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
- word and the pc's been incremented. */
-
- if (gap & 1)
- abort ();
- gap /= 2;
- if (gap > 128 || gap < -128)
- {
- if (! ((*link_info->callbacks->reloc_overflow)
- (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address)))
- abort ();
- }
- bfd_put_8 (in_abfd, gap, data + *dst_ptr);
- (*dst_ptr)++;
- (*src_ptr)++;
- break;
- }
-
- case R_DISP7:
- {
- bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
- input_section);
- bfd_vma dot = (link_order->offset
- + *dst_ptr
- + input_section->output_section->vma);
- int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
- word and the pc's been incremented. */
-
- if (gap & 1)
- abort ();
- gap /= 2;
-
- if (gap > 0 || gap < -128)
- {
- if (! ((*link_info->callbacks->reloc_overflow)
- (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address)))
- abort ();
- }
- bfd_put_8 (in_abfd,
- (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
- data + *dst_ptr);
- (*dst_ptr)++;
- (*src_ptr)++;
- break;
- }
-
- case R_CALLR:
- {
- bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
- input_section);
- bfd_vma dot = (link_order->offset
- + *dst_ptr
- + input_section->output_section->vma);
- int gap = dst - dot - 2;
-
- if (gap & 1)
- abort ();
- gap /= 2;
- if (gap > 8191 || gap < -8192)
- {
- if (! ((*link_info->callbacks->reloc_overflow)
- (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address)))
- abort ();
- }
- bfd_put_16 (in_abfd,
- (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
- data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
- break;
- }
-
- case R_REL16:
- {
- bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
- input_section);
- bfd_vma dot = (link_order->offset
- + *dst_ptr
- + input_section->output_section->vma);
- int gap = dst - dot - 2;
-
- if (gap > 32767 || gap < -32768)
- {
- if (! ((*link_info->callbacks->reloc_overflow)
- (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address)))
- abort ();
- }
- bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
- break;
- }
-
- default:
- abort ();
- }
-}
-
-#define coff_reloc16_extra_cases extra_case
-
-#include "coffcode.h"
-
-#undef coff_bfd_get_relocated_section_contents
-#undef coff_bfd_relax_section
-#define coff_bfd_get_relocated_section_contents \
- bfd_coff_reloc16_get_relocated_section_contents
-#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
-
-CREATE_BIG_COFF_TARGET_VEC (z8kcoff_vec, "coff-z8k", 0, 0, '_', NULL)
diff --git a/contrib/binutils/bfd/cpu-mips.c b/contrib/binutils/bfd/cpu-mips.c
deleted file mode 100644
index d54b0a5..0000000
--- a/contrib/binutils/bfd/cpu-mips.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* bfd back-end for mips support
- Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002
- Free Software Foundation, Inc.
- Written by Steve Chamberlain of Cygnus Support.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-
-static const bfd_arch_info_type *mips_compatible
- PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
-
-/* The default routine tests bits_per_word, which is wrong on mips as
- mips word size doesn't correlate with reloc size. */
-
-static const bfd_arch_info_type *
-mips_compatible (a, b)
- const bfd_arch_info_type *a;
- const bfd_arch_info_type *b;
-{
- if (a->arch != b->arch)
- return NULL;
-
- if (a->mach > b->mach)
- return a;
-
- if (b->mach > a->mach)
- return b;
-
- return a;
-}
-
-#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \
- { \
- BITS_WORD, /* bits in a word */ \
- BITS_ADDR, /* bits in an address */ \
- 8, /* 8 bits in a byte */ \
- bfd_arch_mips, \
- NUMBER, \
- "mips", \
- PRINT, \
- 3, \
- DEFAULT, \
- mips_compatible, \
- bfd_default_scan, \
- NEXT, \
- }
-
-enum
-{
- I_mips3000,
- I_mips3900,
- I_mips4000,
- I_mips4010,
- I_mips4100,
- I_mips4111,
- I_mips4300,
- I_mips4400,
- I_mips4600,
- I_mips4650,
- I_mips5000,
- I_mips6000,
- I_mips8000,
- I_mips10000,
- I_mips12000,
- I_mips16,
- I_mips5,
- I_mipsisa32,
- I_mipsisa64,
- I_sb1,
-};
-
-#define NN(index) (&arch_info_struct[(index) + 1])
-
-static const bfd_arch_info_type arch_info_struct[] =
-{
- N (32, 32, bfd_mach_mips3000, "mips:3000", false, NN(I_mips3000)),
- N (32, 32, bfd_mach_mips3900, "mips:3900", false, NN(I_mips3900)),
- N (64, 64, bfd_mach_mips4000, "mips:4000", false, NN(I_mips4000)),
- N (64, 64, bfd_mach_mips4010, "mips:4010", false, NN(I_mips4010)),
- N (64, 64, bfd_mach_mips4100, "mips:4100", false, NN(I_mips4100)),
- N (64, 64, bfd_mach_mips4111, "mips:4111", false, NN(I_mips4111)),
- N (64, 64, bfd_mach_mips4300, "mips:4300", false, NN(I_mips4300)),
- N (64, 64, bfd_mach_mips4400, "mips:4400", false, NN(I_mips4400)),
- N (64, 64, bfd_mach_mips4600, "mips:4600", false, NN(I_mips4600)),
- N (64, 64, bfd_mach_mips4650, "mips:4650", false, NN(I_mips4650)),
- N (64, 64, bfd_mach_mips5000, "mips:5000", false, NN(I_mips5000)),
- N (32, 32, bfd_mach_mips6000, "mips:6000", false, NN(I_mips6000)),
- N (64, 64, bfd_mach_mips8000, "mips:8000", false, NN(I_mips8000)),
- N (64, 64, bfd_mach_mips10000,"mips:10000", false, NN(I_mips10000)),
- N (64, 64, bfd_mach_mips12000,"mips:12000", false, NN(I_mips12000)),
- N (64, 64, bfd_mach_mips16, "mips:16", false, NN(I_mips16)),
- N (64, 64, bfd_mach_mips5, "mips:mips5", false, NN(I_mips5)),
- N (32, 32, bfd_mach_mipsisa32, "mips:isa32", false, NN(I_mipsisa32)),
- N (64, 64, bfd_mach_mipsisa64, "mips:isa64", false, NN(I_mipsisa64)),
- N (64, 64, bfd_mach_mips_sb1, "mips:sb1", false, 0),
-};
-
-/* The default architecture is mips:3000, but with a machine number of
- zero. This lets the linker distinguish between a default setting
- of mips, and an explicit setting of mips:3000. */
-
-const bfd_arch_info_type bfd_mips_arch =
-N (32, 32, 0, "mips", true, &arch_info_struct[0]);
diff --git a/contrib/binutils/bfd/cpu-sh.c b/contrib/binutils/bfd/cpu-sh.c
deleted file mode 100644
index dff2f88..0000000
--- a/contrib/binutils/bfd/cpu-sh.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* BFD library support routines for the Hitachi-SH architecture.
- Copyright 1993, 1994, 1997, 1998, 2000, 2001
- Free Software Foundation, Inc.
- Hacked by Steve Chamberlain of Cygnus Support.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-
-#if 0
-/* This routine is provided two arch_infos and returns whether
- they'd be compatible */
-
-static const bfd_arch_info_type *
-compatible (a,b)
- const bfd_arch_info_type *a;
- const bfd_arch_info_type *b;
-{
- if (a->arch != b->arch || a->mach != b->mach)
- return NULL;
- return a;
-}
-#endif
-
-#define SH_NEXT &arch_info_struct[0]
-#define SH2_NEXT &arch_info_struct[1]
-#define SH_DSP_NEXT &arch_info_struct[2]
-#define SH3_NEXT &arch_info_struct[3]
-#define SH3_DSP_NEXT &arch_info_struct[4]
-#define SH3E_NEXT &arch_info_struct[5]
-#define SH4_NEXT NULL
-#undef SH4_NEXT
-#define SH4_NEXT &arch_info_struct[6]
-#define SH64_NEXT NULL
-
-static const bfd_arch_info_type arch_info_struct[] =
-{
- {
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh2,
- "sh", /* arch_name */
- "sh2", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH2_NEXT
- },
- {
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh_dsp,
- "sh", /* arch_name */
- "sh-dsp", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH_DSP_NEXT
- },
- {
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh3,
- "sh", /* arch_name */
- "sh3", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH3_NEXT
- },
- {
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh3_dsp,
- "sh", /* arch_name */
- "sh3-dsp", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH3_DSP_NEXT
- },
- {
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh3e,
- "sh", /* arch_name */
- "sh3e", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH3E_NEXT
- },
- {
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh4,
- "sh", /* arch_name */
- "sh4", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH4_NEXT
- },
- {
- 64, /* 64 bits in a word */
- 64, /* 64 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh5,
- "sh", /* arch_name */
- "sh5", /* printable name */
- 1,
- false, /* not the default */
- bfd_default_compatible,
- bfd_default_scan,
- SH64_NEXT
- },
-};
-
-const bfd_arch_info_type bfd_sh_arch =
-{
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_sh,
- bfd_mach_sh,
- "sh", /* arch_name */
- "sh", /* printable name */
- 1,
- true, /* the default machine */
- bfd_default_compatible,
- bfd_default_scan,
- SH_NEXT
-};
diff --git a/contrib/binutils/bfd/cpu-tic30.c b/contrib/binutils/bfd/cpu-tic30.c
deleted file mode 100644
index dd723f7..0000000
--- a/contrib/binutils/bfd/cpu-tic30.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* BFD support for the Texas Instruments TMS320C30 architecture.
- Copyright 1998 Free Software Foundation, Inc.
-
- This file is part of BFD, the Binary File Descriptor library.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-
-const bfd_arch_info_type bfd_tic30_arch =
-{
- 32, /* 32 bits in a word */
- 32, /* 32 bits in an address */
- 8, /* 8 bits in a byte */
- bfd_arch_tic30,
- 0, /* only 1 machine */
- "tic30",
- "tms320c30",
- 2,
- true, /* the one and only */
- bfd_default_compatible,
- bfd_default_scan,
- 0,
-};
diff --git a/contrib/binutils/bfd/cpu-v850.c b/contrib/binutils/bfd/cpu-v850.c
deleted file mode 100644
index 8836362..0000000
--- a/contrib/binutils/bfd/cpu-v850.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* BFD support for the NEC V850 processor
- Copyright 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-#include "safe-ctype.h"
-
-static boolean scan PARAMS ((const struct bfd_arch_info *, const char *));
-
-static boolean
-scan (info, string)
- const struct bfd_arch_info * info;
- const char * string;
-{
- const char *ptr_src;
- const char *ptr_tst;
- unsigned long number;
- enum bfd_architecture arch;
-
- /* First test for an exact match. */
- if (strcasecmp (string, info->printable_name) == 0)
- return true;
-
- /* See how much of the supplied string matches with the
- architecture, eg the string m68k:68020 would match the m68k entry
- up to the :, then we get left with the machine number. */
- for (ptr_src = string, ptr_tst = info->arch_name;
- *ptr_src && *ptr_tst;
- ptr_src++, ptr_tst++)
- if (*ptr_src != *ptr_tst)
- break;
-
- /* Chewed up as much of the architecture as will match;
- if there is a colon present skip it. */
- if (*ptr_src == ':')
- ptr_src ++;
-
- if (*ptr_src == 0)
- /* Nothing more, then only keep this one if it is
- the default machine for this architecture. */
- return info->the_default;
-
- number = 0;
- while (ISDIGIT (*ptr_src))
- {
- number = number * 10 + * ptr_src - '0';
- ptr_src ++;
- }
-
- switch (number)
- {
- case bfd_mach_v850e: arch = bfd_arch_v850; break;
- case bfd_mach_v850ea: arch = bfd_arch_v850; break;
- default:
- return false;
- }
-
- if (arch != info->arch)
- return false;
-
- if (number != info->mach)
- return false;
-
- return true;
-}
-
-#define N(number, print, default, next) \
-{ 32, 32, 8, bfd_arch_v850, number, "v850", print, 2, default, \
- bfd_default_compatible, scan, next }
-
-#define NEXT NULL
-
-static const bfd_arch_info_type arch_info_struct[] =
-{
- N (bfd_mach_v850e, "v850e", false, & arch_info_struct[1]),
- N (bfd_mach_v850ea, "v850ea", false, NULL)
-};
-
-#undef NEXT
-#define NEXT & arch_info_struct[0]
-
-const bfd_arch_info_type bfd_v850_arch =
- N (bfd_mach_v850, "v850", true, NEXT);
diff --git a/contrib/binutils/bfd/cpu-z8k.c b/contrib/binutils/bfd/cpu-z8k.c
deleted file mode 100644
index 0afdfc7..0000000
--- a/contrib/binutils/bfd/cpu-z8k.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* BFD library support routines for the Z800n architecture.
- Copyright 1992, 1993, 1994, 2000, 2001 Free Software Foundation, Inc.
- Hacked by Steve Chamberlain of Cygnus Support.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-
-static boolean scan_mach
- PARAMS ((const struct bfd_arch_info *, const char *));
-static const bfd_arch_info_type *compatible
- PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
-
-#if 0 /* not used currently */
-/*
-Relocations for the Z8K
-
-*/
-static bfd_reloc_status_type
-howto16_callback (abfd, reloc_entry, symbol_in, data,
- ignore_input_section, ignore_bfd)
- bfd *abfd;
- arelent *reloc_entry;
- struct symbol_cache_entry *symbol_in;
- PTR data;
- asection *ignore_input_section;
- bfd *ignore_bfd;
-{
- long relocation = 0;
- bfd_vma addr = reloc_entry->address;
- long x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
-
- HOWTO_PREPARE (relocation, symbol_in);
-
- x = (x + relocation + reloc_entry->addend);
-
- bfd_put_16 (abfd, x, (bfd_byte *) data + addr);
- return bfd_reloc_ok;
-}
-
-static bfd_reloc_status_type
-howto8_callback (abfd, reloc_entry, symbol_in, data,
- ignore_input_section, ignore_bfd)
- bfd *abfd;
- arelent *reloc_entry;
- struct symbol_cache_entry *symbol_in;
- PTR data;
- asection *ignore_input_section;
- bfd *ignore_bfd;
-{
- long relocation = 0;
- bfd_vma addr = reloc_entry->address;
- long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
-
- HOWTO_PREPARE (relocation, symbol_in);
-
- x = (x + relocation + reloc_entry->addend);
-
- bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
- return bfd_reloc_ok;
-}
-
-static bfd_reloc_status_type
-howto8_FFnn_callback (abfd, reloc_entry, symbol_in, data,
- ignore_input_section, ignore_bfd)
- bfd *abfd;
- arelent *reloc_entry;
- struct symbol_cache_entry *symbol_in;
- PTR data;
- asection *ignore_input_section;
- bfd *ignore_bfd;
-{
- long relocation = 0;
- bfd_vma addr = reloc_entry->address;
-
- long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
- abort ();
- HOWTO_PREPARE (relocation, symbol_in);
-
- x = (x + relocation + reloc_entry->addend);
-
- bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
- return bfd_reloc_ok;
-}
-
-static bfd_reloc_status_type
-howto8_pcrel_callback (abfd, reloc_entry, symbol_in, data,
- ignore_input_section, ignore_bfd)
- bfd *abfd;
- arelent *reloc_entry;
- struct symbol_cache_entry *symbol_in;
- PTR data;
- asection *ignore_input_section;
- bfd *ignore_bfd;
-{
- long relocation = 0;
- bfd_vma addr = reloc_entry->address;
- long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
- abort ();
- HOWTO_PREPARE (relocation, symbol_in);
-
- x = (x + relocation + reloc_entry->addend);
-
- bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
- return bfd_reloc_ok;
-}
-
-static reloc_howto_type howto_16
-= NEWHOWTO (howto16_callback, "abs16", 1, false, false);
-static reloc_howto_type howto_8
-= NEWHOWTO (howto8_callback, "abs8", 0, false, false);
-
-static reloc_howto_type howto_8_FFnn
-= NEWHOWTO (howto8_FFnn_callback, "ff00+abs8", 0, false, false);
-
-static reloc_howto_type howto_8_pcrel
-= NEWHOWTO (howto8_pcrel_callback, "pcrel8", 0, false, true);
-
-static reloc_howto_type *
-local_bfd_reloc_type_lookup (arch, code)
- const struct bfd_arch_info *arch;
- bfd_reloc_code_real_type code;
-{
- switch (code)
- {
- case BFD_RELOC_16:
- return &howto_16;
- case BFD_RELOC_8_FFnn:
- return &howto_8_FFnn;
- case BFD_RELOC_8:
- return &howto_8;
- case BFD_RELOC_8_PCREL:
- return &howto_8_pcrel;
- default:
- return (reloc_howto_type *) NULL;
- }
-}
-#endif
-
-static boolean
-scan_mach (info, string)
- const struct bfd_arch_info *info;
- const char *string;
-{
- if (strcmp (string, "z8001") == 0 || strcmp (string, "z8k") == 0)
- {
- return bfd_mach_z8001 == info->mach;
- }
- if (strcmp (string, "z8002") == 0)
- {
- return bfd_mach_z8002 == info->mach;
- }
- return false;
-}
-
-/* This routine is provided two arch_infos and returns whether
- they'd be compatible */
-
-static const bfd_arch_info_type *
-compatible (a, b)
- const bfd_arch_info_type *a;
- const bfd_arch_info_type *b;
-{
- if (a->arch != b->arch || a->mach != b->mach)
- return NULL;
- return a;
-}
-
-static const bfd_arch_info_type arch_info_struct[] =
-{
- {32, 32, 8, bfd_arch_z8k, bfd_mach_z8001, "z8k", "z8001", 1, false, compatible, scan_mach, 0,},
-};
-
-const bfd_arch_info_type bfd_z8k_arch =
-{
- 32, 16, 8, bfd_arch_z8k, bfd_mach_z8002, "z8k", "z8002", 1, true, compatible, scan_mach, &arch_info_struct[0],
-};
diff --git a/contrib/binutils/bfd/elf32-mips.c b/contrib/binutils/bfd/elf32-mips.c
deleted file mode 100644
index ddfe4a0..0000000
--- a/contrib/binutils/bfd/elf32-mips.c
+++ /dev/null
@@ -1,10405 +0,0 @@
-/* MIPS-specific support for 32-bit ELF
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
- Free Software Foundation, Inc.
-
- Most of the information added by Ian Lance Taylor, Cygnus Support,
- <ian@cygnus.com>.
- N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC.
- <mark@codesourcery.com>
- Traditional MIPS targets support added by Koundinya.K, Dansk Data
- Elektronik & Operations Research Group. <kk@ddeorg.soft.net>
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* This file handles MIPS ELF targets. SGI Irix 5 uses a slightly
- different MIPS ELF from other targets. This matters when linking.
- This file supports both, switching at runtime. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-#include "bfdlink.h"
-#include "genlink.h"
-#include "elf-bfd.h"
-#include "elf/mips.h"
-
-/* Get the ECOFF swapping routines. */
-#include "coff/sym.h"
-#include "coff/symconst.h"
-#include "coff/internal.h"
-#include "coff/ecoff.h"
-#include "coff/mips.h"
-#define ECOFF_SIGNED_32
-#include "ecoffswap.h"
-
-/* This structure is used to hold .got information when linking. It
- is stored in the tdata field of the bfd_elf_section_data structure. */
-
-struct mips_got_info
-{
- /* The global symbol in the GOT with the lowest index in the dynamic
- symbol table. */
- struct elf_link_hash_entry *global_gotsym;
- /* The number of global .got entries. */
- unsigned int global_gotno;
- /* The number of local .got entries. */
- unsigned int local_gotno;
- /* The number of local .got entries we have used. */
- unsigned int assigned_gotno;
-};
-
-/* The MIPS ELF linker needs additional information for each symbol in
- the global hash table. */
-
-struct mips_elf_link_hash_entry
-{
- struct elf_link_hash_entry root;
-
- /* External symbol information. */
- EXTR esym;
-
- /* Number of R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 relocs against
- this symbol. */
- unsigned int possibly_dynamic_relocs;
-
- /* If the R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 reloc is against
- a readonly section. */
- boolean readonly_reloc;
-
- /* The index of the first dynamic relocation (in the .rel.dyn
- section) against this symbol. */
- unsigned int min_dyn_reloc_index;
-
- /* We must not create a stub for a symbol that has relocations
- related to taking the function's address, i.e. any but
- R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
- p. 4-20. */
- boolean no_fn_stub;
-
- /* If there is a stub that 32 bit functions should use to call this
- 16 bit function, this points to the section containing the stub. */
- asection *fn_stub;
-
- /* Whether we need the fn_stub; this is set if this symbol appears
- in any relocs other than a 16 bit call. */
- boolean need_fn_stub;
-
- /* If there is a stub that 16 bit functions should use to call this
- 32 bit function, this points to the section containing the stub. */
- asection *call_stub;
-
- /* This is like the call_stub field, but it is used if the function
- being called returns a floating point value. */
- asection *call_fp_stub;
-
- /* Are we forced local? .*/
- boolean forced_local;
-};
-
-static bfd_reloc_status_type mips32_64bit_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-static reloc_howto_type *mips_rtype_to_howto
- PARAMS ((unsigned int));
-static void mips_info_to_howto_rel
- PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
-static void mips_info_to_howto_rela
- PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
-static void bfd_mips_elf32_swap_gptab_in
- PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
-static void bfd_mips_elf32_swap_gptab_out
- PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
-#if 0
-static void bfd_mips_elf_swap_msym_in
- PARAMS ((bfd *, const Elf32_External_Msym *, Elf32_Internal_Msym *));
-#endif
-static void bfd_mips_elf_swap_msym_out
- PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));
-static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));
-static boolean mips_elf_create_procedure_table
- PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *,
- struct ecoff_debug_info *));
-static INLINE int elf_mips_isa PARAMS ((flagword));
-static INLINE unsigned long elf_mips_mach PARAMS ((flagword));
-static INLINE char* elf_mips_abi_name PARAMS ((bfd *));
-static boolean mips_elf_is_local_label_name
- PARAMS ((bfd *, const char *));
-static struct bfd_hash_entry *mips_elf_link_hash_newfunc
- PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static int gptab_compare PARAMS ((const void *, const void *));
-static bfd_reloc_status_type mips16_jump_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips16_gprel_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static boolean mips_elf_create_compact_rel_section
- PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf_create_got_section
- PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_reloc_status_type mips_elf_final_gp
- PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
-static bfd_byte *elf32_mips_get_relocated_section_contents
- PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
- bfd_byte *, boolean, asymbol **));
-static asection *mips_elf_create_msym_section
- PARAMS ((bfd *));
-static void mips_elf_irix6_finish_dynamic_symbol
- PARAMS ((bfd *, const char *, Elf_Internal_Sym *));
-static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));
-static boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));
-static bfd_vma mips_elf_high PARAMS ((bfd_vma));
-static bfd_vma mips_elf_higher PARAMS ((bfd_vma));
-static bfd_vma mips_elf_highest PARAMS ((bfd_vma));
-static bfd_vma mips_elf_global_got_index
- PARAMS ((bfd *, struct elf_link_hash_entry *));
-static bfd_vma mips_elf_local_got_index
- PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
-static bfd_vma mips_elf_got_offset_from_index
- PARAMS ((bfd *, bfd *, bfd_vma));
-static boolean mips_elf_record_global_got_symbol
- PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *,
- struct mips_got_info *));
-static bfd_vma mips_elf_got_page
- PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
-static const Elf_Internal_Rela *mips_elf_next_relocation
- PARAMS ((unsigned int, const Elf_Internal_Rela *,
- const Elf_Internal_Rela *));
-static bfd_reloc_status_type mips_elf_calculate_relocation
- PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
- const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
- Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
- boolean *));
-static bfd_vma mips_elf_obtain_contents
- PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
-static boolean mips_elf_perform_relocation
- PARAMS ((struct bfd_link_info *, reloc_howto_type *,
- const Elf_Internal_Rela *, bfd_vma,
- bfd *, asection *, bfd_byte *, boolean));
-static boolean mips_elf_assign_gp PARAMS ((bfd *, bfd_vma *));
-static boolean mips_elf_sort_hash_table_f
- PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-static boolean mips_elf_sort_hash_table
- PARAMS ((struct bfd_link_info *, unsigned long));
-static asection * mips_elf_got_section PARAMS ((bfd *));
-static struct mips_got_info *mips_elf_got_info
- PARAMS ((bfd *, asection **));
-static boolean mips_elf_local_relocation_p
- PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, boolean));
-static bfd_vma mips_elf_create_local_got_entry
- PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));
-static bfd_vma mips_elf_got16_entry
- PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, boolean));
-static boolean mips_elf_create_dynamic_relocation
- PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
- struct mips_elf_link_hash_entry *, asection *,
- bfd_vma, bfd_vma *, asection *));
-static void mips_elf_allocate_dynamic_relocations
- PARAMS ((bfd *, unsigned int));
-static boolean mips_elf_stub_section_p
- PARAMS ((bfd *, asection *));
-static int sort_dynamic_relocs
- PARAMS ((const void *, const void *));
-static void _bfd_mips_elf_hide_symbol
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
-static void _bfd_mips_elf_copy_indirect_symbol
- PARAMS ((struct elf_link_hash_entry *,
- struct elf_link_hash_entry *));
-static boolean _bfd_elf32_mips_grok_prstatus
- PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean _bfd_elf32_mips_grok_psinfo
- PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean _bfd_elf32_mips_discard_info
- PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *));
-static boolean _bfd_elf32_mips_ignore_discarded_relocs
- PARAMS ((asection *));
-static boolean _bfd_elf32_mips_write_section
- PARAMS ((bfd *, asection *, bfd_byte *));
-
-extern const bfd_target bfd_elf32_tradbigmips_vec;
-extern const bfd_target bfd_elf32_tradlittlemips_vec;
-#ifdef BFD64
-extern const bfd_target bfd_elf64_tradbigmips_vec;
-extern const bfd_target bfd_elf64_tradlittlemips_vec;
-#endif
-
-/* The level of IRIX compatibility we're striving for. */
-
-typedef enum {
- ict_none,
- ict_irix5,
- ict_irix6
-} irix_compat_t;
-
-/* This will be used when we sort the dynamic relocation records. */
-static bfd *reldyn_sorting_bfd;
-
-/* Nonzero if ABFD is using the N32 ABI. */
-
-#define ABI_N32_P(abfd) \
- ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
-
-/* Nonzero if ABFD is using the 64-bit ABI. */
-#define ABI_64_P(abfd) \
- ((elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) != 0)
-
-/* Depending on the target vector we generate some version of Irix
- executables or "normal" MIPS ELF ABI executables. */
-#ifdef BFD64
-#define IRIX_COMPAT(abfd) \
- (((abfd->xvec == &bfd_elf64_tradbigmips_vec) || \
- (abfd->xvec == &bfd_elf64_tradlittlemips_vec) || \
- (abfd->xvec == &bfd_elf32_tradbigmips_vec) || \
- (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) ? ict_none : \
- ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))
-#else
-#define IRIX_COMPAT(abfd) \
- (((abfd->xvec == &bfd_elf32_tradbigmips_vec) || \
- (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) ? ict_none : \
- ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))
-#endif
-
-#define NEWABI_P(abfd) (ABI_N32_P(abfd) || ABI_64_P(abfd))
-
-/* Whether we are trying to be compatible with IRIX at all. */
-#define SGI_COMPAT(abfd) \
- (IRIX_COMPAT (abfd) != ict_none)
-
-/* The name of the msym section. */
-#define MIPS_ELF_MSYM_SECTION_NAME(abfd) ".msym"
-
-/* The name of the srdata section. */
-#define MIPS_ELF_SRDATA_SECTION_NAME(abfd) ".srdata"
-
-/* The name of the options section. */
-#define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \
- (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.options" : ".options")
-
-/* The name of the stub section. */
-#define MIPS_ELF_STUB_SECTION_NAME(abfd) \
- (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.stubs" : ".stub")
-
-/* The name of the dynamic relocation section. */
-#define MIPS_ELF_REL_DYN_SECTION_NAME(abfd) ".rel.dyn"
-
-/* The size of an external REL relocation. */
-#define MIPS_ELF_REL_SIZE(abfd) \
- (get_elf_backend_data (abfd)->s->sizeof_rel)
-
-/* The size of an external dynamic table entry. */
-#define MIPS_ELF_DYN_SIZE(abfd) \
- (get_elf_backend_data (abfd)->s->sizeof_dyn)
-
-/* The size of a GOT entry. */
-#define MIPS_ELF_GOT_SIZE(abfd) \
- (get_elf_backend_data (abfd)->s->arch_size / 8)
-
-/* The size of a symbol-table entry. */
-#define MIPS_ELF_SYM_SIZE(abfd) \
- (get_elf_backend_data (abfd)->s->sizeof_sym)
-
-/* The default alignment for sections, as a power of two. */
-#define MIPS_ELF_LOG_FILE_ALIGN(abfd) \
- (get_elf_backend_data (abfd)->s->file_align == 8 ? 3 : 2)
-
-/* Get word-sized data. */
-#define MIPS_ELF_GET_WORD(abfd, ptr) \
- (ABI_64_P (abfd) ? bfd_get_64 (abfd, ptr) : bfd_get_32 (abfd, ptr))
-
-/* Put out word-sized data. */
-#define MIPS_ELF_PUT_WORD(abfd, val, ptr) \
- (ABI_64_P (abfd) \
- ? bfd_put_64 (abfd, val, ptr) \
- : bfd_put_32 (abfd, val, ptr))
-
-/* Add a dynamic symbol table-entry. */
-#ifdef BFD64
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
- (ABI_64_P (elf_hash_table (info)->dynobj) \
- ? bfd_elf64_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val) \
- : bfd_elf32_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
-#else
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
- (ABI_64_P (elf_hash_table (info)->dynobj) \
- ? (boolean) (abort (), false) \
- : bfd_elf32_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
-#endif
-
-/* The number of local .got entries we reserve. */
-#define MIPS_RESERVED_GOTNO (2)
-
-/* Instructions which appear in a stub. For some reason the stub is
- slightly different on an SGI system. */
-#define ELF_MIPS_GP_OFFSET(abfd) (SGI_COMPAT (abfd) ? 0x7ff0 : 0x8000)
-#define STUB_LW(abfd) \
- (SGI_COMPAT (abfd) \
- ? (ABI_64_P (abfd) \
- ? 0xdf998010 /* ld t9,0x8010(gp) */ \
- : 0x8f998010) /* lw t9,0x8010(gp) */ \
- : 0x8f998010) /* lw t9,0x8000(gp) */
-#define STUB_MOVE(abfd) \
- (SGI_COMPAT (abfd) ? 0x03e07825 : 0x03e07821) /* move t7,ra */
-#define STUB_JALR 0x0320f809 /* jal t9 */
-#define STUB_LI16(abfd) \
- (SGI_COMPAT (abfd) ? 0x34180000 : 0x24180000) /* ori t8,zero,0 */
-#define MIPS_FUNCTION_STUB_SIZE (16)
-
-#if 0
-/* We no longer try to identify particular sections for the .dynsym
- section. When we do, we wind up crashing if there are other random
- sections with relocations. */
-
-/* Names of sections which appear in the .dynsym section in an Irix 5
- executable. */
-
-static const char * const mips_elf_dynsym_sec_names[] =
-{
- ".text",
- ".init",
- ".fini",
- ".data",
- ".rodata",
- ".sdata",
- ".sbss",
- ".bss",
- NULL
-};
-
-#define SIZEOF_MIPS_DYNSYM_SECNAMES \
- (sizeof mips_elf_dynsym_sec_names / sizeof mips_elf_dynsym_sec_names[0])
-
-/* The number of entries in mips_elf_dynsym_sec_names which go in the
- text segment. */
-
-#define MIPS_TEXT_DYNSYM_SECNO (3)
-
-#endif /* 0 */
-
-/* The names of the runtime procedure table symbols used on Irix 5. */
-
-static const char * const mips_elf_dynsym_rtproc_names[] =
-{
- "_procedure_table",
- "_procedure_string_table",
- "_procedure_table_size",
- NULL
-};
-
-/* These structures are used to generate the .compact_rel section on
- Irix 5. */
-
-typedef struct
-{
- unsigned long id1; /* Always one? */
- unsigned long num; /* Number of compact relocation entries. */
- unsigned long id2; /* Always two? */
- unsigned long offset; /* The file offset of the first relocation. */
- unsigned long reserved0; /* Zero? */
- unsigned long reserved1; /* Zero? */
-} Elf32_compact_rel;
-
-typedef struct
-{
- bfd_byte id1[4];
- bfd_byte num[4];
- bfd_byte id2[4];
- bfd_byte offset[4];
- bfd_byte reserved0[4];
- bfd_byte reserved1[4];
-} Elf32_External_compact_rel;
-
-typedef struct
-{
- unsigned int ctype : 1; /* 1: long 0: short format. See below. */
- unsigned int rtype : 4; /* Relocation types. See below. */
- unsigned int dist2to : 8;
- unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */
- unsigned long konst; /* KONST field. See below. */
- unsigned long vaddr; /* VADDR to be relocated. */
-} Elf32_crinfo;
-
-typedef struct
-{
- unsigned int ctype : 1; /* 1: long 0: short format. See below. */
- unsigned int rtype : 4; /* Relocation types. See below. */
- unsigned int dist2to : 8;
- unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */
- unsigned long konst; /* KONST field. See below. */
-} Elf32_crinfo2;
-
-typedef struct
-{
- bfd_byte info[4];
- bfd_byte konst[4];
- bfd_byte vaddr[4];
-} Elf32_External_crinfo;
-
-typedef struct
-{
- bfd_byte info[4];
- bfd_byte konst[4];
-} Elf32_External_crinfo2;
-
-/* These are the constants used to swap the bitfields in a crinfo. */
-
-#define CRINFO_CTYPE (0x1)
-#define CRINFO_CTYPE_SH (31)
-#define CRINFO_RTYPE (0xf)
-#define CRINFO_RTYPE_SH (27)
-#define CRINFO_DIST2TO (0xff)
-#define CRINFO_DIST2TO_SH (19)
-#define CRINFO_RELVADDR (0x7ffff)
-#define CRINFO_RELVADDR_SH (0)
-
-/* A compact relocation info has long (3 words) or short (2 words)
- formats. A short format doesn't have VADDR field and relvaddr
- fields contains ((VADDR - vaddr of the previous entry) >> 2). */
-#define CRF_MIPS_LONG 1
-#define CRF_MIPS_SHORT 0
-
-/* There are 4 types of compact relocation at least. The value KONST
- has different meaning for each type:
-
- (type) (konst)
- CT_MIPS_REL32 Address in data
- CT_MIPS_WORD Address in word (XXX)
- CT_MIPS_GPHI_LO GP - vaddr
- CT_MIPS_JMPAD Address to jump
- */
-
-#define CRT_MIPS_REL32 0xa
-#define CRT_MIPS_WORD 0xb
-#define CRT_MIPS_GPHI_LO 0xc
-#define CRT_MIPS_JMPAD 0xd
-
-#define mips_elf_set_cr_format(x,format) ((x).ctype = (format))
-#define mips_elf_set_cr_type(x,type) ((x).rtype = (type))
-#define mips_elf_set_cr_dist2to(x,v) ((x).dist2to = (v))
-#define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2)
-
-static void bfd_elf32_swap_compact_rel_out
- PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
-static void bfd_elf32_swap_crinfo_out
- PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
-
-/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
- from smaller values. Start with zero, widen, *then* decrement. */
-#define MINUS_ONE (((bfd_vma)0) - 1)
-
-/* The relocation table used for SHT_REL sections. */
-
-static reloc_howto_type elf_mips_howto_table_rel[] =
-{
- /* No relocation. */
- HOWTO (R_MIPS_NONE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_NONE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit relocation. */
- HOWTO (R_MIPS_16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit relocation. */
- HOWTO (R_MIPS_32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit symbol relative relocation. */
- HOWTO (R_MIPS_REL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 26 bit jump address. */
- HOWTO (R_MIPS_26, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper four
- bits must match the PC + 4. */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_26", /* name */
- true, /* partial_inplace */
- 0x03ffffff, /* src_mask */
- 0x03ffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of symbol value. */
- HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_mips_elf_hi16_reloc, /* special_function */
- "R_MIPS_HI16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of symbol value. */
- HOWTO (R_MIPS_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_mips_elf_lo16_reloc, /* special_function */
- "R_MIPS_LO16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GP relative reference. */
- HOWTO (R_MIPS_GPREL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- _bfd_mips_elf_gprel16_reloc, /* special_function */
- "R_MIPS_GPREL16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to literal section. */
- HOWTO (R_MIPS_LITERAL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- _bfd_mips_elf_gprel16_reloc, /* special_function */
- "R_MIPS_LITERAL", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to global offset table. */
- HOWTO (R_MIPS_GOT16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- _bfd_mips_elf_got16_reloc, /* special_function */
- "R_MIPS_GOT16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit PC relative reference. */
- HOWTO (R_MIPS_PC16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_PC16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 16 bit call through global offset table. */
- HOWTO (R_MIPS_CALL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit GP relative reference. */
- HOWTO (R_MIPS_GPREL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_mips_elf_gprel32_reloc, /* special_function */
- "R_MIPS_GPREL32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* The remaining relocs are defined on Irix 5, although they are
- not defined by the ABI. */
- EMPTY_HOWTO (13),
- EMPTY_HOWTO (14),
- EMPTY_HOWTO (15),
-
- /* A 5 bit shift field. */
- HOWTO (R_MIPS_SHIFT5, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 5, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SHIFT5", /* name */
- true, /* partial_inplace */
- 0x000007c0, /* src_mask */
- 0x000007c0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 6 bit shift field. */
- /* FIXME: This is not handled correctly; a special function is
- needed to put the most significant bit in the right place. */
- HOWTO (R_MIPS_SHIFT6, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 6, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SHIFT6", /* name */
- true, /* partial_inplace */
- 0x000007c4, /* src_mask */
- 0x000007c4, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 64 bit relocation. */
- HOWTO (R_MIPS_64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips32_64bit_reloc, /* special_function */
- "R_MIPS_64", /* name */
- true, /* partial_inplace */
- MINUS_ONE, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement in the global offset table. */
- HOWTO (R_MIPS_GOT_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_DISP", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement to page pointer in the global offset table. */
- HOWTO (R_MIPS_GOT_PAGE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_PAGE", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Offset from page pointer in the global offset table. */
- HOWTO (R_MIPS_GOT_OFST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_OFST", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- HOWTO (R_MIPS_GOT_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_HI16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- HOWTO (R_MIPS_GOT_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_LO16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit subtraction. Used in the N32 ABI. */
- HOWTO (R_MIPS_SUB, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SUB", /* name */
- true, /* partial_inplace */
- MINUS_ONE, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used to cause the linker to insert and delete instructions? */
- EMPTY_HOWTO (R_MIPS_INSERT_A),
- EMPTY_HOWTO (R_MIPS_INSERT_B),
- EMPTY_HOWTO (R_MIPS_DELETE),
-
- /* Get the higher value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHER, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HIGHER", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the highest value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHEST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HIGHEST", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- HOWTO (R_MIPS_CALL_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_HI16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- HOWTO (R_MIPS_CALL_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_LO16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Section displacement. */
- HOWTO (R_MIPS_SCN_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SCN_DISP", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- EMPTY_HOWTO (R_MIPS_REL16),
- EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
- EMPTY_HOWTO (R_MIPS_PJUMP),
- EMPTY_HOWTO (R_MIPS_RELGOT),
-
- /* Protected jump conversion. This is an optimization hint. No
- relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
- false, /* partial_inplace */
- 0x00000000, /* src_mask */
- 0x00000000, /* dst_mask */
- false), /* pcrel_offset */
-};
-
-/* The relocation table used for SHT_RELA sections. */
-
-static reloc_howto_type elf_mips_howto_table_rela[] =
-{
- /* No relocation. */
- HOWTO (R_MIPS_NONE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_NONE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit relocation. */
- HOWTO (R_MIPS_16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit relocation. */
- HOWTO (R_MIPS_32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit symbol relative relocation. */
- HOWTO (R_MIPS_REL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 26 bit jump address. */
- HOWTO (R_MIPS_26, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper 36
- bits must match the PC + 4. */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_26", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x03ffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* R_MIPS_HI16 and R_MIPS_LO16 are unsupported for 64 bit REL. */
- /* High 16 bits of symbol value. */
- HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of symbol value. */
- HOWTO (R_MIPS_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_LO16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GP relative reference. */
- HOWTO (R_MIPS_GPREL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- _bfd_mips_elf_gprel16_reloc, /* special_function */
- "R_MIPS_GPREL16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to literal section. */
- HOWTO (R_MIPS_LITERAL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- _bfd_mips_elf_gprel16_reloc, /* special_function */
- "R_MIPS_LITERAL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to global offset table. */
- /* FIXME: This is not handled correctly. */
- HOWTO (R_MIPS_GOT16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit PC relative reference. */
- HOWTO (R_MIPS_PC16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_PC16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 16 bit call through global offset table. */
- /* FIXME: This is not handled correctly. */
- HOWTO (R_MIPS_CALL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit GP relative reference. */
- HOWTO (R_MIPS_GPREL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_mips_elf_gprel32_reloc, /* special_function */
- "R_MIPS_GPREL32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- EMPTY_HOWTO (13),
- EMPTY_HOWTO (14),
- EMPTY_HOWTO (15),
-
- /* A 5 bit shift field. */
- HOWTO (R_MIPS_SHIFT5, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 5, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SHIFT5", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x000007c0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 6 bit shift field. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SHIFT6, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 6, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SHIFT6", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x000007c4, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit relocation. */
- HOWTO (R_MIPS_64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_DISP", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement to page pointer in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_PAGE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_PAGE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Offset from page pointer in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_OFST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_OFST", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_LO16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit substraction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SUB, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SUB", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Insert the addend as an instruction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_INSERT_A, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_INSERT_A", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Insert the addend as an instruction, and change all relocations
- to refer to the old instruction at the address. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_INSERT_B, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_INSERT_B", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Delete a 32 bit instruction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_DELETE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_DELETE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the higher value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHER, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HIGHER", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the highest value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHEST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HIGHEST", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_CALL_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_CALL_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_LO16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Section displacement, used by an associated event location section. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SCN_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SCN_DISP", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_MIPS_REL16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* These two are obsolete. */
- EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
- EMPTY_HOWTO (R_MIPS_PJUMP),
-
- /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
- It must be used for multigot GOT's (and only there). */
- HOWTO (R_MIPS_RELGOT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_RELGOT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Protected jump conversion. This is an optimization hint. No
- relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-};
-
-/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This
- is a hack to make the linker think that we need 64 bit values. */
-static reloc_howto_type elf_mips_ctor64_howto =
- HOWTO (R_MIPS_64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips32_64bit_reloc, /* special_function */
- "R_MIPS_64", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false); /* pcrel_offset */
-
-/* The reloc used for the mips16 jump instruction. */
-static reloc_howto_type elf_mips16_jump_howto =
- HOWTO (R_MIPS16_26, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper four
- bits must match the PC. */
- mips16_jump_reloc, /* special_function */
- "R_MIPS16_26", /* name */
- true, /* partial_inplace */
- 0x3ffffff, /* src_mask */
- 0x3ffffff, /* dst_mask */
- false); /* pcrel_offset */
-
-/* The reloc used for the mips16 gprel instruction. */
-static reloc_howto_type elf_mips16_gprel_howto =
- HOWTO (R_MIPS16_GPREL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips16_gprel_reloc, /* special_function */
- "R_MIPS16_GPREL", /* name */
- true, /* partial_inplace */
- 0x07ff001f, /* src_mask */
- 0x07ff001f, /* dst_mask */
- false); /* pcrel_offset */
-
-/* GNU extensions for embedded-pic. */
-/* High 16 bits of symbol value, pc-relative. */
-static reloc_howto_type elf_mips_gnu_rel_hi16 =
- HOWTO (R_MIPS_GNU_REL_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_mips_elf_hi16_reloc, /* special_function */
- "R_MIPS_GNU_REL_HI16", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- true); /* pcrel_offset */
-
-/* Low 16 bits of symbol value, pc-relative. */
-static reloc_howto_type elf_mips_gnu_rel_lo16 =
- HOWTO (R_MIPS_GNU_REL_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_mips_elf_lo16_reloc, /* special_function */
- "R_MIPS_GNU_REL_LO16", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- true); /* pcrel_offset */
-
-/* 16 bit offset for pc-relative branches. */
-static reloc_howto_type elf_mips_gnu_rel16_s2 =
- HOWTO (R_MIPS_GNU_REL16_S2, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GNU_REL16_S2", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- true); /* pcrel_offset */
-
-/* 64 bit pc-relative. */
-static reloc_howto_type elf_mips_gnu_pcrel64 =
- HOWTO (R_MIPS_PC64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_PC64", /* name */
- true, /* partial_inplace */
- MINUS_ONE, /* src_mask */
- MINUS_ONE, /* dst_mask */
- true); /* pcrel_offset */
-
-/* 32 bit pc-relative. */
-static reloc_howto_type elf_mips_gnu_pcrel32 =
- HOWTO (R_MIPS_PC32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_PC32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- true); /* pcrel_offset */
-
-/* GNU extension to record C++ vtable hierarchy */
-static reloc_howto_type elf_mips_gnu_vtinherit_howto =
- HOWTO (R_MIPS_GNU_VTINHERIT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- NULL, /* special_function */
- "R_MIPS_GNU_VTINHERIT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false); /* pcrel_offset */
-
-/* GNU extension to record C++ vtable member usage */
-static reloc_howto_type elf_mips_gnu_vtentry_howto =
- HOWTO (R_MIPS_GNU_VTENTRY, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_elf_rel_vtable_reloc_fn, /* special_function */
- "R_MIPS_GNU_VTENTRY", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false); /* pcrel_offset */
-
-/* Do a R_MIPS_HI16 relocation. This has to be done in combination
- with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
- the HI16. Here we just save the information we need; we do the
- actual relocation when we see the LO16.
-
- MIPS ELF requires that the LO16 immediately follow the HI16. As a
- GNU extension, for non-pc-relative relocations, we permit an
- arbitrary number of HI16 relocs to be associated with a single LO16
- reloc. This extension permits gcc to output the HI and LO relocs
- itself.
-
- This cannot be done for PC-relative relocations because both the HI16
- and LO16 parts of the relocations must be done relative to the LO16
- part, and there can be carry to or borrow from the HI16 part. */
-
-struct mips_hi16
-{
- struct mips_hi16 *next;
- bfd_byte *addr;
- bfd_vma addend;
-};
-
-/* FIXME: This should not be a static variable. */
-
-static struct mips_hi16 *mips_hi16_list;
-
-bfd_reloc_status_type
-_bfd_mips_elf_hi16_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct mips_hi16 *n;
-
- /* If we're relocating, and this an external symbol, we don't want
- to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- ret = bfd_reloc_ok;
-
- if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
- {
- boolean relocateable;
- bfd_vma gp;
-
- if (ret == bfd_reloc_undefined)
- abort ();
-
- if (output_bfd != NULL)
- relocateable = true;
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
- }
-
- ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
- error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- relocation = gp - reloc_entry->address;
- }
- else
- {
- if (bfd_is_und_section (symbol->section)
- && output_bfd == (bfd *) NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
- }
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Save the information, and let LO16 do the actual relocation. */
- n = (struct mips_hi16 *) bfd_malloc ((bfd_size_type) sizeof *n);
- if (n == NULL)
- return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = mips_hi16_list;
- mips_hi16_list = n;
-
- if (output_bfd != (bfd *) NULL)
- reloc_entry->address += input_section->output_offset;
-
- return ret;
-}
-
-/* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit
- inplace relocation; this function exists in order to do the
- R_MIPS_HI16 relocation described above. */
-
-bfd_reloc_status_type
-_bfd_mips_elf_lo16_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- arelent gp_disp_relent;
-
- if (mips_hi16_list != NULL)
- {
- struct mips_hi16 *l;
-
- l = mips_hi16_list;
- while (l != NULL)
- {
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
- struct mips_hi16 *next;
-
- /* Do the HI16 relocation. Note that we actually don't need
- to know anything about the LO16 itself, except where to
- find the low 16 bits of the addend needed by the LO16. */
- insn = bfd_get_32 (abfd, l->addr);
- vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* The low order 16 bits are always treated as a signed
- value. */
- vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
- val = ((insn & 0xffff) << 16) + vallo;
- val += l->addend;
-
- /* If PC-relative, we need to subtract out the address of the LO
- half of the HI/LO. (The actual relocation is relative
- to that instruction.) */
- if (reloc_entry->howto->pc_relative)
- val -= reloc_entry->address;
-
- /* At this point, "val" has the value of the combined HI/LO
- pair. If the low order 16 bits (which will be used for
- the LO16 insn) are negative, then we will need an
- adjustment for the high order 16 bits. */
- val += 0x8000;
- val = (val >> 16) & 0xffff;
-
- insn &= ~ (bfd_vma) 0xffff;
- insn |= val;
- bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
-
- if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
- {
- gp_disp_relent = *reloc_entry;
- reloc_entry = &gp_disp_relent;
- reloc_entry->addend = l->addend;
- }
-
- next = l->next;
- free (l);
- l = next;
- }
-
- mips_hi16_list = NULL;
- }
- else if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
- {
- bfd_reloc_status_type ret;
- bfd_vma gp, relocation;
-
- /* FIXME: Does this case ever occur? */
-
- ret = mips_elf_final_gp (output_bfd, symbol, true, error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- relocation = gp - reloc_entry->address;
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- gp_disp_relent = *reloc_entry;
- reloc_entry = &gp_disp_relent;
- reloc_entry->addend = relocation - 4;
- }
-
- /* Now do the LO16 reloc in the usual way. */
- return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
-}
-
-/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
- table used for PIC code. If the symbol is an external symbol, the
- instruction is modified to contain the offset of the appropriate
- entry in the global offset table. If the symbol is a section
- symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
- addends are combined to form the real addend against the section
- symbol; the GOT16 is modified to contain the offset of an entry in
- the global offset table, and the LO16 is modified to offset it
- appropriately. Thus an offset larger than 16 bits requires a
- modified value in the global offset table.
-
- This implementation suffices for the assembler, but the linker does
- not yet know how to create global offset tables. */
-
-bfd_reloc_status_type
-_bfd_mips_elf_got16_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- /* If we're relocating, and this an external symbol, we don't want
- to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* If we're relocating, and this is a local symbol, we can handle it
- just like HI16. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) != 0)
- return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
-
- abort ();
-}
-
-/* Set the GP value for OUTPUT_BFD. Returns false if this is a
- dangerous relocation. */
-
-static boolean
-mips_elf_assign_gp (output_bfd, pgp)
- bfd *output_bfd;
- bfd_vma *pgp;
-{
- unsigned int count;
- asymbol **sym;
- unsigned int i;
-
- /* If we've already figured out what GP will be, just return it. */
- *pgp = _bfd_get_gp_value (output_bfd);
- if (*pgp)
- return true;
-
- count = bfd_get_symcount (output_bfd);
- sym = bfd_get_outsymbols (output_bfd);
-
- /* The linker script will have created a symbol named `_gp' with the
- appropriate value. */
- if (sym == (asymbol **) NULL)
- i = count;
- else
- {
- for (i = 0; i < count; i++, sym++)
- {
- register const char *name;
-
- name = bfd_asymbol_name (*sym);
- if (*name == '_' && strcmp (name, "_gp") == 0)
- {
- *pgp = bfd_asymbol_value (*sym);
- _bfd_set_gp_value (output_bfd, *pgp);
- break;
- }
- }
- }
-
- if (i >= count)
- {
- /* Only get the error once. */
- *pgp = 4;
- _bfd_set_gp_value (output_bfd, *pgp);
- return false;
- }
-
- return true;
-}
-
-/* We have to figure out the gp value, so that we can adjust the
- symbol value correctly. We look up the symbol _gp in the output
- BFD. If we can't find it, we're stuck. We cache it in the ELF
- target data. We don't need to adjust the symbol value for an
- external symbol if we are producing relocateable output. */
-
-static bfd_reloc_status_type
-mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
- bfd *output_bfd;
- asymbol *symbol;
- boolean relocateable;
- char **error_message;
- bfd_vma *pgp;
-{
- if (bfd_is_und_section (symbol->section)
- && ! relocateable)
- {
- *pgp = 0;
- return bfd_reloc_undefined;
- }
-
- *pgp = _bfd_get_gp_value (output_bfd);
- if (*pgp == 0
- && (! relocateable
- || (symbol->flags & BSF_SECTION_SYM) != 0))
- {
- if (relocateable)
- {
- /* Make up a value. */
- *pgp = symbol->section->output_section->vma + 0x4000;
- _bfd_set_gp_value (output_bfd, *pgp);
- }
- else if (!mips_elf_assign_gp (output_bfd, pgp))
- {
- *error_message =
- (char *) _("GP relative relocation when _gp not defined");
- return bfd_reloc_dangerous;
- }
- }
-
- return bfd_reloc_ok;
-}
-
-/* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
- become the offset from the gp register. This function also handles
- R_MIPS_LITERAL relocations, although those can be handled more
- cleverly because the entries in the .lit8 and .lit4 sections can be
- merged. */
-
-static bfd_reloc_status_type gprel16_with_gp PARAMS ((bfd *, asymbol *,
- arelent *, asection *,
- boolean, PTR, bfd_vma));
-
-bfd_reloc_status_type
-_bfd_mips_elf_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_reloc_status_type ret;
- bfd_vma gp;
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ELF
- file. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (output_bfd != (bfd *) NULL)
- relocateable = true;
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
- }
-
- ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message,
- &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- return gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
- relocateable, data, gp);
-}
-
-static bfd_reloc_status_type
-gprel16_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
- gp)
- bfd *abfd;
- asymbol *symbol;
- arelent *reloc_entry;
- asection *input_section;
- boolean relocateable;
- PTR data;
- bfd_vma gp;
-{
- bfd_vma relocation;
- unsigned long insn;
- unsigned long val;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* Set val to the offset into the section or symbol. */
- if (reloc_entry->howto->src_mask == 0)
- {
- /* This case occurs with the 64-bit MIPS ELF ABI. */
- val = reloc_entry->addend;
- }
- else
- {
- val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
- if (val & 0x8000)
- val -= 0x10000;
- }
-
- /* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
- an external symbol. */
- if (! relocateable
- || (symbol->flags & BSF_SECTION_SYM) != 0)
- val += relocation - gp;
-
- insn = (insn & ~0xffff) | (val & 0xffff);
- bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
-
- if (relocateable)
- reloc_entry->address += input_section->output_offset;
-
- /* Make sure it fit in 16 bits. */
- if ((long) val >= 0x8000 || (long) val < -0x8000)
- return bfd_reloc_overflow;
-
- return bfd_reloc_ok;
-}
-
-/* Do a R_MIPS_GPREL32 relocation. Is this 32 bit value the offset
- from the gp register? XXX */
-
-static bfd_reloc_status_type gprel32_with_gp PARAMS ((bfd *, asymbol *,
- arelent *, asection *,
- boolean, PTR, bfd_vma));
-
-bfd_reloc_status_type
-_bfd_mips_elf_gprel32_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_reloc_status_type ret;
- bfd_vma gp;
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ELF
- file. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- *error_message = (char *)
- _("32bits gp relative relocation occurs for an external symbol");
- return bfd_reloc_outofrange;
- }
-
- if (output_bfd != (bfd *) NULL)
- {
- relocateable = true;
- gp = _bfd_get_gp_value (output_bfd);
- }
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
-
- ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
- error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
- }
-
- return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
- relocateable, data, gp);
-}
-
-static bfd_reloc_status_type
-gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
- gp)
- bfd *abfd;
- asymbol *symbol;
- arelent *reloc_entry;
- asection *input_section;
- boolean relocateable;
- PTR data;
- bfd_vma gp;
-{
- bfd_vma relocation;
- unsigned long val;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- if (reloc_entry->howto->src_mask == 0)
- {
- /* This case arises with the 64-bit MIPS ELF ABI. */
- val = 0;
- }
- else
- val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* Set val to the offset into the section or symbol. */
- val += reloc_entry->addend;
-
- /* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
- an external symbol. */
- if (! relocateable
- || (symbol->flags & BSF_SECTION_SYM) != 0)
- val += relocation - gp;
-
- bfd_put_32 (abfd, (bfd_vma) val, (bfd_byte *) data + reloc_entry->address);
-
- if (relocateable)
- reloc_entry->address += input_section->output_offset;
-
- return bfd_reloc_ok;
-}
-
-/* Handle a 64 bit reloc in a 32 bit MIPS ELF file. These are
- generated when addresses are 64 bits. The upper 32 bits are a simple
- sign extension. */
-
-static bfd_reloc_status_type
-mips32_64bit_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- bfd_reloc_status_type r;
- arelent reloc32;
- unsigned long val;
- bfd_size_type addr;
-
- r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
- if (r != bfd_reloc_continue)
- return r;
-
- /* Do a normal 32 bit relocation on the lower 32 bits. */
- reloc32 = *reloc_entry;
- if (bfd_big_endian (abfd))
- reloc32.address += 4;
- reloc32.howto = &elf_mips_howto_table_rel[R_MIPS_32];
- r = bfd_perform_relocation (abfd, &reloc32, data, input_section,
- output_bfd, error_message);
-
- /* Sign extend into the upper 32 bits. */
- val = bfd_get_32 (abfd, (bfd_byte *) data + reloc32.address);
- if ((val & 0x80000000) != 0)
- val = 0xffffffff;
- else
- val = 0;
- addr = reloc_entry->address;
- if (bfd_little_endian (abfd))
- addr += 4;
- bfd_put_32 (abfd, (bfd_vma) val, (bfd_byte *) data + addr);
-
- return r;
-}
-
-/* Handle a mips16 jump. */
-
-static bfd_reloc_status_type
-mips16_jump_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* FIXME. */
- {
- static boolean warned;
-
- if (! warned)
- (*_bfd_error_handler)
- (_("Linking mips16 objects into %s format is not supported"),
- bfd_get_target (input_section->output_section->owner));
- warned = true;
- }
-
- return bfd_reloc_undefined;
-}
-
-/* Handle a mips16 GP relative reloc. */
-
-static bfd_reloc_status_type
-mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_reloc_status_type ret;
- bfd_vma gp;
- unsigned short extend, insn;
- unsigned long final;
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ELF
- file. */
- if (output_bfd != NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (output_bfd != NULL)
- relocateable = true;
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
- }
-
- ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message,
- &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Pick up the mips16 extend instruction and the real instruction. */
- extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
- insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
-
- /* Stuff the current addend back as a 32 bit value, do the usual
- relocation, and then clean up. */
- bfd_put_32 (abfd,
- (bfd_vma) (((extend & 0x1f) << 11)
- | (extend & 0x7e0)
- | (insn & 0x1f)),
- (bfd_byte *) data + reloc_entry->address);
-
- ret = gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
- relocateable, data, gp);
-
- final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
- bfd_put_16 (abfd,
- (bfd_vma) ((extend & 0xf800)
- | ((final >> 11) & 0x1f)
- | (final & 0x7e0)),
- (bfd_byte *) data + reloc_entry->address);
- bfd_put_16 (abfd,
- (bfd_vma) ((insn & 0xffe0)
- | (final & 0x1f)),
- (bfd_byte *) data + reloc_entry->address + 2);
-
- return ret;
-}
-
-/* Return the ISA for a MIPS e_flags value. */
-
-static INLINE int
-elf_mips_isa (flags)
- flagword flags;
-{
- switch (flags & EF_MIPS_ARCH)
- {
- case E_MIPS_ARCH_1:
- return 1;
- case E_MIPS_ARCH_2:
- return 2;
- case E_MIPS_ARCH_3:
- return 3;
- case E_MIPS_ARCH_4:
- return 4;
- case E_MIPS_ARCH_5:
- return 5;
- case E_MIPS_ARCH_32:
- return 32;
- case E_MIPS_ARCH_64:
- return 64;
- }
- return 4;
-}
-
-/* Return the MACH for a MIPS e_flags value. */
-
-static INLINE unsigned long
-elf_mips_mach (flags)
- flagword flags;
-{
- switch (flags & EF_MIPS_MACH)
- {
- case E_MIPS_MACH_3900:
- return bfd_mach_mips3900;
-
- case E_MIPS_MACH_4010:
- return bfd_mach_mips4010;
-
- case E_MIPS_MACH_4100:
- return bfd_mach_mips4100;
-
- case E_MIPS_MACH_4111:
- return bfd_mach_mips4111;
-
- case E_MIPS_MACH_4650:
- return bfd_mach_mips4650;
-
- case E_MIPS_MACH_SB1:
- return bfd_mach_mips_sb1;
-
- default:
- switch (flags & EF_MIPS_ARCH)
- {
- default:
- case E_MIPS_ARCH_1:
- return bfd_mach_mips3000;
- break;
-
- case E_MIPS_ARCH_2:
- return bfd_mach_mips6000;
- break;
-
- case E_MIPS_ARCH_3:
- return bfd_mach_mips4000;
- break;
-
- case E_MIPS_ARCH_4:
- return bfd_mach_mips8000;
- break;
-
- case E_MIPS_ARCH_5:
- return bfd_mach_mips5;
- break;
-
- case E_MIPS_ARCH_32:
- return bfd_mach_mipsisa32;
- break;
-
- case E_MIPS_ARCH_64:
- return bfd_mach_mipsisa64;
- break;
- }
- }
-
- return 0;
-}
-
-/* Return printable name for ABI. */
-
-static INLINE char *
-elf_mips_abi_name (abfd)
- bfd *abfd;
-{
- flagword flags;
-
- flags = elf_elfheader (abfd)->e_flags;
- switch (flags & EF_MIPS_ABI)
- {
- case 0:
- if (ABI_N32_P (abfd))
- return "N32";
- else if (ABI_64_P (abfd))
- return "64";
- else
- return "none";
- case E_MIPS_ABI_O32:
- return "O32";
- case E_MIPS_ABI_O64:
- return "O64";
- case E_MIPS_ABI_EABI32:
- return "EABI32";
- case E_MIPS_ABI_EABI64:
- return "EABI64";
- default:
- return "unknown abi";
- }
-}
-
-/* A mapping from BFD reloc types to MIPS ELF reloc types. */
-
-struct elf_reloc_map {
- bfd_reloc_code_real_type bfd_reloc_val;
- enum elf_mips_reloc_type elf_reloc_val;
-};
-
-static const struct elf_reloc_map mips_reloc_map[] =
-{
- { BFD_RELOC_NONE, R_MIPS_NONE, },
- { BFD_RELOC_16, R_MIPS_16 },
- { BFD_RELOC_32, R_MIPS_32 },
- { BFD_RELOC_64, R_MIPS_64 },
- { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
- { BFD_RELOC_HI16_S, R_MIPS_HI16 },
- { BFD_RELOC_LO16, R_MIPS_LO16 },
- { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
- { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
- { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
- { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
- { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
- { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
- { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
- { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
- { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
- { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
- { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
- { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
- { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
- { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }
-};
-
-/* Given a BFD reloc type, return a howto structure. */
-
-static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_lookup (abfd, code)
- bfd *abfd;
- bfd_reloc_code_real_type code;
-{
- unsigned int i;
-
- for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
- {
- if (mips_reloc_map[i].bfd_reloc_val == code)
- return &elf_mips_howto_table_rel[(int) mips_reloc_map[i].elf_reloc_val];
- }
-
- switch (code)
- {
- default:
- bfd_set_error (bfd_error_bad_value);
- return NULL;
-
- case BFD_RELOC_CTOR:
- /* We need to handle BFD_RELOC_CTOR specially.
- Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
- size of addresses on this architecture. */
- if (bfd_arch_bits_per_address (abfd) == 32)
- return &elf_mips_howto_table_rel[(int) R_MIPS_32];
- else
- return &elf_mips_ctor64_howto;
-
- case BFD_RELOC_MIPS16_JMP:
- return &elf_mips16_jump_howto;
- case BFD_RELOC_MIPS16_GPREL:
- return &elf_mips16_gprel_howto;
- case BFD_RELOC_VTABLE_INHERIT:
- return &elf_mips_gnu_vtinherit_howto;
- case BFD_RELOC_VTABLE_ENTRY:
- return &elf_mips_gnu_vtentry_howto;
- case BFD_RELOC_PCREL_HI16_S:
- return &elf_mips_gnu_rel_hi16;
- case BFD_RELOC_PCREL_LO16:
- return &elf_mips_gnu_rel_lo16;
- case BFD_RELOC_16_PCREL_S2:
- return &elf_mips_gnu_rel16_s2;
- case BFD_RELOC_64_PCREL:
- return &elf_mips_gnu_pcrel64;
- case BFD_RELOC_32_PCREL:
- return &elf_mips_gnu_pcrel32;
- }
-}
-
-/* Given a MIPS Elf32_Internal_Rel, fill in an arelent structure. */
-
-static reloc_howto_type *
-mips_rtype_to_howto (r_type)
- unsigned int r_type;
-{
- switch (r_type)
- {
- case R_MIPS16_26:
- return &elf_mips16_jump_howto;
- break;
- case R_MIPS16_GPREL:
- return &elf_mips16_gprel_howto;
- break;
- case R_MIPS_GNU_VTINHERIT:
- return &elf_mips_gnu_vtinherit_howto;
- break;
- case R_MIPS_GNU_VTENTRY:
- return &elf_mips_gnu_vtentry_howto;
- break;
- case R_MIPS_GNU_REL_HI16:
- return &elf_mips_gnu_rel_hi16;
- break;
- case R_MIPS_GNU_REL_LO16:
- return &elf_mips_gnu_rel_lo16;
- break;
- case R_MIPS_GNU_REL16_S2:
- return &elf_mips_gnu_rel16_s2;
- break;
- case R_MIPS_PC64:
- return &elf_mips_gnu_pcrel64;
- break;
- case R_MIPS_PC32:
- return &elf_mips_gnu_pcrel32;
- break;
-
- default:
- BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
- return &elf_mips_howto_table_rel[r_type];
- break;
- }
-}
-
-/* Given a MIPS Elf32_Internal_Rel, fill in an arelent structure. */
-
-static void
-mips_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd *abfd;
- arelent *cache_ptr;
- Elf32_Internal_Rel *dst;
-{
- unsigned int r_type;
-
- r_type = ELF32_R_TYPE (dst->r_info);
- cache_ptr->howto = mips_rtype_to_howto (r_type);
-
- /* The addend for a GPREL16 or LITERAL relocation comes from the GP
- value for the object file. We get the addend now, rather than
- when we do the relocation, because the symbol manipulations done
- by the linker may cause us to lose track of the input BFD. */
- if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
- && (r_type == (unsigned int) R_MIPS_GPREL16
- || r_type == (unsigned int) R_MIPS_LITERAL))
- cache_ptr->addend = elf_gp (abfd);
-}
-
-/* Given a MIPS Elf32_Internal_Rela, fill in an arelent structure. */
-
-static void
-mips_info_to_howto_rela (abfd, cache_ptr, dst)
- bfd *abfd;
- arelent *cache_ptr;
- Elf32_Internal_Rela *dst;
-{
- /* Since an Elf32_Internal_Rel is an initial prefix of an
- Elf32_Internal_Rela, we can just use mips_info_to_howto_rel
- above. */
- mips_info_to_howto_rel (abfd, cache_ptr, (Elf32_Internal_Rel *) dst);
-
- /* If we ever need to do any extra processing with dst->r_addend
- (the field omitted in an Elf32_Internal_Rel) we can do it here. */
-}
-
-/* A .reginfo section holds a single Elf32_RegInfo structure. These
- routines swap this structure in and out. They are used outside of
- BFD, so they are globally visible. */
-
-void
-bfd_mips_elf32_swap_reginfo_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_RegInfo *ex;
- Elf32_RegInfo *in;
-{
- in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
- in->ri_cprmask[0] = H_GET_32 (abfd, ex->ri_cprmask[0]);
- in->ri_cprmask[1] = H_GET_32 (abfd, ex->ri_cprmask[1]);
- in->ri_cprmask[2] = H_GET_32 (abfd, ex->ri_cprmask[2]);
- in->ri_cprmask[3] = H_GET_32 (abfd, ex->ri_cprmask[3]);
- in->ri_gp_value = H_GET_32 (abfd, ex->ri_gp_value);
-}
-
-void
-bfd_mips_elf32_swap_reginfo_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_RegInfo *in;
- Elf32_External_RegInfo *ex;
-{
- H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
- H_PUT_32 (abfd, in->ri_cprmask[0], ex->ri_cprmask[0]);
- H_PUT_32 (abfd, in->ri_cprmask[1], ex->ri_cprmask[1]);
- H_PUT_32 (abfd, in->ri_cprmask[2], ex->ri_cprmask[2]);
- H_PUT_32 (abfd, in->ri_cprmask[3], ex->ri_cprmask[3]);
- H_PUT_32 (abfd, in->ri_gp_value, ex->ri_gp_value);
-}
-
-/* In the 64 bit ABI, the .MIPS.options section holds register
- information in an Elf64_Reginfo structure. These routines swap
- them in and out. They are globally visible because they are used
- outside of BFD. These routines are here so that gas can call them
- without worrying about whether the 64 bit ABI has been included. */
-
-void
-bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
- bfd *abfd;
- const Elf64_External_RegInfo *ex;
- Elf64_Internal_RegInfo *in;
-{
- in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
- in->ri_pad = H_GET_32 (abfd, ex->ri_pad);
- in->ri_cprmask[0] = H_GET_32 (abfd, ex->ri_cprmask[0]);
- in->ri_cprmask[1] = H_GET_32 (abfd, ex->ri_cprmask[1]);
- in->ri_cprmask[2] = H_GET_32 (abfd, ex->ri_cprmask[2]);
- in->ri_cprmask[3] = H_GET_32 (abfd, ex->ri_cprmask[3]);
- in->ri_gp_value = H_GET_64 (abfd, ex->ri_gp_value);
-}
-
-void
-bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
- bfd *abfd;
- const Elf64_Internal_RegInfo *in;
- Elf64_External_RegInfo *ex;
-{
- H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
- H_PUT_32 (abfd, in->ri_pad, ex->ri_pad);
- H_PUT_32 (abfd, in->ri_cprmask[0], ex->ri_cprmask[0]);
- H_PUT_32 (abfd, in->ri_cprmask[1], ex->ri_cprmask[1]);
- H_PUT_32 (abfd, in->ri_cprmask[2], ex->ri_cprmask[2]);
- H_PUT_32 (abfd, in->ri_cprmask[3], ex->ri_cprmask[3]);
- H_PUT_64 (abfd, in->ri_gp_value, ex->ri_gp_value);
-}
-
-/* Swap an entry in a .gptab section. Note that these routines rely
- on the equivalence of the two elements of the union. */
-
-static void
-bfd_mips_elf32_swap_gptab_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_gptab *ex;
- Elf32_gptab *in;
-{
- in->gt_entry.gt_g_value = H_GET_32 (abfd, ex->gt_entry.gt_g_value);
- in->gt_entry.gt_bytes = H_GET_32 (abfd, ex->gt_entry.gt_bytes);
-}
-
-static void
-bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_gptab *in;
- Elf32_External_gptab *ex;
-{
- H_PUT_32 (abfd, in->gt_entry.gt_g_value, ex->gt_entry.gt_g_value);
- H_PUT_32 (abfd, in->gt_entry.gt_bytes, ex->gt_entry.gt_bytes);
-}
-
-static void
-bfd_elf32_swap_compact_rel_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_compact_rel *in;
- Elf32_External_compact_rel *ex;
-{
- H_PUT_32 (abfd, in->id1, ex->id1);
- H_PUT_32 (abfd, in->num, ex->num);
- H_PUT_32 (abfd, in->id2, ex->id2);
- H_PUT_32 (abfd, in->offset, ex->offset);
- H_PUT_32 (abfd, in->reserved0, ex->reserved0);
- H_PUT_32 (abfd, in->reserved1, ex->reserved1);
-}
-
-static void
-bfd_elf32_swap_crinfo_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_crinfo *in;
- Elf32_External_crinfo *ex;
-{
- unsigned long l;
-
- l = (((in->ctype & CRINFO_CTYPE) << CRINFO_CTYPE_SH)
- | ((in->rtype & CRINFO_RTYPE) << CRINFO_RTYPE_SH)
- | ((in->dist2to & CRINFO_DIST2TO) << CRINFO_DIST2TO_SH)
- | ((in->relvaddr & CRINFO_RELVADDR) << CRINFO_RELVADDR_SH));
- H_PUT_32 (abfd, l, ex->info);
- H_PUT_32 (abfd, in->konst, ex->konst);
- H_PUT_32 (abfd, in->vaddr, ex->vaddr);
-}
-
-/* Swap in an options header. */
-
-void
-bfd_mips_elf_swap_options_in (abfd, ex, in)
- bfd *abfd;
- const Elf_External_Options *ex;
- Elf_Internal_Options *in;
-{
- in->kind = H_GET_8 (abfd, ex->kind);
- in->size = H_GET_8 (abfd, ex->size);
- in->section = H_GET_16 (abfd, ex->section);
- in->info = H_GET_32 (abfd, ex->info);
-}
-
-/* Swap out an options header. */
-
-void
-bfd_mips_elf_swap_options_out (abfd, in, ex)
- bfd *abfd;
- const Elf_Internal_Options *in;
- Elf_External_Options *ex;
-{
- H_PUT_8 (abfd, in->kind, ex->kind);
- H_PUT_8 (abfd, in->size, ex->size);
- H_PUT_16 (abfd, in->section, ex->section);
- H_PUT_32 (abfd, in->info, ex->info);
-}
-#if 0
-/* Swap in an MSYM entry. */
-
-static void
-bfd_mips_elf_swap_msym_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_Msym *ex;
- Elf32_Internal_Msym *in;
-{
- in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value);
- in->ms_info = H_GET_32 (abfd, ex->ms_info);
-}
-#endif
-/* Swap out an MSYM entry. */
-
-static void
-bfd_mips_elf_swap_msym_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_Internal_Msym *in;
- Elf32_External_Msym *ex;
-{
- H_PUT_32 (abfd, in->ms_hash_value, ex->ms_hash_value);
- H_PUT_32 (abfd, in->ms_info, ex->ms_info);
-}
-
-/* Determine whether a symbol is global for the purposes of splitting
- the symbol table into global symbols and local symbols. At least
- on Irix 5, this split must be between section symbols and all other
- symbols. On most ELF targets the split is between static symbols
- and externally visible symbols. */
-
-static boolean
-mips_elf_sym_is_global (abfd, sym)
- bfd *abfd ATTRIBUTE_UNUSED;
- asymbol *sym;
-{
- if (SGI_COMPAT (abfd))
- return (sym->flags & BSF_SECTION_SYM) == 0;
- else
- return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
- || bfd_is_und_section (bfd_get_section (sym))
- || bfd_is_com_section (bfd_get_section (sym)));
-}
-
-/* Set the right machine number for a MIPS ELF file. This is used for
- both the 32-bit and the 64-bit ABI. */
-
-boolean
-_bfd_mips_elf_object_p (abfd)
- bfd *abfd;
-{
- /* Irix 5 and 6 are broken. Object file symbol tables are not always
- sorted correctly such that local symbols precede global symbols,
- and the sh_info field in the symbol table is not always right. */
- if (SGI_COMPAT(abfd))
- elf_bad_symtab (abfd) = true;
-
- bfd_default_set_arch_mach (abfd, bfd_arch_mips,
- elf_mips_mach (elf_elfheader (abfd)->e_flags));
- return true;
-}
-
-/* The final processing done just before writing out a MIPS ELF object
- file. This gets the MIPS architecture right based on the machine
- number. This is used by both the 32-bit and the 64-bit ABI. */
-
-void
-_bfd_mips_elf_final_write_processing (abfd, linker)
- bfd *abfd;
- boolean linker ATTRIBUTE_UNUSED;
-{
- unsigned long val;
- unsigned int i;
- Elf_Internal_Shdr **hdrpp;
- const char *name;
- asection *sec;
-
- switch (bfd_get_mach (abfd))
- {
- default:
- case bfd_mach_mips3000:
- val = E_MIPS_ARCH_1;
- break;
-
- case bfd_mach_mips3900:
- val = E_MIPS_ARCH_1 | E_MIPS_MACH_3900;
- break;
-
- case bfd_mach_mips6000:
- val = E_MIPS_ARCH_2;
- break;
-
- case bfd_mach_mips4000:
- case bfd_mach_mips4300:
- case bfd_mach_mips4400:
- case bfd_mach_mips4600:
- val = E_MIPS_ARCH_3;
- break;
-
- case bfd_mach_mips4010:
- val = E_MIPS_ARCH_3 | E_MIPS_MACH_4010;
- break;
-
- case bfd_mach_mips4100:
- val = E_MIPS_ARCH_3 | E_MIPS_MACH_4100;
- break;
-
- case bfd_mach_mips4111:
- val = E_MIPS_ARCH_3 | E_MIPS_MACH_4111;
- break;
-
- case bfd_mach_mips4650:
- val = E_MIPS_ARCH_3 | E_MIPS_MACH_4650;
- break;
-
- case bfd_mach_mips5000:
- case bfd_mach_mips8000:
- case bfd_mach_mips10000:
- case bfd_mach_mips12000:
- val = E_MIPS_ARCH_4;
- break;
-
- case bfd_mach_mips5:
- val = E_MIPS_ARCH_5;
- break;
-
- case bfd_mach_mips_sb1:
- val = E_MIPS_ARCH_64 | E_MIPS_MACH_SB1;
- break;
-
- case bfd_mach_mipsisa32:
- val = E_MIPS_ARCH_32;
- break;
-
- case bfd_mach_mipsisa64:
- val = E_MIPS_ARCH_64;
- }
-
- elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
- elf_elfheader (abfd)->e_flags |= val;
-
- /* Set the sh_info field for .gptab sections and other appropriate
- info for each special section. */
- for (i = 1, hdrpp = elf_elfsections (abfd) + 1;
- i < elf_numsections (abfd);
- i++, hdrpp++)
- {
- switch ((*hdrpp)->sh_type)
- {
- case SHT_MIPS_MSYM:
- case SHT_MIPS_LIBLIST:
- sec = bfd_get_section_by_name (abfd, ".dynstr");
- if (sec != NULL)
- (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
- break;
-
- case SHT_MIPS_GPTAB:
- BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
- name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
- BFD_ASSERT (name != NULL
- && strncmp (name, ".gptab.", sizeof ".gptab." - 1) == 0);
- sec = bfd_get_section_by_name (abfd, name + sizeof ".gptab" - 1);
- BFD_ASSERT (sec != NULL);
- (*hdrpp)->sh_info = elf_section_data (sec)->this_idx;
- break;
-
- case SHT_MIPS_CONTENT:
- BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
- name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
- BFD_ASSERT (name != NULL
- && strncmp (name, ".MIPS.content",
- sizeof ".MIPS.content" - 1) == 0);
- sec = bfd_get_section_by_name (abfd,
- name + sizeof ".MIPS.content" - 1);
- BFD_ASSERT (sec != NULL);
- (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
- break;
-
- case SHT_MIPS_SYMBOL_LIB:
- sec = bfd_get_section_by_name (abfd, ".dynsym");
- if (sec != NULL)
- (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
- sec = bfd_get_section_by_name (abfd, ".liblist");
- if (sec != NULL)
- (*hdrpp)->sh_info = elf_section_data (sec)->this_idx;
- break;
-
- case SHT_MIPS_EVENTS:
- BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
- name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
- BFD_ASSERT (name != NULL);
- if (strncmp (name, ".MIPS.events", sizeof ".MIPS.events" - 1) == 0)
- sec = bfd_get_section_by_name (abfd,
- name + sizeof ".MIPS.events" - 1);
- else
- {
- BFD_ASSERT (strncmp (name, ".MIPS.post_rel",
- sizeof ".MIPS.post_rel" - 1) == 0);
- sec = bfd_get_section_by_name (abfd,
- (name
- + sizeof ".MIPS.post_rel" - 1));
- }
- BFD_ASSERT (sec != NULL);
- (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
- break;
-
- }
- }
-}
-
-/* Function to keep MIPS specific file flags like as EF_MIPS_PIC. */
-
-boolean
-_bfd_mips_elf_set_private_flags (abfd, flags)
- bfd *abfd;
- flagword flags;
-{
- BFD_ASSERT (!elf_flags_init (abfd)
- || elf_elfheader (abfd)->e_flags == flags);
-
- elf_elfheader (abfd)->e_flags = flags;
- elf_flags_init (abfd) = true;
- return true;
-}
-
-/* Merge backend specific data from an object file to the output
- object file when linking. */
-
-boolean
-_bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
-{
- flagword old_flags;
- flagword new_flags;
- boolean ok;
- boolean null_input_bfd = true;
- asection *sec;
-
- /* Check if we have the same endianess */
- if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
- return false;
-
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- new_flags = elf_elfheader (ibfd)->e_flags;
- elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
- old_flags = elf_elfheader (obfd)->e_flags;
-
- if (! elf_flags_init (obfd))
- {
- elf_flags_init (obfd) = true;
- elf_elfheader (obfd)->e_flags = new_flags;
- elf_elfheader (obfd)->e_ident[EI_CLASS]
- = elf_elfheader (ibfd)->e_ident[EI_CLASS];
-
- if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
- && bfd_get_arch_info (obfd)->the_default)
- {
- if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
- bfd_get_mach (ibfd)))
- return false;
- }
-
- return true;
- }
-
- /* Check flag compatibility. */
-
- new_flags &= ~EF_MIPS_NOREORDER;
- old_flags &= ~EF_MIPS_NOREORDER;
-
- if (new_flags == old_flags)
- return true;
-
- /* Check to see if the input BFD actually contains any sections.
- If not, its flags may not have been initialised either, but it cannot
- actually cause any incompatibility. */
- for (sec = ibfd->sections; sec != NULL; sec = sec->next)
- {
- /* Ignore synthetic sections and empty .text, .data and .bss sections
- which are automatically generated by gas. */
- if (strcmp (sec->name, ".reginfo")
- && strcmp (sec->name, ".mdebug")
- && ((!strcmp (sec->name, ".text")
- || !strcmp (sec->name, ".data")
- || !strcmp (sec->name, ".bss"))
- && sec->_raw_size != 0))
- {
- null_input_bfd = false;
- break;
- }
- }
- if (null_input_bfd)
- return true;
-
- ok = true;
-
- if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
- {
- new_flags &= ~EF_MIPS_PIC;
- old_flags &= ~EF_MIPS_PIC;
- (*_bfd_error_handler)
- (_("%s: linking PIC files with non-PIC files"),
- bfd_archive_filename (ibfd));
- ok = false;
- }
-
- if ((new_flags & EF_MIPS_CPIC) != (old_flags & EF_MIPS_CPIC))
- {
- new_flags &= ~EF_MIPS_CPIC;
- old_flags &= ~EF_MIPS_CPIC;
- (*_bfd_error_handler)
- (_("%s: linking abicalls files with non-abicalls files"),
- bfd_archive_filename (ibfd));
- ok = false;
- }
-
- /* Compare the ISA's. */
- if ((new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH))
- != (old_flags & (EF_MIPS_ARCH | EF_MIPS_MACH)))
- {
- int new_mach = new_flags & EF_MIPS_MACH;
- int old_mach = old_flags & EF_MIPS_MACH;
- int new_isa = elf_mips_isa (new_flags);
- int old_isa = elf_mips_isa (old_flags);
-
- /* If either has no machine specified, just compare the general isa's.
- Some combinations of machines are ok, if the isa's match. */
- if (! new_mach
- || ! old_mach
- || new_mach == old_mach
- )
- {
- /* Don't warn about mixing code using 32-bit ISAs, or mixing code
- using 64-bit ISAs. They will normally use the same data sizes
- and calling conventions. */
-
- if (( (new_isa == 1 || new_isa == 2 || new_isa == 32)
- ^ (old_isa == 1 || old_isa == 2 || old_isa == 32)) != 0)
- {
- (*_bfd_error_handler)
- (_("%s: ISA mismatch (-mips%d) with previous modules (-mips%d)"),
- bfd_archive_filename (ibfd), new_isa, old_isa);
- ok = false;
- }
- else
- {
- /* Do we need to update the mach field? */
- if (old_mach == 0 && new_mach != 0)
- elf_elfheader (obfd)->e_flags |= new_mach;
-
- /* Do we need to update the ISA field? */
- if (new_isa > old_isa)
- {
- elf_elfheader (obfd)->e_flags &= ~EF_MIPS_ARCH;
- elf_elfheader (obfd)->e_flags
- |= new_flags & EF_MIPS_ARCH;
- }
- }
- }
- else
- {
- (*_bfd_error_handler)
- (_("%s: ISA mismatch (%d) with previous modules (%d)"),
- bfd_archive_filename (ibfd),
- elf_mips_mach (new_flags),
- elf_mips_mach (old_flags));
- ok = false;
- }
-
- new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
- old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
- }
-
- /* Compare ABI's. The 64-bit ABI does not use EF_MIPS_ABI. But, it
- does set EI_CLASS differently from any 32-bit ABI. */
- if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI)
- || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
- != elf_elfheader (obfd)->e_ident[EI_CLASS]))
- {
- /* Only error if both are set (to different values). */
- if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI))
- || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
- != elf_elfheader (obfd)->e_ident[EI_CLASS]))
- {
- (*_bfd_error_handler)
- (_("%s: ABI mismatch: linking %s module with previous %s modules"),
- bfd_archive_filename (ibfd),
- elf_mips_abi_name (ibfd),
- elf_mips_abi_name (obfd));
- ok = false;
- }
- new_flags &= ~EF_MIPS_ABI;
- old_flags &= ~EF_MIPS_ABI;
- }
-
- /* Warn about any other mismatches */
- if (new_flags != old_flags)
- {
- (*_bfd_error_handler)
- (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
- bfd_archive_filename (ibfd), (unsigned long) new_flags,
- (unsigned long) old_flags);
- ok = false;
- }
-
- if (! ok)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- return true;
-}
-
-boolean
-_bfd_mips_elf_print_private_bfd_data (abfd, ptr)
- bfd *abfd;
- PTR ptr;
-{
- FILE *file = (FILE *) ptr;
-
- BFD_ASSERT (abfd != NULL && ptr != NULL);
-
- /* Print normal ELF private data. */
- _bfd_elf_print_private_bfd_data (abfd, ptr);
-
- /* xgettext:c-format */
- fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
-
- if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O32)
- fprintf (file, _(" [abi=O32]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O64)
- fprintf (file, _(" [abi=O64]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32)
- fprintf (file, _(" [abi=EABI32]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
- fprintf (file, _(" [abi=EABI64]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI))
- fprintf (file, _(" [abi unknown]"));
- else if (ABI_N32_P (abfd))
- fprintf (file, _(" [abi=N32]"));
- else if (ABI_64_P (abfd))
- fprintf (file, _(" [abi=64]"));
- else
- fprintf (file, _(" [no abi set]"));
-
- if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
- fprintf (file, _(" [mips1]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
- fprintf (file, _(" [mips2]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
- fprintf (file, _(" [mips3]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
- fprintf (file, _(" [mips4]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5)
- fprintf (file, _(" [mips5]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32)
- fprintf (file, _(" [mips32]"));
- else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64)
- fprintf (file, _(" [mips64]"));
- else
- fprintf (file, _(" [unknown ISA]"));
-
- if (elf_elfheader (abfd)->e_flags & EF_MIPS_32BITMODE)
- fprintf (file, _(" [32bitmode]"));
- else
- fprintf (file, _(" [not 32bitmode]"));
-
- fputc ('\n', file);
-
- return true;
-}
-
-/* Handle a MIPS specific section when reading an object file. This
- is called when elfcode.h finds a section with an unknown type.
- This routine supports both the 32-bit and 64-bit ELF ABI.
-
- FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure
- how to. */
-
-boolean
-_bfd_mips_elf_section_from_shdr (abfd, hdr, name)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- char *name;
-{
- flagword flags = 0;
-
- /* There ought to be a place to keep ELF backend specific flags, but
- at the moment there isn't one. We just keep track of the
- sections by their name, instead. Fortunately, the ABI gives
- suggested names for all the MIPS specific sections, so we will
- probably get away with this. */
- switch (hdr->sh_type)
- {
- case SHT_MIPS_LIBLIST:
- if (strcmp (name, ".liblist") != 0)
- return false;
- break;
- case SHT_MIPS_MSYM:
- if (strcmp (name, MIPS_ELF_MSYM_SECTION_NAME (abfd)) != 0)
- return false;
- break;
- case SHT_MIPS_CONFLICT:
- if (strcmp (name, ".conflict") != 0)
- return false;
- break;
- case SHT_MIPS_GPTAB:
- if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) != 0)
- return false;
- break;
- case SHT_MIPS_UCODE:
- if (strcmp (name, ".ucode") != 0)
- return false;
- break;
- case SHT_MIPS_DEBUG:
- if (strcmp (name, ".mdebug") != 0)
- return false;
- flags = SEC_DEBUGGING;
- break;
- case SHT_MIPS_REGINFO:
- if (strcmp (name, ".reginfo") != 0
- || hdr->sh_size != sizeof (Elf32_External_RegInfo))
- return false;
- flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
- break;
- case SHT_MIPS_IFACE:
- if (strcmp (name, ".MIPS.interfaces") != 0)
- return false;
- break;
- case SHT_MIPS_CONTENT:
- if (strncmp (name, ".MIPS.content", sizeof ".MIPS.content" - 1) != 0)
- return false;
- break;
- case SHT_MIPS_OPTIONS:
- if (strcmp (name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) != 0)
- return false;
- break;
- case SHT_MIPS_DWARF:
- if (strncmp (name, ".debug_", sizeof ".debug_" - 1) != 0)
- return false;
- break;
- case SHT_MIPS_SYMBOL_LIB:
- if (strcmp (name, ".MIPS.symlib") != 0)
- return false;
- break;
- case SHT_MIPS_EVENTS:
- if (strncmp (name, ".MIPS.events", sizeof ".MIPS.events" - 1) != 0
- && strncmp (name, ".MIPS.post_rel",
- sizeof ".MIPS.post_rel" - 1) != 0)
- return false;
- break;
- default:
- return false;
- }
-
- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
- return false;
-
- if (flags)
- {
- if (! bfd_set_section_flags (abfd, hdr->bfd_section,
- (bfd_get_section_flags (abfd,
- hdr->bfd_section)
- | flags)))
- return false;
- }
-
- /* FIXME: We should record sh_info for a .gptab section. */
-
- /* For a .reginfo section, set the gp value in the tdata information
- from the contents of this section. We need the gp value while
- processing relocs, so we just get it now. The .reginfo section
- is not used in the 64-bit MIPS ELF ABI. */
- if (hdr->sh_type == SHT_MIPS_REGINFO)
- {
- Elf32_External_RegInfo ext;
- Elf32_RegInfo s;
-
- if (! bfd_get_section_contents (abfd, hdr->bfd_section, (PTR) &ext,
- (file_ptr) 0,
- (bfd_size_type) sizeof ext))
- return false;
- bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
- elf_gp (abfd) = s.ri_gp_value;
- }
-
- /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
- set the gp value based on what we find. We may see both
- SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
- they should agree. */
- if (hdr->sh_type == SHT_MIPS_OPTIONS)
- {
- bfd_byte *contents, *l, *lend;
-
- contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
- if (contents == NULL)
- return false;
- if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
- (file_ptr) 0, hdr->sh_size))
- {
- free (contents);
- return false;
- }
- l = contents;
- lend = contents + hdr->sh_size;
- while (l + sizeof (Elf_External_Options) <= lend)
- {
- Elf_Internal_Options intopt;
-
- bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
- &intopt);
- if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
- {
- Elf64_Internal_RegInfo intreg;
-
- bfd_mips_elf64_swap_reginfo_in
- (abfd,
- ((Elf64_External_RegInfo *)
- (l + sizeof (Elf_External_Options))),
- &intreg);
- elf_gp (abfd) = intreg.ri_gp_value;
- }
- else if (intopt.kind == ODK_REGINFO)
- {
- Elf32_RegInfo intreg;
-
- bfd_mips_elf32_swap_reginfo_in
- (abfd,
- ((Elf32_External_RegInfo *)
- (l + sizeof (Elf_External_Options))),
- &intreg);
- elf_gp (abfd) = intreg.ri_gp_value;
- }
- l += intopt.size;
- }
- free (contents);
- }
-
- return true;
-}
-
-/* Set the correct type for a MIPS ELF section. We do this by the
- section name, which is a hack, but ought to work. This routine is
- used by both the 32-bit and the 64-bit ABI. */
-
-boolean
-_bfd_mips_elf_fake_sections (abfd, hdr, sec)
- bfd *abfd;
- Elf32_Internal_Shdr *hdr;
- asection *sec;
-{
- register const char *name;
-
- name = bfd_get_section_name (abfd, sec);
-
- if (strcmp (name, ".liblist") == 0)
- {
- hdr->sh_type = SHT_MIPS_LIBLIST;
- hdr->sh_info = sec->_raw_size / sizeof (Elf32_Lib);
- /* The sh_link field is set in final_write_processing. */
- }
- else if (strcmp (name, ".conflict") == 0)
- hdr->sh_type = SHT_MIPS_CONFLICT;
- else if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) == 0)
- {
- hdr->sh_type = SHT_MIPS_GPTAB;
- hdr->sh_entsize = sizeof (Elf32_External_gptab);
- /* The sh_info field is set in final_write_processing. */
- }
- else if (strcmp (name, ".ucode") == 0)
- hdr->sh_type = SHT_MIPS_UCODE;
- else if (strcmp (name, ".mdebug") == 0)
- {
- hdr->sh_type = SHT_MIPS_DEBUG;
- /* In a shared object on Irix 5.3, the .mdebug section has an
- entsize of 0. FIXME: Does this matter? */
- if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0)
- hdr->sh_entsize = 0;
- else
- hdr->sh_entsize = 1;
- }
- else if (strcmp (name, ".reginfo") == 0)
- {
- hdr->sh_type = SHT_MIPS_REGINFO;
- /* In a shared object on Irix 5.3, the .reginfo section has an
- entsize of 0x18. FIXME: Does this matter? */
- if (SGI_COMPAT (abfd))
- {
- if ((abfd->flags & DYNAMIC) != 0)
- hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
- else
- hdr->sh_entsize = 1;
- }
- else
- hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
- }
- else if (SGI_COMPAT (abfd)
- && (strcmp (name, ".hash") == 0
- || strcmp (name, ".dynamic") == 0
- || strcmp (name, ".dynstr") == 0))
- {
- if (SGI_COMPAT (abfd))
- hdr->sh_entsize = 0;
-#if 0
- /* This isn't how the Irix 6 linker behaves. */
- hdr->sh_info = SIZEOF_MIPS_DYNSYM_SECNAMES;
-#endif
- }
- else if (strcmp (name, ".got") == 0
- || strcmp (name, MIPS_ELF_SRDATA_SECTION_NAME (abfd)) == 0
- || strcmp (name, ".sdata") == 0
- || strcmp (name, ".sbss") == 0
- || strcmp (name, ".lit4") == 0
- || strcmp (name, ".lit8") == 0)
- hdr->sh_flags |= SHF_MIPS_GPREL;
- else if (strcmp (name, ".MIPS.interfaces") == 0)
- {
- hdr->sh_type = SHT_MIPS_IFACE;
- hdr->sh_flags |= SHF_MIPS_NOSTRIP;
- }
- else if (strncmp (name, ".MIPS.content", strlen (".MIPS.content")) == 0)
- {
- hdr->sh_type = SHT_MIPS_CONTENT;
- hdr->sh_flags |= SHF_MIPS_NOSTRIP;
- /* The sh_info field is set in final_write_processing. */
- }
- else if (strcmp (name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
- {
- hdr->sh_type = SHT_MIPS_OPTIONS;
- hdr->sh_entsize = 1;
- hdr->sh_flags |= SHF_MIPS_NOSTRIP;
- }
- else if (strncmp (name, ".debug_", sizeof ".debug_" - 1) == 0)
- hdr->sh_type = SHT_MIPS_DWARF;
- else if (strcmp (name, ".MIPS.symlib") == 0)
- {
- hdr->sh_type = SHT_MIPS_SYMBOL_LIB;
- /* The sh_link and sh_info fields are set in
- final_write_processing. */
- }
- else if (strncmp (name, ".MIPS.events", sizeof ".MIPS.events" - 1) == 0
- || strncmp (name, ".MIPS.post_rel",
- sizeof ".MIPS.post_rel" - 1) == 0)
- {
- hdr->sh_type = SHT_MIPS_EVENTS;
- hdr->sh_flags |= SHF_MIPS_NOSTRIP;
- /* The sh_link field is set in final_write_processing. */
- }
- else if (strcmp (name, MIPS_ELF_MSYM_SECTION_NAME (abfd)) == 0)
- {
- hdr->sh_type = SHT_MIPS_MSYM;
- hdr->sh_flags |= SHF_ALLOC;
- hdr->sh_entsize = 8;
- }
-
- /* The generic elf_fake_sections will set up REL_HDR using the
- default kind of relocations. But, we may actually need both
- kinds of relocations, so we set up the second header here.
-
- This is not necessary for the O32 ABI since that only uses Elf32_Rel
- relocations (cf. System V ABI, MIPS RISC Processor Supplement,
- 3rd Edition, p. 4-17). It breaks the IRIX 5/6 32-bit ld, since one
- of the resulting empty .rela.<section> sections starts with
- sh_offset == object size, and ld doesn't allow that. While the check
- is arguably bogus for empty or SHT_NOBITS sections, it can easily be
- avoided by not emitting those useless sections in the first place. */
- if (IRIX_COMPAT (abfd) != ict_irix5 && (sec->flags & SEC_RELOC) != 0)
- {
- struct bfd_elf_section_data *esd;
- bfd_size_type amt = sizeof (Elf_Internal_Shdr);
-
- esd = elf_section_data (sec);
- BFD_ASSERT (esd->rel_hdr2 == NULL);
- esd->rel_hdr2 = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt);
- if (!esd->rel_hdr2)
- return false;
- _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec,
- !elf_section_data (sec)->use_rela_p);
- }
-
- return true;
-}
-
-/* Given a BFD section, try to locate the corresponding ELF section
- index. This is used by both the 32-bit and the 64-bit ABI.
- Actually, it's not clear to me that the 64-bit ABI supports these,
- but for non-PIC objects we will certainly want support for at least
- the .scommon section. */
-
-boolean
-_bfd_mips_elf_section_from_bfd_section (abfd, sec, retval)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
- int *retval;
-{
- if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
- {
- *retval = SHN_MIPS_SCOMMON;
- return true;
- }
- if (strcmp (bfd_get_section_name (abfd, sec), ".acommon") == 0)
- {
- *retval = SHN_MIPS_ACOMMON;
- return true;
- }
- return false;
-}
-
-/* When are writing out the .options or .MIPS.options section,
- remember the bytes we are writing out, so that we can install the
- GP value in the section_processing routine. */
-
-boolean
-_bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- PTR location;
- file_ptr offset;
- bfd_size_type count;
-{
- if (strcmp (section->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
- {
- bfd_byte *c;
-
- if (elf_section_data (section) == NULL)
- {
- bfd_size_type amt = sizeof (struct bfd_elf_section_data);
- section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
- if (elf_section_data (section) == NULL)
- return false;
- }
- c = (bfd_byte *) elf_section_data (section)->tdata;
- if (c == NULL)
- {
- bfd_size_type size;
-
- if (section->_cooked_size != 0)
- size = section->_cooked_size;
- else
- size = section->_raw_size;
- c = (bfd_byte *) bfd_zalloc (abfd, size);
- if (c == NULL)
- return false;
- elf_section_data (section)->tdata = (PTR) c;
- }
-
- memcpy (c + offset, location, (size_t) count);
- }
-
- return _bfd_elf_set_section_contents (abfd, section, location, offset,
- count);
-}
-
-/* Work over a section just before writing it out. This routine is
- used by both the 32-bit and the 64-bit ABI. FIXME: We recognize
- sections that need the SHF_MIPS_GPREL flag by name; there has to be
- a better way. */
-
-boolean
-_bfd_mips_elf_section_processing (abfd, hdr)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
-{
- if (hdr->sh_type == SHT_MIPS_REGINFO
- && hdr->sh_size > 0)
- {
- bfd_byte buf[4];
-
- BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo));
- BFD_ASSERT (hdr->contents == NULL);
-
- if (bfd_seek (abfd,
- hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4,
- SEEK_SET) != 0)
- return false;
- H_PUT_32 (abfd, elf_gp (abfd), buf);
- if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
- return false;
- }
-
- if (hdr->sh_type == SHT_MIPS_OPTIONS
- && hdr->bfd_section != NULL
- && elf_section_data (hdr->bfd_section) != NULL
- && elf_section_data (hdr->bfd_section)->tdata != NULL)
- {
- bfd_byte *contents, *l, *lend;
-
- /* We stored the section contents in the elf_section_data tdata
- field in the set_section_contents routine. We save the
- section contents so that we don't have to read them again.
- At this point we know that elf_gp is set, so we can look
- through the section contents to see if there is an
- ODK_REGINFO structure. */
-
- contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
- l = contents;
- lend = contents + hdr->sh_size;
- while (l + sizeof (Elf_External_Options) <= lend)
- {
- Elf_Internal_Options intopt;
-
- bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
- &intopt);
- if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
- {
- bfd_byte buf[8];
-
- if (bfd_seek (abfd,
- (hdr->sh_offset
- + (l - contents)
- + sizeof (Elf_External_Options)
- + (sizeof (Elf64_External_RegInfo) - 8)),
- SEEK_SET) != 0)
- return false;
- H_PUT_64 (abfd, elf_gp (abfd), buf);
- if (bfd_bwrite (buf, (bfd_size_type) 8, abfd) != 8)
- return false;
- }
- else if (intopt.kind == ODK_REGINFO)
- {
- bfd_byte buf[4];
-
- if (bfd_seek (abfd,
- (hdr->sh_offset
- + (l - contents)
- + sizeof (Elf_External_Options)
- + (sizeof (Elf32_External_RegInfo) - 4)),
- SEEK_SET) != 0)
- return false;
- H_PUT_32 (abfd, elf_gp (abfd), buf);
- if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
- return false;
- }
- l += intopt.size;
- }
- }
-
- if (hdr->bfd_section != NULL)
- {
- const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
-
- if (strcmp (name, ".sdata") == 0
- || strcmp (name, ".lit8") == 0
- || strcmp (name, ".lit4") == 0)
- {
- hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
- hdr->sh_type = SHT_PROGBITS;
- }
- else if (strcmp (name, ".sbss") == 0)
- {
- hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
- hdr->sh_type = SHT_NOBITS;
- }
- else if (strcmp (name, MIPS_ELF_SRDATA_SECTION_NAME (abfd)) == 0)
- {
- hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
- hdr->sh_type = SHT_PROGBITS;
- }
- else if (strcmp (name, ".compact_rel") == 0)
- {
- hdr->sh_flags = 0;
- hdr->sh_type = SHT_PROGBITS;
- }
- else if (strcmp (name, ".rtproc") == 0)
- {
- if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
- {
- unsigned int adjust;
-
- adjust = hdr->sh_size % hdr->sh_addralign;
- if (adjust != 0)
- hdr->sh_size += hdr->sh_addralign - adjust;
- }
- }
- }
-
- return true;
-}
-
-/* MIPS ELF uses two common sections. One is the usual one, and the
- other is for small objects. All the small objects are kept
- together, and then referenced via the gp pointer, which yields
- faster assembler code. This is what we use for the small common
- section. This approach is copied from ecoff.c. */
-static asection mips_elf_scom_section;
-static asymbol mips_elf_scom_symbol;
-static asymbol *mips_elf_scom_symbol_ptr;
-
-/* MIPS ELF also uses an acommon section, which represents an
- allocated common symbol which may be overridden by a
- definition in a shared library. */
-static asection mips_elf_acom_section;
-static asymbol mips_elf_acom_symbol;
-static asymbol *mips_elf_acom_symbol_ptr;
-
-/* Handle the special MIPS section numbers that a symbol may use.
- This is used for both the 32-bit and the 64-bit ABI. */
-
-void
-_bfd_mips_elf_symbol_processing (abfd, asym)
- bfd *abfd;
- asymbol *asym;
-{
- elf_symbol_type *elfsym;
-
- elfsym = (elf_symbol_type *) asym;
- switch (elfsym->internal_elf_sym.st_shndx)
- {
- case SHN_MIPS_ACOMMON:
- /* This section is used in a dynamically linked executable file.
- It is an allocated common section. The dynamic linker can
- either resolve these symbols to something in a shared
- library, or it can just leave them here. For our purposes,
- we can consider these symbols to be in a new section. */
- if (mips_elf_acom_section.name == NULL)
- {
- /* Initialize the acommon section. */
- mips_elf_acom_section.name = ".acommon";
- mips_elf_acom_section.flags = SEC_ALLOC;
- mips_elf_acom_section.output_section = &mips_elf_acom_section;
- mips_elf_acom_section.symbol = &mips_elf_acom_symbol;
- mips_elf_acom_section.symbol_ptr_ptr = &mips_elf_acom_symbol_ptr;
- mips_elf_acom_symbol.name = ".acommon";
- mips_elf_acom_symbol.flags = BSF_SECTION_SYM;
- mips_elf_acom_symbol.section = &mips_elf_acom_section;
- mips_elf_acom_symbol_ptr = &mips_elf_acom_symbol;
- }
- asym->section = &mips_elf_acom_section;
- break;
-
- case SHN_COMMON:
- /* Common symbols less than the GP size are automatically
- treated as SHN_MIPS_SCOMMON symbols on IRIX5. */
- if (asym->value > elf_gp_size (abfd)
- || IRIX_COMPAT (abfd) == ict_irix6)
- break;
- /* Fall through. */
- case SHN_MIPS_SCOMMON:
- if (mips_elf_scom_section.name == NULL)
- {
- /* Initialize the small common section. */
- mips_elf_scom_section.name = ".scommon";
- mips_elf_scom_section.flags = SEC_IS_COMMON;
- mips_elf_scom_section.output_section = &mips_elf_scom_section;
- mips_elf_scom_section.symbol = &mips_elf_scom_symbol;
- mips_elf_scom_section.symbol_ptr_ptr = &mips_elf_scom_symbol_ptr;
- mips_elf_scom_symbol.name = ".scommon";
- mips_elf_scom_symbol.flags = BSF_SECTION_SYM;
- mips_elf_scom_symbol.section = &mips_elf_scom_section;
- mips_elf_scom_symbol_ptr = &mips_elf_scom_symbol;
- }
- asym->section = &mips_elf_scom_section;
- asym->value = elfsym->internal_elf_sym.st_size;
- break;
-
- case SHN_MIPS_SUNDEFINED:
- asym->section = bfd_und_section_ptr;
- break;
-
-#if 0 /* for SGI_COMPAT */
- case SHN_MIPS_TEXT:
- asym->section = mips_elf_text_section_ptr;
- break;
-
- case SHN_MIPS_DATA:
- asym->section = mips_elf_data_section_ptr;
- break;
-#endif
- }
-}
-
-/* When creating an Irix 5 executable, we need REGINFO and RTPROC
- segments. */
-
-int
-_bfd_mips_elf_additional_program_headers (abfd)
- bfd *abfd;
-{
- asection *s;
- int ret = 0;
-
- /* See if we need a PT_MIPS_REGINFO segment. */
- s = bfd_get_section_by_name (abfd, ".reginfo");
- if (s && (s->flags & SEC_LOAD))
- ++ret;
-
- /* See if we need a PT_MIPS_OPTIONS segment. */
- if (IRIX_COMPAT (abfd) == ict_irix6
- && bfd_get_section_by_name (abfd,
- MIPS_ELF_OPTIONS_SECTION_NAME (abfd)))
- ++ret;
-
- /* See if we need a PT_MIPS_RTPROC segment. */
- if (IRIX_COMPAT (abfd) == ict_irix5
- && bfd_get_section_by_name (abfd, ".dynamic")
- && bfd_get_section_by_name (abfd, ".mdebug"))
- ++ret;
-
- return ret;
-}
-
-/* Modify the segment map for an Irix 5 executable. */
-
-boolean
-_bfd_mips_elf_modify_segment_map (abfd)
- bfd *abfd;
-{
- asection *s;
- struct elf_segment_map *m, **pm;
- bfd_size_type amt;
-
- /* If there is a .reginfo section, we need a PT_MIPS_REGINFO
- segment. */
- s = bfd_get_section_by_name (abfd, ".reginfo");
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
- {
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
- if (m->p_type == PT_MIPS_REGINFO)
- break;
- if (m == NULL)
- {
- amt = sizeof *m;
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
- if (m == NULL)
- return false;
-
- m->p_type = PT_MIPS_REGINFO;
- m->count = 1;
- m->sections[0] = s;
-
- /* We want to put it after the PHDR and INTERP segments. */
- pm = &elf_tdata (abfd)->segment_map;
- while (*pm != NULL
- && ((*pm)->p_type == PT_PHDR
- || (*pm)->p_type == PT_INTERP))
- pm = &(*pm)->next;
-
- m->next = *pm;
- *pm = m;
- }
- }
-
- /* For IRIX 6, we don't have .mdebug sections, nor does anything but
- .dynamic end up in PT_DYNAMIC. However, we do have to insert a
- PT_OPTIONS segement immediately following the program header
- table. */
- if (IRIX_COMPAT (abfd) == ict_irix6)
- {
- for (s = abfd->sections; s; s = s->next)
- if (elf_section_data (s)->this_hdr.sh_type == SHT_MIPS_OPTIONS)
- break;
-
- if (s)
- {
- struct elf_segment_map *options_segment;
-
- /* Usually, there's a program header table. But, sometimes
- there's not (like when running the `ld' testsuite). So,
- if there's no program header table, we just put the
- options segement at the end. */
- for (pm = &elf_tdata (abfd)->segment_map;
- *pm != NULL;
- pm = &(*pm)->next)
- if ((*pm)->p_type == PT_PHDR)
- break;
-
- amt = sizeof (struct elf_segment_map);
- options_segment = bfd_zalloc (abfd, amt);
- options_segment->next = *pm;
- options_segment->p_type = PT_MIPS_OPTIONS;
- options_segment->p_flags = PF_R;
- options_segment->p_flags_valid = true;
- options_segment->count = 1;
- options_segment->sections[0] = s;
- *pm = options_segment;
- }
- }
- else
- {
- if (IRIX_COMPAT (abfd) == ict_irix5)
- {
- /* If there are .dynamic and .mdebug sections, we make a room
- for the RTPROC header. FIXME: Rewrite without section names. */
- if (bfd_get_section_by_name (abfd, ".interp") == NULL
- && bfd_get_section_by_name (abfd, ".dynamic") != NULL
- && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
- {
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
- if (m->p_type == PT_MIPS_RTPROC)
- break;
- if (m == NULL)
- {
- amt = sizeof *m;
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
- if (m == NULL)
- return false;
-
- m->p_type = PT_MIPS_RTPROC;
-
- s = bfd_get_section_by_name (abfd, ".rtproc");
- if (s == NULL)
- {
- m->count = 0;
- m->p_flags = 0;
- m->p_flags_valid = 1;
- }
- else
- {
- m->count = 1;
- m->sections[0] = s;
- }
-
- /* We want to put it after the DYNAMIC segment. */
- pm = &elf_tdata (abfd)->segment_map;
- while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
- pm = &(*pm)->next;
- if (*pm != NULL)
- pm = &(*pm)->next;
-
- m->next = *pm;
- *pm = m;
- }
- }
- }
- /* On Irix 5, the PT_DYNAMIC segment includes the .dynamic,
- .dynstr, .dynsym, and .hash sections, and everything in
- between. */
- for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL;
- pm = &(*pm)->next)
- if ((*pm)->p_type == PT_DYNAMIC)
- break;
- m = *pm;
- if (m != NULL && IRIX_COMPAT (abfd) == ict_none)
- {
- /* For a normal mips executable the permissions for the PT_DYNAMIC
- segment are read, write and execute. We do that here since
- the code in elf.c sets only the read permission. This matters
- sometimes for the dynamic linker. */
- if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
- {
- m->p_flags = PF_R | PF_W | PF_X;
- m->p_flags_valid = 1;
- }
- }
- if (m != NULL
- && m->count == 1 && strcmp (m->sections[0]->name, ".dynamic") == 0)
- {
- static const char *sec_names[] =
- {
- ".dynamic", ".dynstr", ".dynsym", ".hash"
- };
- bfd_vma low, high;
- unsigned int i, c;
- struct elf_segment_map *n;
-
- low = 0xffffffff;
- high = 0;
- for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
- {
- s = bfd_get_section_by_name (abfd, sec_names[i]);
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
- {
- bfd_size_type sz;
-
- if (low > s->vma)
- low = s->vma;
- sz = s->_cooked_size;
- if (sz == 0)
- sz = s->_raw_size;
- if (high < s->vma + sz)
- high = s->vma + sz;
- }
- }
-
- c = 0;
- for (s = abfd->sections; s != NULL; s = s->next)
- if ((s->flags & SEC_LOAD) != 0
- && s->vma >= low
- && ((s->vma
- + (s->_cooked_size !=
- 0 ? s->_cooked_size : s->_raw_size)) <= high))
- ++c;
-
- amt = sizeof *n + (bfd_size_type) (c - 1) * sizeof (asection *);
- n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
- if (n == NULL)
- return false;
- *n = *m;
- n->count = c;
-
- i = 0;
- for (s = abfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LOAD) != 0
- && s->vma >= low
- && ((s->vma
- + (s->_cooked_size != 0 ?
- s->_cooked_size : s->_raw_size)) <= high))
- {
- n->sections[i] = s;
- ++i;
- }
- }
-
- *pm = n;
- }
- }
-
- return true;
-}
-
-/* The structure of the runtime procedure descriptor created by the
- loader for use by the static exception system. */
-
-typedef struct runtime_pdr {
- bfd_vma adr; /* memory address of start of procedure */
- long regmask; /* save register mask */
- long regoffset; /* save register offset */
- long fregmask; /* save floating point register mask */
- long fregoffset; /* save floating point register offset */
- long frameoffset; /* frame size */
- short framereg; /* frame pointer register */
- short pcreg; /* offset or reg of return pc */
- long irpss; /* index into the runtime string table */
- long reserved;
- struct exception_info *exception_info;/* pointer to exception array */
-} RPDR, *pRPDR;
-#define cbRPDR sizeof (RPDR)
-#define rpdNil ((pRPDR) 0)
-
-/* Swap RPDR (runtime procedure table entry) for output. */
-
-static void ecoff_swap_rpdr_out
- PARAMS ((bfd *, const RPDR *, struct rpdr_ext *));
-
-static void
-ecoff_swap_rpdr_out (abfd, in, ex)
- bfd *abfd;
- const RPDR *in;
- struct rpdr_ext *ex;
-{
- /* ECOFF_PUT_OFF was defined in ecoffswap.h. */
- ECOFF_PUT_OFF (abfd, in->adr, ex->p_adr);
- H_PUT_32 (abfd, in->regmask, ex->p_regmask);
- H_PUT_32 (abfd, in->regoffset, ex->p_regoffset);
- H_PUT_32 (abfd, in->fregmask, ex->p_fregmask);
- H_PUT_32 (abfd, in->fregoffset, ex->p_fregoffset);
- H_PUT_32 (abfd, in->frameoffset, ex->p_frameoffset);
-
- H_PUT_16 (abfd, in->framereg, ex->p_framereg);
- H_PUT_16 (abfd, in->pcreg, ex->p_pcreg);
-
- H_PUT_32 (abfd, in->irpss, ex->p_irpss);
-#if 0 /* FIXME */
- ECOFF_PUT_OFF (abfd, in->exception_info, ex->p_exception_info);
-#endif
-}
-
-/* Read ECOFF debugging information from a .mdebug section into a
- ecoff_debug_info structure. */
-
-boolean
-_bfd_mips_elf_read_ecoff_info (abfd, section, debug)
- bfd *abfd;
- asection *section;
- struct ecoff_debug_info *debug;
-{
- HDRR *symhdr;
- const struct ecoff_debug_swap *swap;
- char *ext_hdr = NULL;
-
- swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
- memset (debug, 0, sizeof (*debug));
-
- ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
- if (ext_hdr == NULL && swap->external_hdr_size != 0)
- goto error_return;
-
- if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
- swap->external_hdr_size)
- == false)
- goto error_return;
-
- symhdr = &debug->symbolic_header;
- (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
-
- /* The symbolic header contains absolute file offsets and sizes to
- read. */
-#define READ(ptr, offset, count, size, type) \
- if (symhdr->count == 0) \
- debug->ptr = NULL; \
- else \
- { \
- bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
- debug->ptr = (type) bfd_malloc (amt); \
- if (debug->ptr == NULL) \
- goto error_return; \
- if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
- || bfd_bread (debug->ptr, amt, abfd) != amt) \
- goto error_return; \
- }
-
- READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
- READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
- READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
- READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
- READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
- READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
- union aux_ext *);
- READ (ss, cbSsOffset, issMax, sizeof (char), char *);
- READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
- READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
- READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
- READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
-#undef READ
-
- debug->fdr = NULL;
- debug->adjust = NULL;
-
- return true;
-
- error_return:
- if (ext_hdr != NULL)
- free (ext_hdr);
- if (debug->line != NULL)
- free (debug->line);
- if (debug->external_dnr != NULL)
- free (debug->external_dnr);
- if (debug->external_pdr != NULL)
- free (debug->external_pdr);
- if (debug->external_sym != NULL)
- free (debug->external_sym);
- if (debug->external_opt != NULL)
- free (debug->external_opt);
- if (debug->external_aux != NULL)
- free (debug->external_aux);
- if (debug->ss != NULL)
- free (debug->ss);
- if (debug->ssext != NULL)
- free (debug->ssext);
- if (debug->external_fdr != NULL)
- free (debug->external_fdr);
- if (debug->external_rfd != NULL)
- free (debug->external_rfd);
- if (debug->external_ext != NULL)
- free (debug->external_ext);
- return false;
-}
-
-/* MIPS ELF local labels start with '$', not 'L'. */
-
-static boolean
-mips_elf_is_local_label_name (abfd, name)
- bfd *abfd;
- const char *name;
-{
- if (name[0] == '$')
- return true;
-
- /* On Irix 6, the labels go back to starting with '.', so we accept
- the generic ELF local label syntax as well. */
- return _bfd_elf_is_local_label_name (abfd, name);
-}
-
-/* MIPS ELF uses a special find_nearest_line routine in order the
- handle the ECOFF debugging information. */
-
-struct mips_elf_find_line
-{
- struct ecoff_debug_info d;
- struct ecoff_find_line i;
-};
-
-boolean
-_bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
- functionname_ptr, line_ptr)
- bfd *abfd;
- asection *section;
- asymbol **symbols;
- bfd_vma offset;
- const char **filename_ptr;
- const char **functionname_ptr;
- unsigned int *line_ptr;
-{
- asection *msec;
-
- if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr))
- return true;
-
- if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr,
- (unsigned) (ABI_64_P (abfd) ? 8 : 0),
- &elf_tdata (abfd)->dwarf2_find_line_info))
- return true;
-
- msec = bfd_get_section_by_name (abfd, ".mdebug");
- if (msec != NULL)
- {
- flagword origflags;
- struct mips_elf_find_line *fi;
- const struct ecoff_debug_swap * const swap =
- get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
-
- /* If we are called during a link, mips_elf_final_link may have
- cleared the SEC_HAS_CONTENTS field. We force it back on here
- if appropriate (which it normally will be). */
- origflags = msec->flags;
- if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
- msec->flags |= SEC_HAS_CONTENTS;
-
- fi = elf_tdata (abfd)->find_line_info;
- if (fi == NULL)
- {
- bfd_size_type external_fdr_size;
- char *fraw_src;
- char *fraw_end;
- struct fdr *fdr_ptr;
- bfd_size_type amt = sizeof (struct mips_elf_find_line);
-
- fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
- if (fi == NULL)
- {
- msec->flags = origflags;
- return false;
- }
-
- if (! _bfd_mips_elf_read_ecoff_info (abfd, msec, &fi->d))
- {
- msec->flags = origflags;
- return false;
- }
-
- /* Swap in the FDR information. */
- amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
- fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
- if (fi->d.fdr == NULL)
- {
- msec->flags = origflags;
- return false;
- }
- external_fdr_size = swap->external_fdr_size;
- fdr_ptr = fi->d.fdr;
- fraw_src = (char *) fi->d.external_fdr;
- fraw_end = (fraw_src
- + fi->d.symbolic_header.ifdMax * external_fdr_size);
- for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
- (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
-
- elf_tdata (abfd)->find_line_info = fi;
-
- /* Note that we don't bother to ever free this information.
- find_nearest_line is either called all the time, as in
- objdump -l, so the information should be saved, or it is
- rarely called, as in ld error messages, so the memory
- wasted is unimportant. Still, it would probably be a
- good idea for free_cached_info to throw it away. */
- }
-
- if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
- &fi->i, filename_ptr, functionname_ptr,
- line_ptr))
- {
- msec->flags = origflags;
- return true;
- }
-
- msec->flags = origflags;
- }
-
- /* Fall back on the generic ELF find_nearest_line routine. */
-
- return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr);
-}
-
- /* The mips16 compiler uses a couple of special sections to handle
- floating point arguments.
-
- Section names that look like .mips16.fn.FNNAME contain stubs that
- copy floating point arguments from the fp regs to the gp regs and
- then jump to FNNAME. If any 32 bit function calls FNNAME, the
- call should be redirected to the stub instead. If no 32 bit
- function calls FNNAME, the stub should be discarded. We need to
- consider any reference to the function, not just a call, because
- if the address of the function is taken we will need the stub,
- since the address might be passed to a 32 bit function.
-
- Section names that look like .mips16.call.FNNAME contain stubs
- that copy floating point arguments from the gp regs to the fp
- regs and then jump to FNNAME. If FNNAME is a 32 bit function,
- then any 16 bit function that calls FNNAME should be redirected
- to the stub instead. If FNNAME is not a 32 bit function, the
- stub should be discarded.
-
- .mips16.call.fp.FNNAME sections are similar, but contain stubs
- which call FNNAME and then copy the return value from the fp regs
- to the gp regs. These stubs store the return value in $18 while
- calling FNNAME; any function which might call one of these stubs
- must arrange to save $18 around the call. (This case is not
- needed for 32 bit functions that call 16 bit functions, because
- 16 bit functions always return floating point values in both
- $f0/$f1 and $2/$3.)
-
- Note that in all cases FNNAME might be defined statically.
- Therefore, FNNAME is not used literally. Instead, the relocation
- information will indicate which symbol the section is for.
-
- We record any stubs that we find in the symbol table. */
-
-#define FN_STUB ".mips16.fn."
-#define CALL_STUB ".mips16.call."
-#define CALL_FP_STUB ".mips16.call.fp."
-
-/* MIPS ELF linker hash table. */
-
-struct mips_elf_link_hash_table
-{
- struct elf_link_hash_table root;
-#if 0
- /* We no longer use this. */
- /* String section indices for the dynamic section symbols. */
- bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
-#endif
- /* The number of .rtproc entries. */
- bfd_size_type procedure_count;
- /* The size of the .compact_rel section (if SGI_COMPAT). */
- bfd_size_type compact_rel_size;
- /* This flag indicates that the value of DT_MIPS_RLD_MAP dynamic
- entry is set to the address of __rld_obj_head as in Irix 5. */
- boolean use_rld_obj_head;
- /* This is the value of the __rld_map or __rld_obj_head symbol. */
- bfd_vma rld_value;
- /* This is set if we see any mips16 stub sections. */
- boolean mips16_stubs_seen;
-};
-
-/* Look up an entry in a MIPS ELF linker hash table. */
-
-#define mips_elf_link_hash_lookup(table, string, create, copy, follow) \
- ((struct mips_elf_link_hash_entry *) \
- elf_link_hash_lookup (&(table)->root, (string), (create), \
- (copy), (follow)))
-
-/* Traverse a MIPS ELF linker hash table. */
-
-#define mips_elf_link_hash_traverse(table, func, info) \
- (elf_link_hash_traverse \
- (&(table)->root, \
- (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
- (info)))
-
-/* Get the MIPS ELF linker hash table from a link_info structure. */
-
-#define mips_elf_hash_table(p) \
- ((struct mips_elf_link_hash_table *) ((p)->hash))
-
-static boolean mips_elf_output_extsym
- PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-
-/* Create an entry in a MIPS ELF linker hash table. */
-
-static struct bfd_hash_entry *
-mips_elf_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
-{
- struct mips_elf_link_hash_entry *ret =
- (struct mips_elf_link_hash_entry *) entry;
-
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (ret == (struct mips_elf_link_hash_entry *) NULL)
- ret = ((struct mips_elf_link_hash_entry *)
- bfd_hash_allocate (table,
- sizeof (struct mips_elf_link_hash_entry)));
- if (ret == (struct mips_elf_link_hash_entry *) NULL)
- return (struct bfd_hash_entry *) ret;
-
- /* Call the allocation method of the superclass. */
- ret = ((struct mips_elf_link_hash_entry *)
- _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
- table, string));
- if (ret != (struct mips_elf_link_hash_entry *) NULL)
- {
- /* Set local fields. */
- memset (&ret->esym, 0, sizeof (EXTR));
- /* We use -2 as a marker to indicate that the information has
- not been set. -1 means there is no associated ifd. */
- ret->esym.ifd = -2;
- ret->possibly_dynamic_relocs = 0;
- ret->readonly_reloc = false;
- ret->min_dyn_reloc_index = 0;
- ret->no_fn_stub = false;
- ret->fn_stub = NULL;
- ret->need_fn_stub = false;
- ret->call_stub = NULL;
- ret->call_fp_stub = NULL;
- ret->forced_local = false;
- }
-
- return (struct bfd_hash_entry *) ret;
-}
-
-static void
-_bfd_mips_elf_hide_symbol (info, entry, force_local)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *entry;
- boolean force_local;
-{
- bfd *dynobj;
- asection *got;
- struct mips_got_info *g;
- struct mips_elf_link_hash_entry *h;
-
- h = (struct mips_elf_link_hash_entry *) entry;
- if (h->forced_local)
- return;
- h->forced_local = true;
-
- dynobj = elf_hash_table (info)->dynobj;
- got = bfd_get_section_by_name (dynobj, ".got");
- g = (struct mips_got_info *) elf_section_data (got)->tdata;
-
- _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
-
- /* FIXME: Do we allocate too much GOT space here? */
- g->local_gotno++;
- got->_raw_size += MIPS_ELF_GOT_SIZE (dynobj);
-}
-
-/* Create a MIPS ELF linker hash table. */
-
-struct bfd_link_hash_table *
-_bfd_mips_elf_link_hash_table_create (abfd)
- bfd *abfd;
-{
- struct mips_elf_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
-
- ret = (struct mips_elf_link_hash_table *) bfd_alloc (abfd, amt);
- if (ret == (struct mips_elf_link_hash_table *) NULL)
- return NULL;
-
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- mips_elf_link_hash_newfunc))
- {
- bfd_release (abfd, ret);
- return NULL;
- }
-
-#if 0
- /* We no longer use this. */
- for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
- ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
-#endif
- ret->procedure_count = 0;
- ret->compact_rel_size = 0;
- ret->use_rld_obj_head = false;
- ret->rld_value = 0;
- ret->mips16_stubs_seen = false;
-
- return &ret->root.root;
-}
-
-/* Hook called by the linker routine which adds symbols from an object
- file. We must handle the special MIPS section numbers here. */
-
-boolean
-_bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
- bfd *abfd;
- struct bfd_link_info *info;
- const Elf_Internal_Sym *sym;
- const char **namep;
- flagword *flagsp ATTRIBUTE_UNUSED;
- asection **secp;
- bfd_vma *valp;
-{
- if (SGI_COMPAT (abfd)
- && (abfd->flags & DYNAMIC) != 0
- && strcmp (*namep, "_rld_new_interface") == 0)
- {
- /* Skip Irix 5 rld entry name. */
- *namep = NULL;
- return true;
- }
-
- switch (sym->st_shndx)
- {
- case SHN_COMMON:
- /* Common symbols less than the GP size are automatically
- treated as SHN_MIPS_SCOMMON symbols. */
- if (sym->st_size > elf_gp_size (abfd)
- || IRIX_COMPAT (abfd) == ict_irix6)
- break;
- /* Fall through. */
- case SHN_MIPS_SCOMMON:
- *secp = bfd_make_section_old_way (abfd, ".scommon");
- (*secp)->flags |= SEC_IS_COMMON;
- *valp = sym->st_size;
- break;
-
- case SHN_MIPS_TEXT:
- /* This section is used in a shared object. */
- if (elf_tdata (abfd)->elf_text_section == NULL)
- {
- asymbol *elf_text_symbol;
- asection *elf_text_section;
- bfd_size_type amt = sizeof (asection);
-
- elf_text_section = bfd_zalloc (abfd, amt);
- if (elf_text_section == NULL)
- return false;
-
- amt = sizeof (asymbol);
- elf_text_symbol = bfd_zalloc (abfd, amt);
- if (elf_text_symbol == NULL)
- return false;
-
- /* Initialize the section. */
-
- elf_tdata (abfd)->elf_text_section = elf_text_section;
- elf_tdata (abfd)->elf_text_symbol = elf_text_symbol;
-
- elf_text_section->symbol = elf_text_symbol;
- elf_text_section->symbol_ptr_ptr = &elf_tdata (abfd)->elf_text_symbol;
-
- elf_text_section->name = ".text";
- elf_text_section->flags = SEC_NO_FLAGS;
- elf_text_section->output_section = NULL;
- elf_text_section->owner = abfd;
- elf_text_symbol->name = ".text";
- elf_text_symbol->flags = BSF_SECTION_SYM | BSF_DYNAMIC;
- elf_text_symbol->section = elf_text_section;
- }
- /* This code used to do *secp = bfd_und_section_ptr if
- info->shared. I don't know why, and that doesn't make sense,
- so I took it out. */
- *secp = elf_tdata (abfd)->elf_text_section;
- break;
-
- case SHN_MIPS_ACOMMON:
- /* Fall through. XXX Can we treat this as allocated data? */
- case SHN_MIPS_DATA:
- /* This section is used in a shared object. */
- if (elf_tdata (abfd)->elf_data_section == NULL)
- {
- asymbol *elf_data_symbol;
- asection *elf_data_section;
- bfd_size_type amt = sizeof (asection);
-
- elf_data_section = bfd_zalloc (abfd, amt);
- if (elf_data_section == NULL)
- return false;
-
- amt = sizeof (asymbol);
- elf_data_symbol = bfd_zalloc (abfd, amt);
- if (elf_data_symbol == NULL)
- return false;
-
- /* Initialize the section. */
-
- elf_tdata (abfd)->elf_data_section = elf_data_section;
- elf_tdata (abfd)->elf_data_symbol = elf_data_symbol;
-
- elf_data_section->symbol = elf_data_symbol;
- elf_data_section->symbol_ptr_ptr = &elf_tdata (abfd)->elf_data_symbol;
-
- elf_data_section->name = ".data";
- elf_data_section->flags = SEC_NO_FLAGS;
- elf_data_section->output_section = NULL;
- elf_data_section->owner = abfd;
- elf_data_symbol->name = ".data";
- elf_data_symbol->flags = BSF_SECTION_SYM | BSF_DYNAMIC;
- elf_data_symbol->section = elf_data_section;
- }
- /* This code used to do *secp = bfd_und_section_ptr if
- info->shared. I don't know why, and that doesn't make sense,
- so I took it out. */
- *secp = elf_tdata (abfd)->elf_data_section;
- break;
-
- case SHN_MIPS_SUNDEFINED:
- *secp = bfd_und_section_ptr;
- break;
- }
-
- if (SGI_COMPAT (abfd)
- && ! info->shared
- && info->hash->creator == abfd->xvec
- && strcmp (*namep, "__rld_obj_head") == 0)
- {
- struct elf_link_hash_entry *h;
-
- /* Mark __rld_obj_head as dynamic. */
- h = NULL;
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, *namep, BSF_GLOBAL, *secp,
- (bfd_vma) *valp, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
-
- mips_elf_hash_table (info)->use_rld_obj_head = true;
- }
-
- /* If this is a mips16 text symbol, add 1 to the value to make it
- odd. This will cause something like .word SYM to come up with
- the right value when it is loaded into the PC. */
- if (sym->st_other == STO_MIPS16)
- ++*valp;
-
- return true;
-}
-
-/* Structure used to pass information to mips_elf_output_extsym. */
-
-struct extsym_info
-{
- bfd *abfd;
- struct bfd_link_info *info;
- struct ecoff_debug_info *debug;
- const struct ecoff_debug_swap *swap;
- boolean failed;
-};
-
-/* This routine is used to write out ECOFF debugging external symbol
- information. It is called via mips_elf_link_hash_traverse. The
- ECOFF external symbol information must match the ELF external
- symbol information. Unfortunately, at this point we don't know
- whether a symbol is required by reloc information, so the two
- tables may wind up being different. We must sort out the external
- symbol information before we can set the final size of the .mdebug
- section, and we must set the size of the .mdebug section before we
- can relocate any sections, and we can't know which symbols are
- required by relocation until we relocate the sections.
- Fortunately, it is relatively unlikely that any symbol will be
- stripped but required by a reloc. In particular, it can not happen
- when generating a final executable. */
-
-static boolean
-mips_elf_output_extsym (h, data)
- struct mips_elf_link_hash_entry *h;
- PTR data;
-{
- struct extsym_info *einfo = (struct extsym_info *) data;
- boolean strip;
- asection *sec, *output_section;
-
- if (h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
- if (h->root.indx == -2)
- strip = false;
- else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
- strip = true;
- else if (einfo->info->strip == strip_all
- || (einfo->info->strip == strip_some
- && bfd_hash_lookup (einfo->info->keep_hash,
- h->root.root.root.string,
- false, false) == NULL))
- strip = true;
- else
- strip = false;
-
- if (strip)
- return true;
-
- if (h->esym.ifd == -2)
- {
- h->esym.jmptbl = 0;
- h->esym.cobol_main = 0;
- h->esym.weakext = 0;
- h->esym.reserved = 0;
- h->esym.ifd = ifdNil;
- h->esym.asym.value = 0;
- h->esym.asym.st = stGlobal;
-
- if (h->root.root.type == bfd_link_hash_undefined
- || h->root.root.type == bfd_link_hash_undefweak)
- {
- const char *name;
-
- /* Use undefined class. Also, set class and type for some
- special symbols. */
- name = h->root.root.root.string;
- if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
- || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
- {
- h->esym.asym.sc = scData;
- h->esym.asym.st = stLabel;
- h->esym.asym.value = 0;
- }
- else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
- {
- h->esym.asym.sc = scAbs;
- h->esym.asym.st = stLabel;
- h->esym.asym.value =
- mips_elf_hash_table (einfo->info)->procedure_count;
- }
- else if (strcmp (name, "_gp_disp") == 0)
- {
- h->esym.asym.sc = scAbs;
- h->esym.asym.st = stLabel;
- h->esym.asym.value = elf_gp (einfo->abfd);
- }
- else
- h->esym.asym.sc = scUndefined;
- }
- else if (h->root.root.type != bfd_link_hash_defined
- && h->root.root.type != bfd_link_hash_defweak)
- h->esym.asym.sc = scAbs;
- else
- {
- const char *name;
-
- sec = h->root.root.u.def.section;
- output_section = sec->output_section;
-
- /* When making a shared library and symbol h is the one from
- the another shared library, OUTPUT_SECTION may be null. */
- if (output_section == NULL)
- h->esym.asym.sc = scUndefined;
- else
- {
- name = bfd_section_name (output_section->owner, output_section);
-
- if (strcmp (name, ".text") == 0)
- h->esym.asym.sc = scText;
- else if (strcmp (name, ".data") == 0)
- h->esym.asym.sc = scData;
- else if (strcmp (name, ".sdata") == 0)
- h->esym.asym.sc = scSData;
- else if (strcmp (name, ".rodata") == 0
- || strcmp (name, ".rdata") == 0)
- h->esym.asym.sc = scRData;
- else if (strcmp (name, ".bss") == 0)
- h->esym.asym.sc = scBss;
- else if (strcmp (name, ".sbss") == 0)
- h->esym.asym.sc = scSBss;
- else if (strcmp (name, ".init") == 0)
- h->esym.asym.sc = scInit;
- else if (strcmp (name, ".fini") == 0)
- h->esym.asym.sc = scFini;
- else
- h->esym.asym.sc = scAbs;
- }
- }
-
- h->esym.asym.reserved = 0;
- h->esym.asym.index = indexNil;
- }
-
- if (h->root.root.type == bfd_link_hash_common)
- h->esym.asym.value = h->root.root.u.c.size;
- else if (h->root.root.type == bfd_link_hash_defined
- || h->root.root.type == bfd_link_hash_defweak)
- {
- if (h->esym.asym.sc == scCommon)
- h->esym.asym.sc = scBss;
- else if (h->esym.asym.sc == scSCommon)
- h->esym.asym.sc = scSBss;
-
- sec = h->root.root.u.def.section;
- output_section = sec->output_section;
- if (output_section != NULL)
- h->esym.asym.value = (h->root.root.u.def.value
- + sec->output_offset
- + output_section->vma);
- else
- h->esym.asym.value = 0;
- }
- else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
- {
- struct mips_elf_link_hash_entry *hd = h;
- boolean no_fn_stub = h->no_fn_stub;
-
- while (hd->root.root.type == bfd_link_hash_indirect)
- {
- hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
- no_fn_stub = no_fn_stub || hd->no_fn_stub;
- }
-
- if (!no_fn_stub)
- {
- /* Set type and value for a symbol with a function stub. */
- h->esym.asym.st = stProc;
- sec = hd->root.root.u.def.section;
- if (sec == NULL)
- h->esym.asym.value = 0;
- else
- {
- output_section = sec->output_section;
- if (output_section != NULL)
- h->esym.asym.value = (hd->root.plt.offset
- + sec->output_offset
- + output_section->vma);
- else
- h->esym.asym.value = 0;
- }
-#if 0 /* FIXME? */
- h->esym.ifd = 0;
-#endif
- }
- }
-
- if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
- h->root.root.root.string,
- &h->esym))
- {
- einfo->failed = true;
- return false;
- }
-
- return true;
-}
-
-/* Create a runtime procedure table from the .mdebug section. */
-
-static boolean
-mips_elf_create_procedure_table (handle, abfd, info, s, debug)
- PTR handle;
- bfd *abfd;
- struct bfd_link_info *info;
- asection *s;
- struct ecoff_debug_info *debug;
-{
- const struct ecoff_debug_swap *swap;
- HDRR *hdr = &debug->symbolic_header;
- RPDR *rpdr, *rp;
- struct rpdr_ext *erp;
- PTR rtproc;
- struct pdr_ext *epdr;
- struct sym_ext *esym;
- char *ss, **sv;
- char *str;
- bfd_size_type size;
- bfd_size_type count;
- unsigned long sindex;
- unsigned long i;
- PDR pdr;
- SYMR sym;
- const char *no_name_func = _("static procedure (no name)");
-
- epdr = NULL;
- rpdr = NULL;
- esym = NULL;
- ss = NULL;
- sv = NULL;
-
- swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
-
- sindex = strlen (no_name_func) + 1;
- count = hdr->ipdMax;
- if (count > 0)
- {
- size = swap->external_pdr_size;
-
- epdr = (struct pdr_ext *) bfd_malloc (size * count);
- if (epdr == NULL)
- goto error_return;
-
- if (! _bfd_ecoff_get_accumulated_pdr (handle, (PTR) epdr))
- goto error_return;
-
- size = sizeof (RPDR);
- rp = rpdr = (RPDR *) bfd_malloc (size * count);
- if (rpdr == NULL)
- goto error_return;
-
- size = sizeof (char *);
- sv = (char **) bfd_malloc (size * count);
- if (sv == NULL)
- goto error_return;
-
- count = hdr->isymMax;
- size = swap->external_sym_size;
- esym = (struct sym_ext *) bfd_malloc (size * count);
- if (esym == NULL)
- goto error_return;
-
- if (! _bfd_ecoff_get_accumulated_sym (handle, (PTR) esym))
- goto error_return;
-
- count = hdr->issMax;
- ss = (char *) bfd_malloc (count);
- if (ss == NULL)
- goto error_return;
- if (! _bfd_ecoff_get_accumulated_ss (handle, (PTR) ss))
- goto error_return;
-
- count = hdr->ipdMax;
- for (i = 0; i < (unsigned long) count; i++, rp++)
- {
- (*swap->swap_pdr_in) (abfd, (PTR) (epdr + i), &pdr);
- (*swap->swap_sym_in) (abfd, (PTR) &esym[pdr.isym], &sym);
- rp->adr = sym.value;
- rp->regmask = pdr.regmask;
- rp->regoffset = pdr.regoffset;
- rp->fregmask = pdr.fregmask;
- rp->fregoffset = pdr.fregoffset;
- rp->frameoffset = pdr.frameoffset;
- rp->framereg = pdr.framereg;
- rp->pcreg = pdr.pcreg;
- rp->irpss = sindex;
- sv[i] = ss + sym.iss;
- sindex += strlen (sv[i]) + 1;
- }
- }
-
- size = sizeof (struct rpdr_ext) * (count + 2) + sindex;
- size = BFD_ALIGN (size, 16);
- rtproc = (PTR) bfd_alloc (abfd, size);
- if (rtproc == NULL)
- {
- mips_elf_hash_table (info)->procedure_count = 0;
- goto error_return;
- }
-
- mips_elf_hash_table (info)->procedure_count = count + 2;
-
- erp = (struct rpdr_ext *) rtproc;
- memset (erp, 0, sizeof (struct rpdr_ext));
- erp++;
- str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
- strcpy (str, no_name_func);
- str += strlen (no_name_func) + 1;
- for (i = 0; i < count; i++)
- {
- ecoff_swap_rpdr_out (abfd, rpdr + i, erp + i);
- strcpy (str, sv[i]);
- str += strlen (sv[i]) + 1;
- }
- ECOFF_PUT_OFF (abfd, -1, (erp + count)->p_adr);
-
- /* Set the size and contents of .rtproc section. */
- s->_raw_size = size;
- s->contents = (bfd_byte *) rtproc;
-
- /* Skip this section later on (I don't think this currently
- matters, but someday it might). */
- s->link_order_head = (struct bfd_link_order *) NULL;
-
- if (epdr != NULL)
- free (epdr);
- if (rpdr != NULL)
- free (rpdr);
- if (esym != NULL)
- free (esym);
- if (ss != NULL)
- free (ss);
- if (sv != NULL)
- free (sv);
-
- return true;
-
- error_return:
- if (epdr != NULL)
- free (epdr);
- if (rpdr != NULL)
- free (rpdr);
- if (esym != NULL)
- free (esym);
- if (ss != NULL)
- free (ss);
- if (sv != NULL)
- free (sv);
- return false;
-}
-
-/* A comparison routine used to sort .gptab entries. */
-
-static int
-gptab_compare (p1, p2)
- const PTR p1;
- const PTR p2;
-{
- const Elf32_gptab *a1 = (const Elf32_gptab *) p1;
- const Elf32_gptab *a2 = (const Elf32_gptab *) p2;
-
- return a1->gt_entry.gt_g_value - a2->gt_entry.gt_g_value;
-}
-
-/* We need to use a special link routine to handle the .reginfo and
- the .mdebug sections. We need to merge all instances of these
- sections together, not write them all out sequentially. */
-
-boolean
-_bfd_mips_elf_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- asection **secpp;
- asection *o;
- struct bfd_link_order *p;
- asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
- asection *rtproc_sec;
- Elf32_RegInfo reginfo;
- struct ecoff_debug_info debug;
- const struct ecoff_debug_swap *swap
- = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
- HDRR *symhdr = &debug.symbolic_header;
- PTR mdebug_handle = NULL;
- asection *s;
- EXTR esym;
- unsigned int i;
- bfd_size_type amt;
-
- static const char * const secname[] =
- {
- ".text", ".init", ".fini", ".data",
- ".rodata", ".sdata", ".sbss", ".bss"
- };
- static const int sc[] =
- {
- scText, scInit, scFini, scData,
- scRData, scSData, scSBss, scBss
- };
-
- /* If all the things we linked together were PIC, but we're
- producing an executable (rather than a shared object), then the
- resulting file is CPIC (i.e., it calls PIC code.) */
- if (!info->shared
- && !info->relocateable
- && elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
- {
- elf_elfheader (abfd)->e_flags &= ~EF_MIPS_PIC;
- elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
- }
-
- /* We'd carefully arranged the dynamic symbol indices, and then the
- generic size_dynamic_sections renumbered them out from under us.
- Rather than trying somehow to prevent the renumbering, just do
- the sort again. */
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- bfd *dynobj;
- asection *got;
- struct mips_got_info *g;
-
- /* When we resort, we must tell mips_elf_sort_hash_table what
- the lowest index it may use is. That's the number of section
- symbols we're going to add. The generic ELF linker only
- adds these symbols when building a shared object. Note that
- we count the sections after (possibly) removing the .options
- section above. */
- if (!mips_elf_sort_hash_table (info, (info->shared
- ? bfd_count_sections (abfd) + 1
- : 1)))
- return false;
-
- /* Make sure we didn't grow the global .got region. */
- dynobj = elf_hash_table (info)->dynobj;
- got = bfd_get_section_by_name (dynobj, ".got");
- g = (struct mips_got_info *) elf_section_data (got)->tdata;
-
- if (g->global_gotsym != NULL)
- BFD_ASSERT ((elf_hash_table (info)->dynsymcount
- - g->global_gotsym->dynindx)
- <= g->global_gotno);
- }
-
- /* On IRIX5, we omit the .options section. On IRIX6, however, we
- include it, even though we don't process it quite right. (Some
- entries are supposed to be merged.) Empirically, we seem to be
- better off including it then not. */
- if (IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none)
- for (secpp = &abfd->sections; *secpp != NULL; secpp = &(*secpp)->next)
- {
- if (strcmp ((*secpp)->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
- {
- for (p = (*secpp)->link_order_head; p != NULL; p = p->next)
- if (p->type == bfd_indirect_link_order)
- p->u.indirect.section->flags &= ~SEC_HAS_CONTENTS;
- (*secpp)->link_order_head = NULL;
- bfd_section_list_remove (abfd, secpp);
- --abfd->section_count;
-
- break;
- }
- }
-
- /* Get a value for the GP register. */
- if (elf_gp (abfd) == 0)
- {
- struct bfd_link_hash_entry *h;
-
- h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true);
- if (h != (struct bfd_link_hash_entry *) NULL
- && h->type == bfd_link_hash_defined)
- elf_gp (abfd) = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
- else if (info->relocateable)
- {
- bfd_vma lo;
-
- /* Find the GP-relative section with the lowest offset. */
- lo = (bfd_vma) -1;
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- if (o->vma < lo
- && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
- lo = o->vma;
-
- /* And calculate GP relative to that. */
- elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (abfd);
- }
- else
- {
- /* If the relocate_section function needs to do a reloc
- involving the GP value, it should make a reloc_dangerous
- callback to warn that GP is not defined. */
- }
- }
-
- /* Go through the sections and collect the .reginfo and .mdebug
- information. */
- reginfo_sec = NULL;
- mdebug_sec = NULL;
- gptab_data_sec = NULL;
- gptab_bss_sec = NULL;
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- {
- if (strcmp (o->name, ".reginfo") == 0)
- {
- memset (&reginfo, 0, sizeof reginfo);
-
- /* We have found the .reginfo section in the output file.
- Look through all the link_orders comprising it and merge
- the information together. */
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
- bfd *input_bfd;
- Elf32_External_RegInfo ext;
- Elf32_RegInfo sub;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
- input_bfd = input_section->owner;
-
- /* The linker emulation code has probably clobbered the
- size to be zero bytes. */
- if (input_section->_raw_size == 0)
- input_section->_raw_size = sizeof (Elf32_External_RegInfo);
-
- if (! bfd_get_section_contents (input_bfd, input_section,
- (PTR) &ext,
- (file_ptr) 0,
- (bfd_size_type) sizeof ext))
- return false;
-
- bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub);
-
- reginfo.ri_gprmask |= sub.ri_gprmask;
- reginfo.ri_cprmask[0] |= sub.ri_cprmask[0];
- reginfo.ri_cprmask[1] |= sub.ri_cprmask[1];
- reginfo.ri_cprmask[2] |= sub.ri_cprmask[2];
- reginfo.ri_cprmask[3] |= sub.ri_cprmask[3];
-
- /* ri_gp_value is set by the function
- mips_elf32_section_processing when the section is
- finally written out. */
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &= ~SEC_HAS_CONTENTS;
- }
-
- /* Size has been set in mips_elf_always_size_sections */
- BFD_ASSERT(o->_raw_size == sizeof (Elf32_External_RegInfo));
-
- /* Skip this section later on (I don't think this currently
- matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
-
- reginfo_sec = o;
- }
-
- if (strcmp (o->name, ".mdebug") == 0)
- {
- struct extsym_info einfo;
- bfd_vma last;
-
- /* We have found the .mdebug section in the output file.
- Look through all the link_orders comprising it and merge
- the information together. */
- symhdr->magic = swap->sym_magic;
- /* FIXME: What should the version stamp be? */
- symhdr->vstamp = 0;
- symhdr->ilineMax = 0;
- symhdr->cbLine = 0;
- symhdr->idnMax = 0;
- symhdr->ipdMax = 0;
- symhdr->isymMax = 0;
- symhdr->ioptMax = 0;
- symhdr->iauxMax = 0;
- symhdr->issMax = 0;
- symhdr->issExtMax = 0;
- symhdr->ifdMax = 0;
- symhdr->crfd = 0;
- symhdr->iextMax = 0;
-
- /* We accumulate the debugging information itself in the
- debug_info structure. */
- debug.line = NULL;
- debug.external_dnr = NULL;
- debug.external_pdr = NULL;
- debug.external_sym = NULL;
- debug.external_opt = NULL;
- debug.external_aux = NULL;
- debug.ss = NULL;
- debug.ssext = debug.ssext_end = NULL;
- debug.external_fdr = NULL;
- debug.external_rfd = NULL;
- debug.external_ext = debug.external_ext_end = NULL;
-
- mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
- if (mdebug_handle == (PTR) NULL)
- return false;
-
- esym.jmptbl = 0;
- esym.cobol_main = 0;
- esym.weakext = 0;
- esym.reserved = 0;
- esym.ifd = ifdNil;
- esym.asym.iss = issNil;
- esym.asym.st = stLocal;
- esym.asym.reserved = 0;
- esym.asym.index = indexNil;
- last = 0;
- for (i = 0; i < sizeof (secname) / sizeof (secname[0]); i++)
- {
- esym.asym.sc = sc[i];
- s = bfd_get_section_by_name (abfd, secname[i]);
- if (s != NULL)
- {
- esym.asym.value = s->vma;
- last = s->vma + s->_raw_size;
- }
- else
- esym.asym.value = last;
- if (!bfd_ecoff_debug_one_external (abfd, &debug, swap,
- secname[i], &esym))
- return false;
- }
-
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
- bfd *input_bfd;
- const struct ecoff_debug_swap *input_swap;
- struct ecoff_debug_info input_debug;
- char *eraw_src;
- char *eraw_end;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
- input_bfd = input_section->owner;
-
- if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
- || (get_elf_backend_data (input_bfd)
- ->elf_backend_ecoff_debug_swap) == NULL)
- {
- /* I don't know what a non MIPS ELF bfd would be
- doing with a .mdebug section, but I don't really
- want to deal with it. */
- continue;
- }
-
- input_swap = (get_elf_backend_data (input_bfd)
- ->elf_backend_ecoff_debug_swap);
-
- BFD_ASSERT (p->size == input_section->_raw_size);
-
- /* The ECOFF linking code expects that we have already
- read in the debugging information and set up an
- ecoff_debug_info structure, so we do that now. */
- if (! _bfd_mips_elf_read_ecoff_info (input_bfd, input_section,
- &input_debug))
- return false;
-
- if (! (bfd_ecoff_debug_accumulate
- (mdebug_handle, abfd, &debug, swap, input_bfd,
- &input_debug, input_swap, info)))
- return false;
-
- /* Loop through the external symbols. For each one with
- interesting information, try to find the symbol in
- the linker global hash table and save the information
- for the output external symbols. */
- eraw_src = input_debug.external_ext;
- eraw_end = (eraw_src
- + (input_debug.symbolic_header.iextMax
- * input_swap->external_ext_size));
- for (;
- eraw_src < eraw_end;
- eraw_src += input_swap->external_ext_size)
- {
- EXTR ext;
- const char *name;
- struct mips_elf_link_hash_entry *h;
-
- (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
- if (ext.asym.sc == scNil
- || ext.asym.sc == scUndefined
- || ext.asym.sc == scSUndefined)
- continue;
-
- name = input_debug.ssext + ext.asym.iss;
- h = mips_elf_link_hash_lookup (mips_elf_hash_table (info),
- name, false, false, true);
- if (h == NULL || h->esym.ifd != -2)
- continue;
-
- if (ext.ifd != -1)
- {
- BFD_ASSERT (ext.ifd
- < input_debug.symbolic_header.ifdMax);
- ext.ifd = input_debug.ifdmap[ext.ifd];
- }
-
- h->esym = ext;
- }
-
- /* Free up the information we just read. */
- free (input_debug.line);
- free (input_debug.external_dnr);
- free (input_debug.external_pdr);
- free (input_debug.external_sym);
- free (input_debug.external_opt);
- free (input_debug.external_aux);
- free (input_debug.ss);
- free (input_debug.ssext);
- free (input_debug.external_fdr);
- free (input_debug.external_rfd);
- free (input_debug.external_ext);
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &= ~SEC_HAS_CONTENTS;
- }
-
- if (SGI_COMPAT (abfd) && info->shared)
- {
- /* Create .rtproc section. */
- rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
- if (rtproc_sec == NULL)
- {
- flagword flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED | SEC_READONLY);
-
- rtproc_sec = bfd_make_section (abfd, ".rtproc");
- if (rtproc_sec == NULL
- || ! bfd_set_section_flags (abfd, rtproc_sec, flags)
- || ! bfd_set_section_alignment (abfd, rtproc_sec, 4))
- return false;
- }
-
- if (! mips_elf_create_procedure_table (mdebug_handle, abfd,
- info, rtproc_sec, &debug))
- return false;
- }
-
- /* Build the external symbol information. */
- einfo.abfd = abfd;
- einfo.info = info;
- einfo.debug = &debug;
- einfo.swap = swap;
- einfo.failed = false;
- mips_elf_link_hash_traverse (mips_elf_hash_table (info),
- mips_elf_output_extsym,
- (PTR) &einfo);
- if (einfo.failed)
- return false;
-
- /* Set the size of the .mdebug section. */
- o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
-
- /* Skip this section later on (I don't think this currently
- matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
-
- mdebug_sec = o;
- }
-
- if (strncmp (o->name, ".gptab.", sizeof ".gptab." - 1) == 0)
- {
- const char *subname;
- unsigned int c;
- Elf32_gptab *tab;
- Elf32_External_gptab *ext_tab;
- unsigned int j;
-
- /* The .gptab.sdata and .gptab.sbss sections hold
- information describing how the small data area would
- change depending upon the -G switch. These sections
- not used in executables files. */
- if (! info->relocateable)
- {
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &= ~SEC_HAS_CONTENTS;
- }
-
- /* Skip this section later on (I don't think this
- currently matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
-
- /* Really remove the section. */
- for (secpp = &abfd->sections;
- *secpp != o;
- secpp = &(*secpp)->next)
- ;
- bfd_section_list_remove (abfd, secpp);
- --abfd->section_count;
-
- continue;
- }
-
- /* There is one gptab for initialized data, and one for
- uninitialized data. */
- if (strcmp (o->name, ".gptab.sdata") == 0)
- gptab_data_sec = o;
- else if (strcmp (o->name, ".gptab.sbss") == 0)
- gptab_bss_sec = o;
- else
- {
- (*_bfd_error_handler)
- (_("%s: illegal section name `%s'"),
- bfd_get_filename (abfd), o->name);
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
-
- /* The linker script always combines .gptab.data and
- .gptab.sdata into .gptab.sdata, and likewise for
- .gptab.bss and .gptab.sbss. It is possible that there is
- no .sdata or .sbss section in the output file, in which
- case we must change the name of the output section. */
- subname = o->name + sizeof ".gptab" - 1;
- if (bfd_get_section_by_name (abfd, subname) == NULL)
- {
- if (o == gptab_data_sec)
- o->name = ".gptab.data";
- else
- o->name = ".gptab.bss";
- subname = o->name + sizeof ".gptab" - 1;
- BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL);
- }
-
- /* Set up the first entry. */
- c = 1;
- amt = c * sizeof (Elf32_gptab);
- tab = (Elf32_gptab *) bfd_malloc (amt);
- if (tab == NULL)
- return false;
- tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
- tab[0].gt_header.gt_unused = 0;
-
- /* Combine the input sections. */
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
- bfd *input_bfd;
- bfd_size_type size;
- unsigned long last;
- bfd_size_type gpentry;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
- input_bfd = input_section->owner;
-
- /* Combine the gptab entries for this input section one
- by one. We know that the input gptab entries are
- sorted by ascending -G value. */
- size = bfd_section_size (input_bfd, input_section);
- last = 0;
- for (gpentry = sizeof (Elf32_External_gptab);
- gpentry < size;
- gpentry += sizeof (Elf32_External_gptab))
- {
- Elf32_External_gptab ext_gptab;
- Elf32_gptab int_gptab;
- unsigned long val;
- unsigned long add;
- boolean exact;
- unsigned int look;
-
- if (! (bfd_get_section_contents
- (input_bfd, input_section, (PTR) &ext_gptab,
- (file_ptr) gpentry,
- (bfd_size_type) sizeof (Elf32_External_gptab))))
- {
- free (tab);
- return false;
- }
-
- bfd_mips_elf32_swap_gptab_in (input_bfd, &ext_gptab,
- &int_gptab);
- val = int_gptab.gt_entry.gt_g_value;
- add = int_gptab.gt_entry.gt_bytes - last;
-
- exact = false;
- for (look = 1; look < c; look++)
- {
- if (tab[look].gt_entry.gt_g_value >= val)
- tab[look].gt_entry.gt_bytes += add;
-
- if (tab[look].gt_entry.gt_g_value == val)
- exact = true;
- }
-
- if (! exact)
- {
- Elf32_gptab *new_tab;
- unsigned int max;
-
- /* We need a new table entry. */
- amt = (bfd_size_type) (c + 1) * sizeof (Elf32_gptab);
- new_tab = (Elf32_gptab *) bfd_realloc ((PTR) tab, amt);
- if (new_tab == NULL)
- {
- free (tab);
- return false;
- }
- tab = new_tab;
- tab[c].gt_entry.gt_g_value = val;
- tab[c].gt_entry.gt_bytes = add;
-
- /* Merge in the size for the next smallest -G
- value, since that will be implied by this new
- value. */
- max = 0;
- for (look = 1; look < c; look++)
- {
- if (tab[look].gt_entry.gt_g_value < val
- && (max == 0
- || (tab[look].gt_entry.gt_g_value
- > tab[max].gt_entry.gt_g_value)))
- max = look;
- }
- if (max != 0)
- tab[c].gt_entry.gt_bytes +=
- tab[max].gt_entry.gt_bytes;
-
- ++c;
- }
-
- last = int_gptab.gt_entry.gt_bytes;
- }
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &= ~SEC_HAS_CONTENTS;
- }
-
- /* The table must be sorted by -G value. */
- if (c > 2)
- qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare);
-
- /* Swap out the table. */
- amt = (bfd_size_type) c * sizeof (Elf32_External_gptab);
- ext_tab = (Elf32_External_gptab *) bfd_alloc (abfd, amt);
- if (ext_tab == NULL)
- {
- free (tab);
- return false;
- }
-
- for (j = 0; j < c; j++)
- bfd_mips_elf32_swap_gptab_out (abfd, tab + j, ext_tab + j);
- free (tab);
-
- o->_raw_size = c * sizeof (Elf32_External_gptab);
- o->contents = (bfd_byte *) ext_tab;
-
- /* Skip this section later on (I don't think this currently
- matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
- }
- }
-
- /* Invoke the regular ELF backend linker to do all the work. */
- if (ABI_64_P (abfd))
- {
-#ifdef BFD64
- if (!bfd_elf64_bfd_final_link (abfd, info))
- return false;
-#else
- abort ();
- return false;
-#endif /* BFD64 */
- }
- else if (!bfd_elf32_bfd_final_link (abfd, info))
- return false;
-
- /* Now write out the computed sections. */
-
- if (reginfo_sec != (asection *) NULL)
- {
- Elf32_External_RegInfo ext;
-
- bfd_mips_elf32_swap_reginfo_out (abfd, &reginfo, &ext);
- if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext,
- (file_ptr) 0, (bfd_size_type) sizeof ext))
- return false;
- }
-
- if (mdebug_sec != (asection *) NULL)
- {
- BFD_ASSERT (abfd->output_has_begun);
- if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
- swap, info,
- mdebug_sec->filepos))
- return false;
-
- bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
- }
-
- if (gptab_data_sec != (asection *) NULL)
- {
- if (! bfd_set_section_contents (abfd, gptab_data_sec,
- gptab_data_sec->contents,
- (file_ptr) 0,
- gptab_data_sec->_raw_size))
- return false;
- }
-
- if (gptab_bss_sec != (asection *) NULL)
- {
- if (! bfd_set_section_contents (abfd, gptab_bss_sec,
- gptab_bss_sec->contents,
- (file_ptr) 0,
- gptab_bss_sec->_raw_size))
- return false;
- }
-
- if (SGI_COMPAT (abfd))
- {
- rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
- if (rtproc_sec != NULL)
- {
- if (! bfd_set_section_contents (abfd, rtproc_sec,
- rtproc_sec->contents,
- (file_ptr) 0,
- rtproc_sec->_raw_size))
- return false;
- }
- }
-
- return true;
-}
-
-/* This function is called via qsort() to sort the dynamic relocation
- entries by increasing r_symndx value. */
-
-static int
-sort_dynamic_relocs (arg1, arg2)
- const PTR arg1;
- const PTR arg2;
-{
- const Elf32_External_Rel *ext_reloc1 = (const Elf32_External_Rel *) arg1;
- const Elf32_External_Rel *ext_reloc2 = (const Elf32_External_Rel *) arg2;
-
- Elf_Internal_Rel int_reloc1;
- Elf_Internal_Rel int_reloc2;
-
- bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, ext_reloc1, &int_reloc1);
- bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, ext_reloc2, &int_reloc2);
-
- return (ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info));
-}
-
-/* Returns the GOT section for ABFD. */
-
-static asection *
-mips_elf_got_section (abfd)
- bfd *abfd;
-{
- return bfd_get_section_by_name (abfd, ".got");
-}
-
-/* Returns the GOT information associated with the link indicated by
- INFO. If SGOTP is non-NULL, it is filled in with the GOT
- section. */
-
-static struct mips_got_info *
-mips_elf_got_info (abfd, sgotp)
- bfd *abfd;
- asection **sgotp;
-{
- asection *sgot;
- struct mips_got_info *g;
-
- sgot = mips_elf_got_section (abfd);
- BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
-
- if (sgotp)
- *sgotp = sgot;
- return g;
-}
-
-/* Return whether a relocation is against a local symbol. */
-
-static boolean
-mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
- check_forced)
- bfd *input_bfd;
- const Elf_Internal_Rela *relocation;
- asection **local_sections;
- boolean check_forced;
-{
- unsigned long r_symndx;
- Elf_Internal_Shdr *symtab_hdr;
- struct mips_elf_link_hash_entry *h;
- size_t extsymoff;
-
- r_symndx = ELF32_R_SYM (relocation->r_info);
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
-
- if (r_symndx < extsymoff)
- return true;
- if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL)
- return true;
-
- if (check_forced)
- {
- /* Look up the hash table to check whether the symbol
- was forced local. */
- h = (struct mips_elf_link_hash_entry *)
- elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
- /* Find the real hash-table entry for this symbol. */
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
- if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
- return true;
- }
-
- return false;
-}
-
-/* Sign-extend VALUE, which has the indicated number of BITS. */
-
-static bfd_vma
-mips_elf_sign_extend (value, bits)
- bfd_vma value;
- int bits;
-{
- if (value & ((bfd_vma) 1 << (bits - 1)))
- /* VALUE is negative. */
- value |= ((bfd_vma) - 1) << bits;
-
- return value;
-}
-
-/* Return non-zero if the indicated VALUE has overflowed the maximum
- range expressable by a signed number with the indicated number of
- BITS. */
-
-static boolean
-mips_elf_overflow_p (value, bits)
- bfd_vma value;
- int bits;
-{
- bfd_signed_vma svalue = (bfd_signed_vma) value;
-
- if (svalue > (1 << (bits - 1)) - 1)
- /* The value is too big. */
- return true;
- else if (svalue < -(1 << (bits - 1)))
- /* The value is too small. */
- return true;
-
- /* All is well. */
- return false;
-}
-
-/* Calculate the %high function. */
-
-static bfd_vma
-mips_elf_high (value)
- bfd_vma value;
-{
- return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
-}
-
-/* Calculate the %higher function. */
-
-static bfd_vma
-mips_elf_higher (value)
- bfd_vma value ATTRIBUTE_UNUSED;
-{
-#ifdef BFD64
- return ((value + (bfd_vma) 0x80008000) >> 32) & 0xffff;
-#else
- abort ();
- return (bfd_vma) -1;
-#endif
-}
-
-/* Calculate the %highest function. */
-
-static bfd_vma
-mips_elf_highest (value)
- bfd_vma value ATTRIBUTE_UNUSED;
-{
-#ifdef BFD64
- return ((value + (bfd_vma) 0x800080008000) >> 48) & 0xffff;
-#else
- abort ();
- return (bfd_vma) -1;
-#endif
-}
-
-/* Returns the GOT index for the global symbol indicated by H. */
-
-static bfd_vma
-mips_elf_global_got_index (abfd, h)
- bfd *abfd;
- struct elf_link_hash_entry *h;
-{
- bfd_vma index;
- asection *sgot;
- struct mips_got_info *g;
-
- g = mips_elf_got_info (abfd, &sgot);
-
- /* Once we determine the global GOT entry with the lowest dynamic
- symbol table index, we must put all dynamic symbols with greater
- indices into the GOT. That makes it easy to calculate the GOT
- offset. */
- BFD_ASSERT (h->dynindx >= g->global_gotsym->dynindx);
- index = ((h->dynindx - g->global_gotsym->dynindx + g->local_gotno)
- * MIPS_ELF_GOT_SIZE (abfd));
- BFD_ASSERT (index < sgot->_raw_size);
-
- return index;
-}
-
-/* Returns the offset for the entry at the INDEXth position
- in the GOT. */
-
-static bfd_vma
-mips_elf_got_offset_from_index (dynobj, output_bfd, index)
- bfd *dynobj;
- bfd *output_bfd;
- bfd_vma index;
-{
- asection *sgot;
- bfd_vma gp;
-
- sgot = mips_elf_got_section (dynobj);
- gp = _bfd_get_gp_value (output_bfd);
- return (sgot->output_section->vma + sgot->output_offset + index -
- gp);
-}
-
-/* If H is a symbol that needs a global GOT entry, but has a dynamic
- symbol table index lower than any we've seen to date, record it for
- posterity. */
-
-static boolean
-mips_elf_record_global_got_symbol (h, info, g)
- struct elf_link_hash_entry *h;
- struct bfd_link_info *info;
- struct mips_got_info *g ATTRIBUTE_UNUSED;
-{
- /* A global symbol in the GOT must also be in the dynamic symbol
- table. */
- if (h->dynindx == -1)
- {
- switch (ELF_ST_VISIBILITY (h->other))
- {
- case STV_INTERNAL:
- case STV_HIDDEN:
- _bfd_mips_elf_hide_symbol (info, h, true);
- break;
- }
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
-
- /* If we've already marked this entry as needing GOT space, we don't
- need to do it again. */
- if (h->got.offset != (bfd_vma) -1)
- return true;
-
- /* By setting this to a value other than -1, we are indicating that
- there needs to be a GOT entry for H. Avoid using zero, as the
- generic ELF copy_indirect_symbol tests for <= 0. */
- h->got.offset = 1;
-
- return true;
-}
-
-/* This structure is passed to mips_elf_sort_hash_table_f when sorting
- the dynamic symbols. */
-
-struct mips_elf_hash_sort_data
-{
- /* The symbol in the global GOT with the lowest dynamic symbol table
- index. */
- struct elf_link_hash_entry *low;
- /* The least dynamic symbol table index corresponding to a symbol
- with a GOT entry. */
- long min_got_dynindx;
- /* The greatest dynamic symbol table index not corresponding to a
- symbol without a GOT entry. */
- long max_non_got_dynindx;
-};
-
-/* If H needs a GOT entry, assign it the highest available dynamic
- index. Otherwise, assign it the lowest available dynamic
- index. */
-
-static boolean
-mips_elf_sort_hash_table_f (h, data)
- struct mips_elf_link_hash_entry *h;
- PTR data;
-{
- struct mips_elf_hash_sort_data *hsd
- = (struct mips_elf_hash_sort_data *) data;
-
- if (h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
- /* Symbols without dynamic symbol table entries aren't interesting
- at all. */
- if (h->root.dynindx == -1)
- return true;
-
- if (h->root.got.offset != 1)
- h->root.dynindx = hsd->max_non_got_dynindx++;
- else
- {
- h->root.dynindx = --hsd->min_got_dynindx;
- hsd->low = (struct elf_link_hash_entry *) h;
- }
-
- return true;
-}
-
-/* Sort the dynamic symbol table so that symbols that need GOT entries
- appear towards the end. This reduces the amount of GOT space
- required. MAX_LOCAL is used to set the number of local symbols
- known to be in the dynamic symbol table. During
- mips_elf_size_dynamic_sections, this value is 1. Afterward, the
- section symbols are added and the count is higher. */
-
-static boolean
-mips_elf_sort_hash_table (info, max_local)
- struct bfd_link_info *info;
- unsigned long max_local;
-{
- struct mips_elf_hash_sort_data hsd;
- struct mips_got_info *g;
- bfd *dynobj;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- hsd.low = NULL;
- hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount;
- hsd.max_non_got_dynindx = max_local;
- mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *)
- elf_hash_table (info)),
- mips_elf_sort_hash_table_f,
- &hsd);
-
- /* There should have been enough room in the symbol table to
- accomodate both the GOT and non-GOT symbols. */
- BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
-
- /* Now we know which dynamic symbol has the lowest dynamic symbol
- table index in the GOT. */
- g = mips_elf_got_info (dynobj, NULL);
- g->global_gotsym = hsd.low;
-
- return true;
-}
-
-/* Create a local GOT entry for VALUE. Return the index of the entry,
- or -1 if it could not be created. */
-
-static bfd_vma
-mips_elf_create_local_got_entry (abfd, g, sgot, value)
- bfd *abfd;
- struct mips_got_info *g;
- asection *sgot;
- bfd_vma value;
-{
- if (g->assigned_gotno >= g->local_gotno)
- {
- /* We didn't allocate enough space in the GOT. */
- (*_bfd_error_handler)
- (_("not enough GOT space for local GOT entries"));
- bfd_set_error (bfd_error_bad_value);
- return (bfd_vma) -1;
- }
-
- MIPS_ELF_PUT_WORD (abfd, value,
- (sgot->contents
- + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno));
- return MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
-}
-
-/* Returns the GOT offset at which the indicated address can be found.
- If there is not yet a GOT entry for this value, create one. Returns
- -1 if no satisfactory GOT offset can be found. */
-
-static bfd_vma
-mips_elf_local_got_index (abfd, info, value)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_vma value;
-{
- asection *sgot;
- struct mips_got_info *g;
- bfd_byte *entry;
-
- g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- /* Look to see if we already have an appropriate entry. */
- for (entry = (sgot->contents
- + MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO);
- entry != sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
- entry += MIPS_ELF_GOT_SIZE (abfd))
- {
- bfd_vma address = MIPS_ELF_GET_WORD (abfd, entry);
- if (address == value)
- return entry - sgot->contents;
- }
-
- return mips_elf_create_local_got_entry (abfd, g, sgot, value);
-}
-
-/* Find a GOT entry that is within 32KB of the VALUE. These entries
- are supposed to be placed at small offsets in the GOT, i.e.,
- within 32KB of GP. Return the index into the GOT for this page,
- and store the offset from this entry to the desired address in
- OFFSETP, if it is non-NULL. */
-
-static bfd_vma
-mips_elf_got_page (abfd, info, value, offsetp)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_vma value;
- bfd_vma *offsetp;
-{
- asection *sgot;
- struct mips_got_info *g;
- bfd_byte *entry;
- bfd_byte *last_entry;
- bfd_vma index = 0;
- bfd_vma address;
-
- g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- /* Look to see if we aleady have an appropriate entry. */
- last_entry = sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
- for (entry = (sgot->contents
- + MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO);
- entry != last_entry;
- entry += MIPS_ELF_GOT_SIZE (abfd))
- {
- address = MIPS_ELF_GET_WORD (abfd, entry);
-
- if (!mips_elf_overflow_p (value - address, 16))
- {
- /* This entry will serve as the page pointer. We can add a
- 16-bit number to it to get the actual address. */
- index = entry - sgot->contents;
- break;
- }
- }
-
- /* If we didn't have an appropriate entry, we create one now. */
- if (entry == last_entry)
- index = mips_elf_create_local_got_entry (abfd, g, sgot, value);
-
- if (offsetp)
- {
- address = MIPS_ELF_GET_WORD (abfd, entry);
- *offsetp = value - address;
- }
-
- return index;
-}
-
-/* Find a GOT entry whose higher-order 16 bits are the same as those
- for value. Return the index into the GOT for this entry. */
-
-static bfd_vma
-mips_elf_got16_entry (abfd, info, value, external)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_vma value;
- boolean external;
-{
- asection *sgot;
- struct mips_got_info *g;
- bfd_byte *entry;
- bfd_byte *last_entry;
- bfd_vma index = 0;
- bfd_vma address;
-
- if (! external)
- {
- /* Although the ABI says that it is "the high-order 16 bits" that we
- want, it is really the %high value. The complete value is
- calculated with a `addiu' of a LO16 relocation, just as with a
- HI16/LO16 pair. */
- value = mips_elf_high (value) << 16;
- }
-
- g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- /* Look to see if we already have an appropriate entry. */
- last_entry = sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
- for (entry = (sgot->contents
- + MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO);
- entry != last_entry;
- entry += MIPS_ELF_GOT_SIZE (abfd))
- {
- address = MIPS_ELF_GET_WORD (abfd, entry);
- if (address == value)
- {
- /* This entry has the right high-order 16 bits, and the low-order
- 16 bits are set to zero. */
- index = entry - sgot->contents;
- break;
- }
- }
-
- /* If we didn't have an appropriate entry, we create one now. */
- if (entry == last_entry)
- index = mips_elf_create_local_got_entry (abfd, g, sgot, value);
-
- return index;
-}
-
-/* Returns the first relocation of type r_type found, beginning with
- RELOCATION. RELEND is one-past-the-end of the relocation table. */
-
-static const Elf_Internal_Rela *
-mips_elf_next_relocation (r_type, relocation, relend)
- unsigned int r_type;
- const Elf_Internal_Rela *relocation;
- const Elf_Internal_Rela *relend;
-{
- /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
- immediately following. However, for the IRIX6 ABI, the next
- relocation may be a composed relocation consisting of several
- relocations for the same address. In that case, the R_MIPS_LO16
- relocation may occur as one of these. We permit a similar
- extension in general, as that is useful for GCC. */
- while (relocation < relend)
- {
- if (ELF32_R_TYPE (relocation->r_info) == r_type)
- return relocation;
-
- ++relocation;
- }
-
- /* We didn't find it. */
- bfd_set_error (bfd_error_bad_value);
- return NULL;
-}
-
-/* Create a rel.dyn relocation for the dynamic linker to resolve. REL
- is the original relocation, which is now being transformed into a
- dynamic relocation. The ADDENDP is adjusted if necessary; the
- caller should store the result in place of the original addend. */
-
-static boolean
-mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
- symbol, addendp, input_section)
- bfd *output_bfd;
- struct bfd_link_info *info;
- const Elf_Internal_Rela *rel;
- struct mips_elf_link_hash_entry *h;
- asection *sec;
- bfd_vma symbol;
- bfd_vma *addendp;
- asection *input_section;
-{
- Elf_Internal_Rel outrel;
- boolean skip;
- asection *sreloc;
- bfd *dynobj;
- int r_type;
-
- r_type = ELF32_R_TYPE (rel->r_info);
- dynobj = elf_hash_table (info)->dynobj;
- sreloc
- = bfd_get_section_by_name (dynobj,
- MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd));
- BFD_ASSERT (sreloc != NULL);
- BFD_ASSERT (sreloc->contents != NULL);
- BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd)
- < sreloc->_raw_size);
-
- skip = false;
- outrel.r_offset =
- _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset);
- if (outrel.r_offset == (bfd_vma) -1)
- skip = true;
- /* FIXME: For -2 runtime relocation needs to be skipped, but
- properly resolved statically and installed. */
- BFD_ASSERT (outrel.r_offset != (bfd_vma) -2);
-
- /* If we've decided to skip this relocation, just output an empty
- record. Note that R_MIPS_NONE == 0, so that this call to memset
- is a way of setting R_TYPE to R_MIPS_NONE. */
- if (skip)
- memset (&outrel, 0, sizeof (outrel));
- else
- {
- long indx;
- bfd_vma section_offset;
-
- /* We must now calculate the dynamic symbol table index to use
- in the relocation. */
- if (h != NULL
- && (! info->symbolic || (h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- {
- indx = h->root.dynindx;
- /* h->root.dynindx may be -1 if this symbol was marked to
- become local. */
- if (indx == -1)
- indx = 0;
- }
- else
- {
- if (sec != NULL && bfd_is_abs_section (sec))
- indx = 0;
- else if (sec == NULL || sec->owner == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- else
- {
- indx = elf_section_data (sec->output_section)->dynindx;
- if (indx == 0)
- abort ();
- }
-
- /* Figure out how far the target of the relocation is from
- the beginning of its section. */
- section_offset = symbol - sec->output_section->vma;
- /* The relocation we're building is section-relative.
- Therefore, the original addend must be adjusted by the
- section offset. */
- *addendp += section_offset;
- /* Now, the relocation is just against the section. */
- symbol = sec->output_section->vma;
- }
-
- /* If the relocation was previously an absolute relocation and
- this symbol will not be referred to by the relocation, we must
- adjust it by the value we give it in the dynamic symbol table.
- Otherwise leave the job up to the dynamic linker. */
- if (!indx && r_type != R_MIPS_REL32)
- *addendp += symbol;
-
- /* The relocation is always an REL32 relocation because we don't
- know where the shared library will wind up at load-time. */
- outrel.r_info = ELF32_R_INFO (indx, R_MIPS_REL32);
-
- /* Adjust the output offset of the relocation to reference the
- correct location in the output file. */
- outrel.r_offset += (input_section->output_section->vma
- + input_section->output_offset);
- }
-
- /* Put the relocation back out. We have to use the special
- relocation outputter in the 64-bit case since the 64-bit
- relocation format is non-standard. */
- if (ABI_64_P (output_bfd))
- {
- (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
- (output_bfd, &outrel,
- (sreloc->contents
- + sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
- }
- else
- bfd_elf32_swap_reloc_out (output_bfd, &outrel,
- (((Elf32_External_Rel *)
- sreloc->contents)
- + sreloc->reloc_count));
-
- /* Record the index of the first relocation referencing H. This
- information is later emitted in the .msym section. */
- if (h != NULL
- && (h->min_dyn_reloc_index == 0
- || sreloc->reloc_count < h->min_dyn_reloc_index))
- h->min_dyn_reloc_index = sreloc->reloc_count;
-
- /* We've now added another relocation. */
- ++sreloc->reloc_count;
-
- /* Make sure the output section is writable. The dynamic linker
- will be writing to it. */
- elf_section_data (input_section->output_section)->this_hdr.sh_flags
- |= SHF_WRITE;
-
- /* On IRIX5, make an entry of compact relocation info. */
- if (! skip && IRIX_COMPAT (output_bfd) == ict_irix5)
- {
- asection *scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
- bfd_byte *cr;
-
- if (scpt)
- {
- Elf32_crinfo cptrel;
-
- mips_elf_set_cr_format (cptrel, CRF_MIPS_LONG);
- cptrel.vaddr = (rel->r_offset
- + input_section->output_section->vma
- + input_section->output_offset);
- if (r_type == R_MIPS_REL32)
- mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32);
- else
- mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
- mips_elf_set_cr_dist2to (cptrel, 0);
- cptrel.konst = *addendp;
-
- cr = (scpt->contents
- + sizeof (Elf32_External_compact_rel));
- bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
- ((Elf32_External_crinfo *) cr
- + scpt->reloc_count));
- ++scpt->reloc_count;
- }
- }
-
- return true;
-}
-
-/* Calculate the value produced by the RELOCATION (which comes from
- the INPUT_BFD). The ADDEND is the addend to use for this
- RELOCATION; RELOCATION->R_ADDEND is ignored.
-
- The result of the relocation calculation is stored in VALUEP.
- REQUIRE_JALXP indicates whether or not the opcode used with this
- relocation must be JALX.
-
- This function returns bfd_reloc_continue if the caller need take no
- further action regarding this relocation, bfd_reloc_notsupported if
- something goes dramatically wrong, bfd_reloc_overflow if an
- overflow occurs, and bfd_reloc_ok to indicate success. */
-
-static bfd_reloc_status_type
-mips_elf_calculate_relocation (abfd,
- input_bfd,
- input_section,
- info,
- relocation,
- addend,
- howto,
- local_syms,
- local_sections,
- valuep,
- namep,
- require_jalxp)
- bfd *abfd;
- bfd *input_bfd;
- asection *input_section;
- struct bfd_link_info *info;
- const Elf_Internal_Rela *relocation;
- bfd_vma addend;
- reloc_howto_type *howto;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
- bfd_vma *valuep;
- const char **namep;
- boolean *require_jalxp;
-{
- /* The eventual value we will return. */
- bfd_vma value;
- /* The address of the symbol against which the relocation is
- occurring. */
- bfd_vma symbol = 0;
- /* The final GP value to be used for the relocatable, executable, or
- shared object file being produced. */
- bfd_vma gp = (bfd_vma) - 1;
- /* The place (section offset or address) of the storage unit being
- relocated. */
- bfd_vma p;
- /* The value of GP used to create the relocatable object. */
- bfd_vma gp0 = (bfd_vma) - 1;
- /* The offset into the global offset table at which the address of
- the relocation entry symbol, adjusted by the addend, resides
- during execution. */
- bfd_vma g = (bfd_vma) - 1;
- /* The section in which the symbol referenced by the relocation is
- located. */
- asection *sec = NULL;
- struct mips_elf_link_hash_entry *h = NULL;
- /* True if the symbol referred to by this relocation is a local
- symbol. */
- boolean local_p;
- /* True if the symbol referred to by this relocation is "_gp_disp". */
- boolean gp_disp_p = false;
- Elf_Internal_Shdr *symtab_hdr;
- size_t extsymoff;
- unsigned long r_symndx;
- int r_type;
- /* True if overflow occurred during the calculation of the
- relocation value. */
- boolean overflowed_p;
- /* True if this relocation refers to a MIPS16 function. */
- boolean target_is_16_bit_code_p = false;
-
- /* Parse the relocation. */
- r_symndx = ELF32_R_SYM (relocation->r_info);
- r_type = ELF32_R_TYPE (relocation->r_info);
- p = (input_section->output_section->vma
- + input_section->output_offset
- + relocation->r_offset);
-
- /* Assume that there will be no overflow. */
- overflowed_p = false;
-
- /* Figure out whether or not the symbol is local, and get the offset
- used in the array of hash table entries. */
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- local_p = mips_elf_local_relocation_p (input_bfd, relocation,
- local_sections, false);
- if (! elf_bad_symtab (input_bfd))
- extsymoff = symtab_hdr->sh_info;
- else
- {
- /* The symbol table does not follow the rule that local symbols
- must come before globals. */
- extsymoff = 0;
- }
-
- /* Figure out the value of the symbol. */
- if (local_p)
- {
- Elf_Internal_Sym *sym;
-
- sym = local_syms + r_symndx;
- sec = local_sections[r_symndx];
-
- symbol = sec->output_section->vma + sec->output_offset;
- if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
- symbol += sym->st_value;
-
- /* MIPS16 text labels should be treated as odd. */
- if (sym->st_other == STO_MIPS16)
- ++symbol;
-
- /* Record the name of this symbol, for our caller. */
- *namep = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (*namep == '\0')
- *namep = bfd_section_name (input_bfd, sec);
-
- target_is_16_bit_code_p = (sym->st_other == STO_MIPS16);
- }
- else
- {
- /* For global symbols we look up the symbol in the hash-table. */
- h = ((struct mips_elf_link_hash_entry *)
- elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
- /* Find the real hash-table entry for this symbol. */
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
- /* Record the name of this symbol, for our caller. */
- *namep = h->root.root.root.string;
-
- /* See if this is the special _gp_disp symbol. Note that such a
- symbol must always be a global symbol. */
- if (strcmp (h->root.root.root.string, "_gp_disp") == 0)
- {
- /* Relocations against _gp_disp are permitted only with
- R_MIPS_HI16 and R_MIPS_LO16 relocations. */
- if (r_type != R_MIPS_HI16 && r_type != R_MIPS_LO16)
- return bfd_reloc_notsupported;
-
- gp_disp_p = true;
- }
- /* If this symbol is defined, calculate its address. Note that
- _gp_disp is a magic symbol, always implicitly defined by the
- linker, so it's inappropriate to check to see whether or not
- its defined. */
- else if ((h->root.root.type == bfd_link_hash_defined
- || h->root.root.type == bfd_link_hash_defweak)
- && h->root.root.u.def.section)
- {
- sec = h->root.root.u.def.section;
- if (sec->output_section)
- symbol = (h->root.root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- else
- symbol = h->root.root.u.def.value;
- }
- else if (h->root.root.type == bfd_link_hash_undefweak)
- /* We allow relocations against undefined weak symbols, giving
- it the value zero, so that you can undefined weak functions
- and check to see if they exist by looking at their
- addresses. */
- symbol = 0;
- else if (info->shared
- && (!info->symbolic || info->allow_shlib_undefined)
- && !info->no_undefined
- && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
- symbol = 0;
- else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0 ||
- strcmp (h->root.root.root.string, "_DYNAMIC_LINKING") == 0)
- {
- /* If this is a dynamic link, we should have created a
- _DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol
- in in mips_elf_create_dynamic_sections.
- Otherwise, we should define the symbol with a value of 0.
- FIXME: It should probably get into the symbol table
- somehow as well. */
- BFD_ASSERT (! info->shared);
- BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
- symbol = 0;
- }
- else
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.root.string, input_bfd,
- input_section, relocation->r_offset,
- (!info->shared || info->no_undefined
- || ELF_ST_VISIBILITY (h->root.other)))))
- return bfd_reloc_undefined;
- symbol = 0;
- }
-
- target_is_16_bit_code_p = (h->root.other == STO_MIPS16);
- }
-
- /* If this is a 32-bit call to a 16-bit function with a stub, we
- need to redirect the call to the stub, unless we're already *in*
- a stub. */
- if (r_type != R_MIPS16_26 && !info->relocateable
- && ((h != NULL && h->fn_stub != NULL)
- || (local_p && elf_tdata (input_bfd)->local_stubs != NULL
- && elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
- && !mips_elf_stub_section_p (input_bfd, input_section))
- {
- /* This is a 32-bit call to a 16-bit function. We should
- have already noticed that we were going to need the
- stub. */
- if (local_p)
- sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
- else
- {
- BFD_ASSERT (h->need_fn_stub);
- sec = h->fn_stub;
- }
-
- symbol = sec->output_section->vma + sec->output_offset;
- }
- /* If this is a 16-bit call to a 32-bit function with a stub, we
- need to redirect the call to the stub. */
- else if (r_type == R_MIPS16_26 && !info->relocateable
- && h != NULL
- && (h->call_stub != NULL || h->call_fp_stub != NULL)
- && !target_is_16_bit_code_p)
- {
- /* If both call_stub and call_fp_stub are defined, we can figure
- out which one to use by seeing which one appears in the input
- file. */
- if (h->call_stub != NULL && h->call_fp_stub != NULL)
- {
- asection *o;
-
- sec = NULL;
- for (o = input_bfd->sections; o != NULL; o = o->next)
- {
- if (strncmp (bfd_get_section_name (input_bfd, o),
- CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
- {
- sec = h->call_fp_stub;
- break;
- }
- }
- if (sec == NULL)
- sec = h->call_stub;
- }
- else if (h->call_stub != NULL)
- sec = h->call_stub;
- else
- sec = h->call_fp_stub;
-
- BFD_ASSERT (sec->_raw_size > 0);
- symbol = sec->output_section->vma + sec->output_offset;
- }
-
- /* Calls from 16-bit code to 32-bit code and vice versa require the
- special jalx instruction. */
- *require_jalxp = (!info->relocateable
- && (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
- || ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
-
- local_p = mips_elf_local_relocation_p (input_bfd, relocation,
- local_sections, true);
-
- /* If we haven't already determined the GOT offset, or the GP value,
- and we're going to need it, get it now. */
- switch (r_type)
- {
- case R_MIPS_CALL16:
- case R_MIPS_GOT16:
- case R_MIPS_GOT_DISP:
- case R_MIPS_GOT_HI16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_CALL_LO16:
- /* Find the index into the GOT where this value is located. */
- if (!local_p)
- {
- BFD_ASSERT (addend == 0);
- g = mips_elf_global_got_index
- (elf_hash_table (info)->dynobj,
- (struct elf_link_hash_entry *) h);
- if (! elf_hash_table(info)->dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->root.dynindx == -1)
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
- {
- /* This is a static link or a -Bsymbolic link. The
- symbol is defined locally, or was forced to be local.
- We must initialize this entry in the GOT. */
- asection *sgot = mips_elf_got_section(elf_hash_table
- (info)->dynobj);
- MIPS_ELF_PUT_WORD (elf_hash_table (info)->dynobj,
- symbol + addend, sgot->contents + g);
- }
- }
- else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
- /* There's no need to create a local GOT entry here; the
- calculation for a local GOT16 entry does not involve G. */
- break;
- else
- {
- g = mips_elf_local_got_index (abfd, info, symbol + addend);
- if (g == (bfd_vma) -1)
- return bfd_reloc_outofrange;
- }
-
- /* Convert GOT indices to actual offsets. */
- g = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd, g);
- break;
-
- case R_MIPS_HI16:
- case R_MIPS_LO16:
- case R_MIPS16_GPREL:
- case R_MIPS_GPREL16:
- case R_MIPS_GPREL32:
- case R_MIPS_LITERAL:
- gp0 = _bfd_get_gp_value (input_bfd);
- gp = _bfd_get_gp_value (abfd);
- break;
-
- default:
- break;
- }
-
- /* Figure out what kind of relocation is being performed. */
- switch (r_type)
- {
- case R_MIPS_NONE:
- return bfd_reloc_continue;
-
- case R_MIPS_16:
- value = symbol + mips_elf_sign_extend (addend, 16);
- overflowed_p = mips_elf_overflow_p (value, 16);
- break;
-
- case R_MIPS_32:
- case R_MIPS_REL32:
- case R_MIPS_64:
- if ((info->shared
- || (elf_hash_table (info)->dynamic_sections_created
- && h != NULL
- && ((h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
- && ((h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
- && r_symndx != 0
- && (input_section->flags & SEC_ALLOC) != 0)
- {
- /* If we're creating a shared library, or this relocation is
- against a symbol in a shared library, then we can't know
- where the symbol will end up. So, we create a relocation
- record in the output, and leave the job up to the dynamic
- linker. */
- value = addend;
- if (!mips_elf_create_dynamic_relocation (abfd,
- info,
- relocation,
- h,
- sec,
- symbol,
- &value,
- input_section))
- return bfd_reloc_undefined;
- }
- else
- {
- if (r_type != R_MIPS_REL32)
- value = symbol + addend;
- else
- value = addend;
- }
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_PC32:
- case R_MIPS_PC64:
- case R_MIPS_GNU_REL_LO16:
- value = symbol + addend - p;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_GNU_REL16_S2:
- value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
- overflowed_p = mips_elf_overflow_p (value, 18);
- value = (value >> 2) & howto->dst_mask;
- break;
-
- case R_MIPS_GNU_REL_HI16:
- /* Instead of subtracting 'p' here, we should be subtracting the
- equivalent value for the LO part of the reloc, since the value
- here is relative to that address. Because that's not easy to do,
- we adjust 'addend' in _bfd_mips_elf_relocate_section(). See also
- the comment there for more information. */
- value = mips_elf_high (addend + symbol - p);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS16_26:
- /* The calculation for R_MIPS16_26 is just the same as for an
- R_MIPS_26. It's only the storage of the relocated field into
- the output file that's different. That's handled in
- mips_elf_perform_relocation. So, we just fall through to the
- R_MIPS_26 case here. */
- case R_MIPS_26:
- if (local_p)
- value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
- else
- value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_HI16:
- if (!gp_disp_p)
- {
- value = mips_elf_high (addend + symbol);
- value &= howto->dst_mask;
- }
- else
- {
- value = mips_elf_high (addend + gp - p);
- overflowed_p = mips_elf_overflow_p (value, 16);
- }
- break;
-
- case R_MIPS_LO16:
- if (!gp_disp_p)
- value = (symbol + addend) & howto->dst_mask;
- else
- {
- value = addend + gp - p + 4;
- /* The MIPS ABI requires checking the R_MIPS_LO16 relocation
- for overflow. But, on, say, Irix 5, relocations against
- _gp_disp are normally generated from the .cpload
- pseudo-op. It generates code that normally looks like
- this:
-
- lui $gp,%hi(_gp_disp)
- addiu $gp,$gp,%lo(_gp_disp)
- addu $gp,$gp,$t9
-
- Here $t9 holds the address of the function being called,
- as required by the MIPS ELF ABI. The R_MIPS_LO16
- relocation can easily overflow in this situation, but the
- R_MIPS_HI16 relocation will handle the overflow.
- Therefore, we consider this a bug in the MIPS ABI, and do
- not check for overflow here. */
- }
- break;
-
- case R_MIPS_LITERAL:
- /* Because we don't merge literal sections, we can handle this
- just like R_MIPS_GPREL16. In the long run, we should merge
- shared literals, and then we will need to additional work
- here. */
-
- /* Fall through. */
-
- case R_MIPS16_GPREL:
- /* The R_MIPS16_GPREL performs the same calculation as
- R_MIPS_GPREL16, but stores the relocated bits in a different
- order. We don't need to do anything special here; the
- differences are handled in mips_elf_perform_relocation. */
- case R_MIPS_GPREL16:
- if (local_p)
- value = mips_elf_sign_extend (addend, 16) + symbol + gp0 - gp;
- else
- value = mips_elf_sign_extend (addend, 16) + symbol - gp;
- overflowed_p = mips_elf_overflow_p (value, 16);
- break;
-
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- if (local_p)
- {
- boolean forced;
-
- /* The special case is when the symbol is forced to be local. We
- need the full address in the GOT since no R_MIPS_LO16 relocation
- follows. */
- forced = ! mips_elf_local_relocation_p (input_bfd, relocation,
- local_sections, false);
- value = mips_elf_got16_entry (abfd, info, symbol + addend, forced);
- if (value == (bfd_vma) -1)
- return bfd_reloc_outofrange;
- value
- = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd,
- value);
- overflowed_p = mips_elf_overflow_p (value, 16);
- break;
- }
-
- /* Fall through. */
-
- case R_MIPS_GOT_DISP:
- value = g;
- overflowed_p = mips_elf_overflow_p (value, 16);
- break;
-
- case R_MIPS_GPREL32:
- value = (addend + symbol + gp0 - gp) & howto->dst_mask;
- break;
-
- case R_MIPS_PC16:
- value = mips_elf_sign_extend (addend, 16) + symbol - p;
- overflowed_p = mips_elf_overflow_p (value, 16);
- value = (bfd_vma) ((bfd_signed_vma) value / 4);
- break;
-
- case R_MIPS_GOT_HI16:
- case R_MIPS_CALL_HI16:
- /* We're allowed to handle these two relocations identically.
- The dynamic linker is allowed to handle the CALL relocations
- differently by creating a lazy evaluation stub. */
- value = g;
- value = mips_elf_high (value);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_GOT_LO16:
- case R_MIPS_CALL_LO16:
- value = g & howto->dst_mask;
- break;
-
- case R_MIPS_GOT_PAGE:
- value = mips_elf_got_page (abfd, info, symbol + addend, NULL);
- if (value == (bfd_vma) -1)
- return bfd_reloc_outofrange;
- value = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd,
- value);
- overflowed_p = mips_elf_overflow_p (value, 16);
- break;
-
- case R_MIPS_GOT_OFST:
- mips_elf_got_page (abfd, info, symbol + addend, &value);
- overflowed_p = mips_elf_overflow_p (value, 16);
- break;
-
- case R_MIPS_SUB:
- value = symbol - addend;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_HIGHER:
- value = mips_elf_higher (addend + symbol);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_HIGHEST:
- value = mips_elf_highest (addend + symbol);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_SCN_DISP:
- value = symbol + addend - sec->output_offset;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_PJUMP:
- case R_MIPS_JALR:
- /* Both of these may be ignored. R_MIPS_JALR is an optimization
- hint; we could improve performance by honoring that hint. */
- return bfd_reloc_continue;
-
- case R_MIPS_GNU_VTINHERIT:
- case R_MIPS_GNU_VTENTRY:
- /* We don't do anything with these at present. */
- return bfd_reloc_continue;
-
- default:
- /* An unrecognized relocation type. */
- return bfd_reloc_notsupported;
- }
-
- /* Store the VALUE for our caller. */
- *valuep = value;
- return overflowed_p ? bfd_reloc_overflow : bfd_reloc_ok;
-}
-
-/* Obtain the field relocated by RELOCATION. */
-
-static bfd_vma
-mips_elf_obtain_contents (howto, relocation, input_bfd, contents)
- reloc_howto_type *howto;
- const Elf_Internal_Rela *relocation;
- bfd *input_bfd;
- bfd_byte *contents;
-{
- bfd_vma x;
- bfd_byte *location = contents + relocation->r_offset;
-
- /* Obtain the bytes. */
- x = bfd_get (((bfd_vma)(8 * bfd_get_reloc_size (howto))), input_bfd, location);
-
- if ((ELF32_R_TYPE (relocation->r_info) == R_MIPS16_26
- || ELF32_R_TYPE (relocation->r_info) == R_MIPS16_GPREL)
- && bfd_little_endian (input_bfd))
- /* The two 16-bit words will be reversed on a little-endian
- system. See mips_elf_perform_relocation for more details. */
- x = (((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
-
- return x;
-}
-
-/* It has been determined that the result of the RELOCATION is the
- VALUE. Use HOWTO to place VALUE into the output file at the
- appropriate position. The SECTION is the section to which the
- relocation applies. If REQUIRE_JALX is true, then the opcode used
- for the relocation must be either JAL or JALX, and it is
- unconditionally converted to JALX.
-
- Returns false if anything goes wrong. */
-
-static boolean
-mips_elf_perform_relocation (info, howto, relocation, value,
- input_bfd, input_section,
- contents, require_jalx)
- struct bfd_link_info *info;
- reloc_howto_type *howto;
- const Elf_Internal_Rela *relocation;
- bfd_vma value;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- boolean require_jalx;
-{
- bfd_vma x;
- bfd_byte *location;
- int r_type = ELF32_R_TYPE (relocation->r_info);
-
- /* Figure out where the relocation is occurring. */
- location = contents + relocation->r_offset;
-
- /* Obtain the current value. */
- x = mips_elf_obtain_contents (howto, relocation, input_bfd, contents);
-
- /* Clear the field we are setting. */
- x &= ~howto->dst_mask;
-
- /* If this is the R_MIPS16_26 relocation, we must store the
- value in a funny way. */
- if (r_type == R_MIPS16_26)
- {
- /* R_MIPS16_26 is used for the mips16 jal and jalx instructions.
- Most mips16 instructions are 16 bits, but these instructions
- are 32 bits.
-
- The format of these instructions is:
-
- +--------------+--------------------------------+
- ! JALX ! X! Imm 20:16 ! Imm 25:21 !
- +--------------+--------------------------------+
- ! Immediate 15:0 !
- +-----------------------------------------------+
-
- JALX is the 5-bit value 00011. X is 0 for jal, 1 for jalx.
- Note that the immediate value in the first word is swapped.
-
- When producing a relocateable object file, R_MIPS16_26 is
- handled mostly like R_MIPS_26. In particular, the addend is
- stored as a straight 26-bit value in a 32-bit instruction.
- (gas makes life simpler for itself by never adjusting a
- R_MIPS16_26 reloc to be against a section, so the addend is
- always zero). However, the 32 bit instruction is stored as 2
- 16-bit values, rather than a single 32-bit value. In a
- big-endian file, the result is the same; in a little-endian
- file, the two 16-bit halves of the 32 bit value are swapped.
- This is so that a disassembler can recognize the jal
- instruction.
-
- When doing a final link, R_MIPS16_26 is treated as a 32 bit
- instruction stored as two 16-bit values. The addend A is the
- contents of the targ26 field. The calculation is the same as
- R_MIPS_26. When storing the calculated value, reorder the
- immediate value as shown above, and don't forget to store the
- value as two 16-bit values.
-
- To put it in MIPS ABI terms, the relocation field is T-targ26-16,
- defined as
-
- big-endian:
- +--------+----------------------+
- | | |
- | | targ26-16 |
- |31 26|25 0|
- +--------+----------------------+
-
- little-endian:
- +----------+------+-------------+
- | | | |
- | sub1 | | sub2 |
- |0 9|10 15|16 31|
- +----------+--------------------+
- where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
- ((sub1 << 16) | sub2)).
-
- When producing a relocateable object file, the calculation is
- (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
- When producing a fully linked file, the calculation is
- let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
- ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */
-
- if (!info->relocateable)
- /* Shuffle the bits according to the formula above. */
- value = (((value & 0x1f0000) << 5)
- | ((value & 0x3e00000) >> 5)
- | (value & 0xffff));
- }
- else if (r_type == R_MIPS16_GPREL)
- {
- /* R_MIPS16_GPREL is used for GP-relative addressing in mips16
- mode. A typical instruction will have a format like this:
-
- +--------------+--------------------------------+
- ! EXTEND ! Imm 10:5 ! Imm 15:11 !
- +--------------+--------------------------------+
- ! Major ! rx ! ry ! Imm 4:0 !
- +--------------+--------------------------------+
-
- EXTEND is the five bit value 11110. Major is the instruction
- opcode.
-
- This is handled exactly like R_MIPS_GPREL16, except that the
- addend is retrieved and stored as shown in this diagram; that
- is, the Imm fields above replace the V-rel16 field.
-
- All we need to do here is shuffle the bits appropriately. As
- above, the two 16-bit halves must be swapped on a
- little-endian system. */
- value = (((value & 0x7e0) << 16)
- | ((value & 0xf800) << 5)
- | (value & 0x1f));
- }
-
- /* Set the field. */
- x |= (value & howto->dst_mask);
-
- /* If required, turn JAL into JALX. */
- if (require_jalx)
- {
- boolean ok;
- bfd_vma opcode = x >> 26;
- bfd_vma jalx_opcode;
-
- /* Check to see if the opcode is already JAL or JALX. */
- if (r_type == R_MIPS16_26)
- {
- ok = ((opcode == 0x6) || (opcode == 0x7));
- jalx_opcode = 0x7;
- }
- else
- {
- ok = ((opcode == 0x3) || (opcode == 0x1d));
- jalx_opcode = 0x1d;
- }
-
- /* If the opcode is not JAL or JALX, there's a problem. */
- if (!ok)
- {
- (*_bfd_error_handler)
- (_("%s: %s+0x%lx: jump to stub routine which is not jal"),
- bfd_archive_filename (input_bfd),
- input_section->name,
- (unsigned long) relocation->r_offset);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- /* Make this the JALX opcode. */
- x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
- }
-
- /* Swap the high- and low-order 16 bits on little-endian systems
- when doing a MIPS16 relocation. */
- if ((r_type == R_MIPS16_GPREL || r_type == R_MIPS16_26)
- && bfd_little_endian (input_bfd))
- x = (((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
-
- /* Put the value into the output. */
- bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
- return true;
-}
-
-/* Returns true if SECTION is a MIPS16 stub section. */
-
-static boolean
-mips_elf_stub_section_p (abfd, section)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *section;
-{
- const char *name = bfd_get_section_name (abfd, section);
-
- return (strncmp (name, FN_STUB, sizeof FN_STUB - 1) == 0
- || strncmp (name, CALL_STUB, sizeof CALL_STUB - 1) == 0
- || strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0);
-}
-
-/* Relocate a MIPS ELF section. */
-
-boolean
-_bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- Elf_Internal_Rela *relocs;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
-{
- Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *relend;
- bfd_vma addend = 0;
- boolean use_saved_addend_p = false;
- struct elf_backend_data *bed;
-
- bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
- for (rel = relocs; rel < relend; ++rel)
- {
- const char *name;
- bfd_vma value;
- reloc_howto_type *howto;
- boolean require_jalx;
- /* True if the relocation is a RELA relocation, rather than a
- REL relocation. */
- boolean rela_relocation_p = true;
- unsigned int r_type = ELF32_R_TYPE (rel->r_info);
- const char * msg = (const char *) NULL;
-
- /* Find the relocation howto for this relocation. */
- if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
- {
- /* Some 32-bit code uses R_MIPS_64. In particular, people use
- 64-bit code, but make sure all their addresses are in the
- lowermost or uppermost 32-bit section of the 64-bit address
- space. Thus, when they use an R_MIPS_64 they mean what is
- usually meant by R_MIPS_32, with the exception that the
- stored value is sign-extended to 64 bits. */
- howto = elf_mips_howto_table_rel + R_MIPS_32;
-
- /* On big-endian systems, we need to lie about the position
- of the reloc. */
- if (bfd_big_endian (input_bfd))
- rel->r_offset += 4;
- }
- else
- howto = mips_rtype_to_howto (r_type);
-
- if (!use_saved_addend_p)
- {
- Elf_Internal_Shdr *rel_hdr;
-
- /* If these relocations were originally of the REL variety,
- we must pull the addend out of the field that will be
- relocated. Otherwise, we simply use the contents of the
- RELA relocation. To determine which flavor or relocation
- this is, we depend on the fact that the INPUT_SECTION's
- REL_HDR is read before its REL_HDR2. */
- rel_hdr = &elf_section_data (input_section)->rel_hdr;
- if ((size_t) (rel - relocs)
- >= (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel))
- rel_hdr = elf_section_data (input_section)->rel_hdr2;
- if (rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (input_bfd))
- {
- /* Note that this is a REL relocation. */
- rela_relocation_p = false;
-
- /* Get the addend, which is stored in the input file. */
- addend = mips_elf_obtain_contents (howto,
- rel,
- input_bfd,
- contents);
- addend &= howto->src_mask;
-
- /* For some kinds of relocations, the ADDEND is a
- combination of the addend stored in two different
- relocations. */
- if (r_type == R_MIPS_HI16
- || r_type == R_MIPS_GNU_REL_HI16
- || (r_type == R_MIPS_GOT16
- && mips_elf_local_relocation_p (input_bfd, rel,
- local_sections, false)))
- {
- bfd_vma l;
- const Elf_Internal_Rela *lo16_relocation;
- reloc_howto_type *lo16_howto;
- unsigned int lo;
-
- /* The combined value is the sum of the HI16 addend,
- left-shifted by sixteen bits, and the LO16
- addend, sign extended. (Usually, the code does
- a `lui' of the HI16 value, and then an `addiu' of
- the LO16 value.)
-
- Scan ahead to find a matching LO16 relocation. */
- if (r_type == R_MIPS_GNU_REL_HI16)
- lo = R_MIPS_GNU_REL_LO16;
- else
- lo = R_MIPS_LO16;
- lo16_relocation
- = mips_elf_next_relocation (lo, rel, relend);
- if (lo16_relocation == NULL)
- return false;
-
- /* Obtain the addend kept there. */
- lo16_howto = mips_rtype_to_howto (lo);
- l = mips_elf_obtain_contents (lo16_howto,
- lo16_relocation,
- input_bfd, contents);
- l &= lo16_howto->src_mask;
- l = mips_elf_sign_extend (l, 16);
-
- addend <<= 16;
-
- /* Compute the combined addend. */
- addend += l;
-
- /* If PC-relative, subtract the difference between the
- address of the LO part of the reloc and the address of
- the HI part. The relocation is relative to the LO
- part, but mips_elf_calculate_relocation() doesn't know
- it address or the difference from the HI part, so
- we subtract that difference here. See also the
- comment in mips_elf_calculate_relocation(). */
- if (r_type == R_MIPS_GNU_REL_HI16)
- addend -= (lo16_relocation->r_offset - rel->r_offset);
- }
- else if (r_type == R_MIPS16_GPREL)
- {
- /* The addend is scrambled in the object file. See
- mips_elf_perform_relocation for details on the
- format. */
- addend = (((addend & 0x1f0000) >> 5)
- | ((addend & 0x7e00000) >> 16)
- | (addend & 0x1f));
- }
- }
- else
- addend = rel->r_addend;
- }
-
- if (info->relocateable)
- {
- Elf_Internal_Sym *sym;
- unsigned long r_symndx;
-
- if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd)
- && bfd_big_endian (input_bfd))
- rel->r_offset -= 4;
-
- /* Since we're just relocating, all we need to do is copy
- the relocations back out to the object file, unless
- they're against a section symbol, in which case we need
- to adjust by the section offset, or unless they're GP
- relative in which case we need to adjust by the amount
- that we're adjusting GP in this relocateable object. */
-
- if (!mips_elf_local_relocation_p (input_bfd, rel, local_sections,
- false))
- /* There's nothing to do for non-local relocations. */
- continue;
-
- if (r_type == R_MIPS16_GPREL
- || r_type == R_MIPS_GPREL16
- || r_type == R_MIPS_GPREL32
- || r_type == R_MIPS_LITERAL)
- addend -= (_bfd_get_gp_value (output_bfd)
- - _bfd_get_gp_value (input_bfd));
- else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26
- || r_type == R_MIPS_GNU_REL16_S2)
- /* The addend is stored without its two least
- significant bits (which are always zero.) In a
- non-relocateable link, calculate_relocation will do
- this shift; here, we must do it ourselves. */
- addend <<= 2;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- /* Adjust the addend appropriately. */
- addend += local_sections[r_symndx]->output_offset;
-
- /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
- then we only want to write out the high-order 16 bits.
- The subsequent R_MIPS_LO16 will handle the low-order bits. */
- if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16
- || r_type == R_MIPS_GNU_REL_HI16)
- addend = mips_elf_high (addend);
- /* If the relocation is for an R_MIPS_26 relocation, then
- the two low-order bits are not stored in the object file;
- they are implicitly zero. */
- else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26
- || r_type == R_MIPS_GNU_REL16_S2)
- addend >>= 2;
-
- if (rela_relocation_p)
- /* If this is a RELA relocation, just update the addend.
- We have to cast away constness for REL. */
- rel->r_addend = addend;
- else
- {
- /* Otherwise, we have to write the value back out. Note
- that we use the source mask, rather than the
- destination mask because the place to which we are
- writing will be source of the addend in the final
- link. */
- addend &= howto->src_mask;
-
- if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
- /* See the comment above about using R_MIPS_64 in the 32-bit
- ABI. Here, we need to update the addend. It would be
- possible to get away with just using the R_MIPS_32 reloc
- but for endianness. */
- {
- bfd_vma sign_bits;
- bfd_vma low_bits;
- bfd_vma high_bits;
-
- if (addend & ((bfd_vma) 1 << 31))
-#ifdef BFD64
- sign_bits = ((bfd_vma) 1 << 32) - 1;
-#else
- sign_bits = -1;
-#endif
- else
- sign_bits = 0;
-
- /* If we don't know that we have a 64-bit type,
- do two separate stores. */
- if (bfd_big_endian (input_bfd))
- {
- /* Store the sign-bits (which are most significant)
- first. */
- low_bits = sign_bits;
- high_bits = addend;
- }
- else
- {
- low_bits = addend;
- high_bits = sign_bits;
- }
- bfd_put_32 (input_bfd, low_bits,
- contents + rel->r_offset);
- bfd_put_32 (input_bfd, high_bits,
- contents + rel->r_offset + 4);
- continue;
- }
-
- if (!mips_elf_perform_relocation (info, howto, rel, addend,
- input_bfd, input_section,
- contents, false))
- return false;
- }
-
- /* Go on to the next relocation. */
- continue;
- }
-
- /* In the N32 and 64-bit ABIs there may be multiple consecutive
- relocations for the same offset. In that case we are
- supposed to treat the output of each relocation as the addend
- for the next. */
- if (rel + 1 < relend
- && rel->r_offset == rel[1].r_offset
- && ELF32_R_TYPE (rel[1].r_info) != R_MIPS_NONE)
- use_saved_addend_p = true;
- else
- use_saved_addend_p = false;
-
- /* Figure out what value we are supposed to relocate. */
- switch (mips_elf_calculate_relocation (output_bfd,
- input_bfd,
- input_section,
- info,
- rel,
- addend,
- howto,
- local_syms,
- local_sections,
- &value,
- &name,
- &require_jalx))
- {
- case bfd_reloc_continue:
- /* There's nothing to do. */
- continue;
-
- case bfd_reloc_undefined:
- /* mips_elf_calculate_relocation already called the
- undefined_symbol callback. There's no real point in
- trying to perform the relocation at this point, so we
- just skip ahead to the next relocation. */
- continue;
-
- case bfd_reloc_notsupported:
- msg = _("internal error: unsupported relocation error");
- info->callbacks->warning
- (info, msg, name, input_bfd, input_section, rel->r_offset);
- return false;
-
- case bfd_reloc_overflow:
- if (use_saved_addend_p)
- /* Ignore overflow until we reach the last relocation for
- a given location. */
- ;
- else
- {
- BFD_ASSERT (name != NULL);
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset)))
- return false;
- }
- break;
-
- case bfd_reloc_ok:
- break;
-
- default:
- abort ();
- break;
- }
-
- /* If we've got another relocation for the address, keep going
- until we reach the last one. */
- if (use_saved_addend_p)
- {
- addend = value;
- continue;
- }
-
- if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
- /* See the comment above about using R_MIPS_64 in the 32-bit
- ABI. Until now, we've been using the HOWTO for R_MIPS_32;
- that calculated the right value. Now, however, we
- sign-extend the 32-bit result to 64-bits, and store it as a
- 64-bit value. We are especially generous here in that we
- go to extreme lengths to support this usage on systems with
- only a 32-bit VMA. */
- {
- bfd_vma sign_bits;
- bfd_vma low_bits;
- bfd_vma high_bits;
-
- if (value & ((bfd_vma) 1 << 31))
-#ifdef BFD64
- sign_bits = ((bfd_vma) 1 << 32) - 1;
-#else
- sign_bits = -1;
-#endif
- else
- sign_bits = 0;
-
- /* If we don't know that we have a 64-bit type,
- do two separate stores. */
- if (bfd_big_endian (input_bfd))
- {
- /* Undo what we did above. */
- rel->r_offset -= 4;
- /* Store the sign-bits (which are most significant)
- first. */
- low_bits = sign_bits;
- high_bits = value;
- }
- else
- {
- low_bits = value;
- high_bits = sign_bits;
- }
- bfd_put_32 (input_bfd, low_bits,
- contents + rel->r_offset);
- bfd_put_32 (input_bfd, high_bits,
- contents + rel->r_offset + 4);
- continue;
- }
-
- /* Actually perform the relocation. */
- if (!mips_elf_perform_relocation (info, howto, rel, value, input_bfd,
- input_section, contents,
- require_jalx))
- return false;
- }
-
- return true;
-}
-
-/* This hook function is called before the linker writes out a global
- symbol. We mark symbols as small common if appropriate. This is
- also where we undo the increment of the value for a mips16 symbol. */
-
-boolean
-_bfd_mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- const char *name ATTRIBUTE_UNUSED;
- Elf_Internal_Sym *sym;
- asection *input_sec;
-{
- /* If we see a common symbol, which implies a relocatable link, then
- if a symbol was small common in an input file, mark it as small
- common in the output file. */
- if (sym->st_shndx == SHN_COMMON
- && strcmp (input_sec->name, ".scommon") == 0)
- sym->st_shndx = SHN_MIPS_SCOMMON;
-
- if (sym->st_other == STO_MIPS16
- && (sym->st_value & 1) != 0)
- --sym->st_value;
-
- return true;
-}
-
-/* Functions for the dynamic linker. */
-
-/* The name of the dynamic interpreter. This is put in the .interp
- section. */
-
-#define ELF_DYNAMIC_INTERPRETER(abfd) \
- (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" \
- : ABI_64_P (abfd) ? "/usr/lib64/libc.so.1" \
- : "/usr/lib/libc.so.1")
-
-/* Create dynamic sections when linking against a dynamic object. */
-
-boolean
-_bfd_mips_elf_create_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- struct elf_link_hash_entry *h;
- flagword flags;
- register asection *s;
- const char * const *namep;
-
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED | SEC_READONLY);
-
- /* Mips ABI requests the .dynamic section to be read only. */
- s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s != NULL)
- {
- if (! bfd_set_section_flags (abfd, s, flags))
- return false;
- }
-
- /* We need to create .got section. */
- if (! mips_elf_create_got_section (abfd, info))
- return false;
-
- /* Create the .msym section on IRIX6. It is used by the dynamic
- linker to speed up dynamic relocations, and to avoid computing
- the ELF hash for symbols. */
- if (IRIX_COMPAT (abfd) == ict_irix6
- && !mips_elf_create_msym_section (abfd))
- return false;
-
- /* Create .stub section. */
- if (bfd_get_section_by_name (abfd,
- MIPS_ELF_STUB_SECTION_NAME (abfd)) == NULL)
- {
- s = bfd_make_section (abfd, MIPS_ELF_STUB_SECTION_NAME (abfd));
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE)
- || ! bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
- return false;
- }
-
- if ((IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none)
- && !info->shared
- && bfd_get_section_by_name (abfd, ".rld_map") == NULL)
- {
- s = bfd_make_section (abfd, ".rld_map");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags &~ (flagword) SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
- return false;
- }
-
- /* On IRIX5, we adjust add some additional symbols and change the
- alignments of several sections. There is no ABI documentation
- indicating that this is necessary on IRIX6, nor any evidence that
- the linker takes such action. */
- if (IRIX_COMPAT (abfd) == ict_irix5)
- {
- for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
- {
- h = NULL;
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_SECTION;
-
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
-
- /* We need to create a .compact_rel section. */
- if (SGI_COMPAT (abfd))
- {
- if (!mips_elf_create_compact_rel_section (abfd, info))
- return false;
- }
-
- /* Change aligments of some sections. */
- s = bfd_get_section_by_name (abfd, ".hash");
- if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
- s = bfd_get_section_by_name (abfd, ".dynsym");
- if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
- s = bfd_get_section_by_name (abfd, ".dynstr");
- if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
- s = bfd_get_section_by_name (abfd, ".reginfo");
- if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
- s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
- }
-
- if (!info->shared)
- {
- h = NULL;
- if (SGI_COMPAT (abfd))
- {
- if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- }
- else
- {
- /* For normal mips it is _DYNAMIC_LINKING. */
- if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, "_DYNAMIC_LINKING", BSF_GLOBAL,
- bfd_abs_section_ptr, (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- }
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_SECTION;
-
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
-
- if (! mips_elf_hash_table (info)->use_rld_obj_head)
- {
- /* __rld_map is a four byte word located in the .data section
- and is filled in by the rtld to contain a pointer to
- the _r_debug structure. Its symbol value will be set in
- mips_elf_finish_dynamic_symbol. */
- s = bfd_get_section_by_name (abfd, ".rld_map");
- BFD_ASSERT (s != NULL);
-
- h = NULL;
- if (SGI_COMPAT (abfd))
- {
- if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, "__rld_map", BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- }
- else
- {
- /* For normal mips the symbol is __RLD_MAP. */
- if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, "__RLD_MAP", BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- }
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
- }
-
- return true;
-}
-
-/* Create the .compact_rel section. */
-
-static boolean
-mips_elf_create_compact_rel_section (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
-{
- flagword flags;
- register asection *s;
-
- if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
- {
- flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_READONLY);
-
- s = bfd_make_section (abfd, ".compact_rel");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags)
- || ! bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
- return false;
-
- s->_raw_size = sizeof (Elf32_External_compact_rel);
- }
-
- return true;
-}
-
-/* Create the .got section to hold the global offset table. */
-
-static boolean
-mips_elf_create_got_section (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- flagword flags;
- register asection *s;
- struct elf_link_hash_entry *h;
- struct mips_got_info *g;
- bfd_size_type amt;
-
- /* This function may be called more than once. */
- if (mips_elf_got_section (abfd))
- return true;
-
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED);
-
- s = bfd_make_section (abfd, ".got");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags)
- || ! bfd_set_section_alignment (abfd, s, 4))
- return false;
-
- /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
- linker script because we don't want to define the symbol if we
- are not creating a global offset table. */
- h = NULL;
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (info->shared
- && ! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
-
- /* The first several global offset table entries are reserved. */
- s->_raw_size = MIPS_RESERVED_GOTNO * MIPS_ELF_GOT_SIZE (abfd);
-
- amt = sizeof (struct mips_got_info);
- g = (struct mips_got_info *) bfd_alloc (abfd, amt);
- if (g == NULL)
- return false;
- g->global_gotsym = NULL;
- g->local_gotno = MIPS_RESERVED_GOTNO;
- g->assigned_gotno = MIPS_RESERVED_GOTNO;
- if (elf_section_data (s) == NULL)
- {
- amt = sizeof (struct bfd_elf_section_data);
- s->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
- if (elf_section_data (s) == NULL)
- return false;
- }
- elf_section_data (s)->tdata = (PTR) g;
- elf_section_data (s)->this_hdr.sh_flags
- |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
-
- return true;
-}
-
-/* Returns the .msym section for ABFD, creating it if it does not
- already exist. Returns NULL to indicate error. */
-
-static asection *
-mips_elf_create_msym_section (abfd)
- bfd *abfd;
-{
- asection *s;
-
- s = bfd_get_section_by_name (abfd, MIPS_ELF_MSYM_SECTION_NAME (abfd));
- if (!s)
- {
- s = bfd_make_section (abfd, MIPS_ELF_MSYM_SECTION_NAME (abfd));
- if (!s
- || !bfd_set_section_flags (abfd, s,
- SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_LINKER_CREATED
- | SEC_READONLY)
- || !bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
- return NULL;
- }
-
- return s;
-}
-
-/* Add room for N relocations to the .rel.dyn section in ABFD. */
-
-static void
-mips_elf_allocate_dynamic_relocations (abfd, n)
- bfd *abfd;
- unsigned int n;
-{
- asection *s;
-
- s = bfd_get_section_by_name (abfd, MIPS_ELF_REL_DYN_SECTION_NAME (abfd));
- BFD_ASSERT (s != NULL);
-
- if (s->_raw_size == 0)
- {
- /* Make room for a null element. */
- s->_raw_size += MIPS_ELF_REL_SIZE (abfd);
- ++s->reloc_count;
- }
- s->_raw_size += n * MIPS_ELF_REL_SIZE (abfd);
-}
-
-/* Look through the relocs for a section during the first phase, and
- allocate space in the global offset table. */
-
-boolean
-_bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
-{
- const char *name;
- bfd *dynobj;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- struct mips_got_info *g;
- size_t extsymoff;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
- asection *sgot;
- asection *sreloc;
- struct elf_backend_data *bed;
-
- if (info->relocateable)
- return true;
-
- dynobj = elf_hash_table (info)->dynobj;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
-
- /* Check for the mips16 stub sections. */
-
- name = bfd_get_section_name (abfd, sec);
- if (strncmp (name, FN_STUB, sizeof FN_STUB - 1) == 0)
- {
- unsigned long r_symndx;
-
- /* Look at the relocation information to figure out which symbol
- this is for. */
-
- r_symndx = ELF32_R_SYM (relocs->r_info);
-
- if (r_symndx < extsymoff
- || sym_hashes[r_symndx - extsymoff] == NULL)
- {
- asection *o;
-
- /* This stub is for a local symbol. This stub will only be
- needed if there is some relocation in this BFD, other
- than a 16 bit function call, which refers to this symbol. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- Elf_Internal_Rela *sec_relocs;
- const Elf_Internal_Rela *r, *rend;
-
- /* We can ignore stub sections when looking for relocs. */
- if ((o->flags & SEC_RELOC) == 0
- || o->reloc_count == 0
- || strncmp (bfd_get_section_name (abfd, o), FN_STUB,
- sizeof FN_STUB - 1) == 0
- || strncmp (bfd_get_section_name (abfd, o), CALL_STUB,
- sizeof CALL_STUB - 1) == 0
- || strncmp (bfd_get_section_name (abfd, o), CALL_FP_STUB,
- sizeof CALL_FP_STUB - 1) == 0)
- continue;
-
- sec_relocs = (_bfd_elf32_link_read_relocs
- (abfd, o, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory));
- if (sec_relocs == NULL)
- return false;
-
- rend = sec_relocs + o->reloc_count;
- for (r = sec_relocs; r < rend; r++)
- if (ELF32_R_SYM (r->r_info) == r_symndx
- && ELF32_R_TYPE (r->r_info) != R_MIPS16_26)
- break;
-
- if (! info->keep_memory)
- free (sec_relocs);
-
- if (r < rend)
- break;
- }
-
- if (o == NULL)
- {
- /* There is no non-call reloc for this stub, so we do
- not need it. Since this function is called before
- the linker maps input sections to output sections, we
- can easily discard it by setting the SEC_EXCLUDE
- flag. */
- sec->flags |= SEC_EXCLUDE;
- return true;
- }
-
- /* Record this stub in an array of local symbol stubs for
- this BFD. */
- if (elf_tdata (abfd)->local_stubs == NULL)
- {
- unsigned long symcount;
- asection **n;
- bfd_size_type amt;
-
- if (elf_bad_symtab (abfd))
- symcount = NUM_SHDR_ENTRIES (symtab_hdr);
- else
- symcount = symtab_hdr->sh_info;
- amt = symcount * sizeof (asection *);
- n = (asection **) bfd_zalloc (abfd, amt);
- if (n == NULL)
- return false;
- elf_tdata (abfd)->local_stubs = n;
- }
-
- elf_tdata (abfd)->local_stubs[r_symndx] = sec;
-
- /* We don't need to set mips16_stubs_seen in this case.
- That flag is used to see whether we need to look through
- the global symbol table for stubs. We don't need to set
- it here, because we just have a local stub. */
- }
- else
- {
- struct mips_elf_link_hash_entry *h;
-
- h = ((struct mips_elf_link_hash_entry *)
- sym_hashes[r_symndx - extsymoff]);
-
- /* H is the symbol this stub is for. */
-
- h->fn_stub = sec;
- mips_elf_hash_table (info)->mips16_stubs_seen = true;
- }
- }
- else if (strncmp (name, CALL_STUB, sizeof CALL_STUB - 1) == 0
- || strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
- {
- unsigned long r_symndx;
- struct mips_elf_link_hash_entry *h;
- asection **loc;
-
- /* Look at the relocation information to figure out which symbol
- this is for. */
-
- r_symndx = ELF32_R_SYM (relocs->r_info);
-
- if (r_symndx < extsymoff
- || sym_hashes[r_symndx - extsymoff] == NULL)
- {
- /* This stub was actually built for a static symbol defined
- in the same file. We assume that all static symbols in
- mips16 code are themselves mips16, so we can simply
- discard this stub. Since this function is called before
- the linker maps input sections to output sections, we can
- easily discard it by setting the SEC_EXCLUDE flag. */
- sec->flags |= SEC_EXCLUDE;
- return true;
- }
-
- h = ((struct mips_elf_link_hash_entry *)
- sym_hashes[r_symndx - extsymoff]);
-
- /* H is the symbol this stub is for. */
-
- if (strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
- loc = &h->call_fp_stub;
- else
- loc = &h->call_stub;
-
- /* If we already have an appropriate stub for this function, we
- don't need another one, so we can discard this one. Since
- this function is called before the linker maps input sections
- to output sections, we can easily discard it by setting the
- SEC_EXCLUDE flag. We can also discard this section if we
- happen to already know that this is a mips16 function; it is
- not necessary to check this here, as it is checked later, but
- it is slightly faster to check now. */
- if (*loc != NULL || h->root.other == STO_MIPS16)
- {
- sec->flags |= SEC_EXCLUDE;
- return true;
- }
-
- *loc = sec;
- mips_elf_hash_table (info)->mips16_stubs_seen = true;
- }
-
- if (dynobj == NULL)
- {
- sgot = NULL;
- g = NULL;
- }
- else
- {
- sgot = mips_elf_got_section (dynobj);
- if (sgot == NULL)
- g = NULL;
- else
- {
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
- }
- }
-
- sreloc = NULL;
- bed = get_elf_backend_data (abfd);
- rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
- for (rel = relocs; rel < rel_end; ++rel)
- {
- unsigned long r_symndx;
- unsigned int r_type;
- struct elf_link_hash_entry *h;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- r_type = ELF32_R_TYPE (rel->r_info);
-
- if (r_symndx < extsymoff)
- h = NULL;
- else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
- {
- (*_bfd_error_handler)
- (_("%s: Malformed reloc detected for section %s"),
- bfd_archive_filename (abfd), name);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- else
- {
- h = sym_hashes[r_symndx - extsymoff];
-
- /* This may be an indirect symbol created because of a version. */
- if (h != NULL)
- {
- while (h->root.type == bfd_link_hash_indirect)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
- }
-
- /* Some relocs require a global offset table. */
- if (dynobj == NULL || sgot == NULL)
- {
- switch (r_type)
- {
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_GOT_PAGE:
- case R_MIPS_GOT_OFST:
- case R_MIPS_GOT_DISP:
- if (dynobj == NULL)
- elf_hash_table (info)->dynobj = dynobj = abfd;
- if (! mips_elf_create_got_section (dynobj, info))
- return false;
- g = mips_elf_got_info (dynobj, &sgot);
- break;
-
- case R_MIPS_32:
- case R_MIPS_REL32:
- case R_MIPS_64:
- if (dynobj == NULL
- && (info->shared || h != NULL)
- && (sec->flags & SEC_ALLOC) != 0)
- elf_hash_table (info)->dynobj = dynobj = abfd;
- break;
-
- default:
- break;
- }
- }
-
- if (!h && (r_type == R_MIPS_CALL_LO16
- || r_type == R_MIPS_GOT_LO16
- || r_type == R_MIPS_GOT_DISP))
- {
- /* We may need a local GOT entry for this relocation. We
- don't count R_MIPS_GOT_PAGE because we can estimate the
- maximum number of pages needed by looking at the size of
- the segment. Similar comments apply to R_MIPS_GOT16 and
- R_MIPS_CALL16. We don't count R_MIPS_GOT_HI16, or
- R_MIPS_CALL_HI16 because these are always followed by an
- R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.
-
- This estimation is very conservative since we can merge
- duplicate entries in the GOT. In order to be less
- conservative, we could actually build the GOT here,
- rather than in relocate_section. */
- g->local_gotno++;
- sgot->_raw_size += MIPS_ELF_GOT_SIZE (dynobj);
- }
-
- switch (r_type)
- {
- case R_MIPS_CALL16:
- if (h == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: CALL16 reloc at 0x%lx not against global symbol"),
- bfd_archive_filename (abfd), (unsigned long) rel->r_offset);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- /* Fall through. */
-
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- if (h != NULL)
- {
- /* This symbol requires a global offset table entry. */
- if (!mips_elf_record_global_got_symbol (h, info, g))
- return false;
-
- /* We need a stub, not a plt entry for the undefined
- function. But we record it as if it needs plt. See
- elf_adjust_dynamic_symbol in elflink.h. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->type = STT_FUNC;
- }
- break;
-
- case R_MIPS_GOT16:
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_GOT_DISP:
- /* This symbol requires a global offset table entry. */
- if (h && !mips_elf_record_global_got_symbol (h, info, g))
- return false;
- break;
-
- case R_MIPS_32:
- case R_MIPS_REL32:
- case R_MIPS_64:
- if ((info->shared || h != NULL)
- && (sec->flags & SEC_ALLOC) != 0)
- {
- if (sreloc == NULL)
- {
- const char *dname = MIPS_ELF_REL_DYN_SECTION_NAME (dynobj);
-
- sreloc = bfd_get_section_by_name (dynobj, dname);
- if (sreloc == NULL)
- {
- sreloc = bfd_make_section (dynobj, dname);
- if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY))
- || ! bfd_set_section_alignment (dynobj, sreloc,
- 4))
- return false;
- }
- }
-#define MIPS_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
- if (info->shared)
- {
- /* When creating a shared object, we must copy these
- reloc types into the output file as R_MIPS_REL32
- relocs. We make room for this reloc in the
- .rel.dyn reloc section. */
- mips_elf_allocate_dynamic_relocations (dynobj, 1);
- if ((sec->flags & MIPS_READONLY_SECTION)
- == MIPS_READONLY_SECTION)
- /* We tell the dynamic linker that there are
- relocations against the text segment. */
- info->flags |= DF_TEXTREL;
- }
- else
- {
- struct mips_elf_link_hash_entry *hmips;
-
- /* We only need to copy this reloc if the symbol is
- defined in a dynamic object. */
- hmips = (struct mips_elf_link_hash_entry *) h;
- ++hmips->possibly_dynamic_relocs;
- if ((sec->flags & MIPS_READONLY_SECTION)
- == MIPS_READONLY_SECTION)
- /* We need it to tell the dynamic linker if there
- are relocations against the text segment. */
- hmips->readonly_reloc = true;
- }
-
- /* Even though we don't directly need a GOT entry for
- this symbol, a symbol must have a dynamic symbol
- table index greater that DT_MIPS_GOTSYM if there are
- dynamic relocations against it. */
- if (h != NULL
- && !mips_elf_record_global_got_symbol (h, info, g))
- return false;
- }
-
- if (SGI_COMPAT (abfd))
- mips_elf_hash_table (info)->compact_rel_size +=
- sizeof (Elf32_External_crinfo);
- break;
-
- case R_MIPS_26:
- case R_MIPS_GPREL16:
- case R_MIPS_LITERAL:
- case R_MIPS_GPREL32:
- if (SGI_COMPAT (abfd))
- mips_elf_hash_table (info)->compact_rel_size +=
- sizeof (Elf32_External_crinfo);
- break;
-
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_MIPS_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return false;
- break;
-
- /* This relocation describes which C++ vtable entries are actually
- used. Record for later use during GC. */
- case R_MIPS_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
- return false;
- break;
-
- default:
- break;
- }
-
- /* We must not create a stub for a symbol that has relocations
- related to taking the function's address. */
- switch (r_type)
- {
- default:
- if (h != NULL)
- {
- struct mips_elf_link_hash_entry *mh;
-
- mh = (struct mips_elf_link_hash_entry *) h;
- mh->no_fn_stub = true;
- }
- break;
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- break;
- }
-
- /* If this reloc is not a 16 bit call, and it has a global
- symbol, then we will need the fn_stub if there is one.
- References from a stub section do not count. */
- if (h != NULL
- && r_type != R_MIPS16_26
- && strncmp (bfd_get_section_name (abfd, sec), FN_STUB,
- sizeof FN_STUB - 1) != 0
- && strncmp (bfd_get_section_name (abfd, sec), CALL_STUB,
- sizeof CALL_STUB - 1) != 0
- && strncmp (bfd_get_section_name (abfd, sec), CALL_FP_STUB,
- sizeof CALL_FP_STUB - 1) != 0)
- {
- struct mips_elf_link_hash_entry *mh;
-
- mh = (struct mips_elf_link_hash_entry *) h;
- mh->need_fn_stub = true;
- }
- }
-
- return true;
-}
-
-/* Return the section that should be marked against GC for a given
- relocation. */
-
-asection *
-_bfd_mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- /* ??? Do mips16 stub sections need to be handled special? */
-
- if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_MIPS_GNU_VTINHERIT:
- case R_MIPS_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
-
- return NULL;
-}
-
-/* Update the got entry reference counts for the section being removed. */
-
-boolean
-_bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
-{
-#if 0
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel, *relend;
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- /* ??? It would seem that the existing MIPS code does no sort
- of reference counting or whatnot on its GOT and PLT entries,
- so it is not possible to garbage collect them at this time. */
- break;
-
- default:
- break;
- }
-#endif
-
- return true;
-}
-
-/* Copy data from a MIPS ELF indirect symbol to its direct symbol,
- hiding the old indirect symbol. Process additional relocation
- information. Also called for weakdefs, in which case we just let
- _bfd_elf_link_hash_copy_indirect copy the flags for us. */
-
-static void
-_bfd_mips_elf_copy_indirect_symbol (dir, ind)
- struct elf_link_hash_entry *dir, *ind;
-{
- struct mips_elf_link_hash_entry *dirmips, *indmips;
-
- _bfd_elf_link_hash_copy_indirect (dir, ind);
-
- if (ind->root.type != bfd_link_hash_indirect)
- return;
-
- dirmips = (struct mips_elf_link_hash_entry *) dir;
- indmips = (struct mips_elf_link_hash_entry *) ind;
- dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
- if (indmips->readonly_reloc)
- dirmips->readonly_reloc = true;
- if (dirmips->min_dyn_reloc_index == 0
- || (indmips->min_dyn_reloc_index != 0
- && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
- dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
- if (indmips->no_fn_stub)
- dirmips->no_fn_stub = true;
-}
-
-/* Adjust a symbol defined by a dynamic object and referenced by a
- regular object. The current definition is in some section of the
- dynamic object, but we're not including those sections. We have to
- change the definition to something the rest of the link can
- understand. */
-
-boolean
-_bfd_mips_elf_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
-{
- bfd *dynobj;
- struct mips_elf_link_hash_entry *hmips;
- asection *s;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- /* Make sure we know what is going on here. */
- BFD_ASSERT (dynobj != NULL
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
- || h->weakdef != NULL
- || ((h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)));
-
- /* If this symbol is defined in a dynamic object, we need to copy
- any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
- file. */
- hmips = (struct mips_elf_link_hash_entry *) h;
- if (! info->relocateable
- && hmips->possibly_dynamic_relocs != 0
- && (h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- {
- mips_elf_allocate_dynamic_relocations (dynobj,
- hmips->possibly_dynamic_relocs);
- if (hmips->readonly_reloc)
- /* We tell the dynamic linker that there are relocations
- against the text segment. */
- info->flags |= DF_TEXTREL;
- }
-
- /* For a function, create a stub, if allowed. */
- if (! hmips->no_fn_stub
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
- {
- if (! elf_hash_table (info)->dynamic_sections_created)
- return true;
-
- /* If this symbol is not defined in a regular file, then set
- the symbol to the stub location. This is required to make
- function pointers compare as equal between the normal
- executable and the shared library. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- {
- /* We need .stub section. */
- s = bfd_get_section_by_name (dynobj,
- MIPS_ELF_STUB_SECTION_NAME (dynobj));
- BFD_ASSERT (s != NULL);
-
- h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
-
- /* XXX Write this stub address somewhere. */
- h->plt.offset = s->_raw_size;
-
- /* Make room for this stub code. */
- s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
-
- /* The last half word of the stub will be filled with the index
- of this symbol in .dynsym section. */
- return true;
- }
- }
- else if ((h->type == STT_FUNC)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
- {
- /* This will set the entry for this symbol in the GOT to 0, and
- the dynamic linker will take care of this. */
- h->root.u.def.value = 0;
- return true;
- }
-
- /* If this is a weak symbol, and there is a real definition, the
- processor independent code will have arranged for us to see the
- real definition first, and we can just use the same value. */
- if (h->weakdef != NULL)
- {
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
- return true;
- }
-
- /* This is a reference to a symbol defined by a dynamic object which
- is not a function. */
-
- return true;
-}
-
-/* This function is called after all the input files have been read,
- and the input sections have been assigned to output sections. We
- check for any mips16 stub sections that we can discard. */
-
-static boolean mips_elf_check_mips16_stubs
- PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-
-boolean
-_bfd_mips_elf_always_size_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
-{
- asection *ri;
-
- /* The .reginfo section has a fixed size. */
- ri = bfd_get_section_by_name (output_bfd, ".reginfo");
- if (ri != NULL)
- bfd_set_section_size (output_bfd, ri,
- (bfd_size_type) sizeof (Elf32_External_RegInfo));
-
- if (info->relocateable
- || ! mips_elf_hash_table (info)->mips16_stubs_seen)
- return true;
-
- mips_elf_link_hash_traverse (mips_elf_hash_table (info),
- mips_elf_check_mips16_stubs,
- (PTR) NULL);
-
- return true;
-}
-
-/* Check the mips16 stubs for a particular symbol, and see if we can
- discard them. */
-
-static boolean
-mips_elf_check_mips16_stubs (h, data)
- struct mips_elf_link_hash_entry *h;
- PTR data ATTRIBUTE_UNUSED;
-{
- if (h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
- if (h->fn_stub != NULL
- && ! h->need_fn_stub)
- {
- /* We don't need the fn_stub; the only references to this symbol
- are 16 bit calls. Clobber the size to 0 to prevent it from
- being included in the link. */
- h->fn_stub->_raw_size = 0;
- h->fn_stub->_cooked_size = 0;
- h->fn_stub->flags &= ~SEC_RELOC;
- h->fn_stub->reloc_count = 0;
- h->fn_stub->flags |= SEC_EXCLUDE;
- }
-
- if (h->call_stub != NULL
- && h->root.other == STO_MIPS16)
- {
- /* We don't need the call_stub; this is a 16 bit function, so
- calls from other 16 bit functions are OK. Clobber the size
- to 0 to prevent it from being included in the link. */
- h->call_stub->_raw_size = 0;
- h->call_stub->_cooked_size = 0;
- h->call_stub->flags &= ~SEC_RELOC;
- h->call_stub->reloc_count = 0;
- h->call_stub->flags |= SEC_EXCLUDE;
- }
-
- if (h->call_fp_stub != NULL
- && h->root.other == STO_MIPS16)
- {
- /* We don't need the call_stub; this is a 16 bit function, so
- calls from other 16 bit functions are OK. Clobber the size
- to 0 to prevent it from being included in the link. */
- h->call_fp_stub->_raw_size = 0;
- h->call_fp_stub->_cooked_size = 0;
- h->call_fp_stub->flags &= ~SEC_RELOC;
- h->call_fp_stub->reloc_count = 0;
- h->call_fp_stub->flags |= SEC_EXCLUDE;
- }
-
- return true;
-}
-
-/* Set the sizes of the dynamic sections. */
-
-boolean
-_bfd_mips_elf_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
-{
- bfd *dynobj;
- asection *s;
- boolean reltext;
- struct mips_got_info *g = NULL;
-
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- /* Set the contents of the .interp section to the interpreter. */
- if (! info->shared)
- {
- s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
- s->_raw_size
- = strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1;
- s->contents
- = (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
- }
- }
-
- /* The check_relocs and adjust_dynamic_symbol entry points have
- determined the sizes of the various dynamic sections. Allocate
- memory for them. */
- reltext = false;
- for (s = dynobj->sections; s != NULL; s = s->next)
- {
- const char *name;
- boolean strip;
-
- /* It's OK to base decisions on the section name, because none
- of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
-
- if ((s->flags & SEC_LINKER_CREATED) == 0)
- continue;
-
- strip = false;
-
- if (strncmp (name, ".rel", 4) == 0)
- {
- if (s->_raw_size == 0)
- {
- /* We only strip the section if the output section name
- has the same name. Otherwise, there might be several
- input sections for this output section. FIXME: This
- code is probably not needed these days anyhow, since
- the linker now does not create empty output sections. */
- if (s->output_section != NULL
- && strcmp (name,
- bfd_get_section_name (s->output_section->owner,
- s->output_section)) == 0)
- strip = true;
- }
- else
- {
- const char *outname;
- asection *target;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL entry.
- If the relocation section is .rel.dyn, we always
- assert a DT_TEXTREL entry rather than testing whether
- there exists a relocation to a read only section or
- not. */
- outname = bfd_get_section_name (output_bfd,
- s->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 4);
- if ((target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0)
- || strcmp (outname,
- MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd)) == 0)
- reltext = true;
-
- /* We use the reloc_count field as a counter if we need
- to copy relocs into the output file. */
- if (strcmp (name,
- MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd)) != 0)
- s->reloc_count = 0;
- }
- }
- else if (strncmp (name, ".got", 4) == 0)
- {
- int i;
- bfd_size_type loadable_size = 0;
- bfd_size_type local_gotno;
- bfd *sub;
-
- BFD_ASSERT (elf_section_data (s) != NULL);
- g = (struct mips_got_info *) elf_section_data (s)->tdata;
- BFD_ASSERT (g != NULL);
-
- /* Calculate the total loadable size of the output. That
- will give us the maximum number of GOT_PAGE entries
- required. */
- for (sub = info->input_bfds; sub; sub = sub->link_next)
- {
- asection *subsection;
-
- for (subsection = sub->sections;
- subsection;
- subsection = subsection->next)
- {
- if ((subsection->flags & SEC_ALLOC) == 0)
- continue;
- loadable_size += ((subsection->_raw_size + 0xf)
- &~ (bfd_size_type) 0xf);
- }
- }
- loadable_size += MIPS_FUNCTION_STUB_SIZE;
-
- /* Assume there are two loadable segments consisting of
- contiguous sections. Is 5 enough? */
- local_gotno = (loadable_size >> 16) + 5;
- if (IRIX_COMPAT (output_bfd) == ict_irix6)
- /* It's possible we will need GOT_PAGE entries as well as
- GOT16 entries. Often, these will be able to share GOT
- entries, but not always. */
- local_gotno *= 2;
-
- g->local_gotno += local_gotno;
- s->_raw_size += local_gotno * MIPS_ELF_GOT_SIZE (dynobj);
-
- /* There has to be a global GOT entry for every symbol with
- a dynamic symbol table index of DT_MIPS_GOTSYM or
- higher. Therefore, it make sense to put those symbols
- that need GOT entries at the end of the symbol table. We
- do that here. */
- if (!mips_elf_sort_hash_table (info, 1))
- return false;
-
- if (g->global_gotsym != NULL)
- i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
- else
- /* If there are no global symbols, or none requiring
- relocations, then GLOBAL_GOTSYM will be NULL. */
- i = 0;
- g->global_gotno = i;
- s->_raw_size += i * MIPS_ELF_GOT_SIZE (dynobj);
- }
- else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
- {
- /* Irix rld assumes that the function stub isn't at the end
- of .text section. So put a dummy. XXX */
- s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
- }
- else if (! info->shared
- && ! mips_elf_hash_table (info)->use_rld_obj_head
- && strncmp (name, ".rld_map", 8) == 0)
- {
- /* We add a room for __rld_map. It will be filled in by the
- rtld to contain a pointer to the _r_debug structure. */
- s->_raw_size += 4;
- }
- else if (SGI_COMPAT (output_bfd)
- && strncmp (name, ".compact_rel", 12) == 0)
- s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
- else if (strcmp (name, MIPS_ELF_MSYM_SECTION_NAME (output_bfd))
- == 0)
- s->_raw_size = (sizeof (Elf32_External_Msym)
- * (elf_hash_table (info)->dynsymcount
- + bfd_count_sections (output_bfd)));
- else if (strncmp (name, ".init", 5) != 0)
- {
- /* It's not one of our sections, so don't allocate space. */
- continue;
- }
-
- if (strip)
- {
- _bfd_strip_section_from_output (info, s);
- continue;
- }
-
- /* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- }
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- /* Add some entries to the .dynamic section. We fill in the
- values later, in elf_mips_finish_dynamic_sections, but we
- must add the entries now so that we get the correct size for
- the .dynamic section. The DT_DEBUG entry is filled in by the
- dynamic linker and used by the debugger. */
- if (! info->shared)
- {
- /* SGI object has the equivalence of DT_DEBUG in the
- DT_MIPS_RLD_MAP entry. */
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
- return false;
- if (!SGI_COMPAT (output_bfd))
- {
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
- return false;
- }
- }
- else
- {
- /* Shared libraries on traditional mips have DT_DEBUG. */
- if (!SGI_COMPAT (output_bfd))
- {
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
- return false;
- }
- }
-
- if (reltext && SGI_COMPAT (output_bfd))
- info->flags |= DF_TEXTREL;
-
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
- return false;
- }
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
- return false;
-
- if (bfd_get_section_by_name (dynobj,
- MIPS_ELF_REL_DYN_SECTION_NAME (dynobj)))
- {
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
- return false;
- }
-
- if (SGI_COMPAT (output_bfd))
- {
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
- return false;
- }
-
- if (SGI_COMPAT (output_bfd))
- {
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
- return false;
- }
-
- if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
- {
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICT, 0))
- return false;
-
- s = bfd_get_section_by_name (dynobj, ".liblist");
- BFD_ASSERT (s != NULL);
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLIST, 0))
- return false;
- }
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0))
- return false;
-
-#if 0
- /* Time stamps in executable files are a bad idea. */
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_TIME_STAMP, 0))
- return false;
-#endif
-
-#if 0 /* FIXME */
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_ICHECKSUM, 0))
- return false;
-#endif
-
-#if 0 /* FIXME */
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_IVERSION, 0))
- return false;
-#endif
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0))
- return false;
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
- return false;
-
- if (IRIX_COMPAT (dynobj) == ict_irix5
- && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
- return false;
-
- if (IRIX_COMPAT (dynobj) == ict_irix6
- && (bfd_get_section_by_name
- (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
- && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
- return false;
-
- if (bfd_get_section_by_name (dynobj,
- MIPS_ELF_MSYM_SECTION_NAME (dynobj))
- && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_MSYM, 0))
- return false;
- }
-
- return true;
-}
-
-/* If NAME is one of the special IRIX6 symbols defined by the linker,
- adjust it appropriately now. */
-
-static void
-mips_elf_irix6_finish_dynamic_symbol (abfd, name, sym)
- bfd *abfd ATTRIBUTE_UNUSED;
- const char *name;
- Elf_Internal_Sym *sym;
-{
- /* The linker script takes care of providing names and values for
- these, but we must place them into the right sections. */
- static const char* const text_section_symbols[] = {
- "_ftext",
- "_etext",
- "__dso_displacement",
- "__elf_header",
- "__program_header_table",
- NULL
- };
-
- static const char* const data_section_symbols[] = {
- "_fdata",
- "_edata",
- "_end",
- "_fbss",
- NULL
- };
-
- const char* const *p;
- int i;
-
- for (i = 0; i < 2; ++i)
- for (p = (i == 0) ? text_section_symbols : data_section_symbols;
- *p;
- ++p)
- if (strcmp (*p, name) == 0)
- {
- /* All of these symbols are given type STT_SECTION by the
- IRIX6 linker. */
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
-
- /* The IRIX linker puts these symbols in special sections. */
- if (i == 0)
- sym->st_shndx = SHN_MIPS_TEXT;
- else
- sym->st_shndx = SHN_MIPS_DATA;
-
- break;
- }
-}
-
-/* Finish up dynamic symbol handling. We set the contents of various
- dynamic sections here. */
-
-boolean
-_bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
- bfd *output_bfd;
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- bfd *dynobj;
- bfd_vma gval;
- asection *sgot;
- asection *smsym;
- struct mips_got_info *g;
- const char *name;
- struct mips_elf_link_hash_entry *mh;
-
- dynobj = elf_hash_table (info)->dynobj;
- gval = sym->st_value;
- mh = (struct mips_elf_link_hash_entry *) h;
-
- if (h->plt.offset != (bfd_vma) -1)
- {
- asection *s;
- bfd_byte *p;
- bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
-
- /* This symbol has a stub. Set it up. */
-
- BFD_ASSERT (h->dynindx != -1);
-
- s = bfd_get_section_by_name (dynobj,
- MIPS_ELF_STUB_SECTION_NAME (dynobj));
- BFD_ASSERT (s != NULL);
-
- /* Fill the stub. */
- p = stub;
- bfd_put_32 (output_bfd, (bfd_vma) STUB_LW (output_bfd), p);
- p += 4;
- bfd_put_32 (output_bfd, (bfd_vma) STUB_MOVE (output_bfd), p);
- p += 4;
-
- /* FIXME: Can h->dynindex be more than 64K? */
- if (h->dynindx & 0xffff0000)
- return false;
-
- bfd_put_32 (output_bfd, (bfd_vma) STUB_JALR, p);
- p += 4;
- bfd_put_32 (output_bfd, (bfd_vma) STUB_LI16 (output_bfd) + h->dynindx, p);
-
- BFD_ASSERT (h->plt.offset <= s->_raw_size);
- memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
-
- /* Mark the symbol as undefined. plt.offset != -1 occurs
- only for the referenced symbol. */
- sym->st_shndx = SHN_UNDEF;
-
- /* The run-time linker uses the st_value field of the symbol
- to reset the global offset table entry for this external
- to its stub address when unlinking a shared object. */
- gval = s->output_section->vma + s->output_offset + h->plt.offset;
- sym->st_value = gval;
- }
-
- BFD_ASSERT (h->dynindx != -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
-
- sgot = mips_elf_got_section (dynobj);
- BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
-
- /* Run through the global symbol table, creating GOT entries for all
- the symbols that need them. */
- if (g->global_gotsym != NULL
- && h->dynindx >= g->global_gotsym->dynindx)
- {
- bfd_vma offset;
- bfd_vma value;
-
- if (sym->st_value)
- value = sym->st_value;
- else
- {
- /* For an entity defined in a shared object, this will be
- NULL. (For functions in shared objects for
- which we have created stubs, ST_VALUE will be non-NULL.
- That's because such the functions are now no longer defined
- in a shared object.) */
-
- if (info->shared && h->root.type == bfd_link_hash_undefined)
- value = 0;
- else
- value = h->root.u.def.value;
- }
- offset = mips_elf_global_got_index (dynobj, h);
- MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
- }
-
- /* Create a .msym entry, if appropriate. */
- smsym = bfd_get_section_by_name (dynobj,
- MIPS_ELF_MSYM_SECTION_NAME (dynobj));
- if (smsym)
- {
- Elf32_Internal_Msym msym;
-
- msym.ms_hash_value = bfd_elf_hash (h->root.root.string);
- /* It is undocumented what the `1' indicates, but IRIX6 uses
- this value. */
- msym.ms_info = ELF32_MS_INFO (mh->min_dyn_reloc_index, 1);
- bfd_mips_elf_swap_msym_out
- (dynobj, &msym,
- ((Elf32_External_Msym *) smsym->contents) + h->dynindx);
- }
-
- /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
- name = h->root.root.string;
- if (strcmp (name, "_DYNAMIC") == 0
- || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
- sym->st_shndx = SHN_ABS;
- else if (strcmp (name, "_DYNAMIC_LINK") == 0
- || strcmp (name, "_DYNAMIC_LINKING") == 0)
- {
- sym->st_shndx = SHN_ABS;
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
- sym->st_value = 1;
- }
- else if (strcmp (name, "_gp_disp") == 0)
- {
- sym->st_shndx = SHN_ABS;
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
- sym->st_value = elf_gp (output_bfd);
- }
- else if (SGI_COMPAT (output_bfd))
- {
- if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
- || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
- {
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
- sym->st_other = STO_PROTECTED;
- sym->st_value = 0;
- sym->st_shndx = SHN_MIPS_DATA;
- }
- else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
- {
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
- sym->st_other = STO_PROTECTED;
- sym->st_value = mips_elf_hash_table (info)->procedure_count;
- sym->st_shndx = SHN_ABS;
- }
- else if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS)
- {
- if (h->type == STT_FUNC)
- sym->st_shndx = SHN_MIPS_TEXT;
- else if (h->type == STT_OBJECT)
- sym->st_shndx = SHN_MIPS_DATA;
- }
- }
-
- /* Handle the IRIX6-specific symbols. */
- if (IRIX_COMPAT (output_bfd) == ict_irix6)
- mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);
-
- if (! info->shared)
- {
- if (! mips_elf_hash_table (info)->use_rld_obj_head
- && (strcmp (name, "__rld_map") == 0
- || strcmp (name, "__RLD_MAP") == 0))
- {
- asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
- BFD_ASSERT (s != NULL);
- sym->st_value = s->output_section->vma + s->output_offset;
- bfd_put_32 (output_bfd, (bfd_vma) 0, s->contents);
- if (mips_elf_hash_table (info)->rld_value == 0)
- mips_elf_hash_table (info)->rld_value = sym->st_value;
- }
- else if (mips_elf_hash_table (info)->use_rld_obj_head
- && strcmp (name, "__rld_obj_head") == 0)
- {
- /* IRIX6 does not use a .rld_map section. */
- if (IRIX_COMPAT (output_bfd) == ict_irix5
- || IRIX_COMPAT (output_bfd) == ict_none)
- BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map")
- != NULL);
- mips_elf_hash_table (info)->rld_value = sym->st_value;
- }
- }
-
- /* If this is a mips16 symbol, force the value to be even. */
- if (sym->st_other == STO_MIPS16
- && (sym->st_value & 1) != 0)
- --sym->st_value;
-
- return true;
-}
-
-/* Finish up the dynamic sections. */
-
-boolean
-_bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
-{
- bfd *dynobj;
- asection *sdyn;
- asection *sgot;
- struct mips_got_info *g;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
-
- sgot = mips_elf_got_section (dynobj);
- if (sgot == NULL)
- g = NULL;
- else
- {
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
- }
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- bfd_byte *b;
-
- BFD_ASSERT (sdyn != NULL);
- BFD_ASSERT (g != NULL);
-
- for (b = sdyn->contents;
- b < sdyn->contents + sdyn->_raw_size;
- b += MIPS_ELF_DYN_SIZE (dynobj))
- {
- Elf_Internal_Dyn dyn;
- const char *name;
- size_t elemsize;
- asection *s;
- boolean swap_out_p;
-
- /* Read in the current dynamic entry. */
- (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
-
- /* Assume that we're going to modify it and write it out. */
- swap_out_p = true;
-
- switch (dyn.d_tag)
- {
- case DT_RELENT:
- s = (bfd_get_section_by_name
- (dynobj,
- MIPS_ELF_REL_DYN_SECTION_NAME (dynobj)));
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
- break;
-
- case DT_STRSZ:
- /* Rewrite DT_STRSZ. */
- dyn.d_un.d_val =
- _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
- break;
-
- case DT_PLTGOT:
- name = ".got";
- goto get_vma;
- case DT_MIPS_CONFLICT:
- name = ".conflict";
- goto get_vma;
- case DT_MIPS_LIBLIST:
- name = ".liblist";
- get_vma:
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
- break;
-
- case DT_MIPS_RLD_VERSION:
- dyn.d_un.d_val = 1; /* XXX */
- break;
-
- case DT_MIPS_FLAGS:
- dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
- break;
-
- case DT_MIPS_CONFLICTNO:
- name = ".conflict";
- elemsize = sizeof (Elf32_Conflict);
- goto set_elemno;
-
- case DT_MIPS_LIBLISTNO:
- name = ".liblist";
- elemsize = sizeof (Elf32_Lib);
- set_elemno:
- s = bfd_get_section_by_name (output_bfd, name);
- if (s != NULL)
- {
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size / elemsize;
- else
- dyn.d_un.d_val = s->_raw_size / elemsize;
- }
- else
- dyn.d_un.d_val = 0;
- break;
-
- case DT_MIPS_TIME_STAMP:
- time ((time_t *) &dyn.d_un.d_val);
- break;
-
- case DT_MIPS_ICHECKSUM:
- /* XXX FIXME: */
- swap_out_p = false;
- break;
-
- case DT_MIPS_IVERSION:
- /* XXX FIXME: */
- swap_out_p = false;
- break;
-
- case DT_MIPS_BASE_ADDRESS:
- s = output_bfd->sections;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
- break;
-
- case DT_MIPS_LOCAL_GOTNO:
- dyn.d_un.d_val = g->local_gotno;
- break;
-
- case DT_MIPS_UNREFEXTNO:
- /* The index into the dynamic symbol table which is the
- entry of the first external symbol that is not
- referenced within the same object. */
- dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
- break;
-
- case DT_MIPS_GOTSYM:
- if (g->global_gotsym)
- {
- dyn.d_un.d_val = g->global_gotsym->dynindx;
- break;
- }
- /* In case if we don't have global got symbols we default
- to setting DT_MIPS_GOTSYM to the same value as
- DT_MIPS_SYMTABNO, so we just fall through. */
-
- case DT_MIPS_SYMTABNO:
- name = ".dynsym";
- elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
-
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size / elemsize;
- else
- dyn.d_un.d_val = s->_raw_size / elemsize;
- break;
-
- case DT_MIPS_HIPAGENO:
- dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO;
- break;
-
- case DT_MIPS_RLD_MAP:
- dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value;
- break;
-
- case DT_MIPS_OPTIONS:
- s = (bfd_get_section_by_name
- (output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
- dyn.d_un.d_ptr = s->vma;
- break;
-
- case DT_MIPS_MSYM:
- s = (bfd_get_section_by_name
- (output_bfd, MIPS_ELF_MSYM_SECTION_NAME (output_bfd)));
- dyn.d_un.d_ptr = s->vma;
- break;
-
- default:
- swap_out_p = false;
- break;
- }
-
- if (swap_out_p)
- (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
- (dynobj, &dyn, b);
- }
- }
-
- /* The first entry of the global offset table will be filled at
- runtime. The second entry will be used by some runtime loaders.
- This isn't the case of Irix rld. */
- if (sgot != NULL && sgot->_raw_size > 0)
- {
- MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
- MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
- sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
- }
-
- if (sgot != NULL)
- elf_section_data (sgot->output_section)->this_hdr.sh_entsize
- = MIPS_ELF_GOT_SIZE (output_bfd);
-
- {
- asection *smsym;
- asection *s;
- Elf32_compact_rel cpt;
-
- /* ??? The section symbols for the output sections were set up in
- _bfd_elf_final_link. SGI sets the STT_NOTYPE attribute for these
- symbols. Should we do so? */
-
- smsym = bfd_get_section_by_name (dynobj,
- MIPS_ELF_MSYM_SECTION_NAME (dynobj));
- if (smsym != NULL)
- {
- Elf32_Internal_Msym msym;
-
- msym.ms_hash_value = 0;
- msym.ms_info = ELF32_MS_INFO (0, 1);
-
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- long dynindx = elf_section_data (s)->dynindx;
-
- bfd_mips_elf_swap_msym_out
- (output_bfd, &msym,
- (((Elf32_External_Msym *) smsym->contents)
- + dynindx));
- }
- }
-
- if (SGI_COMPAT (output_bfd))
- {
- /* Write .compact_rel section out. */
- s = bfd_get_section_by_name (dynobj, ".compact_rel");
- if (s != NULL)
- {
- cpt.id1 = 1;
- cpt.num = s->reloc_count;
- cpt.id2 = 2;
- cpt.offset = (s->output_section->filepos
- + sizeof (Elf32_External_compact_rel));
- cpt.reserved0 = 0;
- cpt.reserved1 = 0;
- bfd_elf32_swap_compact_rel_out (output_bfd, &cpt,
- ((Elf32_External_compact_rel *)
- s->contents));
-
- /* Clean up a dummy stub function entry in .text. */
- s = bfd_get_section_by_name (dynobj,
- MIPS_ELF_STUB_SECTION_NAME (dynobj));
- if (s != NULL)
- {
- file_ptr dummy_offset;
-
- BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
- dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
- memset (s->contents + dummy_offset, 0,
- MIPS_FUNCTION_STUB_SIZE);
- }
- }
- }
-
- /* We need to sort the entries of the dynamic relocation section. */
-
- if (!ABI_64_P (output_bfd))
- {
- asection *reldyn;
-
- reldyn = bfd_get_section_by_name (dynobj,
- MIPS_ELF_REL_DYN_SECTION_NAME (dynobj));
- if (reldyn != NULL && reldyn->reloc_count > 2)
- {
- reldyn_sorting_bfd = output_bfd;
- qsort ((Elf32_External_Rel *) reldyn->contents + 1,
- (size_t) reldyn->reloc_count - 1,
- sizeof (Elf32_External_Rel), sort_dynamic_relocs);
- }
- }
-
- /* Clean up a first relocation in .rel.dyn. */
- s = bfd_get_section_by_name (dynobj,
- MIPS_ELF_REL_DYN_SECTION_NAME (dynobj));
- if (s != NULL && s->_raw_size > 0)
- memset (s->contents, 0, MIPS_ELF_REL_SIZE (dynobj));
- }
-
- return true;
-}
-
-/* Support for core dump NOTE sections */
-static boolean
-_bfd_elf32_mips_grok_prstatus (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
-{
- int offset;
- unsigned int raw_size;
-
- switch (note->descsz)
- {
- default:
- return false;
-
- case 256: /* Linux/MIPS */
- /* pr_cursig */
- elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
-
- /* pr_pid */
- elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
-
- /* pr_reg */
- offset = 72;
- raw_size = 180;
-
- break;
- }
-
- /* Make a ".reg/999" section. */
- return _bfd_elfcore_make_pseudosection (abfd, ".reg",
- raw_size, note->descpos + offset);
-}
-
-static boolean
-_bfd_elf32_mips_grok_psinfo (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
-{
- switch (note->descsz)
- {
- default:
- return false;
-
- case 128: /* Linux/MIPS elf_prpsinfo */
- elf_tdata (abfd)->core_program
- = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
- elf_tdata (abfd)->core_command
- = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
- }
-
- /* Note that for some reason, a spurious space is tacked
- onto the end of the args in some (at least one anyway)
- implementations, so strip it off if it exists. */
-
- {
- char *command = elf_tdata (abfd)->core_command;
- int n = strlen (command);
-
- if (0 < n && command[n - 1] == ' ')
- command[n - 1] = '\0';
- }
-
- return true;
-}
-
-#define PDR_SIZE 32
-
-static boolean
-_bfd_elf32_mips_discard_info (abfd, cookie, info)
- bfd *abfd;
- struct elf_reloc_cookie *cookie;
- struct bfd_link_info *info;
-{
- asection *o;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- boolean ret = false;
- unsigned char *tdata;
- size_t i, skip;
-
- o = bfd_get_section_by_name (abfd, ".pdr");
- if (! o)
- return false;
- if (o->_raw_size == 0)
- return false;
- if (o->_raw_size % PDR_SIZE != 0)
- return false;
- if (o->output_section != NULL
- && bfd_is_abs_section (o->output_section))
- return false;
-
- tdata = bfd_zmalloc (o->_raw_size / PDR_SIZE);
- if (! tdata)
- return false;
-
- cookie->rels = _bfd_elf32_link_read_relocs (abfd, o, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory);
- if (!cookie->rels)
- {
- free (tdata);
- return false;
- }
-
- cookie->rel = cookie->rels;
- cookie->relend =
- cookie->rels + o->reloc_count * bed->s->int_rels_per_ext_rel;
-
- for (i = 0, skip = 0; i < o->_raw_size; i ++)
- {
- if (_bfd_elf32_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
- {
- tdata[i] = 1;
- skip ++;
- }
- }
-
- if (skip != 0)
- {
- elf_section_data (o)->tdata = tdata;
- o->_cooked_size = o->_raw_size - skip * PDR_SIZE;
- ret = true;
- }
- else
- free (tdata);
-
- if (! info->keep_memory)
- free (cookie->rels);
-
- return ret;
-}
-
-static boolean
-_bfd_elf32_mips_ignore_discarded_relocs (sec)
- asection *sec;
-{
- if (strcmp (sec->name, ".pdr") == 0)
- return true;
- return false;
-}
-
-static boolean
-_bfd_elf32_mips_write_section (output_bfd, sec, contents)
- bfd *output_bfd;
- asection *sec;
- bfd_byte *contents;
-{
- bfd_byte *to, *from, *end;
- int i;
-
- if (strcmp (sec->name, ".pdr") != 0)
- return false;
-
- if (elf_section_data (sec)->tdata == NULL)
- return false;
-
- to = contents;
- end = contents + sec->_raw_size;
- for (from = contents, i = 0;
- from < end;
- from += PDR_SIZE, i++)
- {
- if (((unsigned char *)elf_section_data (sec)->tdata)[i] == 1)
- continue;
- if (to != from)
- memcpy (to, from, PDR_SIZE);
- to += PDR_SIZE;
- }
- bfd_set_section_contents (output_bfd, sec->output_section, contents,
- (file_ptr) sec->output_offset,
- sec->_cooked_size);
- return true;
-}
-
-/* Given a data section and an in-memory embedded reloc section, store
- relocation information into the embedded reloc section which can be
- used at runtime to relocate the data section. This is called by the
- linker when the --embedded-relocs switch is used. This is called
- after the add_symbols entry point has been called for all the
- objects, and before the final_link entry point is called. */
-
-boolean
-bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *datasec;
- asection *relsec;
- char **errmsg;
-{
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *shndx_hdr;
- Elf32_External_Sym *extsyms;
- Elf32_External_Sym *free_extsyms = NULL;
- Elf_External_Sym_Shndx *shndx_buf = NULL;
- Elf_Internal_Rela *internal_relocs;
- Elf_Internal_Rela *free_relocs = NULL;
- Elf_Internal_Rela *irel, *irelend;
- bfd_byte *p;
- bfd_size_type amt;
-
- BFD_ASSERT (! info->relocateable);
-
- *errmsg = NULL;
-
- if (datasec->reloc_count == 0)
- return true;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- /* Read this BFD's symbols if we haven't done so already, or get the cached
- copy if it exists. */
- if (symtab_hdr->contents != NULL)
- extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
- else
- {
- /* Go get them off disk. */
- if (info->keep_memory)
- extsyms = ((Elf32_External_Sym *)
- bfd_alloc (abfd, symtab_hdr->sh_size));
- else
- extsyms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_size));
- if (extsyms == NULL)
- goto error_return;
- if (! info->keep_memory)
- free_extsyms = extsyms;
- if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
- != symtab_hdr->sh_size))
- goto error_return;
- if (info->keep_memory)
- symtab_hdr->contents = (unsigned char *) extsyms;
- }
-
- shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (shndx_hdr->sh_size != 0)
- {
- amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
- shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
- if (shndx_buf == NULL)
- goto error_return;
- if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
- goto error_return;
- }
-
- /* Get a copy of the native relocations. */
- internal_relocs = (_bfd_elf32_link_read_relocs
- (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
- info->keep_memory));
- if (internal_relocs == NULL)
- goto error_return;
- if (! info->keep_memory)
- free_relocs = internal_relocs;
-
- relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
- if (relsec->contents == NULL)
- goto error_return;
-
- p = relsec->contents;
-
- irelend = internal_relocs + datasec->reloc_count;
-
- for (irel = internal_relocs; irel < irelend; irel++, p += 12)
- {
- asection *targetsec;
-
- /* We are going to write a four byte longword into the runtime
- reloc section. The longword will be the address in the data
- section which must be relocated. It is followed by the name
- of the target section NUL-padded or truncated to 8
- characters. */
-
- /* We can only relocate absolute longword relocs at run time. */
- if ((ELF32_R_TYPE (irel->r_info) != (int) R_MIPS_32) &&
- (ELF32_R_TYPE (irel->r_info) != (int) R_MIPS_64))
- {
- *errmsg = _("unsupported reloc type");
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
- /* Get the target section referred to by the reloc. */
- if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
- {
- Elf32_External_Sym *esym;
- Elf_External_Sym_Shndx *shndx;
- Elf_Internal_Sym isym;
-
- /* A local symbol. */
- esym = extsyms + ELF32_R_SYM (irel->r_info);
- shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
- bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
-
- targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
- }
- else
- {
- unsigned long indx;
- struct elf_link_hash_entry *h;
-
- /* An external symbol. */
- indx = ELF32_R_SYM (irel->r_info);
- h = elf_sym_hashes (abfd)[indx];
- targetsec = NULL;
- /*
- * For some reason, in certain programs, the symbol will
- * not be in the hash table. It seems to happen when you
- * declare a static table of pointers to const external structures.
- * In this case, the relocs are relative to data, not
- * text, so just treating it like an undefined link
- * should be sufficient.
- */
- BFD_ASSERT(h != NULL);
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- targetsec = h->root.u.def.section;
- }
-
-
- /*
- * Set the low bit of the relocation offset if it's a MIPS64 reloc.
- * Relocations will always be on (at least) 32-bit boundaries.
- */
-
- bfd_put_32 (abfd, ((irel->r_offset + datasec->output_offset) +
- ((ELF32_R_TYPE (irel->r_info) == (int) R_MIPS_64) ? 1 : 0)),
- p);
- memset (p + 4, 0, 8);
- if (targetsec != NULL)
- strncpy (p + 4, targetsec->output_section->name, 8);
- }
-
- if (shndx_buf != NULL)
- free (shndx_buf);
- if (free_extsyms != NULL)
- free (free_extsyms);
- if (free_relocs != NULL)
- free (free_relocs);
- return true;
-
- error_return:
- if (shndx_buf != NULL)
- free (shndx_buf);
- if (free_extsyms != NULL)
- free (free_extsyms);
- if (free_relocs != NULL)
- free (free_relocs);
- return false;
-}
-
-/* This is almost identical to bfd_generic_get_... except that some
- MIPS relocations need to be handled specially. Sigh. */
-
-static bfd_byte *
-elf32_mips_get_relocated_section_contents (abfd, link_info, link_order, data,
- relocateable, symbols)
- bfd *abfd;
- struct bfd_link_info *link_info;
- struct bfd_link_order *link_order;
- bfd_byte *data;
- boolean relocateable;
- asymbol **symbols;
-{
- /* Get enough memory to hold the stuff */
- bfd *input_bfd = link_order->u.indirect.section->owner;
- asection *input_section = link_order->u.indirect.section;
-
- long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
- arelent **reloc_vector = NULL;
- long reloc_count;
-
- if (reloc_size < 0)
- goto error_return;
-
- reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
- if (reloc_vector == NULL && reloc_size != 0)
- goto error_return;
-
- /* read in the section */
- if (!bfd_get_section_contents (input_bfd,
- input_section,
- (PTR) data,
- (file_ptr) 0,
- input_section->_raw_size))
- goto error_return;
-
- /* We're not relaxing the section, so just copy the size info */
- input_section->_cooked_size = input_section->_raw_size;
- input_section->reloc_done = true;
-
- reloc_count = bfd_canonicalize_reloc (input_bfd,
- input_section,
- reloc_vector,
- symbols);
- if (reloc_count < 0)
- goto error_return;
-
- if (reloc_count > 0)
- {
- arelent **parent;
- /* for mips */
- int gp_found;
- bfd_vma gp = 0x12345678; /* initialize just to shut gcc up */
-
- {
- struct bfd_hash_entry *h;
- struct bfd_link_hash_entry *lh;
- /* Skip all this stuff if we aren't mixing formats. */
- if (abfd && input_bfd
- && abfd->xvec == input_bfd->xvec)
- lh = 0;
- else
- {
- h = bfd_hash_lookup (&link_info->hash->table, "_gp", false, false);
- lh = (struct bfd_link_hash_entry *) h;
- }
- lookup:
- if (lh)
- {
- switch (lh->type)
- {
- case bfd_link_hash_undefined:
- case bfd_link_hash_undefweak:
- case bfd_link_hash_common:
- gp_found = 0;
- break;
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- gp_found = 1;
- gp = lh->u.def.value;
- break;
- case bfd_link_hash_indirect:
- case bfd_link_hash_warning:
- lh = lh->u.i.link;
- /* @@FIXME ignoring warning for now */
- goto lookup;
- case bfd_link_hash_new:
- default:
- abort ();
- }
- }
- else
- gp_found = 0;
- }
- /* end mips */
- for (parent = reloc_vector; *parent != (arelent *) NULL;
- parent++)
- {
- char *error_message = (char *) NULL;
- bfd_reloc_status_type r;
-
- /* Specific to MIPS: Deal with relocation types that require
- knowing the gp of the output bfd. */
- asymbol *sym = *(*parent)->sym_ptr_ptr;
- if (bfd_is_abs_section (sym->section) && abfd)
- {
- /* The special_function wouldn't get called anyways. */
- }
- else if (!gp_found)
- {
- /* The gp isn't there; let the special function code
- fall over on its own. */
- }
- else if ((*parent)->howto->special_function
- == _bfd_mips_elf_gprel16_reloc)
- {
- /* bypass special_function call */
- r = gprel16_with_gp (input_bfd, sym, *parent, input_section,
- relocateable, (PTR) data, gp);
- goto skip_bfd_perform_relocation;
- }
- /* end mips specific stuff */
-
- r = bfd_perform_relocation (input_bfd,
- *parent,
- (PTR) data,
- input_section,
- relocateable ? abfd : (bfd *) NULL,
- &error_message);
- skip_bfd_perform_relocation:
-
- if (relocateable)
- {
- asection *os = input_section->output_section;
-
- /* A partial link, so keep the relocs */
- os->orelocation[os->reloc_count] = *parent;
- os->reloc_count++;
- }
-
- if (r != bfd_reloc_ok)
- {
- switch (r)
- {
- case bfd_reloc_undefined:
- if (!((*link_info->callbacks->undefined_symbol)
- (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
- input_bfd, input_section, (*parent)->address,
- true)))
- goto error_return;
- break;
- case bfd_reloc_dangerous:
- BFD_ASSERT (error_message != (char *) NULL);
- if (!((*link_info->callbacks->reloc_dangerous)
- (link_info, error_message, input_bfd, input_section,
- (*parent)->address)))
- goto error_return;
- break;
- case bfd_reloc_overflow:
- if (!((*link_info->callbacks->reloc_overflow)
- (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
- (*parent)->howto->name, (*parent)->addend,
- input_bfd, input_section, (*parent)->address)))
- goto error_return;
- break;
- case bfd_reloc_outofrange:
- default:
- abort ();
- break;
- }
-
- }
- }
- }
- if (reloc_vector != NULL)
- free (reloc_vector);
- return data;
-
-error_return:
- if (reloc_vector != NULL)
- free (reloc_vector);
- return NULL;
-}
-
-#define bfd_elf32_bfd_get_relocated_section_contents \
- elf32_mips_get_relocated_section_contents
-
-/* ECOFF swapping routines. These are used when dealing with the
- .mdebug section, which is in the ECOFF debugging format. */
-static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
- /* Symbol table magic number. */
- magicSym,
- /* Alignment of debugging information. E.g., 4. */
- 4,
- /* Sizes of external symbolic information. */
- sizeof (struct hdr_ext),
- sizeof (struct dnr_ext),
- sizeof (struct pdr_ext),
- sizeof (struct sym_ext),
- sizeof (struct opt_ext),
- sizeof (struct fdr_ext),
- sizeof (struct rfd_ext),
- sizeof (struct ext_ext),
- /* Functions to swap in external symbolic data. */
- ecoff_swap_hdr_in,
- ecoff_swap_dnr_in,
- ecoff_swap_pdr_in,
- ecoff_swap_sym_in,
- ecoff_swap_opt_in,
- ecoff_swap_fdr_in,
- ecoff_swap_rfd_in,
- ecoff_swap_ext_in,
- _bfd_ecoff_swap_tir_in,
- _bfd_ecoff_swap_rndx_in,
- /* Functions to swap out external symbolic data. */
- ecoff_swap_hdr_out,
- ecoff_swap_dnr_out,
- ecoff_swap_pdr_out,
- ecoff_swap_sym_out,
- ecoff_swap_opt_out,
- ecoff_swap_fdr_out,
- ecoff_swap_rfd_out,
- ecoff_swap_ext_out,
- _bfd_ecoff_swap_tir_out,
- _bfd_ecoff_swap_rndx_out,
- /* Function to read in symbolic data. */
- _bfd_mips_elf_read_ecoff_info
-};
-
-#define ELF_ARCH bfd_arch_mips
-#define ELF_MACHINE_CODE EM_MIPS
-
-/* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses
- a value of 0x1000, and we are compatible. */
-#define ELF_MAXPAGESIZE 0x1000
-
-#define elf_backend_collect true
-#define elf_backend_type_change_ok true
-#define elf_backend_can_gc_sections true
-#define elf_info_to_howto mips_info_to_howto_rela
-#define elf_info_to_howto_rel mips_info_to_howto_rel
-#define elf_backend_sym_is_global mips_elf_sym_is_global
-#define elf_backend_object_p _bfd_mips_elf_object_p
-#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
-#define elf_backend_section_processing _bfd_mips_elf_section_processing
-#define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
-#define elf_backend_fake_sections _bfd_mips_elf_fake_sections
-#define elf_backend_section_from_bfd_section \
- _bfd_mips_elf_section_from_bfd_section
-#define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
-#define elf_backend_link_output_symbol_hook \
- _bfd_mips_elf_link_output_symbol_hook
-#define elf_backend_create_dynamic_sections \
- _bfd_mips_elf_create_dynamic_sections
-#define elf_backend_check_relocs _bfd_mips_elf_check_relocs
-#define elf_backend_adjust_dynamic_symbol \
- _bfd_mips_elf_adjust_dynamic_symbol
-#define elf_backend_always_size_sections \
- _bfd_mips_elf_always_size_sections
-#define elf_backend_size_dynamic_sections \
- _bfd_mips_elf_size_dynamic_sections
-#define elf_backend_relocate_section _bfd_mips_elf_relocate_section
-#define elf_backend_finish_dynamic_symbol \
- _bfd_mips_elf_finish_dynamic_symbol
-#define elf_backend_finish_dynamic_sections \
- _bfd_mips_elf_finish_dynamic_sections
-#define elf_backend_final_write_processing \
- _bfd_mips_elf_final_write_processing
-#define elf_backend_additional_program_headers \
- _bfd_mips_elf_additional_program_headers
-#define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
-#define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
-#define elf_backend_copy_indirect_symbol \
- _bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
-#define elf_backend_grok_prstatus _bfd_elf32_mips_grok_prstatus
-#define elf_backend_grok_psinfo _bfd_elf32_mips_grok_psinfo
-#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap
-
-#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
-#define elf_backend_plt_header_size 0
-#define elf_backend_may_use_rel_p 1
-#define elf_backend_may_use_rela_p 0
-#define elf_backend_default_use_rela_p 0
-#define elf_backend_sign_extend_vma true
-
-#define elf_backend_discard_info _bfd_elf32_mips_discard_info
-#define elf_backend_ignore_discarded_relocs \
- _bfd_elf32_mips_ignore_discarded_relocs
-#define elf_backend_write_section _bfd_elf32_mips_write_section
-
-#define bfd_elf32_bfd_is_local_label_name \
- mips_elf_is_local_label_name
-#define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line
-#define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents
-#define bfd_elf32_bfd_link_hash_table_create \
- _bfd_mips_elf_link_hash_table_create
-#define bfd_elf32_bfd_final_link _bfd_mips_elf_final_link
-#define bfd_elf32_bfd_merge_private_bfd_data \
- _bfd_mips_elf_merge_private_bfd_data
-#define bfd_elf32_bfd_set_private_flags _bfd_mips_elf_set_private_flags
-#define bfd_elf32_bfd_print_private_bfd_data \
- _bfd_mips_elf_print_private_bfd_data
-
-/* Support for SGI-ish mips targets. */
-#define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec
-#define TARGET_LITTLE_NAME "elf32-littlemips"
-#define TARGET_BIG_SYM bfd_elf32_bigmips_vec
-#define TARGET_BIG_NAME "elf32-bigmips"
-
-#include "elf32-target.h"
-
-/* Support for traditional mips targets. */
-#define INCLUDED_TARGET_FILE /* More a type of flag. */
-
-#undef TARGET_LITTLE_SYM
-#undef TARGET_LITTLE_NAME
-#undef TARGET_BIG_SYM
-#undef TARGET_BIG_NAME
-
-#define TARGET_LITTLE_SYM bfd_elf32_tradlittlemips_vec
-#define TARGET_LITTLE_NAME "elf32-tradlittlemips"
-#define TARGET_BIG_SYM bfd_elf32_tradbigmips_vec
-#define TARGET_BIG_NAME "elf32-tradbigmips"
-
-/* Include the target file again for this target */
-#include "elf32-target.h"
diff --git a/contrib/binutils/bfd/elf32-sh.c b/contrib/binutils/bfd/elf32-sh.c
deleted file mode 100644
index 841c42a..0000000
--- a/contrib/binutils/bfd/elf32-sh.c
+++ /dev/null
@@ -1,6285 +0,0 @@
-/* Hitachi SH specific support for 32-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
- Free Software Foundation, Inc.
- Contributed by Ian Lance Taylor, Cygnus Support.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "bfdlink.h"
-#include "libbfd.h"
-#include "elf-bfd.h"
-#include "elf/sh.h"
-
-static bfd_reloc_status_type sh_elf_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type sh_elf_ignore_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static reloc_howto_type *sh_elf_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-static void sh_elf_info_to_howto
- PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static boolean sh_elf_set_private_flags
- PARAMS ((bfd *, flagword));
-static boolean sh_elf_copy_private_data
- PARAMS ((bfd *, bfd *));
-static boolean sh_elf_merge_private_data
- PARAMS ((bfd *, bfd *));
-static boolean sh_elf_set_mach_from_flags
- PARAMS ((bfd *));
-static boolean sh_elf_relax_section
- PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
-static boolean sh_elf_relax_delete_bytes
- PARAMS ((bfd *, asection *, bfd_vma, int));
-static boolean sh_elf_align_loads
- PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, boolean *));
-static boolean sh_elf_swap_insns
- PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
-static boolean sh_elf_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static bfd_byte *sh_elf_get_relocated_section_contents
- PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
- bfd_byte *, boolean, asymbol **));
-static void sh_elf_copy_indirect_symbol
- PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
- struct elf_link_hash_entry *));
-static boolean sh_elf_check_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-static struct bfd_hash_entry *sh_elf_link_hash_newfunc
- PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static struct bfd_link_hash_table *sh_elf_link_hash_table_create
- PARAMS ((bfd *));
-static boolean sh_elf_adjust_dynamic_symbol
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean sh_elf_size_dynamic_sections
- PARAMS ((bfd *, struct bfd_link_info *));
-static boolean sh_elf_finish_dynamic_symbol
- PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
- Elf_Internal_Sym *));
-static boolean sh_elf_finish_dynamic_sections
- PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_reloc_status_type sh_elf_reloc_loop
- PARAMS ((int, bfd *, asection *, bfd_byte *, bfd_vma, asection *,
- bfd_vma, bfd_vma));
-static boolean create_got_section
- PARAMS((bfd *, struct bfd_link_info *));
-static boolean sh_elf_create_dynamic_sections
- PARAMS ((bfd *, struct bfd_link_info *));
-static asection * sh_elf_gc_mark_hook
- PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *));
-static boolean sh_elf_gc_sweep_hook
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-static boolean allocate_dynrelocs
- PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean readonly_dynrelocs
- PARAMS ((struct elf_link_hash_entry *, PTR));
-static enum elf_reloc_type_class sh_elf_reloc_type_class
- PARAMS ((const Elf_Internal_Rela *));
-#ifdef INCLUDE_SHMEDIA
-inline static void movi_shori_putval PARAMS ((bfd *, unsigned long, char *));
-#endif
-
-/* The name of the dynamic interpreter. This is put in the .interp
- section. */
-
-#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
-
-static reloc_howto_type sh_elf_howto_table[] =
-{
- /* No relocation. */
- HOWTO (R_SH_NONE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_NONE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit absolute relocation. Setting partial_inplace to true and
- src_mask to a non-zero value is similar to the COFF toolchain. */
- HOWTO (R_SH_DIR32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
- "R_SH_DIR32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit PC relative relocation. */
- HOWTO (R_SH_REL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_REL32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit PC relative branch divided by 2. */
- HOWTO (R_SH_DIR8WPN, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DIR8WPN", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 12 bit PC relative branch divided by 2. */
- HOWTO (R_SH_IND12W, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 12, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
- "R_SH_IND12W", /* name */
- true, /* partial_inplace */
- 0xfff, /* src_mask */
- 0xfff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit unsigned PC relative divided by 4. */
- HOWTO (R_SH_DIR8WPL, /* type */
- 2, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DIR8WPL", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit unsigned PC relative divided by 2. */
- HOWTO (R_SH_DIR8WPZ, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DIR8WPZ", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit GBR relative. FIXME: This only makes sense if we have some
- special symbol for the GBR relative area, and that is not
- implemented. */
- HOWTO (R_SH_DIR8BP, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DIR8BP", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit GBR relative divided by 2. FIXME: This only makes sense if
- we have some special symbol for the GBR relative area, and that
- is not implemented. */
- HOWTO (R_SH_DIR8W, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DIR8W", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit GBR relative divided by 4. FIXME: This only makes sense if
- we have some special symbol for the GBR relative area, and that
- is not implemented. */
- HOWTO (R_SH_DIR8L, /* type */
- 2, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DIR8L", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- EMPTY_HOWTO (10),
- EMPTY_HOWTO (11),
- EMPTY_HOWTO (12),
- EMPTY_HOWTO (13),
- EMPTY_HOWTO (14),
- EMPTY_HOWTO (15),
- EMPTY_HOWTO (16),
- EMPTY_HOWTO (17),
- EMPTY_HOWTO (18),
- EMPTY_HOWTO (19),
- EMPTY_HOWTO (20),
- EMPTY_HOWTO (21),
- EMPTY_HOWTO (22),
- EMPTY_HOWTO (23),
- EMPTY_HOWTO (24),
-
- /* The remaining relocs are a GNU extension used for relaxing. The
- final pass of the linker never needs to do anything with any of
- these relocs. Any required operations are handled by the
- relaxation code. */
-
- /* A 16 bit switch table entry. This is generated for an expression
- such as ``.word L1 - L2''. The offset holds the difference
- between the reloc address and L2. */
- HOWTO (R_SH_SWITCH16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_SWITCH16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* A 32 bit switch table entry. This is generated for an expression
- such as ``.long L1 - L2''. The offset holds the difference
- between the reloc address and L2. */
- HOWTO (R_SH_SWITCH32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_SWITCH32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Indicates a .uses pseudo-op. The compiler will generate .uses
- pseudo-ops when it finds a function call which can be relaxed.
- The offset field holds the PC relative offset to the instruction
- which loads the register used in the function call. */
- HOWTO (R_SH_USES, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_USES", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* The assembler will generate this reloc for addresses referred to
- by the register loads associated with USES relocs. The offset
- field holds the number of times the address is referenced in the
- object file. */
- HOWTO (R_SH_COUNT, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_COUNT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Indicates an alignment statement. The offset field is the power
- of 2 to which subsequent portions of the object file must be
- aligned. */
- HOWTO (R_SH_ALIGN, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_ALIGN", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* The assembler will generate this reloc before a block of
- instructions. A section should be processed as assumining it
- contains data, unless this reloc is seen. */
- HOWTO (R_SH_CODE, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_CODE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* The assembler will generate this reloc after a block of
- instructions when it sees data that is not instructions. */
- HOWTO (R_SH_DATA, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_DATA", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* The assembler generates this reloc for each label within a block
- of instructions. This permits the linker to avoid swapping
- instructions which are the targets of branches. */
- HOWTO (R_SH_LABEL, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_LABEL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* An 8 bit switch table entry. This is generated for an expression
- such as ``.word L1 - L2''. The offset holds the difference
- between the reloc address and L2. */
- HOWTO (R_SH_SWITCH8, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_SWITCH8", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
-
- /* GNU extension to record C++ vtable hierarchy */
- HOWTO (R_SH_GNU_VTINHERIT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- NULL, /* special_function */
- "R_SH_GNU_VTINHERIT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GNU extension to record C++ vtable member usage */
- HOWTO (R_SH_GNU_VTENTRY, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_elf_rel_vtable_reloc_fn, /* special_function */
- "R_SH_GNU_VTENTRY", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 8 bit PC relative divided by 2 - but specified in a very odd way. */
- HOWTO (R_SH_LOOP_START, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_LOOP_START", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 8 bit PC relative divided by 2 - but specified in a very odd way. */
- HOWTO (R_SH_LOOP_END, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_LOOP_END", /* name */
- true, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- true), /* pcrel_offset */
-
- EMPTY_HOWTO (38),
- EMPTY_HOWTO (39),
- EMPTY_HOWTO (40),
- EMPTY_HOWTO (41),
- EMPTY_HOWTO (42),
- EMPTY_HOWTO (43),
- EMPTY_HOWTO (44),
-
-#ifdef INCLUDE_SHMEDIA
- /* Used in SHLLI.L and SHLRI.L. */
- HOWTO (R_SH_DIR5U, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 5, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR5U", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xfc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in SHARI, SHLLI et al. */
- HOWTO (R_SH_DIR6U, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 6, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR6U", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xfc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in BxxI, LDHI.L et al. */
- HOWTO (R_SH_DIR6S, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 6, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR6S", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xfc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in ADDI, ANDI et al. */
- HOWTO (R_SH_DIR10S, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 10, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR10S", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in LD.UW, ST.W et al. */
- HOWTO (R_SH_DIR10SW, /* type */
- 1, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 11, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR10SW", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in LD.L, FLD.S et al. */
- HOWTO (R_SH_DIR10SL, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 12, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR10SL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in FLD.D, FST.P et al. */
- HOWTO (R_SH_DIR10SQ, /* type */
- 3, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 13, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_DIR10SQ", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
-#else
- EMPTY_HOWTO (45),
- EMPTY_HOWTO (46),
- EMPTY_HOWTO (47),
- EMPTY_HOWTO (48),
- EMPTY_HOWTO (49),
- EMPTY_HOWTO (50),
- EMPTY_HOWTO (51),
-#endif
-
- EMPTY_HOWTO (52),
- EMPTY_HOWTO (53),
- EMPTY_HOWTO (54),
- EMPTY_HOWTO (55),
- EMPTY_HOWTO (56),
- EMPTY_HOWTO (57),
- EMPTY_HOWTO (58),
- EMPTY_HOWTO (59),
- EMPTY_HOWTO (60),
- EMPTY_HOWTO (61),
- EMPTY_HOWTO (62),
- EMPTY_HOWTO (63),
- EMPTY_HOWTO (64),
- EMPTY_HOWTO (65),
- EMPTY_HOWTO (66),
- EMPTY_HOWTO (67),
- EMPTY_HOWTO (68),
- EMPTY_HOWTO (69),
- EMPTY_HOWTO (70),
- EMPTY_HOWTO (71),
- EMPTY_HOWTO (72),
- EMPTY_HOWTO (73),
- EMPTY_HOWTO (74),
- EMPTY_HOWTO (75),
- EMPTY_HOWTO (76),
- EMPTY_HOWTO (77),
- EMPTY_HOWTO (78),
- EMPTY_HOWTO (79),
- EMPTY_HOWTO (80),
- EMPTY_HOWTO (81),
- EMPTY_HOWTO (82),
- EMPTY_HOWTO (83),
- EMPTY_HOWTO (84),
- EMPTY_HOWTO (85),
- EMPTY_HOWTO (86),
- EMPTY_HOWTO (87),
- EMPTY_HOWTO (88),
- EMPTY_HOWTO (89),
- EMPTY_HOWTO (90),
- EMPTY_HOWTO (91),
- EMPTY_HOWTO (92),
- EMPTY_HOWTO (93),
- EMPTY_HOWTO (94),
- EMPTY_HOWTO (95),
- EMPTY_HOWTO (96),
- EMPTY_HOWTO (97),
- EMPTY_HOWTO (98),
- EMPTY_HOWTO (99),
- EMPTY_HOWTO (100),
- EMPTY_HOWTO (101),
- EMPTY_HOWTO (102),
- EMPTY_HOWTO (103),
- EMPTY_HOWTO (104),
- EMPTY_HOWTO (105),
- EMPTY_HOWTO (106),
- EMPTY_HOWTO (107),
- EMPTY_HOWTO (108),
- EMPTY_HOWTO (109),
- EMPTY_HOWTO (110),
- EMPTY_HOWTO (111),
- EMPTY_HOWTO (112),
- EMPTY_HOWTO (113),
- EMPTY_HOWTO (114),
- EMPTY_HOWTO (115),
- EMPTY_HOWTO (116),
- EMPTY_HOWTO (117),
- EMPTY_HOWTO (118),
- EMPTY_HOWTO (119),
- EMPTY_HOWTO (120),
- EMPTY_HOWTO (121),
- EMPTY_HOWTO (122),
- EMPTY_HOWTO (123),
- EMPTY_HOWTO (124),
- EMPTY_HOWTO (125),
- EMPTY_HOWTO (126),
- EMPTY_HOWTO (127),
- EMPTY_HOWTO (128),
- EMPTY_HOWTO (129),
- EMPTY_HOWTO (130),
- EMPTY_HOWTO (131),
- EMPTY_HOWTO (132),
- EMPTY_HOWTO (133),
- EMPTY_HOWTO (134),
- EMPTY_HOWTO (135),
- EMPTY_HOWTO (136),
- EMPTY_HOWTO (137),
- EMPTY_HOWTO (138),
- EMPTY_HOWTO (139),
- EMPTY_HOWTO (140),
- EMPTY_HOWTO (141),
- EMPTY_HOWTO (142),
- EMPTY_HOWTO (143),
- EMPTY_HOWTO (144),
- EMPTY_HOWTO (145),
- EMPTY_HOWTO (146),
- EMPTY_HOWTO (147),
- EMPTY_HOWTO (148),
- EMPTY_HOWTO (149),
- EMPTY_HOWTO (150),
- EMPTY_HOWTO (151),
- EMPTY_HOWTO (152),
- EMPTY_HOWTO (153),
- EMPTY_HOWTO (154),
- EMPTY_HOWTO (155),
- EMPTY_HOWTO (156),
- EMPTY_HOWTO (157),
- EMPTY_HOWTO (158),
- EMPTY_HOWTO (159),
-
- HOWTO (R_SH_GOT32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_GOT32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_PLT32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_PLT32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- true), /* pcrel_offset */
-
- HOWTO (R_SH_COPY, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_COPY", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_GLOB_DAT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_GLOB_DAT", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_JMP_SLOT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_JMP_SLOT", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_RELATIVE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_RELATIVE", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_GOTOFF, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_GOTOFF", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_GOTPC, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_GOTPC", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- true), /* pcrel_offset */
-
- HOWTO (R_SH_GOTPLT32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* */
- "R_SH_GOTPLT32", /* name */
- false, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
-#ifdef INCLUDE_SHMEDIA
- /* Used in MOVI and SHORI (x & 65536). */
- HOWTO (R_SH_GOT_LOW16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOT_LOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 16) & 65536). */
- HOWTO (R_SH_GOT_MEDLOW16, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOT_MEDLOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 32) & 65536). */
- HOWTO (R_SH_GOT_MEDHI16, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOT_MEDHI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 48) & 65536). */
- HOWTO (R_SH_GOT_HI16, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOT_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (x & 65536). */
- HOWTO (R_SH_GOTPLT_LOW16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPLT_LOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 16) & 65536). */
- HOWTO (R_SH_GOTPLT_MEDLOW16, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPLT_MEDLOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 32) & 65536). */
- HOWTO (R_SH_GOTPLT_MEDHI16, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPLT_MEDHI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 48) & 65536). */
- HOWTO (R_SH_GOTPLT_HI16, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPLT_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (x & 65536). */
- HOWTO (R_SH_PLT_LOW16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_PLT_LOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 16) & 65536). */
- HOWTO (R_SH_PLT_MEDLOW16, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_PLT_MEDLOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 32) & 65536). */
- HOWTO (R_SH_PLT_MEDHI16, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_PLT_MEDHI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 48) & 65536). */
- HOWTO (R_SH_PLT_HI16, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_PLT_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (x & 65536). */
- HOWTO (R_SH_GOTOFF_LOW16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTOFF_LOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 16) & 65536). */
- HOWTO (R_SH_GOTOFF_MEDLOW16, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTOFF_MEDLOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 32) & 65536). */
- HOWTO (R_SH_GOTOFF_MEDHI16, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTOFF_MEDHI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 48) & 65536). */
- HOWTO (R_SH_GOTOFF_HI16, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTOFF_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (x & 65536). */
- HOWTO (R_SH_GOTPC_LOW16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPC_LOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 16) & 65536). */
- HOWTO (R_SH_GOTPC_MEDLOW16, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPC_MEDLOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 32) & 65536). */
- HOWTO (R_SH_GOTPC_MEDHI16, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPC_MEDHI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 48) & 65536). */
- HOWTO (R_SH_GOTPC_HI16, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPC_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in LD.L, FLD.S et al. */
- HOWTO (R_SH_GOT10BY4, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 12, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOT10BY4", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in LD.L, FLD.S et al. */
- HOWTO (R_SH_GOTPLT10BY4, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 12, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPLT10BY4", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in FLD.D, FST.P et al. */
- HOWTO (R_SH_GOT10BY8, /* type */
- 3, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 13, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOT10BY8", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in FLD.D, FST.P et al. */
- HOWTO (R_SH_GOTPLT10BY8, /* type */
- 3, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 13, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GOTPLT10BY8", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_COPY64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_COPY64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- ((bfd_vma) 0) - 1, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_GLOB_DAT64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_GLOB_DAT64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- ((bfd_vma) 0) - 1, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_JMP_SLOT64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_JMP_SLOT64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- ((bfd_vma) 0) - 1, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_SH_RELATIVE64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_RELATIVE64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- ((bfd_vma) 0) - 1, /* dst_mask */
- false), /* pcrel_offset */
-
- EMPTY_HOWTO (197),
- EMPTY_HOWTO (198),
- EMPTY_HOWTO (199),
- EMPTY_HOWTO (200),
- EMPTY_HOWTO (201),
- EMPTY_HOWTO (202),
- EMPTY_HOWTO (203),
- EMPTY_HOWTO (204),
- EMPTY_HOWTO (205),
- EMPTY_HOWTO (206),
- EMPTY_HOWTO (207),
- EMPTY_HOWTO (208),
- EMPTY_HOWTO (209),
- EMPTY_HOWTO (210),
- EMPTY_HOWTO (211),
- EMPTY_HOWTO (212),
- EMPTY_HOWTO (213),
- EMPTY_HOWTO (214),
- EMPTY_HOWTO (215),
- EMPTY_HOWTO (216),
- EMPTY_HOWTO (217),
- EMPTY_HOWTO (218),
- EMPTY_HOWTO (219),
- EMPTY_HOWTO (220),
- EMPTY_HOWTO (221),
- EMPTY_HOWTO (222),
- EMPTY_HOWTO (223),
- EMPTY_HOWTO (224),
- EMPTY_HOWTO (225),
- EMPTY_HOWTO (226),
- EMPTY_HOWTO (227),
- EMPTY_HOWTO (228),
- EMPTY_HOWTO (229),
- EMPTY_HOWTO (230),
- EMPTY_HOWTO (231),
- EMPTY_HOWTO (232),
- EMPTY_HOWTO (233),
- EMPTY_HOWTO (234),
- EMPTY_HOWTO (235),
- EMPTY_HOWTO (236),
- EMPTY_HOWTO (237),
- EMPTY_HOWTO (238),
- EMPTY_HOWTO (239),
- EMPTY_HOWTO (240),
- EMPTY_HOWTO (241),
-
- /* Relocations for SHmedia code. None of these are partial_inplace or
- use the field being relocated (except R_SH_PT_16). */
-
- /* The assembler will generate this reloc before a block of SHmedia
- instructions. A section should be processed as assuming it contains
- data, unless this reloc is seen. Note that a block of SHcompact
- instructions are instead preceded by R_SH_CODE.
- This is currently not implemented, but should be used for SHmedia
- linker relaxation. */
- HOWTO (R_SH_SHMEDIA_CODE, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- sh_elf_ignore_reloc, /* special_function */
- "R_SH_SHMEDIA_CODE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* The assembler will generate this reloc at a PTA or PTB instruction,
- and the linker checks the right type of target, or changes a PTA to a
- PTB, if the original insn was PT. */
- HOWTO (R_SH_PT_16, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 18, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_PT_16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in unexpanded MOVI. */
- HOWTO (R_SH_IMMS16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMMS16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in SHORI. */
- HOWTO (R_SH_IMMU16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_unsigned, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMMU16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (x & 65536). */
- HOWTO (R_SH_IMM_LOW16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_LOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x - $) & 65536). */
- HOWTO (R_SH_IMM_LOW16_PCREL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_LOW16_PCREL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 16) & 65536). */
- HOWTO (R_SH_IMM_MEDLOW16, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_MEDLOW16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (((x - $) >> 16) & 65536). */
- HOWTO (R_SH_IMM_MEDLOW16_PCREL, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_MEDLOW16_PCREL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 32) & 65536). */
- HOWTO (R_SH_IMM_MEDHI16, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_MEDHI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (((x - $) >> 32) & 65536). */
- HOWTO (R_SH_IMM_MEDHI16_PCREL, /* type */
- 32, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_MEDHI16_PCREL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* Used in MOVI and SHORI ((x >> 48) & 65536). */
- HOWTO (R_SH_IMM_HI16, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Used in MOVI and SHORI (((x - $) >> 48) & 65536). */
- HOWTO (R_SH_IMM_HI16_PCREL, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_IMM_HI16_PCREL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x3fffc00, /* dst_mask */
- true), /* pcrel_offset */
-
- /* For the .uaquad pseudo. */
- HOWTO (R_SH_64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- ((bfd_vma) 0) - 1, /* dst_mask */
- false), /* pcrel_offset */
-
- /* For the .uaquad pseudo, (x - $). */
- HOWTO (R_SH_64_PCREL, /* type */
- 48, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- true, /* pc_relative */
- 10, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_SH_64_PCREL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- ((bfd_vma) 0) - 1, /* dst_mask */
- true), /* pcrel_offset */
-
-#endif
-};
-
-static bfd_reloc_status_type
-sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
- symbol_section, start, end)
- int r_type ATTRIBUTE_UNUSED;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- bfd_vma addr;
- asection *symbol_section;
- bfd_vma start, end;
-{
- static bfd_vma last_addr;
- static asection *last_symbol_section;
- bfd_byte *start_ptr, *ptr, *last_ptr;
- int diff, cum_diff;
- bfd_signed_vma x;
- int insn;
-
- /* Sanity check the address. */
- if (addr > input_section->_raw_size)
- return bfd_reloc_outofrange;
-
- /* We require the start and end relocations to be processed consecutively -
- although we allow then to be processed forwards or backwards. */
- if (! last_addr)
- {
- last_addr = addr;
- last_symbol_section = symbol_section;
- return bfd_reloc_ok;
- }
- if (last_addr != addr)
- abort ();
- last_addr = 0;
-
- if (! symbol_section || last_symbol_section != symbol_section || end < start)
- return bfd_reloc_outofrange;
-
- /* Get the symbol_section contents. */
- if (symbol_section != input_section)
- {
- if (elf_section_data (symbol_section)->this_hdr.contents != NULL)
- contents = elf_section_data (symbol_section)->this_hdr.contents;
- else
- {
- contents = (bfd_byte *) bfd_malloc (symbol_section->_raw_size);
- if (contents == NULL)
- return bfd_reloc_outofrange;
- if (! bfd_get_section_contents (input_bfd, symbol_section, contents,
- (file_ptr) 0,
- symbol_section->_raw_size))
- {
- free (contents);
- return bfd_reloc_outofrange;
- }
- }
- }
-#define IS_PPI(PTR) ((bfd_get_16 (input_bfd, (PTR)) & 0xfc00) == 0xf800)
- start_ptr = contents + start;
- for (cum_diff = -6, ptr = contents + end; cum_diff < 0 && ptr > start_ptr;)
- {
- for (last_ptr = ptr, ptr -= 4; ptr >= start_ptr && IS_PPI (ptr);)
- ptr -= 2;
- ptr += 2;
- diff = (last_ptr - ptr) >> 1;
- cum_diff += diff & 1;
- cum_diff += diff;
- }
- /* Calculate the start / end values to load into rs / re minus four -
- so that will cancel out the four we would otherwise have to add to
- addr to get the value to subtract in order to get relative addressing. */
- if (cum_diff >= 0)
- {
- start -= 4;
- end = (ptr + cum_diff * 2) - contents;
- }
- else
- {
- bfd_vma start0 = start - 4;
-
- while (start0 && IS_PPI (contents + start0))
- start0 -= 2;
- start0 = start - 2 - ((start - start0) & 2);
- start = start0 - cum_diff - 2;
- end = start0;
- }
-
- if (contents != NULL
- && elf_section_data (symbol_section)->this_hdr.contents != contents)
- free (contents);
-
- insn = bfd_get_16 (input_bfd, contents + addr);
-
- x = (insn & 0x200 ? end : start) - addr;
- if (input_section != symbol_section)
- x += ((symbol_section->output_section->vma + symbol_section->output_offset)
- - (input_section->output_section->vma
- + input_section->output_offset));
- x >>= 1;
- if (x < -128 || x > 127)
- return bfd_reloc_overflow;
-
- x = (insn & ~0xff) | (x & 0xff);
- bfd_put_16 (input_bfd, (bfd_vma) x, contents + addr);
-
- return bfd_reloc_ok;
-}
-
-/* This function is used for normal relocs. This used to be like the COFF
- function, and is almost certainly incorrect for other ELF targets. */
-
-static bfd_reloc_status_type
-sh_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol_in;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- unsigned long insn;
- bfd_vma sym_value;
- enum elf_sh_reloc_type r_type;
- bfd_vma addr = reloc_entry->address;
- bfd_byte *hit_data = addr + (bfd_byte *) data;
-
- r_type = (enum elf_sh_reloc_type) reloc_entry->howto->type;
-
- if (output_bfd != NULL)
- {
- /* Partial linking--do nothing. */
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* Almost all relocs have to do with relaxing. If any work must be
- done for them, it has been done in sh_relax_section. */
- if (r_type == R_SH_IND12W && (symbol_in->flags & BSF_LOCAL) != 0)
- return bfd_reloc_ok;
-
- if (symbol_in != NULL
- && bfd_is_und_section (symbol_in->section))
- return bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol_in->section))
- sym_value = 0;
- else
- sym_value = (symbol_in->value +
- symbol_in->section->output_section->vma +
- symbol_in->section->output_offset);
-
- switch (r_type)
- {
- case R_SH_DIR32:
- insn = bfd_get_32 (abfd, hit_data);
- insn += sym_value + reloc_entry->addend;
- bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
- break;
- case R_SH_IND12W:
- insn = bfd_get_16 (abfd, hit_data);
- sym_value += reloc_entry->addend;
- sym_value -= (input_section->output_section->vma
- + input_section->output_offset
- + addr
- + 4);
- sym_value += (insn & 0xfff) << 1;
- if (insn & 0x800)
- sym_value -= 0x1000;
- insn = (insn & 0xf000) | (sym_value & 0xfff);
- bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
- if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
- return bfd_reloc_overflow;
- break;
- default:
- abort ();
- break;
- }
-
- return bfd_reloc_ok;
-}
-
-/* This function is used for relocs which are only used for relaxing,
- which the linker should otherwise ignore. */
-
-static bfd_reloc_status_type
-sh_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol ATTRIBUTE_UNUSED;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- if (output_bfd != NULL)
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
-}
-
-/* This structure is used to map BFD reloc codes to SH ELF relocs. */
-
-struct elf_reloc_map
-{
- bfd_reloc_code_real_type bfd_reloc_val;
- unsigned char elf_reloc_val;
-};
-
-/* An array mapping BFD reloc codes to SH ELF relocs. */
-
-static const struct elf_reloc_map sh_reloc_map[] =
-{
- { BFD_RELOC_NONE, R_SH_NONE },
- { BFD_RELOC_32, R_SH_DIR32 },
- { BFD_RELOC_CTOR, R_SH_DIR32 },
- { BFD_RELOC_32_PCREL, R_SH_REL32 },
- { BFD_RELOC_SH_PCDISP8BY2, R_SH_DIR8WPN },
- { BFD_RELOC_SH_PCDISP12BY2, R_SH_IND12W },
- { BFD_RELOC_SH_PCRELIMM8BY2, R_SH_DIR8WPZ },
- { BFD_RELOC_SH_PCRELIMM8BY4, R_SH_DIR8WPL },
- { BFD_RELOC_8_PCREL, R_SH_SWITCH8 },
- { BFD_RELOC_SH_SWITCH16, R_SH_SWITCH16 },
- { BFD_RELOC_SH_SWITCH32, R_SH_SWITCH32 },
- { BFD_RELOC_SH_USES, R_SH_USES },
- { BFD_RELOC_SH_COUNT, R_SH_COUNT },
- { BFD_RELOC_SH_ALIGN, R_SH_ALIGN },
- { BFD_RELOC_SH_CODE, R_SH_CODE },
- { BFD_RELOC_SH_DATA, R_SH_DATA },
- { BFD_RELOC_SH_LABEL, R_SH_LABEL },
- { BFD_RELOC_VTABLE_INHERIT, R_SH_GNU_VTINHERIT },
- { BFD_RELOC_VTABLE_ENTRY, R_SH_GNU_VTENTRY },
- { BFD_RELOC_SH_LOOP_START, R_SH_LOOP_START },
- { BFD_RELOC_SH_LOOP_END, R_SH_LOOP_END },
- { BFD_RELOC_32_GOT_PCREL, R_SH_GOT32 },
- { BFD_RELOC_32_PLT_PCREL, R_SH_PLT32 },
- { BFD_RELOC_SH_COPY, R_SH_COPY },
- { BFD_RELOC_SH_GLOB_DAT, R_SH_GLOB_DAT },
- { BFD_RELOC_SH_JMP_SLOT, R_SH_JMP_SLOT },
- { BFD_RELOC_SH_RELATIVE, R_SH_RELATIVE },
- { BFD_RELOC_32_GOTOFF, R_SH_GOTOFF },
- { BFD_RELOC_SH_GOTPC, R_SH_GOTPC },
- { BFD_RELOC_SH_GOTPLT32, R_SH_GOTPLT32 },
-#ifdef INCLUDE_SHMEDIA
- { BFD_RELOC_SH_GOT_LOW16, R_SH_GOT_LOW16 },
- { BFD_RELOC_SH_GOT_MEDLOW16, R_SH_GOT_MEDLOW16 },
- { BFD_RELOC_SH_GOT_MEDHI16, R_SH_GOT_MEDHI16 },
- { BFD_RELOC_SH_GOT_HI16, R_SH_GOT_HI16 },
- { BFD_RELOC_SH_GOTPLT_LOW16, R_SH_GOTPLT_LOW16 },
- { BFD_RELOC_SH_GOTPLT_MEDLOW16, R_SH_GOTPLT_MEDLOW16 },
- { BFD_RELOC_SH_GOTPLT_MEDHI16, R_SH_GOTPLT_MEDHI16 },
- { BFD_RELOC_SH_GOTPLT_HI16, R_SH_GOTPLT_HI16 },
- { BFD_RELOC_SH_PLT_LOW16, R_SH_PLT_LOW16 },
- { BFD_RELOC_SH_PLT_MEDLOW16, R_SH_PLT_MEDLOW16 },
- { BFD_RELOC_SH_PLT_MEDHI16, R_SH_PLT_MEDHI16 },
- { BFD_RELOC_SH_PLT_HI16, R_SH_PLT_HI16 },
- { BFD_RELOC_SH_GOTOFF_LOW16, R_SH_GOTOFF_LOW16 },
- { BFD_RELOC_SH_GOTOFF_MEDLOW16, R_SH_GOTOFF_MEDLOW16 },
- { BFD_RELOC_SH_GOTOFF_MEDHI16, R_SH_GOTOFF_MEDHI16 },
- { BFD_RELOC_SH_GOTOFF_HI16, R_SH_GOTOFF_HI16 },
- { BFD_RELOC_SH_GOTPC_LOW16, R_SH_GOTPC_LOW16 },
- { BFD_RELOC_SH_GOTPC_MEDLOW16, R_SH_GOTPC_MEDLOW16 },
- { BFD_RELOC_SH_GOTPC_MEDHI16, R_SH_GOTPC_MEDHI16 },
- { BFD_RELOC_SH_GOTPC_HI16, R_SH_GOTPC_HI16 },
- { BFD_RELOC_SH_COPY64, R_SH_COPY64 },
- { BFD_RELOC_SH_GLOB_DAT64, R_SH_GLOB_DAT64 },
- { BFD_RELOC_SH_JMP_SLOT64, R_SH_JMP_SLOT64 },
- { BFD_RELOC_SH_RELATIVE64, R_SH_RELATIVE64 },
- { BFD_RELOC_SH_GOT10BY4, R_SH_GOT10BY4 },
- { BFD_RELOC_SH_GOT10BY8, R_SH_GOT10BY8 },
- { BFD_RELOC_SH_GOTPLT10BY4, R_SH_GOTPLT10BY4 },
- { BFD_RELOC_SH_GOTPLT10BY8, R_SH_GOTPLT10BY8 },
- { BFD_RELOC_SH_PT_16, R_SH_PT_16 },
- { BFD_RELOC_SH_SHMEDIA_CODE, R_SH_SHMEDIA_CODE },
- { BFD_RELOC_SH_IMMU5, R_SH_DIR5U },
- { BFD_RELOC_SH_IMMS6, R_SH_DIR6S },
- { BFD_RELOC_SH_IMMU6, R_SH_DIR6U },
- { BFD_RELOC_SH_IMMS10, R_SH_DIR10S },
- { BFD_RELOC_SH_IMMS10BY2, R_SH_DIR10SW },
- { BFD_RELOC_SH_IMMS10BY4, R_SH_DIR10SL },
- { BFD_RELOC_SH_IMMS10BY8, R_SH_DIR10SQ },
- { BFD_RELOC_SH_IMMS16, R_SH_IMMS16 },
- { BFD_RELOC_SH_IMMU16, R_SH_IMMU16 },
- { BFD_RELOC_SH_IMM_LOW16, R_SH_IMM_LOW16 },
- { BFD_RELOC_SH_IMM_LOW16_PCREL, R_SH_IMM_LOW16_PCREL },
- { BFD_RELOC_SH_IMM_MEDLOW16, R_SH_IMM_MEDLOW16 },
- { BFD_RELOC_SH_IMM_MEDLOW16_PCREL, R_SH_IMM_MEDLOW16_PCREL },
- { BFD_RELOC_SH_IMM_MEDHI16, R_SH_IMM_MEDHI16 },
- { BFD_RELOC_SH_IMM_MEDHI16_PCREL, R_SH_IMM_MEDHI16_PCREL },
- { BFD_RELOC_SH_IMM_HI16, R_SH_IMM_HI16 },
- { BFD_RELOC_SH_IMM_HI16_PCREL, R_SH_IMM_HI16_PCREL },
- { BFD_RELOC_64, R_SH_64 },
- { BFD_RELOC_64_PCREL, R_SH_64_PCREL },
-#endif /* not INCLUDE_SHMEDIA */
-};
-
-/* Given a BFD reloc code, return the howto structure for the
- corresponding SH ELf reloc. */
-
-static reloc_howto_type *
-sh_elf_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- unsigned int i;
-
- for (i = 0; i < sizeof (sh_reloc_map) / sizeof (struct elf_reloc_map); i++)
- {
- if (sh_reloc_map[i].bfd_reloc_val == code)
- return &sh_elf_howto_table[(int) sh_reloc_map[i].elf_reloc_val];
- }
-
- return NULL;
-}
-
-/* Given an ELF reloc, fill in the howto field of a relent. */
-
-static void
-sh_elf_info_to_howto (abfd, cache_ptr, dst)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *cache_ptr;
- Elf_Internal_Rela *dst;
-{
- unsigned int r;
-
- r = ELF32_R_TYPE (dst->r_info);
-
- BFD_ASSERT (r < (unsigned int) R_SH_max);
- BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC || r > R_SH_LAST_INVALID_RELOC);
- BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_2 || r > R_SH_LAST_INVALID_RELOC_2);
- BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_3 || r > R_SH_LAST_INVALID_RELOC_3);
- BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_4 || r > R_SH_LAST_INVALID_RELOC_4);
-
- cache_ptr->howto = &sh_elf_howto_table[r];
-}
-
-/* This function handles relaxing for SH ELF. See the corresponding
- function in coff-sh.c for a description of what this does. FIXME:
- There is a lot of duplication here between this code and the COFF
- specific code. The format of relocs and symbols is wound deeply
- into this code, but it would still be better if the duplication
- could be eliminated somehow. Note in particular that although both
- functions use symbols like R_SH_CODE, those symbols have different
- values; in coff-sh.c they come from include/coff/sh.h, whereas here
- they come from enum elf_sh_reloc_type in include/elf/sh.h. */
-
-static boolean
-sh_elf_relax_section (abfd, sec, link_info, again)
- bfd *abfd;
- asection *sec;
- struct bfd_link_info *link_info;
- boolean *again;
-{
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Rela *internal_relocs;
- boolean have_code;
- Elf_Internal_Rela *irel, *irelend;
- bfd_byte *contents = NULL;
- Elf_Internal_Sym *isymbuf = NULL;
-
- *again = false;
-
- if (link_info->relocateable
- || (sec->flags & SEC_RELOC) == 0
- || sec->reloc_count == 0)
- return true;
-
-#ifdef INCLUDE_SHMEDIA
- if (elf_section_data (sec)->this_hdr.sh_flags
- & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
- {
- return true;
- }
-#endif
-
- /* 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;
-
- internal_relocs = (_bfd_elf32_link_read_relocs
- (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
- link_info->keep_memory));
- if (internal_relocs == NULL)
- goto error_return;
-
- have_code = false;
-
- irelend = internal_relocs + sec->reloc_count;
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- bfd_vma laddr, paddr, symval;
- unsigned short insn;
- Elf_Internal_Rela *irelfn, *irelscan, *irelcount;
- bfd_signed_vma foff;
-
- if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_CODE)
- have_code = true;
-
- if (ELF32_R_TYPE (irel->r_info) != (int) R_SH_USES)
- continue;
-
- /* Get the section contents. */
- if (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;
-
- if (! bfd_get_section_contents (abfd, sec, contents,
- (file_ptr) 0, sec->_raw_size))
- goto error_return;
- }
- }
-
- /* The r_addend field of the R_SH_USES reloc will point us to
- the register load. The 4 is because the r_addend field is
- computed as though it were a jump offset, which are based
- from 4 bytes after the jump instruction. */
- laddr = irel->r_offset + 4 + irel->r_addend;
- if (laddr >= sec->_raw_size)
- {
- (*_bfd_error_handler) (_("%s: 0x%lx: warning: bad R_SH_USES offset"),
- bfd_archive_filename (abfd),
- (unsigned long) irel->r_offset);
- continue;
- }
- insn = bfd_get_16 (abfd, contents + laddr);
-
- /* If the instruction is not mov.l NN,rN, we don't know what to
- do. */
- if ((insn & 0xf000) != 0xd000)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x"),
- bfd_archive_filename (abfd), (unsigned long) irel->r_offset, insn));
- continue;
- }
-
- /* Get the address from which the register is being loaded. The
- displacement in the mov.l instruction is quadrupled. It is a
- displacement from four bytes after the movl instruction, but,
- before adding in the PC address, two least significant bits
- of the PC are cleared. We assume that the section is aligned
- on a four byte boundary. */
- paddr = insn & 0xff;
- paddr *= 4;
- paddr += (laddr + 4) &~ (bfd_vma) 3;
- if (paddr >= sec->_raw_size)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: warning: bad R_SH_USES load offset"),
- bfd_archive_filename (abfd), (unsigned long) irel->r_offset));
- continue;
- }
-
- /* Get the reloc for the address from which the register is
- being loaded. This reloc will tell us which function is
- actually being called. */
- for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
- if (irelfn->r_offset == paddr
- && ELF32_R_TYPE (irelfn->r_info) == (int) R_SH_DIR32)
- break;
- if (irelfn >= irelend)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: warning: could not find expected reloc"),
- bfd_archive_filename (abfd), (unsigned long) paddr));
- continue;
- }
-
- /* Read this BFD's symbols if we haven't done so already. */
- if (isymbuf == NULL && symtab_hdr->sh_info != 0)
- {
- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (isymbuf == NULL)
- isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
- if (isymbuf == NULL)
- goto error_return;
- }
-
- /* Get the value of the symbol referred to by the reloc. */
- if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
- {
- /* A local symbol. */
- Elf_Internal_Sym *isym;
-
- isym = isymbuf + ELF32_R_SYM (irelfn->r_info);
- if (isym->st_shndx
- != (unsigned int) _bfd_elf_section_from_bfd_section (abfd, sec))
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: warning: symbol in unexpected section"),
- bfd_archive_filename (abfd), (unsigned long) paddr));
- continue;
- }
-
- symval = (isym->st_value
- + sec->output_section->vma
- + sec->output_offset);
- }
- else
- {
- unsigned long indx;
- struct elf_link_hash_entry *h;
-
- indx = ELF32_R_SYM (irelfn->r_info) - symtab_hdr->sh_info;
- h = elf_sym_hashes (abfd)[indx];
- BFD_ASSERT (h != NULL);
- if (h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak)
- {
- /* This appears to be a reference to an undefined
- symbol. Just ignore it--it will be caught by the
- regular reloc processing. */
- continue;
- }
-
- symval = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
-
- symval += bfd_get_32 (abfd, contents + paddr);
-
- /* See if this function call can be shortened. */
- foff = (symval
- - (irel->r_offset
- + sec->output_section->vma
- + sec->output_offset
- + 4));
- if (foff < -0x1000 || foff >= 0x1000)
- {
- /* After all that work, we can't shorten this function call. */
- continue;
- }
-
- /* Shorten the function call. */
-
- /* For simplicity of coding, we are going to modify the section
- contents, the section relocs, and the BFD symbol table. We
- must tell the rest of the code not to free up this
- information. It would be possible to instead create a table
- of changes which have to be made, as is done in coff-mips.c;
- that would be more work, but would require less memory when
- the linker is run. */
-
- elf_section_data (sec)->relocs = internal_relocs;
- elf_section_data (sec)->this_hdr.contents = contents;
- symtab_hdr->contents = (unsigned char *) isymbuf;
-
- /* Replace the jsr with a bsr. */
-
- /* Change the R_SH_USES reloc into an R_SH_IND12W reloc, and
- replace the jsr with a bsr. */
- irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irelfn->r_info), R_SH_IND12W);
- if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
- {
- /* If this needs to be changed because of future relaxing,
- it will be handled here like other internal IND12W
- relocs. */
- bfd_put_16 (abfd,
- (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff),
- contents + irel->r_offset);
- }
- else
- {
- /* We can't fully resolve this yet, because the external
- symbol value may be changed by future relaxing. We let
- the final link phase handle it. */
- bfd_put_16 (abfd, (bfd_vma) 0xb000, contents + irel->r_offset);
- }
-
- /* See if there is another R_SH_USES reloc referring to the same
- register load. */
- for (irelscan = internal_relocs; irelscan < irelend; irelscan++)
- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_USES
- && laddr == irelscan->r_offset + 4 + irelscan->r_addend)
- break;
- if (irelscan < irelend)
- {
- /* Some other function call depends upon this register load,
- and we have not yet converted that function call.
- Indeed, we may never be able to convert it. There is
- nothing else we can do at this point. */
- continue;
- }
-
- /* Look for a R_SH_COUNT reloc on the location where the
- function address is stored. Do this before deleting any
- bytes, to avoid confusion about the address. */
- for (irelcount = internal_relocs; irelcount < irelend; irelcount++)
- if (irelcount->r_offset == paddr
- && ELF32_R_TYPE (irelcount->r_info) == (int) R_SH_COUNT)
- break;
-
- /* Delete the register load. */
- if (! sh_elf_relax_delete_bytes (abfd, sec, laddr, 2))
- goto error_return;
-
- /* That will change things, so, just in case it permits some
- other function call to come within range, we should relax
- again. Note that this is not required, and it may be slow. */
- *again = true;
-
- /* Now check whether we got a COUNT reloc. */
- if (irelcount >= irelend)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: warning: could not find expected COUNT reloc"),
- bfd_archive_filename (abfd), (unsigned long) paddr));
- continue;
- }
-
- /* The number of uses is stored in the r_addend field. We've
- just deleted one. */
- if (irelcount->r_addend == 0)
- {
- ((*_bfd_error_handler) (_("%s: 0x%lx: warning: bad count"),
- bfd_archive_filename (abfd),
- (unsigned long) paddr));
- continue;
- }
-
- --irelcount->r_addend;
-
- /* If there are no more uses, we can delete the address. Reload
- the address from irelfn, in case it was changed by the
- previous call to sh_elf_relax_delete_bytes. */
- if (irelcount->r_addend == 0)
- {
- if (! sh_elf_relax_delete_bytes (abfd, sec, irelfn->r_offset, 4))
- goto error_return;
- }
-
- /* We've done all we can with that function call. */
- }
-
- /* Look for load and store instructions that we can align on four
- byte boundaries. */
- if (have_code)
- {
- boolean swapped;
-
- /* Get the section contents. */
- if (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;
-
- if (! bfd_get_section_contents (abfd, sec, contents,
- (file_ptr) 0, sec->_raw_size))
- goto error_return;
- }
- }
-
- if (! sh_elf_align_loads (abfd, sec, internal_relocs, contents,
- &swapped))
- goto error_return;
-
- if (swapped)
- {
- elf_section_data (sec)->relocs = internal_relocs;
- elf_section_data (sec)->this_hdr.contents = contents;
- symtab_hdr->contents = (unsigned char *) isymbuf;
- }
- }
-
- if (isymbuf != NULL
- && symtab_hdr->contents != (unsigned char *) isymbuf)
- {
- if (! link_info->keep_memory)
- free (isymbuf);
- else
- {
- /* Cache the symbols for elf_link_input_bfd. */
- symtab_hdr->contents = (unsigned char *) isymbuf;
- }
- }
-
- if (contents != NULL
- && elf_section_data (sec)->this_hdr.contents != contents)
- {
- if (! link_info->keep_memory)
- free (contents);
- else
- {
- /* Cache the section contents for elf_link_input_bfd. */
- elf_section_data (sec)->this_hdr.contents = contents;
- }
- }
-
- if (internal_relocs != NULL
- && elf_section_data (sec)->relocs != internal_relocs)
- free (internal_relocs);
-
- return true;
-
- error_return:
- if (isymbuf != NULL
- && symtab_hdr->contents != (unsigned char *) isymbuf)
- free (isymbuf);
- if (contents != NULL
- && elf_section_data (sec)->this_hdr.contents != contents)
- free (contents);
- if (internal_relocs != NULL
- && elf_section_data (sec)->relocs != internal_relocs)
- free (internal_relocs);
-
- return false;
-}
-
-/* Delete some bytes from a section while relaxing. FIXME: There is a
- lot of duplication between this function and sh_relax_delete_bytes
- in coff-sh.c. */
-
-static boolean
-sh_elf_relax_delete_bytes (abfd, sec, addr, count)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
- int count;
-{
- Elf_Internal_Shdr *symtab_hdr;
- unsigned int sec_shndx;
- bfd_byte *contents;
- Elf_Internal_Rela *irel, *irelend;
- Elf_Internal_Rela *irelalign;
- bfd_vma toaddr;
- Elf_Internal_Sym *isymbuf, *isym, *isymend;
- struct elf_link_hash_entry **sym_hashes;
- struct elf_link_hash_entry **end_hashes;
- unsigned int symcount;
- asection *o;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
-
- sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
-
- contents = elf_section_data (sec)->this_hdr.contents;
-
- /* The deletion must stop at the next ALIGN reloc for an aligment
- power larger than the number of bytes we are deleting. */
-
- irelalign = NULL;
- toaddr = sec->_cooked_size;
-
- irel = elf_section_data (sec)->relocs;
- irelend = irel + sec->reloc_count;
- for (; irel < irelend; irel++)
- {
- if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_ALIGN
- && irel->r_offset > addr
- && count < (1 << irel->r_addend))
- {
- irelalign = irel;
- toaddr = irel->r_offset;
- break;
- }
- }
-
- /* Actually delete the bytes. */
- memmove (contents + addr, contents + addr + count,
- (size_t) (toaddr - addr - count));
- if (irelalign == NULL)
- sec->_cooked_size -= count;
- else
- {
- int i;
-
-#define NOP_OPCODE (0x0009)
-
- BFD_ASSERT ((count & 1) == 0);
- for (i = 0; i < count; i += 2)
- bfd_put_16 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
- }
-
- /* Adjust all the relocs. */
- for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
- {
- bfd_vma nraddr, stop;
- bfd_vma start = 0;
- int insn = 0;
- int off, adjust, oinsn;
- bfd_signed_vma voff = 0;
- boolean overflow;
-
- /* Get the new reloc address. */
- nraddr = irel->r_offset;
- if ((irel->r_offset > addr
- && irel->r_offset < toaddr)
- || (ELF32_R_TYPE (irel->r_info) == (int) R_SH_ALIGN
- && irel->r_offset == toaddr))
- nraddr -= count;
-
- /* See if this reloc was for the bytes we have deleted, in which
- case we no longer care about it. Don't delete relocs which
- represent addresses, though. */
- if (irel->r_offset >= addr
- && irel->r_offset < addr + count
- && ELF32_R_TYPE (irel->r_info) != (int) R_SH_ALIGN
- && ELF32_R_TYPE (irel->r_info) != (int) R_SH_CODE
- && ELF32_R_TYPE (irel->r_info) != (int) R_SH_DATA
- && ELF32_R_TYPE (irel->r_info) != (int) R_SH_LABEL)
- irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- (int) R_SH_NONE);
-
- /* If this is a PC relative reloc, see if the range it covers
- includes the bytes we have deleted. */
- switch ((enum elf_sh_reloc_type) ELF32_R_TYPE (irel->r_info))
- {
- default:
- break;
-
- case R_SH_DIR8WPN:
- case R_SH_IND12W:
- case R_SH_DIR8WPZ:
- case R_SH_DIR8WPL:
- start = irel->r_offset;
- insn = bfd_get_16 (abfd, contents + nraddr);
- break;
- }
-
- switch ((enum elf_sh_reloc_type) ELF32_R_TYPE (irel->r_info))
- {
- default:
- start = stop = addr;
- break;
-
- case R_SH_DIR32:
- /* If this reloc is against a symbol defined in this
- section, and the symbol will not be adjusted below, we
- must check the addend to see it will put the value in
- range to be adjusted, and hence must be changed. */
- if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
- {
- isym = isymbuf + ELF32_R_SYM (irel->r_info);
- if (isym->st_shndx == sec_shndx
- && (isym->st_value <= addr
- || isym->st_value >= toaddr))
- {
- bfd_vma val;
-
- val = bfd_get_32 (abfd, contents + nraddr);
- val += isym->st_value;
- if (val > addr && val < toaddr)
- bfd_put_32 (abfd, val - count, contents + nraddr);
- }
- }
- start = stop = addr;
- break;
-
- case R_SH_DIR8WPN:
- off = insn & 0xff;
- if (off & 0x80)
- off -= 0x100;
- stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
- break;
-
- case R_SH_IND12W:
- if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info)
- start = stop = addr;
- else
- {
- off = insn & 0xfff;
- if (off & 0x800)
- off -= 0x1000;
- stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
- }
- break;
-
- case R_SH_DIR8WPZ:
- off = insn & 0xff;
- stop = start + 4 + off * 2;
- break;
-
- case R_SH_DIR8WPL:
- off = insn & 0xff;
- stop = (start & ~(bfd_vma) 3) + 4 + off * 4;
- break;
-
- case R_SH_SWITCH8:
- case R_SH_SWITCH16:
- case R_SH_SWITCH32:
- /* These relocs types represent
- .word L2-L1
- The r_addend field holds the difference between the reloc
- address and L1. That is the start of the reloc, and
- adding in the contents gives us the top. We must adjust
- both the r_offset field and the section contents.
- N.B. in gas / coff bfd, the elf bfd r_addend is called r_offset,
- and the elf bfd r_offset is called r_vaddr. */
-
- stop = irel->r_offset;
- start = (bfd_vma) ((bfd_signed_vma) stop - (long) irel->r_addend);
-
- if (start > addr
- && start < toaddr
- && (stop <= addr || stop >= toaddr))
- irel->r_addend += count;
- else if (stop > addr
- && stop < toaddr
- && (start <= addr || start >= toaddr))
- irel->r_addend -= count;
-
- if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_SWITCH16)
- voff = bfd_get_signed_16 (abfd, contents + nraddr);
- else if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_SWITCH8)
- voff = bfd_get_8 (abfd, contents + nraddr);
- else
- voff = bfd_get_signed_32 (abfd, contents + nraddr);
- stop = (bfd_vma) ((bfd_signed_vma) start + voff);
-
- break;
-
- case R_SH_USES:
- start = irel->r_offset;
- stop = (bfd_vma) ((bfd_signed_vma) start
- + (long) irel->r_addend
- + 4);
- break;
- }
-
- if (start > addr
- && start < toaddr
- && (stop <= addr || stop >= toaddr))
- adjust = count;
- else if (stop > addr
- && stop < toaddr
- && (start <= addr || start >= toaddr))
- adjust = - count;
- else
- adjust = 0;
-
- if (adjust != 0)
- {
- oinsn = insn;
- overflow = false;
- switch ((enum elf_sh_reloc_type) ELF32_R_TYPE (irel->r_info))
- {
- default:
- abort ();
- break;
-
- case R_SH_DIR8WPN:
- case R_SH_DIR8WPZ:
- insn += adjust / 2;
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
- break;
-
- case R_SH_IND12W:
- insn += adjust / 2;
- if ((oinsn & 0xf000) != (insn & 0xf000))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
- break;
-
- case R_SH_DIR8WPL:
- BFD_ASSERT (adjust == count || count >= 4);
- if (count >= 4)
- insn += adjust / 4;
- else
- {
- if ((irel->r_offset & 3) == 0)
- ++insn;
- }
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
- break;
-
- case R_SH_SWITCH8:
- voff += adjust;
- if (voff < 0 || voff >= 0xff)
- overflow = true;
- bfd_put_8 (abfd, voff, contents + nraddr);
- break;
-
- case R_SH_SWITCH16:
- voff += adjust;
- if (voff < - 0x8000 || voff >= 0x8000)
- overflow = true;
- bfd_put_signed_16 (abfd, (bfd_vma) voff, contents + nraddr);
- break;
-
- case R_SH_SWITCH32:
- voff += adjust;
- bfd_put_signed_32 (abfd, (bfd_vma) voff, contents + nraddr);
- break;
-
- case R_SH_USES:
- irel->r_addend += adjust;
- break;
- }
-
- if (overflow)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: fatal: reloc overflow while relaxing"),
- bfd_archive_filename (abfd), (unsigned long) irel->r_offset));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
-
- irel->r_offset = nraddr;
- }
-
- /* Look through all the other sections. If there contain any IMM32
- relocs against internal symbols which we are not going to adjust
- below, we may need to adjust the addends. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- Elf_Internal_Rela *internal_relocs;
- Elf_Internal_Rela *irelscan, *irelscanend;
- bfd_byte *ocontents;
-
- if (o == sec
- || (o->flags & SEC_RELOC) == 0
- || o->reloc_count == 0)
- continue;
-
- /* We always cache the relocs. Perhaps, if info->keep_memory is
- false, we should free them, if we are permitted to, when we
- leave sh_coff_relax_section. */
- internal_relocs = (_bfd_elf32_link_read_relocs
- (abfd, o, (PTR) NULL, (Elf_Internal_Rela *) NULL,
- true));
- if (internal_relocs == NULL)
- return false;
-
- ocontents = NULL;
- irelscanend = internal_relocs + o->reloc_count;
- for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
- {
- /* Dwarf line numbers use R_SH_SWITCH32 relocs. */
- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_SWITCH32)
- {
- bfd_vma start, stop;
- bfd_signed_vma voff;
-
- if (ocontents == NULL)
- {
- if (elf_section_data (o)->this_hdr.contents != NULL)
- ocontents = elf_section_data (o)->this_hdr.contents;
- else
- {
- /* We always cache the section contents.
- Perhaps, if info->keep_memory is false, we
- should free them, if we are permitted to,
- when we leave sh_coff_relax_section. */
- ocontents = (bfd_byte *) bfd_malloc (o->_raw_size);
- if (ocontents == NULL)
- return false;
- if (! bfd_get_section_contents (abfd, o, ocontents,
- (file_ptr) 0,
- o->_raw_size))
- return false;
- elf_section_data (o)->this_hdr.contents = ocontents;
- }
- }
-
- stop = irelscan->r_offset;
- start
- = (bfd_vma) ((bfd_signed_vma) stop - (long) irelscan->r_addend);
-
- /* STOP is in a different section, so it won't change. */
- if (start > addr && start < toaddr)
- irelscan->r_addend += count;
-
- voff = bfd_get_signed_32 (abfd, ocontents + irelscan->r_offset);
- stop = (bfd_vma) ((bfd_signed_vma) start + voff);
-
- if (start > addr
- && start < toaddr
- && (stop <= addr || stop >= toaddr))
- bfd_put_signed_32 (abfd, (bfd_vma) voff + count,
- ocontents + irelscan->r_offset);
- else if (stop > addr
- && stop < toaddr
- && (start <= addr || start >= toaddr))
- bfd_put_signed_32 (abfd, (bfd_vma) voff - count,
- ocontents + irelscan->r_offset);
- }
-
- if (ELF32_R_TYPE (irelscan->r_info) != (int) R_SH_DIR32)
- continue;
-
- if (ELF32_R_SYM (irelscan->r_info) >= symtab_hdr->sh_info)
- continue;
-
-
- isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
- if (isym->st_shndx == sec_shndx
- && (isym->st_value <= addr
- || isym->st_value >= toaddr))
- {
- bfd_vma val;
-
- if (ocontents == NULL)
- {
- if (elf_section_data (o)->this_hdr.contents != NULL)
- ocontents = elf_section_data (o)->this_hdr.contents;
- else
- {
- /* We always cache the section contents.
- Perhaps, if info->keep_memory is false, we
- should free them, if we are permitted to,
- when we leave sh_coff_relax_section. */
- ocontents = (bfd_byte *) bfd_malloc (o->_raw_size);
- if (ocontents == NULL)
- return false;
- if (! bfd_get_section_contents (abfd, o, ocontents,
- (file_ptr) 0,
- o->_raw_size))
- return false;
- elf_section_data (o)->this_hdr.contents = ocontents;
- }
- }
-
- val = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
- val += isym->st_value;
- if (val > addr && val < toaddr)
- bfd_put_32 (abfd, val - count,
- ocontents + irelscan->r_offset);
- }
- }
- }
-
- /* Adjust the local symbols defined in this section. */
- isymend = isymbuf + symtab_hdr->sh_info;
- for (isym = isymbuf; isym < isymend; isym++)
- {
- if (isym->st_shndx == sec_shndx
- && isym->st_value > addr
- && isym->st_value < toaddr)
- isym->st_value -= count;
- }
-
- /* Now adjust the global symbols defined in this section. */
- symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
- - symtab_hdr->sh_info);
- sym_hashes = elf_sym_hashes (abfd);
- end_hashes = sym_hashes + symcount;
- for (; sym_hashes < end_hashes; sym_hashes++)
- {
- struct elf_link_hash_entry *sym_hash = *sym_hashes;
- if ((sym_hash->root.type == bfd_link_hash_defined
- || sym_hash->root.type == bfd_link_hash_defweak)
- && sym_hash->root.u.def.section == sec
- && sym_hash->root.u.def.value > addr
- && sym_hash->root.u.def.value < toaddr)
- {
- sym_hash->root.u.def.value -= count;
- }
- }
-
- /* See if we can move the ALIGN reloc forward. We have adjusted
- r_offset for it already. */
- if (irelalign != NULL)
- {
- bfd_vma alignto, alignaddr;
-
- alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_addend);
- alignaddr = BFD_ALIGN (irelalign->r_offset,
- 1 << irelalign->r_addend);
- if (alignto != alignaddr)
- {
- /* Tail recursion. */
- return sh_elf_relax_delete_bytes (abfd, sec, alignaddr,
- (int) (alignto - alignaddr));
- }
- }
-
- return true;
-}
-
-/* Look for loads and stores which we can align to four byte
- boundaries. This is like sh_align_loads in coff-sh.c. */
-
-static boolean
-sh_elf_align_loads (abfd, sec, internal_relocs, contents, pswapped)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
- Elf_Internal_Rela *internal_relocs;
- bfd_byte *contents ATTRIBUTE_UNUSED;
- boolean *pswapped;
-{
- Elf_Internal_Rela *irel, *irelend;
- bfd_vma *labels = NULL;
- bfd_vma *label, *label_end;
- bfd_size_type amt;
-
- *pswapped = false;
-
- irelend = internal_relocs + sec->reloc_count;
-
- /* Get all the addresses with labels on them. */
- amt = sec->reloc_count;
- amt *= sizeof (bfd_vma);
- labels = (bfd_vma *) bfd_malloc (amt);
- if (labels == NULL)
- goto error_return;
- label_end = labels;
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_LABEL)
- {
- *label_end = irel->r_offset;
- ++label_end;
- }
- }
-
- /* Note that the assembler currently always outputs relocs in
- address order. If that ever changes, this code will need to sort
- the label values and the relocs. */
-
- label = labels;
-
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- bfd_vma start, stop;
-
- if (ELF32_R_TYPE (irel->r_info) != (int) R_SH_CODE)
- continue;
-
- start = irel->r_offset;
-
- for (irel++; irel < irelend; irel++)
- if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_DATA)
- break;
- if (irel < irelend)
- stop = irel->r_offset;
- else
- stop = sec->_cooked_size;
-
- if (! _bfd_sh_align_load_span (abfd, sec, contents, sh_elf_swap_insns,
- (PTR) internal_relocs, &label,
- label_end, start, stop, pswapped))
- goto error_return;
- }
-
- free (labels);
-
- return true;
-
- error_return:
- if (labels != NULL)
- free (labels);
- return false;
-}
-
-/* Swap two SH instructions. This is like sh_swap_insns in coff-sh.c. */
-
-static boolean
-sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
- bfd *abfd;
- asection *sec;
- PTR relocs;
- bfd_byte *contents;
- bfd_vma addr;
-{
- Elf_Internal_Rela *internal_relocs = (Elf_Internal_Rela *) relocs;
- unsigned short i1, i2;
- Elf_Internal_Rela *irel, *irelend;
-
- /* Swap the instructions themselves. */
- i1 = bfd_get_16 (abfd, contents + addr);
- i2 = bfd_get_16 (abfd, contents + addr + 2);
- bfd_put_16 (abfd, (bfd_vma) i2, contents + addr);
- bfd_put_16 (abfd, (bfd_vma) i1, contents + addr + 2);
-
- /* Adjust all reloc addresses. */
- irelend = internal_relocs + sec->reloc_count;
- for (irel = internal_relocs; irel < irelend; irel++)
- {
- enum elf_sh_reloc_type type;
- int add;
-
- /* There are a few special types of relocs that we don't want to
- adjust. These relocs do not apply to the instruction itself,
- but are only associated with the address. */
- type = (enum elf_sh_reloc_type) ELF32_R_TYPE (irel->r_info);
- if (type == R_SH_ALIGN
- || type == R_SH_CODE
- || type == R_SH_DATA
- || type == R_SH_LABEL)
- continue;
-
- /* If an R_SH_USES reloc points to one of the addresses being
- swapped, we must adjust it. It would be incorrect to do this
- for a jump, though, since we want to execute both
- instructions after the jump. (We have avoided swapping
- around a label, so the jump will not wind up executing an
- instruction it shouldn't). */
- if (type == R_SH_USES)
- {
- bfd_vma off;
-
- off = irel->r_offset + 4 + irel->r_addend;
- if (off == addr)
- irel->r_offset += 2;
- else if (off == addr + 2)
- irel->r_offset -= 2;
- }
-
- if (irel->r_offset == addr)
- {
- irel->r_offset += 2;
- add = -2;
- }
- else if (irel->r_offset == addr + 2)
- {
- irel->r_offset -= 2;
- add = 2;
- }
- else
- add = 0;
-
- if (add != 0)
- {
- bfd_byte *loc;
- unsigned short insn, oinsn;
- boolean overflow;
-
- loc = contents + irel->r_offset;
- overflow = false;
- switch (type)
- {
- default:
- break;
-
- case R_SH_DIR8WPN:
- case R_SH_DIR8WPZ:
- insn = bfd_get_16 (abfd, loc);
- oinsn = insn;
- insn += add / 2;
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, loc);
- break;
-
- case R_SH_IND12W:
- insn = bfd_get_16 (abfd, loc);
- oinsn = insn;
- insn += add / 2;
- if ((oinsn & 0xf000) != (insn & 0xf000))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, loc);
- break;
-
- case R_SH_DIR8WPL:
- /* This reloc ignores the least significant 3 bits of
- the program counter before adding in the offset.
- This means that if ADDR is at an even address, the
- swap will not affect the offset. If ADDR is an at an
- odd address, then the instruction will be crossing a
- four byte boundary, and must be adjusted. */
- if ((addr & 3) != 0)
- {
- insn = bfd_get_16 (abfd, loc);
- oinsn = insn;
- insn += add / 2;
- if ((oinsn & 0xff00) != (insn & 0xff00))
- overflow = true;
- bfd_put_16 (abfd, (bfd_vma) insn, loc);
- }
-
- break;
- }
-
- if (overflow)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: fatal: reloc overflow while relaxing"),
- bfd_archive_filename (abfd), (unsigned long) irel->r_offset));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
- }
-
- return true;
-}
-
-#ifdef INCLUDE_SHMEDIA
-
-/* The size in bytes of an entry in the procedure linkage table. */
-
-#define PLT_ENTRY_SIZE 64
-
-/* First entry in an absolute procedure linkage table look like this. */
-
-static const bfd_byte elf_sh_plt0_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xcc, 0x00, 0x01, 0x10, /* movi .got.plt >> 16, r17 */
- 0xc8, 0x00, 0x01, 0x10, /* shori .got.plt & 65535, r17 */
- 0x89, 0x10, 0x09, 0x90, /* ld.l r17, 8, r25 */
- 0x6b, 0xf1, 0x46, 0x00, /* ptabs r17, tr0 */
- 0x89, 0x10, 0x05, 0x10, /* ld.l r17, 4, r17 */
- 0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
-};
-
-static const bfd_byte elf_sh_plt0_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x10, 0x01, 0x00, 0xcc, /* movi .got.plt >> 16, r17 */
- 0x10, 0x01, 0x00, 0xc8, /* shori .got.plt & 65535, r17 */
- 0x90, 0x09, 0x10, 0x89, /* ld.l r17, 8, r25 */
- 0x00, 0x46, 0xf1, 0x6b, /* ptabs r17, tr0 */
- 0x10, 0x05, 0x10, 0x89, /* ld.l r17, 4, r17 */
- 0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
-};
-
-/* Sebsequent entries in an absolute procedure linkage table look like
- this. */
-
-static const bfd_byte elf_sh_plt_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xcc, 0x00, 0x01, 0x90, /* movi nameN-in-GOT >> 16, r25 */
- 0xc8, 0x00, 0x01, 0x90, /* shori nameN-in-GOT & 65535, r25 */
- 0x89, 0x90, 0x01, 0x90, /* ld.l r25, 0, r25 */
- 0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
- 0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0xcc, 0x00, 0x01, 0x90, /* movi .PLT0 >> 16, r25 */
- 0xc8, 0x00, 0x01, 0x90, /* shori .PLT0 & 65535, r25 */
- 0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
- 0xcc, 0x00, 0x01, 0x50, /* movi reloc-offset >> 16, r21 */
- 0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
- 0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
-};
-
-static const bfd_byte elf_sh_plt_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x90, 0x01, 0x00, 0xcc, /* movi nameN-in-GOT >> 16, r25 */
- 0x90, 0x01, 0x00, 0xc8, /* shori nameN-in-GOT & 65535, r25 */
- 0x90, 0x01, 0x90, 0x89, /* ld.l r25, 0, r25 */
- 0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
- 0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0x90, 0x01, 0x00, 0xcc, /* movi .PLT0 >> 16, r25 */
- 0x90, 0x01, 0x00, 0xc8, /* shori .PLT0 & 65535, r25 */
- 0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
- 0x50, 0x01, 0x00, 0xcc, /* movi reloc-offset >> 16, r21 */
- 0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
- 0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
-};
-
-/* Entries in a PIC procedure linkage table look like this. */
-
-static const bfd_byte elf_sh_pic_plt_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xcc, 0x00, 0x01, 0x90, /* movi nameN@GOT >> 16, r25 */
- 0xc8, 0x00, 0x01, 0x90, /* shori nameN@GOT & 65535, r25 */
- 0x40, 0xc2, 0x65, 0x90, /* ldx.l r12, r25, r25 */
- 0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
- 0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0x6f, 0xf0, 0xff, 0xf0, /* nop */
- 0xce, 0x00, 0x01, 0x10, /* movi -GOT_BIAS, r17 */
- 0x00, 0xca, 0x45, 0x10, /* sub.l r12, r17, r17 */
- 0x89, 0x10, 0x09, 0x90, /* ld.l r17, 8, r25 */
- 0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
- 0x89, 0x10, 0x05, 0x10, /* ld.l r17, 4, r17 */
- 0xcc, 0x00, 0x01, 0x50, /* movi reloc-offset >> 16, r21 */
- 0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
- 0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
-};
-
-static const bfd_byte elf_sh_pic_plt_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x90, 0x01, 0x00, 0xcc, /* movi nameN@GOT >> 16, r25 */
- 0x90, 0x01, 0x00, 0xc8, /* shori nameN@GOT & 65535, r25 */
- 0x90, 0x65, 0xc2, 0x40, /* ldx.l r12, r25, r25 */
- 0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
- 0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0xf0, 0xff, 0xf0, 0x6f, /* nop */
- 0x10, 0x01, 0x00, 0xce, /* movi -GOT_BIAS, r17 */
- 0x10, 0x45, 0xca, 0x00, /* sub.l r12, r17, r17 */
- 0x90, 0x09, 0x10, 0x89, /* ld.l r17, 8, r25 */
- 0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
- 0x10, 0x05, 0x10, 0x89, /* ld.l r17, 4, r17 */
- 0x50, 0x01, 0x00, 0xcc, /* movi reloc-offset >> 16, r21 */
- 0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
- 0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
-};
-
-static const bfd_byte *elf_sh_plt0_entry;
-static const bfd_byte *elf_sh_plt_entry;
-static const bfd_byte *elf_sh_pic_plt_entry;
-
-/* Return size of a PLT entry. */
-#define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
-
-/* Return offset of the PLT0 address in an absolute PLT entry. */
-#define elf_sh_plt_plt0_offset(info) 32
-
-/* Return offset of the linker in PLT0 entry. */
-#define elf_sh_plt0_gotplt_offset(info) 0
-
-/* Return offset of the trampoline in PLT entry */
-#define elf_sh_plt_temp_offset(info) 33 /* Add one because it's SHmedia. */
-
-/* Return offset of the symbol in PLT entry. */
-#define elf_sh_plt_symbol_offset(info) 0
-
-/* Return offset of the relocation in PLT entry. */
-#define elf_sh_plt_reloc_offset(info) (info->shared ? 52 : 44)
-
-inline static void
-movi_shori_putval (output_bfd, value, addr)
- bfd *output_bfd;
- unsigned long value;
- char *addr;
-{
- bfd_put_32 (output_bfd,
- bfd_get_32 (output_bfd, addr)
- | ((value >> 6) & 0x3fffc00),
- addr);
- bfd_put_32 (output_bfd,
- bfd_get_32 (output_bfd, addr + 4)
- | ((value << 10) & 0x3fffc00),
- addr + 4);
-}
-
-#else
-/* The size in bytes of an entry in the procedure linkage table. */
-
-#define PLT_ENTRY_SIZE 28
-
-/* First entry in an absolute procedure linkage table look like this. */
-
-#if 1
-/* Note - this code has been "optimised" not to use r2. r2 is used by
- GCC to return the address of large strutcures, so it should not be
- corrupted here. This does mean however, that this PLT does not conform
- to the SH PIC ABI. That spec says that r0 contains the type of the PLT
- and r2 contains the GOT id. This version stores the GOT id in r0 and
- ignores the type. Loaders can easily detect this difference however,
- since the type will always be 0 or 8, and the GOT ids will always be
- greater than or equal to 12. */
-static const bfd_byte elf_sh_plt0_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xd0, 0x05, /* mov.l 2f,r0 */
- 0x60, 0x02, /* mov.l @r0,r0 */
- 0x2f, 0x06, /* mov.l r0,@-r15 */
- 0xd0, 0x03, /* mov.l 1f,r0 */
- 0x60, 0x02, /* mov.l @r0,r0 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x60, 0xf6, /* mov.l @r15+,r0 */
- 0x00, 0x09, /* nop */
- 0x00, 0x09, /* nop */
- 0x00, 0x09, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of .got.plt + 8. */
- 0, 0, 0, 0, /* 2: replaced with address of .got.plt + 4. */
-};
-
-static const bfd_byte elf_sh_plt0_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x05, 0xd0, /* mov.l 2f,r0 */
- 0x02, 0x60, /* mov.l @r0,r0 */
- 0x06, 0x2f, /* mov.l r0,@-r15 */
- 0x03, 0xd0, /* mov.l 1f,r0 */
- 0x02, 0x60, /* mov.l @r0,r0 */
- 0x2b, 0x40, /* jmp @r0 */
- 0xf6, 0x60, /* mov.l @r15+,r0 */
- 0x09, 0x00, /* nop */
- 0x09, 0x00, /* nop */
- 0x09, 0x00, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of .got.plt + 8. */
- 0, 0, 0, 0, /* 2: replaced with address of .got.plt + 4. */
-};
-
-/* Sebsequent entries in an absolute procedure linkage table look like
- this. */
-
-static const bfd_byte elf_sh_plt_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xd0, 0x04, /* mov.l 1f,r0 */
- 0x60, 0x02, /* mov.l @r0,r0 */
- 0xd1, 0x02, /* mov.l 0f,r1 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x60, 0x13, /* mov r1,r0 */
- 0xd1, 0x03, /* mov.l 2f,r1 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x00, 0x09, /* nop */
- 0, 0, 0, 0, /* 0: replaced with address of .PLT0. */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0, /* 2: replaced with offset into relocation table. */
-};
-
-static const bfd_byte elf_sh_plt_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x04, 0xd0, /* mov.l 1f,r0 */
- 0x02, 0x60, /* mov.l @r0,r0 */
- 0x02, 0xd1, /* mov.l 0f,r1 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x13, 0x60, /* mov r1,r0 */
- 0x03, 0xd1, /* mov.l 2f,r1 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x09, 0x00, /* nop */
- 0, 0, 0, 0, /* 0: replaced with address of .PLT0. */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0, /* 2: replaced with offset into relocation table. */
-};
-
-/* Entries in a PIC procedure linkage table look like this. */
-
-static const bfd_byte elf_sh_pic_plt_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xd0, 0x04, /* mov.l 1f,r0 */
- 0x00, 0xce, /* mov.l @(r0,r12),r0 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x00, 0x09, /* nop */
- 0x50, 0xc2, /* mov.l @(8,r12),r0 */
- 0xd1, 0x03, /* mov.l 2f,r1 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x50, 0xc1, /* mov.l @(4,r12),r0 */
- 0x00, 0x09, /* nop */
- 0x00, 0x09, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0 /* 2: replaced with offset into relocation table. */
-};
-
-static const bfd_byte elf_sh_pic_plt_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x04, 0xd0, /* mov.l 1f,r0 */
- 0xce, 0x00, /* mov.l @(r0,r12),r0 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x09, 0x00, /* nop */
- 0xc2, 0x50, /* mov.l @(8,r12),r0 */
- 0x03, 0xd1, /* mov.l 2f,r1 */
- 0x2b, 0x40, /* jmp @r0 */
- 0xc1, 0x50, /* mov.l @(4,r12),r0 */
- 0x09, 0x00, /* nop */
- 0x09, 0x00, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0 /* 2: replaced with offset into relocation table. */
-};
-
-#else /* These are the old style PLT entries. */
-static const bfd_byte elf_sh_plt0_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xd0, 0x04, /* mov.l 1f,r0 */
- 0xd2, 0x05, /* mov.l 2f,r2 */
- 0x60, 0x02, /* mov.l @r0,r0 */
- 0x62, 0x22, /* mov.l @r2,r2 */
- 0x40, 0x2b, /* jmp @r0 */
- 0xe0, 0x00, /* mov #0,r0 */
- 0x00, 0x09, /* nop */
- 0x00, 0x09, /* nop */
- 0x00, 0x09, /* nop */
- 0x00, 0x09, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of .got.plt + 8. */
- 0, 0, 0, 0, /* 2: replaced with address of .got.plt + 4. */
-};
-
-static const bfd_byte elf_sh_plt0_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x04, 0xd0, /* mov.l 1f,r0 */
- 0x05, 0xd2, /* mov.l 2f,r2 */
- 0x02, 0x60, /* mov.l @r0,r0 */
- 0x22, 0x62, /* mov.l @r2,r2 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x00, 0xe0, /* mov #0,r0 */
- 0x09, 0x00, /* nop */
- 0x09, 0x00, /* nop */
- 0x09, 0x00, /* nop */
- 0x09, 0x00, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of .got.plt + 8. */
- 0, 0, 0, 0, /* 2: replaced with address of .got.plt + 4. */
-};
-
-/* Sebsequent entries in an absolute procedure linkage table look like
- this. */
-
-static const bfd_byte elf_sh_plt_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xd0, 0x04, /* mov.l 1f,r0 */
- 0x60, 0x02, /* mov.l @r0,r0 */
- 0xd2, 0x02, /* mov.l 0f,r2 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x60, 0x23, /* mov r2,r0 */
- 0xd1, 0x03, /* mov.l 2f,r1 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x00, 0x09, /* nop */
- 0, 0, 0, 0, /* 0: replaced with address of .PLT0. */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0, /* 2: replaced with offset into relocation table. */
-};
-
-static const bfd_byte elf_sh_plt_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x04, 0xd0, /* mov.l 1f,r0 */
- 0x02, 0x60, /* mov.l @r0,r0 */
- 0x02, 0xd2, /* mov.l 0f,r2 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x23, 0x60, /* mov r2,r0 */
- 0x03, 0xd1, /* mov.l 2f,r1 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x09, 0x00, /* nop */
- 0, 0, 0, 0, /* 0: replaced with address of .PLT. */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0, /* 2: replaced with offset into relocation table. */
-};
-
-/* Entries in a PIC procedure linkage table look like this. */
-
-static const bfd_byte elf_sh_pic_plt_entry_be[PLT_ENTRY_SIZE] =
-{
- 0xd0, 0x04, /* mov.l 1f,r0 */
- 0x00, 0xce, /* mov.l @(r0,r12),r0 */
- 0x40, 0x2b, /* jmp @r0 */
- 0x00, 0x09, /* nop */
- 0x50, 0xc2, /* 0: mov.l @(8,r12),r0 */
- 0x52, 0xc1, /* 1: mov.l @(4,r12),r2 */
- 0xd1, 0x02, /* mov.l 2f,r1 */
- 0x40, 0x2b, /* jmp @r0 */
- 0xe0, 0x00, /* mov #0,r0 ! shows the type of PLT. */
- 0x00, 0x09, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0 /* 2: replaced with offset into relocation table. */
-};
-
-static const bfd_byte elf_sh_pic_plt_entry_le[PLT_ENTRY_SIZE] =
-{
- 0x04, 0xd0, /* mov.l 1f,r0 */
- 0xce, 0x00, /* mov.l @(r0,r12),r0 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x09, 0x00, /* nop */
- 0xc2, 0x50, /* 0: mov.l @(8,r12),r0 */
- 0xc1, 0x52, /* 1: mov.l @(4,r12),r2 */
- 0x02, 0xd1, /* mov.l 2f,r1 */
- 0x2b, 0x40, /* jmp @r0 */
- 0x00, 0xe0, /* mov #0,r0 ! shows the type of PLT. */
- 0x09, 0x00, /* nop */
- 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
- 0, 0, 0, 0 /* 2: replaced with offset into relocation table. */
-};
-#endif /* old style PLT entries. */
-
-static const bfd_byte *elf_sh_plt0_entry;
-static const bfd_byte *elf_sh_plt_entry;
-static const bfd_byte *elf_sh_pic_plt_entry;
-
-/* Return size of a PLT entry. */
-#define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
-
-/* Return offset of the PLT0 address in an absolute PLT entry. */
-#define elf_sh_plt_plt0_offset(info) 16
-
-/* Return offset of the linker in PLT0 entry. */
-#define elf_sh_plt0_linker_offset(info) 20
-
-/* Return offset of the GOT id in PLT0 entry. */
-#define elf_sh_plt0_gotid_offset(info) 24
-
-/* Return offset of the tempoline in PLT entry */
-#define elf_sh_plt_temp_offset(info) 8
-
-/* Return offset of the symbol in PLT entry. */
-#define elf_sh_plt_symbol_offset(info) 20
-
-/* Return offset of the relocation in PLT entry. */
-#define elf_sh_plt_reloc_offset(info) 24
-#endif
-
-/* The sh linker needs to keep track of the number of relocs that it
- decides to copy as dynamic relocs in check_relocs for each symbol.
- This is so that it can later discard them if they are found to be
- unnecessary. We store the information in a field extending the
- regular ELF linker hash table. */
-
-struct elf_sh_dyn_relocs
-{
- struct elf_sh_dyn_relocs *next;
-
- /* The input section of the reloc. */
- asection *sec;
-
- /* Total number of relocs copied for the input section. */
- bfd_size_type count;
-
- /* Number of pc-relative relocs copied for the input section. */
- bfd_size_type pc_count;
-};
-
-/* sh ELF linker hash entry. */
-
-struct elf_sh_link_hash_entry
-{
- struct elf_link_hash_entry root;
-
-#ifdef INCLUDE_SHMEDIA
- bfd_vma datalabel_got_offset;
-#endif
-
- /* Track dynamic relocs copied for this symbol. */
- struct elf_sh_dyn_relocs *dyn_relocs;
-
- bfd_signed_vma gotplt_refcount;
-};
-
-/* sh ELF linker hash table. */
-
-struct elf_sh_link_hash_table
-{
- struct elf_link_hash_table root;
-
- /* Short-cuts to get to dynamic linker sections. */
- asection *sgot;
- asection *sgotplt;
- asection *srelgot;
- asection *splt;
- asection *srelplt;
- asection *sdynbss;
- asection *srelbss;
-
- /* Small local sym to section mapping cache. */
- struct sym_sec_cache sym_sec;
-};
-
-/* Traverse an sh ELF linker hash table. */
-
-#define sh_elf_link_hash_traverse(table, func, info) \
- (elf_link_hash_traverse \
- (&(table)->root, \
- (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
- (info)))
-
-/* Get the sh ELF linker hash table from a link_info structure. */
-
-#define sh_elf_hash_table(p) \
- ((struct elf_sh_link_hash_table *) ((p)->hash))
-
-/* Create an entry in an sh ELF linker hash table. */
-
-static struct bfd_hash_entry *
-sh_elf_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
-{
- struct elf_sh_link_hash_entry *ret =
- (struct elf_sh_link_hash_entry *) entry;
-
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (ret == (struct elf_sh_link_hash_entry *) NULL)
- ret = ((struct elf_sh_link_hash_entry *)
- bfd_hash_allocate (table,
- sizeof (struct elf_sh_link_hash_entry)));
- if (ret == (struct elf_sh_link_hash_entry *) NULL)
- return (struct bfd_hash_entry *) ret;
-
- /* Call the allocation method of the superclass. */
- ret = ((struct elf_sh_link_hash_entry *)
- _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
- table, string));
- if (ret != (struct elf_sh_link_hash_entry *) NULL)
- {
- struct elf_sh_link_hash_entry *eh;
-
- eh = (struct elf_sh_link_hash_entry *) ret;
- eh->dyn_relocs = NULL;
- eh->gotplt_refcount = 0;
-#ifdef INCLUDE_SHMEDIA
- ret->datalabel_got_offset = (bfd_vma) -1;
-#endif
- }
-
- return (struct bfd_hash_entry *) ret;
-}
-
-/* Create an sh ELF linker hash table. */
-
-static struct bfd_link_hash_table *
-sh_elf_link_hash_table_create (abfd)
- bfd *abfd;
-{
- struct elf_sh_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct elf_sh_link_hash_table);
-
- ret = (struct elf_sh_link_hash_table *) bfd_malloc (amt);
- if (ret == (struct elf_sh_link_hash_table *) NULL)
- return NULL;
-
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- sh_elf_link_hash_newfunc))
- {
- free (ret);
- return NULL;
- }
-
- ret->sgot = NULL;
- ret->sgotplt = NULL;
- ret->srelgot = NULL;
- ret->splt = NULL;
- ret->srelplt = NULL;
- ret->sdynbss = NULL;
- ret->srelbss = NULL;
- ret->sym_sec.abfd = NULL;
-
- return &ret->root.root;
-}
-
-/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
- shortcuts to them in our hash table. */
-
-static boolean
-create_got_section (dynobj, info)
- bfd *dynobj;
- struct bfd_link_info *info;
-{
- struct elf_sh_link_hash_table *htab;
-
- if (! _bfd_elf_create_got_section (dynobj, info))
- return false;
-
- htab = sh_elf_hash_table (info);
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- if (! htab->sgot || ! htab->sgotplt)
- abort ();
-
- htab->srelgot = bfd_make_section (dynobj, ".rela.got");
- if (htab->srelgot == NULL
- || ! bfd_set_section_flags (dynobj, htab->srelgot,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY))
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return false;
- return true;
-}
-
-/* Create dynamic sections when linking against a dynamic object. */
-
-static boolean
-sh_elf_create_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- struct elf_sh_link_hash_table *htab;
- flagword flags, pltflags;
- register asection *s;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- int ptralign = 0;
-
- switch (bed->s->arch_size)
- {
- case 32:
- ptralign = 2;
- break;
-
- case 64:
- ptralign = 3;
- break;
-
- default:
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- htab = sh_elf_hash_table (info);
-
- /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
- .rel[a].bss sections. */
-
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED);
-
- pltflags = flags;
- pltflags |= SEC_CODE;
- if (bed->plt_not_loaded)
- pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
- if (bed->plt_readonly)
- pltflags |= SEC_READONLY;
-
- s = bfd_make_section (abfd, ".plt");
- htab->splt = s;
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, pltflags)
- || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
- return false;
-
- if (bed->want_plt_sym)
- {
- /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
- .plt section. */
- struct elf_link_hash_entry *h;
- struct bfd_link_hash_entry *bh = NULL;
-
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect, &bh)))
- return false;
-
- h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
- return false;
- }
-
- s = bfd_make_section (abfd,
- bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
- htab->srelplt = s;
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, ptralign))
- return false;
-
- if (! create_got_section (abfd, info))
- return false;
-
- {
- const char *secname;
- char *relname;
- flagword secflags;
- asection *sec;
-
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- secflags = bfd_get_section_flags (abfd, sec);
- if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
- || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
- continue;
- secname = bfd_get_section_name (abfd, sec);
- relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6);
- strcpy (relname, ".rela");
- strcat (relname, secname);
- s = bfd_make_section (abfd, relname);
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, ptralign))
- return false;
- }
- }
-
- if (bed->want_dynbss)
- {
- /* The .dynbss section is a place to put symbols which are defined
- by dynamic objects, are referenced by regular objects, and are
- not functions. We must allocate space for them in the process
- image and use a R_*_COPY reloc to tell the dynamic linker to
- initialize them at run time. The linker script puts the .dynbss
- section into the .bss section of the final image. */
- s = bfd_make_section (abfd, ".dynbss");
- htab->sdynbss = s;
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
- return false;
-
- /* The .rel[a].bss section holds copy relocs. This section is not
- normally needed. We need to create it here, though, so that the
- linker will map it to an output section. We can't just create it
- only if we need it, because we will not know whether we need it
- until we have seen all the input files, and the first time the
- main linker code calls BFD after examining all the input files
- (size_dynamic_sections) the input sections have already been
- mapped to the output sections. If the section turns out not to
- be needed, we can discard it later. We will never need this
- section when generating a shared object, since they do not use
- copy relocs. */
- if (! info->shared)
- {
- s = bfd_make_section (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"));
- htab->srelbss = s;
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, ptralign))
- return false;
- }
- }
-
- return true;
-}
-
-/* Adjust a symbol defined by a dynamic object and referenced by a
- regular object. The current definition is in some section of the
- dynamic object, but we're not including those sections. We have to
- change the definition to something the rest of the link can
- understand. */
-
-static boolean
-sh_elf_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
-{
- struct elf_sh_link_hash_table *htab;
- struct elf_sh_link_hash_entry *eh;
- struct elf_sh_dyn_relocs *p;
- bfd *dynobj;
- asection *s;
- unsigned int power_of_two;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- /* Make sure we know what is going on here. */
- BFD_ASSERT (dynobj != NULL
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
- || h->weakdef != NULL
- || ((h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)));
-
- /* If this is a function, put it in the procedure linkage table. We
- will fill in the contents of the procedure linkage table later,
- when we know the address of the .got section. */
- if (h->type == STT_FUNC
- || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
- {
- if (h->plt.refcount <= 0
- || (! info->shared
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0
- && h->root.type != bfd_link_hash_undefweak
- && h->root.type != bfd_link_hash_undefined))
- {
- /* This case can occur if we saw a PLT reloc in an input
- file, but the symbol was never referred to by a dynamic
- object. In such a case, we don't actually need to build
- a procedure linkage table, and we can just do a REL32
- reloc instead. */
- h->plt.offset = (bfd_vma) -1;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- }
-
- return true;
- }
- else
- h->plt.offset = (bfd_vma) -1;
-
- /* If this is a weak symbol, and there is a real definition, the
- processor independent code will have arranged for us to see the
- real definition first, and we can just use the same value. */
- if (h->weakdef != NULL)
- {
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
- return true;
- }
-
- /* This is a reference to a symbol defined by a dynamic object which
- is not a function. */
-
- /* If we are creating a shared library, we must presume that the
- only references to the symbol are via the global offset table.
- For such cases we need not do anything here; the relocations will
- be handled correctly by relocate_section. */
- if (info->shared)
- return true;
-
- /* If there are no references to this symbol that do not use the
- GOT, we don't need to generate a copy reloc. */
- if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
- return true;
-
- /* If -z nocopyreloc was given, we won't generate them either. */
- if (info->nocopyreloc)
- {
- h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
- return true;
- }
-
- eh = (struct elf_sh_link_hash_entry *) h;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- s = p->sec->output_section;
- if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0)
- break;
- }
-
- /* If we didn't find any dynamic relocs in sections which needs the
- copy reloc, then we'll be keeping the dynamic relocs and avoiding
- the copy reloc. */
- if (p == NULL)
- {
- h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
- return true;
- }
-
- /* We must allocate the symbol in our .dynbss section, which will
- become part of the .bss section of the executable. There will be
- an entry for this symbol in the .dynsym section. The dynamic
- object will contain position independent code, so all references
- from the dynamic object to this symbol will go through the global
- offset table. The dynamic linker will use the .dynsym entry to
- determine the address it must put in the global offset table, so
- both the dynamic object and the regular object will refer to the
- same memory location for the variable. */
-
- htab = sh_elf_hash_table (info);
- s = htab->sdynbss;
- BFD_ASSERT (s != NULL);
-
- /* We must generate a R_SH_COPY reloc to tell the dynamic linker to
- copy the initial value out of the dynamic object and into the
- runtime process image. We need to remember the offset into the
- .rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
- {
- asection *srel;
-
- srel = htab->srelbss;
- BFD_ASSERT (srel != NULL);
- srel->_raw_size += sizeof (Elf32_External_Rela);
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
- }
-
- /* We need to figure out the alignment required for this symbol. I
- have no idea how ELF linkers handle this. */
- power_of_two = bfd_log2 (h->size);
- if (power_of_two > 3)
- power_of_two = 3;
-
- /* Apply the required alignment. */
- s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, s))
- {
- if (! bfd_set_section_alignment (dynobj, s, power_of_two))
- return false;
- }
-
- /* Define the symbol as being at this point in the section. */
- h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
-
- /* Increment the section size to make room for the symbol. */
- s->_raw_size += h->size;
-
- return true;
-}
-
-/* This is the condition under which sh_elf_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in sh_elf_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
- ((DYN) \
- && ((INFO)->shared \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
-/* Allocate space in .plt, .got and associated reloc sections for
- dynamic relocs. */
-
-static boolean
-allocate_dynrelocs (h, inf)
- struct elf_link_hash_entry *h;
- PTR inf;
-{
- struct bfd_link_info *info;
- struct elf_sh_link_hash_table *htab;
- struct elf_sh_link_hash_entry *eh;
- struct elf_sh_dyn_relocs *p;
-
- if (h->root.type == bfd_link_hash_indirect)
- return true;
-
- if (h->root.type == bfd_link_hash_warning)
- /* When warning symbols are created, they **replace** the "real"
- entry in the hash table, thus we never get to see the real
- symbol in a hash traversal. So look at it now. */
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- info = (struct bfd_link_info *) inf;
- htab = sh_elf_hash_table (info);
-
- eh = (struct elf_sh_link_hash_entry *) h;
- if ((h->got.refcount > 0
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
- && eh->gotplt_refcount > 0)
- {
- /* The symbol has been forced local, or we have some direct got refs,
- so treat all the gotplt refs as got refs. */
- h->got.refcount += eh->gotplt_refcount;
- if (h->plt.refcount >= eh->gotplt_refcount)
- h->plt.refcount -= eh->gotplt_refcount;
- }
-
- if (htab->root.dynamic_sections_created
- && h->plt.refcount > 0)
- {
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
-
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
- {
- asection *s = htab->splt;
-
- /* If this is the first .plt entry, make room for the special
- first entry. */
- if (s->_raw_size == 0)
- s->_raw_size += PLT_ENTRY_SIZE;
-
- h->plt.offset = s->_raw_size;
-
- /* If this symbol is not defined in a regular file, and we are
- not generating a shared library, then set the symbol to this
- location in the .plt. This is required to make function
- pointers compare as equal between the normal executable and
- the shared library. */
- if (! info->shared
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- {
- h->root.u.def.section = s;
- h->root.u.def.value = h->plt.offset;
- }
-
- /* Make room for this entry. */
- s->_raw_size += PLT_ENTRY_SIZE;
-
- /* We also need to make an entry in the .got.plt section, which
- will be placed in the .got section by the linker script. */
- htab->sgotplt->_raw_size += 4;
-
- /* We also need to make an entry in the .rel.plt section. */
- htab->srelplt->_raw_size += sizeof (Elf32_External_Rela);
- }
- else
- {
- h->plt.offset = (bfd_vma) -1;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- }
- }
- else
- {
- h->plt.offset = (bfd_vma) -1;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- }
-
- if (h->got.refcount > 0)
- {
- asection *s;
- boolean dyn;
-
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
-
- s = htab->sgot;
-#ifdef INCLUDE_SHMEDIA
- if (h->type == STT_DATALABEL)
- {
- struct elf_sh_link_hash_entry *hsh;
-
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- hsh = (struct elf_sh_link_hash_entry *)h;
- hsh->datalabel_got_offset = s->_raw_size;
- }
- else
- h->got.offset = s->_raw_size;
-#else
- h->got.offset = s->_raw_size;
-#endif
- s->_raw_size += 4;
- dyn = htab->root.dynamic_sections_created;
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
- htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
- }
- else
- h->got.offset = (bfd_vma) -1;
-
- if (eh->dyn_relocs == NULL)
- return true;
-
- /* In the shared -Bsymbolic case, discard space allocated for
- dynamic pc-relative relocs against symbols which turn out to be
- defined in regular objects. For the normal shared case, discard
- space for pc-relative relocs that have become local due to symbol
- visibility changes. */
-
- if (info->shared)
- {
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
- && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
- || info->symbolic))
- {
- struct elf_sh_dyn_relocs **pp;
-
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
- {
- p->count -= p->pc_count;
- p->pc_count = 0;
- if (p->count == 0)
- *pp = p->next;
- else
- pp = &p->next;
- }
- }
- }
- else
- {
- /* For the non-shared case, discard space for relocs against
- symbols which turn out to need copy relocs or are not
- dynamic. */
-
- if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
- && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- || (htab->root.dynamic_sections_created
- && (h->root.type == bfd_link_hash_undefweak
- || h->root.type == bfd_link_hash_undefined))))
- {
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
-
- /* If that succeeded, we know we'll be keeping all the
- relocs. */
- if (h->dynindx != -1)
- goto keep;
- }
-
- eh->dyn_relocs = NULL;
-
- keep: ;
- }
-
- /* Finally, allocate space. */
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- asection *sreloc = elf_section_data (p->sec)->sreloc;
- sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela);
- }
-
- return true;
-}
-
-/* Find any dynamic relocs that apply to read-only sections. */
-
-static boolean
-readonly_dynrelocs (h, inf)
- struct elf_link_hash_entry *h;
- PTR inf;
-{
- struct elf_sh_link_hash_entry *eh;
- struct elf_sh_dyn_relocs *p;
-
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- eh = (struct elf_sh_link_hash_entry *) h;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- asection *s = p->sec->output_section;
-
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- {
- struct bfd_link_info *info = (struct bfd_link_info *) inf;
-
- info->flags |= DF_TEXTREL;
-
- /* Not an error, just cut short the traversal. */
- return false;
- }
- }
- return true;
-}
-
-/* Set the sizes of the dynamic sections. */
-
-static boolean
-sh_elf_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info;
-{
- struct elf_sh_link_hash_table *htab;
- bfd *dynobj;
- asection *s;
- boolean relocs;
- bfd *ibfd;
-
- htab = sh_elf_hash_table (info);
- dynobj = htab->root.dynobj;
- BFD_ASSERT (dynobj != NULL);
-
- if (htab->root.dynamic_sections_created)
- {
- /* Set the contents of the .interp section to the interpreter. */
- if (! info->shared)
- {
- s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
- s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
- s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
- }
- }
-
- /* Set up .got offsets for local syms, and space for local dynamic
- relocs. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
- {
- bfd_signed_vma *local_got;
- bfd_signed_vma *end_local_got;
- bfd_size_type locsymcount;
- Elf_Internal_Shdr *symtab_hdr;
- asection *srel;
-
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
- continue;
-
- for (s = ibfd->sections; s != NULL; s = s->next)
- {
- struct elf_sh_dyn_relocs *p;
-
- for (p = ((struct elf_sh_dyn_relocs *)
- elf_section_data (s)->local_dynrel);
- p != NULL;
- p = p->next)
- {
- if (! bfd_is_abs_section (p->sec)
- && bfd_is_abs_section (p->sec->output_section))
- {
- /* Input section has been discarded, either because
- it is a copy of a linkonce section or due to
- linker script /DISCARD/, so we'll be discarding
- the relocs too. */
- }
- else if (p->count != 0)
- {
- srel = elf_section_data (p->sec)->sreloc;
- srel->_raw_size += p->count * sizeof (Elf32_External_Rela);
- if ((p->sec->output_section->flags & SEC_READONLY) != 0)
- info->flags |= DF_TEXTREL;
- }
- }
- }
-
- local_got = elf_local_got_refcounts (ibfd);
- if (!local_got)
- continue;
-
- symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
- locsymcount = symtab_hdr->sh_info;
-#ifdef INCLUDE_SHMEDIA
- /* Count datalabel local GOT. */
- locsymcount *= 2;
-#endif
- end_local_got = local_got + locsymcount;
- s = htab->sgot;
- srel = htab->srelgot;
- for (; local_got < end_local_got; ++local_got)
- {
- if (*local_got > 0)
- {
- *local_got = s->_raw_size;
- s->_raw_size += 4;
- if (info->shared)
- srel->_raw_size += sizeof (Elf32_External_Rela);
- }
- else
- *local_got = (bfd_vma) -1;
- }
- }
-
- /* Allocate global sym .plt and .got entries, and space for global
- sym dynamic relocs. */
- elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
-
- /* We now have determined the sizes of the various dynamic sections.
- Allocate memory for them. */
- relocs = false;
- for (s = dynobj->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LINKER_CREATED) == 0)
- continue;
-
- if (s == htab->splt
- || s == htab->sgot
- || s == htab->sgotplt)
- {
- /* Strip this section if we don't need it; see the
- comment below. */
- }
- else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
- {
- if (s->_raw_size != 0 && s != htab->srelplt)
- relocs = true;
-
- /* We use the reloc_count field as a counter if we need
- to copy relocs into the output file. */
- s->reloc_count = 0;
- }
- else
- {
- /* It's not one of our sections, so don't allocate space. */
- continue;
- }
-
- if (s->_raw_size == 0)
- {
- /* If we don't need this section, strip it from the
- output file. This is mostly to handle .rela.bss and
- .rela.plt. We must create both sections in
- create_dynamic_sections, because they must be created
- before the linker maps input sections to output
- sections. The linker does that before
- adjust_dynamic_symbol is called, and it is that
- function which decides whether anything needs to go
- into these sections. */
-
- _bfd_strip_section_from_output (info, s);
- continue;
- }
-
- /* Allocate memory for the section contents. We use bfd_zalloc
- here in case unused entries are not reclaimed before the
- section's contents are written out. This should not happen,
- but this way if it does, we get a R_SH_NONE reloc instead
- of garbage. */
- s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
- if (s->contents == NULL)
- return false;
- }
-
- if (htab->root.dynamic_sections_created)
- {
- /* Add some entries to the .dynamic section. We fill in the
- values later, in sh_elf_finish_dynamic_sections, but we
- must add the entries now so that we get the correct size for
- the .dynamic section. The DT_DEBUG entry is filled in by the
- dynamic linker and used by the debugger. */
-#define add_dynamic_entry(TAG, VAL) \
- bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
-
- if (! info->shared)
- {
- if (! add_dynamic_entry (DT_DEBUG, 0))
- return false;
- }
-
- if (htab->splt->_raw_size != 0)
- {
- if (! add_dynamic_entry (DT_PLTGOT, 0)
- || ! add_dynamic_entry (DT_PLTRELSZ, 0)
- || ! add_dynamic_entry (DT_PLTREL, DT_RELA)
- || ! add_dynamic_entry (DT_JMPREL, 0))
- return false;
- }
-
- if (relocs)
- {
- if (! add_dynamic_entry (DT_RELA, 0)
- || ! add_dynamic_entry (DT_RELASZ, 0)
- || ! add_dynamic_entry (DT_RELAENT,
- sizeof (Elf32_External_Rela)))
- return false;
-
- /* If any dynamic relocs apply to a read-only section,
- then we need a DT_TEXTREL entry. */
- if ((info->flags & DF_TEXTREL) == 0)
- elf_link_hash_traverse (&htab->root, readonly_dynrelocs,
- (PTR) info);
-
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (! add_dynamic_entry (DT_TEXTREL, 0))
- return false;
- }
- }
- }
-#undef add_dynamic_entry
-
- return true;
-}
-
-/* Relocate an SH ELF section. */
-
-static boolean
-sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- Elf_Internal_Rela *relocs;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
-{
- struct elf_sh_link_hash_table *htab;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- Elf_Internal_Rela *rel, *relend;
- bfd *dynobj;
- bfd_vma *local_got_offsets;
- asection *sgot;
- asection *sgotplt;
- asection *splt;
- asection *sreloc;
-
- htab = sh_elf_hash_table (info);
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (input_bfd);
- dynobj = htab->root.dynobj;
- local_got_offsets = elf_local_got_offsets (input_bfd);
-
- sgot = htab->sgot;
- sgotplt = htab->sgotplt;
- splt = htab->splt;
- sreloc = NULL;
-
- rel = relocs;
- relend = relocs + input_section->reloc_count;
- for (; rel < relend; rel++)
- {
- int r_type;
- reloc_howto_type *howto;
- unsigned long r_symndx;
- Elf_Internal_Sym *sym;
- asection *sec;
- struct elf_link_hash_entry *h;
- bfd_vma relocation;
- bfd_vma addend = (bfd_vma) 0;
- bfd_reloc_status_type r;
- int seen_stt_datalabel = 0;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
-
- r_type = ELF32_R_TYPE (rel->r_info);
-
- /* Many of the relocs are only used for relaxing, and are
- handled entirely by the relaxation code. */
- if (r_type > (int) R_SH_LAST_INVALID_RELOC
- && r_type < (int) R_SH_LOOP_START)
- continue;
- if (r_type == (int) R_SH_NONE)
- continue;
-
- if (r_type < 0
- || r_type >= R_SH_max
- || (r_type >= (int) R_SH_FIRST_INVALID_RELOC
- && r_type <= (int) R_SH_LAST_INVALID_RELOC)
- || ( r_type >= (int) R_SH_FIRST_INVALID_RELOC_3
- && r_type <= (int) R_SH_LAST_INVALID_RELOC_3)
- || ( r_type >= (int) R_SH_FIRST_INVALID_RELOC_4
- && r_type <= (int) R_SH_LAST_INVALID_RELOC_4)
- || (r_type >= (int) R_SH_FIRST_INVALID_RELOC_2
- && r_type <= (int) R_SH_LAST_INVALID_RELOC_2))
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- howto = sh_elf_howto_table + r_type;
-
- /* For relocs that aren't partial_inplace, we get the addend from
- the relocation. */
- if (! howto->partial_inplace)
- addend = rel->r_addend;
-
- h = NULL;
- sym = NULL;
- sec = NULL;
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- sec = local_sections[r_symndx];
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
- /* A local symbol never has STO_SH5_ISA32, so we don't need
- datalabel processing here. Make sure this does not change
- without notice. */
- if ((sym->st_other & STO_SH5_ISA32) != 0)
- ((*info->callbacks->reloc_dangerous)
- (info,
- _("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
- input_bfd, input_section, rel->r_offset));
- 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. */
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- if (! howto->partial_inplace)
- {
- /* For relocations with the addend in the
- relocation, we need just to update the addend.
- All real relocs are of type partial_inplace; this
- code is mostly for completeness. */
- rel->r_addend += sec->output_offset + sym->st_value;
-
- continue;
- }
-
- /* Relocs of type partial_inplace need to pick up the
- contents in the contents and add the offset resulting
- from the changed location of the section symbol.
- Using _bfd_final_link_relocate (e.g. goto
- final_link_relocate) here would be wrong, because
- relocations marked pc_relative would get the current
- location subtracted, and we must only do that at the
- final link. */
- r = _bfd_relocate_contents (howto, input_bfd,
- sec->output_offset
- + sym->st_value,
- contents + rel->r_offset);
- goto relocation_done;
- }
-
- continue;
- }
- else if (! howto->partial_inplace)
- {
- relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
- addend = rel->r_addend;
- }
- else if ((sec->flags & SEC_MERGE)
- && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- asection *msec;
-
- if (howto->rightshift || howto->src_mask != 0xffffffff)
- {
- (*_bfd_error_handler)
- (_("%s(%s+0x%lx): %s relocation against SEC_MERGE section"),
- bfd_archive_filename (input_bfd),
- bfd_get_section_name (input_bfd, input_section),
- (long) rel->r_offset, howto->name);
- return false;
- }
-
- addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
- msec = sec;
- addend =
- _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend)
- - relocation;
- addend += msec->output_section->vma + msec->output_offset;
- bfd_put_32 (input_bfd, addend, contents + rel->r_offset);
- addend = 0;
- }
- }
- else
- {
- /* Section symbol are never (?) placed in the hash table, so
- we can just ignore hash relocations when creating a
- relocateable object file. */
- if (info->relocateable)
- continue;
-
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- {
-#ifdef INCLUDE_SHMEDIA
- /* If the reference passes a symbol marked with
- STT_DATALABEL, then any STO_SH5_ISA32 on the final value
- doesn't count. */
- seen_stt_datalabel |= h->type == STT_DATALABEL;
-#endif
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- boolean dyn;
-
- dyn = htab->root.dynamic_sections_created;
- sec = h->root.u.def.section;
- /* In these cases, we don't need the relocation value.
- We check specially because in some obscure cases
- sec->output_section will be NULL. */
- if (r_type == R_SH_GOTPC
- || r_type == R_SH_GOTPC_LOW16
- || r_type == R_SH_GOTPC_MEDLOW16
- || r_type == R_SH_GOTPC_MEDHI16
- || r_type == R_SH_GOTPC_HI16
- || ((r_type == R_SH_PLT32
- || r_type == R_SH_PLT_LOW16
- || r_type == R_SH_PLT_MEDLOW16
- || r_type == R_SH_PLT_MEDHI16
- || r_type == R_SH_PLT_HI16)
- && h->plt.offset != (bfd_vma) -1)
- || ((r_type == R_SH_GOT32
- || r_type == R_SH_GOT_LOW16
- || r_type == R_SH_GOT_MEDLOW16
- || r_type == R_SH_GOT_MEDHI16
- || r_type == R_SH_GOT_HI16)
- && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
- && (! info->shared
- || (! info->symbolic && h->dynindx != -1)
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- /* The cases above are those in which relocation is
- overwritten in the switch block below. The cases
- below are those in which we must defer relocation
- to run-time, because we can't resolve absolute
- addresses when creating a shared library. */
- || (info->shared
- && ((! info->symbolic && h->dynindx != -1)
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)
- && ((r_type == R_SH_DIR32
- && (h->elf_link_hash_flags
- & ELF_LINK_FORCED_LOCAL) == 0)
- || r_type == R_SH_REL32)
- && ((input_section->flags & SEC_ALLOC) != 0
- /* DWARF will emit R_SH_DIR32 relocations in its
- sections against symbols defined externally
- in shared libraries. We can't do anything
- with them here. */
- || ((input_section->flags & SEC_DEBUGGING) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
- relocation = 0;
- else if (sec->output_section == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
- bfd_archive_filename (input_bfd), h->root.root.string,
- bfd_get_section_name (input_bfd, input_section));
- relocation = 0;
- }
- else
- relocation = ((h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset)
- /* A STO_SH5_ISA32 causes a "bitor 1" to the
- symbol value, unless we've seen
- STT_DATALABEL on the way to it. */
- | ((h->other & STO_SH5_ISA32) != 0
- && ! seen_stt_datalabel));
- }
- else if (h->root.type == bfd_link_hash_undefweak)
- relocation = 0;
- else if (info->shared
- && (! info->symbolic || info->allow_shlib_undefined)
- && ! info->no_undefined
- && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
- relocation = 0;
- else
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd,
- input_section, rel->r_offset,
- (!info->shared || info->no_undefined
- || ELF_ST_VISIBILITY (h->other)))))
- return false;
- relocation = 0;
- }
- }
-
- switch ((int) r_type)
- {
- final_link_relocate:
- /* COFF relocs don't use the addend. The addend is used for
- R_SH_DIR32 to be compatible with other compilers. */
- r = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, rel->r_offset,
- relocation, addend);
- break;
-
- case R_SH_IND12W:
- relocation -= 4;
- goto final_link_relocate;
-
- case R_SH_DIR8WPN:
- case R_SH_DIR8WPZ:
- case R_SH_DIR8WPL:
- /* If the reloc is against the start of this section, then
- the assembler has already taken care of it and the reloc
- is here only to assist in relaxing. If the reloc is not
- against the start of this section, then it's against an
- external symbol and we must deal with it ourselves. */
- if (input_section->output_section->vma + input_section->output_offset
- != relocation)
- {
- int disp = (relocation
- - input_section->output_section->vma
- - input_section->output_offset
- - rel->r_offset);
- int mask = 0;
- switch (r_type)
- {
- case R_SH_DIR8WPN:
- case R_SH_DIR8WPZ: mask = 1; break;
- case R_SH_DIR8WPL: mask = 3; break;
- default: mask = 0; break;
- }
- if (disp & mask)
- {
- ((*_bfd_error_handler)
- (_("%s: 0x%lx: fatal: unaligned branch target for relax-support relocation"),
- bfd_archive_filename (input_section->owner),
- (unsigned long) rel->r_offset));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- relocation -= 4;
- goto final_link_relocate;
- }
- r = bfd_reloc_ok;
- break;
-
- default:
-#ifdef INCLUDE_SHMEDIA
- if (shmedia_prepare_reloc (info, input_bfd, input_section,
- contents, rel, &relocation))
- goto final_link_relocate;
-#endif
- bfd_set_error (bfd_error_bad_value);
- return false;
-
- case R_SH_DIR32:
- case R_SH_REL32:
- if (info->shared
- && r_symndx != 0
- && (input_section->flags & SEC_ALLOC) != 0
- && (r_type != R_SH_REL32
- || (h != NULL
- && h->dynindx != -1
- && (! info->symbolic
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))))
- {
- Elf_Internal_Rela outrel;
- boolean skip, relocate;
-
- /* When generating a shared object, these relocations
- are copied into the output file to be resolved at run
- time. */
-
- if (sreloc == NULL)
- {
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd,
- elf_elfheader (input_bfd)->e_shstrndx,
- elf_section_data (input_section)->rel_hdr.sh_name));
- if (name == NULL)
- return false;
-
- BFD_ASSERT (strncmp (name, ".rela", 5) == 0
- && strcmp (bfd_get_section_name (input_bfd,
- input_section),
- name + 5) == 0);
-
- sreloc = bfd_get_section_by_name (dynobj, name);
- BFD_ASSERT (sreloc != NULL);
- }
-
- skip = false;
- relocate = false;
-
- outrel.r_offset =
- _bfd_elf_section_offset (output_bfd, info, input_section,
- rel->r_offset);
- if (outrel.r_offset == (bfd_vma) -1)
- skip = true;
- else if (outrel.r_offset == (bfd_vma) -2)
- skip = true, relocate = true;
- outrel.r_offset += (input_section->output_section->vma
- + input_section->output_offset);
-
- if (skip)
- memset (&outrel, 0, sizeof outrel);
- else if (r_type == R_SH_REL32)
- {
- BFD_ASSERT (h != NULL && h->dynindx != -1);
- outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
- outrel.r_addend
- = bfd_get_32 (input_bfd, contents + rel->r_offset);
- }
- else
- {
- /* h->dynindx may be -1 if this symbol was marked to
- become local. */
- if (h == NULL
- || ((info->symbolic || h->dynindx == -1)
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) != 0))
- {
- relocate = true;
- outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
- outrel.r_addend
- = relocation + bfd_get_32 (input_bfd,
- contents + rel->r_offset);
- }
- else
- {
- BFD_ASSERT (h->dynindx != -1);
- outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
- outrel.r_addend
- = relocation + bfd_get_32 (input_bfd,
- contents + rel->r_offset);
- }
- }
-
- bfd_elf32_swap_reloca_out (output_bfd, &outrel,
- (((Elf32_External_Rela *)
- sreloc->contents)
- + sreloc->reloc_count));
- ++sreloc->reloc_count;
-
- /* If this reloc is against an external symbol, we do
- not want to fiddle with the addend. Otherwise, we
- need to include the symbol value so that it becomes
- an addend for the dynamic reloc. */
- if (! relocate)
- continue;
- }
- goto final_link_relocate;
-
- case R_SH_GOTPLT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOTPLT_LOW16:
- case R_SH_GOTPLT_MEDLOW16:
- case R_SH_GOTPLT_MEDHI16:
- case R_SH_GOTPLT_HI16:
- case R_SH_GOTPLT10BY4:
- case R_SH_GOTPLT10BY8:
-#endif
- /* Relocation is to the entry for this symbol in the
- procedure linkage table. */
-
- if (h == NULL
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
- || ! info->shared
- || info->symbolic
- || h->dynindx == -1
- || h->plt.offset == (bfd_vma) -1
- || h->got.offset != (bfd_vma) -1)
- goto force_got;
-
- /* Relocation is to the entry for this symbol in the global
- offset table extension for the procedure linkage table. */
-
- BFD_ASSERT (sgotplt != NULL);
- relocation = (sgotplt->output_offset
- + ((h->plt.offset / elf_sh_sizeof_plt (info)
- - 1 + 3) * 4));
-
-#ifdef GOT_BIAS
- relocation -= GOT_BIAS;
-#endif
-
- goto final_link_relocate;
-
- force_got:
- case R_SH_GOT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOT_LOW16:
- case R_SH_GOT_MEDLOW16:
- case R_SH_GOT_MEDHI16:
- case R_SH_GOT_HI16:
- case R_SH_GOT10BY4:
- case R_SH_GOT10BY8:
-#endif
- /* Relocation is to the entry for this symbol in the global
- offset table. */
-
- BFD_ASSERT (sgot != NULL);
-
- if (h != NULL)
- {
- bfd_vma off;
- boolean dyn;
-
- off = h->got.offset;
-#ifdef INCLUDE_SHMEDIA
- if (seen_stt_datalabel)
- {
- struct elf_sh_link_hash_entry *hsh;
-
- hsh = (struct elf_sh_link_hash_entry *)h;
- off = hsh->datalabel_got_offset;
- }
-#endif
- BFD_ASSERT (off != (bfd_vma) -1);
-
- dyn = htab->root.dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
- || (info->shared
- && (info->symbolic || h->dynindx == -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
- {
- /* This is actually a static link, or it is a
- -Bsymbolic link and the symbol is defined
- locally, or the symbol was forced to be local
- because of a version file. We must initialize
- this entry in the global offset table. Since the
- offset must always be a multiple of 4, we use the
- least significant bit to record whether we have
- initialized it already.
-
- When doing a dynamic link, we create a .rela.got
- relocation entry to initialize the value. This
- is done in the finish_dynamic_symbol routine. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation,
- sgot->contents + off);
-#ifdef INCLUDE_SHMEDIA
- if (seen_stt_datalabel)
- {
- struct elf_sh_link_hash_entry *hsh;
-
- hsh = (struct elf_sh_link_hash_entry *)h;
- hsh->datalabel_got_offset |= 1;
- }
- else
-#endif
- h->got.offset |= 1;
- }
- }
-
- relocation = sgot->output_offset + off;
- }
- else
- {
- bfd_vma off;
-
-#ifdef INCLUDE_SHMEDIA
- if (rel->r_addend)
- {
- BFD_ASSERT (local_got_offsets != NULL
- && (local_got_offsets[symtab_hdr->sh_info
- + r_symndx]
- != (bfd_vma) -1));
-
- off = local_got_offsets[symtab_hdr->sh_info
- + r_symndx];
- }
- else
- {
-#endif
- BFD_ASSERT (local_got_offsets != NULL
- && local_got_offsets[r_symndx] != (bfd_vma) -1);
-
- off = local_got_offsets[r_symndx];
-#ifdef INCLUDE_SHMEDIA
- }
-#endif
-
- /* The offset must always be a multiple of 4. We use
- the least significant bit to record whether we have
- already generated the necessary reloc. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation, sgot->contents + off);
-
- if (info->shared)
- {
- asection *srelgot;
- Elf_Internal_Rela outrel;
-
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- BFD_ASSERT (srelgot != NULL);
-
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + off);
- outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
- outrel.r_addend = relocation;
- bfd_elf32_swap_reloca_out (output_bfd, &outrel,
- (((Elf32_External_Rela *)
- srelgot->contents)
- + srelgot->reloc_count));
- ++srelgot->reloc_count;
- }
-
-#ifdef INCLUDE_SHMEDIA
- if (rel->r_addend)
- local_got_offsets[symtab_hdr->sh_info + r_symndx] |= 1;
- else
-#endif
- local_got_offsets[r_symndx] |= 1;
- }
-
- relocation = sgot->output_offset + off;
- }
-
-#ifdef GOT_BIAS
- relocation -= GOT_BIAS;
-#endif
-
- goto final_link_relocate;
-
- case R_SH_GOTOFF:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOTOFF_LOW16:
- case R_SH_GOTOFF_MEDLOW16:
- case R_SH_GOTOFF_MEDHI16:
- case R_SH_GOTOFF_HI16:
-#endif
- /* Relocation is relative to the start of the global offset
- table. */
-
- BFD_ASSERT (sgot != NULL);
-
- /* Note that sgot->output_offset is not involved in this
- calculation. We always want the start of .got. If we
- defined _GLOBAL_OFFSET_TABLE in a different way, as is
- permitted by the ABI, we might have to change this
- calculation. */
- relocation -= sgot->output_section->vma;
-
-#ifdef GOT_BIAS
- relocation -= GOT_BIAS;
-#endif
-
- addend = rel->r_addend;
-
- goto final_link_relocate;
-
- case R_SH_GOTPC:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOTPC_LOW16:
- case R_SH_GOTPC_MEDLOW16:
- case R_SH_GOTPC_MEDHI16:
- case R_SH_GOTPC_HI16:
-#endif
- /* Use global offset table as symbol value. */
-
- BFD_ASSERT (sgot != NULL);
- relocation = sgot->output_section->vma;
-
-#ifdef GOT_BIAS
- relocation += GOT_BIAS;
-#endif
-
- addend = rel->r_addend;
-
- goto final_link_relocate;
-
- case R_SH_PLT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_PLT_LOW16:
- case R_SH_PLT_MEDLOW16:
- case R_SH_PLT_MEDHI16:
- case R_SH_PLT_HI16:
-#endif
- /* Relocation is to the entry for this symbol in the
- procedure linkage table. */
-
- /* Resolve a PLT reloc against a local symbol directly,
- without using the procedure linkage table. */
- if (h == NULL)
- goto final_link_relocate;
-
- if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
- goto final_link_relocate;
-
- if (h->plt.offset == (bfd_vma) -1)
- {
- /* We didn't make a PLT entry for this symbol. This
- happens when statically linking PIC code, or when
- using -Bsymbolic. */
- goto final_link_relocate;
- }
-
- BFD_ASSERT (splt != NULL);
- relocation = (splt->output_section->vma
- + splt->output_offset
- + h->plt.offset);
-
-#ifdef INCLUDE_SHMEDIA
- relocation++;
-#endif
-
- addend = rel->r_addend;
-
- goto final_link_relocate;
-
- case R_SH_LOOP_START:
- {
- static bfd_vma start, end;
-
- start = (relocation + rel->r_addend
- - (sec->output_section->vma + sec->output_offset));
- r = sh_elf_reloc_loop (r_type, input_bfd, input_section, contents,
- rel->r_offset, sec, start, end);
- break;
-
- case R_SH_LOOP_END:
- end = (relocation + rel->r_addend
- - (sec->output_section->vma + sec->output_offset));
- r = sh_elf_reloc_loop (r_type, input_bfd, input_section, contents,
- rel->r_offset, sec, start, end);
- break;
- }
- }
-
- relocation_done:
- if (r != bfd_reloc_ok)
- {
- switch (r)
- {
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
- {
- const char *name;
-
- if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = (bfd_elf_string_from_elf_section
- (input_bfd, symtab_hdr->sh_link, sym->st_name));
- if (name == NULL)
- return false;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, sec);
- }
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset)))
- return false;
- }
- break;
- }
- }
- }
-
- return true;
-}
-
-/* This is a version of bfd_generic_get_relocated_section_contents
- which uses sh_elf_relocate_section. */
-
-static bfd_byte *
-sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
- data, relocateable, symbols)
- bfd *output_bfd;
- struct bfd_link_info *link_info;
- struct bfd_link_order *link_order;
- bfd_byte *data;
- boolean relocateable;
- asymbol **symbols;
-{
- Elf_Internal_Shdr *symtab_hdr;
- asection *input_section = link_order->u.indirect.section;
- bfd *input_bfd = input_section->owner;
- asection **sections = NULL;
- Elf_Internal_Rela *internal_relocs = NULL;
- Elf_Internal_Sym *isymbuf = NULL;
-
- /* We only need to handle the case of relaxing, or of having a
- particular set of section contents, specially. */
- if (relocateable
- || elf_section_data (input_section)->this_hdr.contents == NULL)
- return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
- link_order, data,
- relocateable,
- symbols);
-
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-
- memcpy (data, elf_section_data (input_section)->this_hdr.contents,
- (size_t) input_section->_raw_size);
-
- if ((input_section->flags & SEC_RELOC) != 0
- && input_section->reloc_count > 0)
- {
- asection **secpp;
- Elf_Internal_Sym *isym, *isymend;
- bfd_size_type amt;
-
- internal_relocs = (_bfd_elf32_link_read_relocs
- (input_bfd, input_section, (PTR) NULL,
- (Elf_Internal_Rela *) NULL, false));
- if (internal_relocs == NULL)
- goto error_return;
-
- if (symtab_hdr->sh_info != 0)
- {
- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (isymbuf == NULL)
- isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
- symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
- if (isymbuf == NULL)
- goto error_return;
- }
-
- amt = symtab_hdr->sh_info;
- amt *= sizeof (asection *);
- sections = (asection **) bfd_malloc (amt);
- if (sections == NULL && amt != 0)
- goto error_return;
-
- isymend = isymbuf + symtab_hdr->sh_info;
- for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
- {
- asection *isec;
-
- if (isym->st_shndx == SHN_UNDEF)
- isec = bfd_und_section_ptr;
- else if (isym->st_shndx == SHN_ABS)
- isec = bfd_abs_section_ptr;
- else if (isym->st_shndx == SHN_COMMON)
- isec = bfd_com_section_ptr;
- else
- isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
-
- *secpp = isec;
- }
-
- if (! sh_elf_relocate_section (output_bfd, link_info, input_bfd,
- input_section, data, internal_relocs,
- isymbuf, sections))
- goto error_return;
-
- if (sections != NULL)
- free (sections);
- if (isymbuf != NULL
- && symtab_hdr->contents != (unsigned char *) isymbuf)
- free (isymbuf);
- if (elf_section_data (input_section)->relocs != internal_relocs)
- free (internal_relocs);
- }
-
- return data;
-
- error_return:
- if (sections != NULL)
- free (sections);
- if (isymbuf != NULL
- && symtab_hdr->contents != (unsigned char *) isymbuf)
- free (isymbuf);
- if (internal_relocs != NULL
- && elf_section_data (input_section)->relocs != internal_relocs)
- free (internal_relocs);
- return NULL;
-}
-
-static asection *
-sh_elf_gc_mark_hook (sec, info, rel, h, sym)
- asection *sec;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_SH_GNU_VTINHERIT:
- case R_SH_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
-}
-
-/* Update the got entry reference counts for the section being removed. */
-
-static boolean
-sh_elf_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
-{
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel, *relend;
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
- struct elf_sh_link_hash_entry *eh;
-
- elf_section_data (sec)->local_dynrel = NULL;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_SH_GOT32:
- case R_SH_GOTOFF:
- case R_SH_GOTPC:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOT_LOW16:
- case R_SH_GOT_MEDLOW16:
- case R_SH_GOT_MEDHI16:
- case R_SH_GOT_HI16:
- case R_SH_GOT10BY4:
- case R_SH_GOT10BY8:
- case R_SH_GOTOFF_LOW16:
- case R_SH_GOTOFF_MEDLOW16:
- case R_SH_GOTOFF_MEDHI16:
- case R_SH_GOTOFF_HI16:
- case R_SH_GOTPC_LOW16:
- case R_SH_GOTPC_MEDLOW16:
- case R_SH_GOTPC_MEDHI16:
- case R_SH_GOTPC_HI16:
-#endif
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h->got.refcount > 0)
- h->got.refcount -= 1;
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- local_got_refcounts[r_symndx] -= 1;
- }
- break;
-
- case R_SH_DIR32:
- case R_SH_REL32:
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- struct elf_sh_link_hash_entry *eh;
- struct elf_sh_dyn_relocs **pp;
- struct elf_sh_dyn_relocs *p;
-
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
- if (!info->shared && h->plt.refcount > 0)
- h->plt.refcount -= 1;
-
- eh = (struct elf_sh_link_hash_entry *) h;
-
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
- if (p->sec == sec)
- {
- if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32)
- p->pc_count -= 1;
- p->count -= 1;
- if (p->count == 0)
- *pp = p->next;
- break;
- }
- }
- break;
-
- case R_SH_PLT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_PLT_LOW16:
- case R_SH_PLT_MEDLOW16:
- case R_SH_PLT_MEDHI16:
- case R_SH_PLT_HI16:
-#endif
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h->plt.refcount > 0)
- h->plt.refcount -= 1;
- }
- break;
-
- case R_SH_GOTPLT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOTPLT_LOW16:
- case R_SH_GOTPLT_MEDLOW16:
- case R_SH_GOTPLT_MEDHI16:
- case R_SH_GOTPLT_HI16:
- case R_SH_GOTPLT10BY4:
- case R_SH_GOTPLT10BY8:
-#endif
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- eh = (struct elf_sh_link_hash_entry *) h;
- if (eh->gotplt_refcount > 0)
- {
- eh->gotplt_refcount -= 1;
- if (h->plt.refcount > 0)
- h->plt.refcount -= 1;
- }
- else if (h->got.refcount > 0)
- h->got.refcount -= 1;
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- local_got_refcounts[r_symndx] -= 1;
- }
- break;
-
- default:
- break;
- }
-
- return true;
-}
-
-/* Copy the extra info we tack onto an elf_link_hash_entry. */
-
-static void
-sh_elf_copy_indirect_symbol (bed, dir, ind)
- struct elf_backend_data *bed;
- struct elf_link_hash_entry *dir, *ind;
-{
- struct elf_sh_link_hash_entry *edir, *eind;
-
- edir = (struct elf_sh_link_hash_entry *) dir;
- eind = (struct elf_sh_link_hash_entry *) ind;
-
- if (eind->dyn_relocs != NULL)
- {
- if (edir->dyn_relocs != NULL)
- {
- struct elf_sh_dyn_relocs **pp;
- struct elf_sh_dyn_relocs *p;
-
- BFD_ASSERT (ind->root.type != bfd_link_hash_indirect);
-
- /* Add reloc counts against the weak sym to the strong sym
- list. Merge any entries against the same section. */
- for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
- {
- struct elf_sh_dyn_relocs *q;
-
- for (q = edir->dyn_relocs; q != NULL; q = q->next)
- if (q->sec == p->sec)
- {
- q->pc_count += p->pc_count;
- q->count += p->count;
- *pp = p->next;
- break;
- }
- if (q == NULL)
- pp = &p->next;
- }
- *pp = edir->dyn_relocs;
- }
-
- edir->dyn_relocs = eind->dyn_relocs;
- eind->dyn_relocs = NULL;
- }
- edir->gotplt_refcount = eind->gotplt_refcount;
- eind->gotplt_refcount = 0;
-
- _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
-}
-
-/* Look through the relocs for a section during the first phase.
- Since we don't do .gots or .plts, we just need to consider the
- virtual table relocs for gc. */
-
-static boolean
-sh_elf_check_relocs (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
-{
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
- struct elf_sh_link_hash_table *htab;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
- bfd *dynobj;
- bfd_vma *local_got_offsets;
- asection *sgot;
- asection *srelgot;
- asection *sreloc;
-
- sgot = NULL;
- srelgot = NULL;
- sreloc = NULL;
-
- if (info->relocateable)
- return true;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
- if (!elf_bad_symtab (abfd))
- sym_hashes_end -= symtab_hdr->sh_info;
-
- htab = sh_elf_hash_table (info);
- dynobj = htab->root.dynobj;
- local_got_offsets = elf_local_got_offsets (abfd);
-
- rel_end = relocs + sec->reloc_count;
- for (rel = relocs; rel < rel_end; rel++)
- {
- struct elf_link_hash_entry *h;
- unsigned long r_symndx;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
- else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
- /* Some relocs require a global offset table. */
- if (htab->sgot == NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_SH_GOTPLT32:
- case R_SH_GOT32:
- case R_SH_GOTOFF:
- case R_SH_GOTPC:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOTPLT_LOW16:
- case R_SH_GOTPLT_MEDLOW16:
- case R_SH_GOTPLT_MEDHI16:
- case R_SH_GOTPLT_HI16:
- case R_SH_GOTPLT10BY4:
- case R_SH_GOTPLT10BY8:
- case R_SH_GOT_LOW16:
- case R_SH_GOT_MEDLOW16:
- case R_SH_GOT_MEDHI16:
- case R_SH_GOT_HI16:
- case R_SH_GOT10BY4:
- case R_SH_GOT10BY8:
- case R_SH_GOTOFF_LOW16:
- case R_SH_GOTOFF_MEDLOW16:
- case R_SH_GOTOFF_MEDHI16:
- case R_SH_GOTOFF_HI16:
- case R_SH_GOTPC_LOW16:
- case R_SH_GOTPC_MEDLOW16:
- case R_SH_GOTPC_MEDHI16:
- case R_SH_GOTPC_HI16:
-#endif
- if (dynobj == NULL)
- htab->root.dynobj = dynobj = abfd;
- if (! create_got_section (dynobj, info))
- return false;
- break;
-
- default:
- break;
- }
- }
-
- switch (ELF32_R_TYPE (rel->r_info))
- {
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_SH_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return false;
- break;
-
- /* This relocation describes which C++ vtable entries are actually
- used. Record for later use during GC. */
- case R_SH_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
- return false;
- break;
-
- force_got:
- case R_SH_GOT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOT_LOW16:
- case R_SH_GOT_MEDLOW16:
- case R_SH_GOT_MEDHI16:
- case R_SH_GOT_HI16:
- case R_SH_GOT10BY4:
- case R_SH_GOT10BY8:
-#endif
- if (h != NULL)
- h->got.refcount += 1;
- else
- {
- bfd_signed_vma *local_got_refcounts;
-
- /* This is a global offset table entry for a local
- symbol. */
- local_got_refcounts = elf_local_got_refcounts (abfd);
- if (local_got_refcounts == NULL)
- {
- bfd_size_type size;
-
- size = symtab_hdr->sh_info;
- size *= sizeof (bfd_signed_vma);
-#ifdef INCLUDE_SHMEDIA
- /* Reserve space for both the datalabel and
- codelabel local GOT offsets. */
- size *= 2;
-#endif
- local_got_refcounts = ((bfd_signed_vma *)
- bfd_zalloc (abfd, size));
- if (local_got_refcounts == NULL)
- return false;
- elf_local_got_refcounts (abfd) = local_got_refcounts;
- }
- local_got_refcounts[r_symndx] += 1;
- }
- break;
-
- case R_SH_GOTPLT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_GOTPLT_LOW16:
- case R_SH_GOTPLT_MEDLOW16:
- case R_SH_GOTPLT_MEDHI16:
- case R_SH_GOTPLT_HI16:
- case R_SH_GOTPLT10BY4:
- case R_SH_GOTPLT10BY8:
-#endif
- /* If this is a local symbol, we resolve it directly without
- creating a procedure linkage table entry. */
-
- if (h == NULL
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
- || ! info->shared
- || info->symbolic
- || h->dynindx == -1)
- goto force_got;
-
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->plt.refcount += 1;
- ((struct elf_sh_link_hash_entry *) h)->gotplt_refcount += 1;
-
- break;
-
- case R_SH_PLT32:
-#ifdef INCLUDE_SHMEDIA
- case R_SH_PLT_LOW16:
- case R_SH_PLT_MEDLOW16:
- case R_SH_PLT_MEDHI16:
- case R_SH_PLT_HI16:
-#endif
- /* This symbol requires a procedure linkage table entry. We
- actually build the entry in adjust_dynamic_symbol,
- because this might be a case of linking PIC code which is
- never referenced by a dynamic object, in which case we
- don't need to generate a procedure linkage table entry
- after all. */
-
- /* If this is a local symbol, we resolve it directly without
- creating a procedure linkage table entry. */
- if (h == NULL)
- continue;
-
- if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
- break;
-
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->plt.refcount += 1;
- break;
-
- case R_SH_DIR32:
- case R_SH_REL32:
- if (h != NULL && ! info->shared)
- {
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
- h->plt.refcount += 1;
- }
-
- /* If we are creating a shared library, and this is a reloc
- against a global symbol, or a non PC relative reloc
- against a local symbol, then we need to copy the reloc
- into the shared library. However, if we are linking with
- -Bsymbolic, we do not need to copy a reloc against a
- global symbol which is defined in an object we are
- including in the link (i.e., DEF_REGULAR is set). At
- this point we have not seen all the input files, so it is
- possible that DEF_REGULAR is not set now but will be set
- later (it is never cleared). We account for that
- possibility below by storing information in the
- dyn_relocs field of the hash table entry. A similar
- situation occurs when creating shared libraries and symbol
- visibility changes render the symbol local.
-
- If on the other hand, we are creating an executable, we
- may need to keep relocations for symbols satisfied by a
- dynamic library if we manage to avoid copy relocs for the
- symbol. */
- if ((info->shared
- && (sec->flags & SEC_ALLOC) != 0
- && (ELF32_R_TYPE (rel->r_info) != R_SH_REL32
- || (h != NULL
- && (! info->symbolic
- || h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))))
- || (! info->shared
- && (sec->flags & SEC_ALLOC) != 0
- && h != NULL
- && (h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
- {
- struct elf_sh_dyn_relocs *p;
- struct elf_sh_dyn_relocs **head;
-
- if (dynobj == NULL)
- htab->root.dynobj = dynobj = abfd;
-
- /* When creating a shared object, we must copy these
- reloc types into the output file. We create a reloc
- section in dynobj and make room for this reloc. */
- if (sreloc == NULL)
- {
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name));
- if (name == NULL)
- return false;
-
- BFD_ASSERT (strncmp (name, ".rela", 5) == 0
- && strcmp (bfd_get_section_name (abfd, sec),
- name + 5) == 0);
-
- sreloc = bfd_get_section_by_name (dynobj, name);
- if (sreloc == NULL)
- {
- flagword flags;
-
- sreloc = bfd_make_section (dynobj, name);
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc, flags)
- || ! bfd_set_section_alignment (dynobj, sreloc, 2))
- return false;
- }
- if (sec->flags & SEC_READONLY)
- info->flags |= DF_TEXTREL;
- elf_section_data (sec)->sreloc = sreloc;
- }
-
- /* If this is a global symbol, we count the number of
- relocations we need for this symbol. */
- if (h != NULL)
- head = &((struct elf_sh_link_hash_entry *) h)->dyn_relocs;
- else
- {
- asection *s;
-
- /* Track dynamic relocs needed for local syms too. */
- s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
- sec, r_symndx);
- if (s == NULL)
- return false;
-
- head = ((struct elf_sh_dyn_relocs **)
- &elf_section_data (s)->local_dynrel);
- }
-
- p = *head;
- if (p == NULL || p->sec != sec)
- {
- bfd_size_type amt = sizeof (*p);
- p = ((struct elf_sh_dyn_relocs *) bfd_alloc (dynobj, amt));
- if (p == NULL)
- return false;
- p->next = *head;
- *head = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- p->count += 1;
- if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32)
- p->pc_count += 1;
- }
-
- break;
- }
- }
-
- return true;
-}
-
-#ifndef sh_elf_set_mach_from_flags
-static boolean
-sh_elf_set_mach_from_flags (abfd)
- bfd *abfd;
-{
- flagword flags = elf_elfheader (abfd)->e_flags;
-
- switch (flags & EF_SH_MACH_MASK)
- {
- case EF_SH1:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh);
- break;
- case EF_SH2:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh2);
- break;
- case EF_SH_DSP:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh_dsp);
- break;
- case EF_SH3:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3);
- break;
- case EF_SH3_DSP:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3_dsp);
- break;
- case EF_SH3E:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3e);
- break;
- case EF_SH_UNKNOWN:
- case EF_SH4:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4);
- break;
- default:
- return false;
- }
- return true;
-}
-#endif /* not sh_elf_set_mach_from_flags */
-
-#ifndef sh_elf_set_private_flags
-/* Function to keep SH specific file flags. */
-
-static boolean
-sh_elf_set_private_flags (abfd, flags)
- bfd *abfd;
- flagword flags;
-{
- BFD_ASSERT (! elf_flags_init (abfd)
- || elf_elfheader (abfd)->e_flags == flags);
-
- elf_elfheader (abfd)->e_flags = flags;
- elf_flags_init (abfd) = true;
- return sh_elf_set_mach_from_flags (abfd);
-}
-#endif /* not sh_elf_set_private_flags */
-
-#ifndef sh_elf_copy_private_data
-/* Copy backend specific data from one object module to another */
-
-static boolean
-sh_elf_copy_private_data (ibfd, obfd)
- bfd * ibfd;
- bfd * obfd;
-{
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
-}
-#endif /* not sh_elf_copy_private_data */
-
-#ifndef sh_elf_merge_private_data
-/* This routine checks for linking big and little endian objects
- together, and for linking sh-dsp with sh3e / sh4 objects. */
-
-static boolean
-sh_elf_merge_private_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
-{
- flagword old_flags, new_flags;
-
- if (! _bfd_generic_verify_endian_match (ibfd, obfd))
- return false;
-
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- if (! elf_flags_init (obfd))
- {
- /* This happens when ld starts out with a 'blank' output file. */
- elf_flags_init (obfd) = true;
- elf_elfheader (obfd)->e_flags = EF_SH1;
- }
- old_flags = elf_elfheader (obfd)->e_flags;
- new_flags = elf_elfheader (ibfd)->e_flags;
- if ((EF_SH_HAS_DSP (old_flags) && EF_SH_HAS_FP (new_flags))
- || (EF_SH_HAS_DSP (new_flags) && EF_SH_HAS_FP (old_flags)))
- {
- (*_bfd_error_handler)
- ("%s: uses %s instructions while previous modules use %s instructions",
- bfd_archive_filename (ibfd),
- EF_SH_HAS_DSP (new_flags) ? "dsp" : "floating point",
- EF_SH_HAS_DSP (new_flags) ? "floating point" : "dsp");
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- elf_elfheader (obfd)->e_flags = EF_SH_MERGE_MACH (old_flags, new_flags);
-
- return sh_elf_set_mach_from_flags (obfd);
-}
-#endif /* not sh_elf_merge_private_data */
-
-/* Finish up dynamic symbol handling. We set the contents of various
- dynamic sections here. */
-
-static boolean
-sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
- bfd *output_bfd;
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- struct elf_sh_link_hash_table *htab;
- bfd *dynobj;
-
- htab = sh_elf_hash_table (info);
- dynobj = htab->root.dynobj;
-
- if (h->plt.offset != (bfd_vma) -1)
- {
- asection *splt;
- asection *sgot;
- asection *srel;
-
- bfd_vma plt_index;
- bfd_vma got_offset;
- Elf_Internal_Rela rel;
-
- /* This symbol has an entry in the procedure linkage table. Set
- it up. */
-
- BFD_ASSERT (h->dynindx != -1);
-
- splt = htab->splt;
- sgot = htab->sgotplt;
- srel = htab->srelplt;
- BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
-
- /* Get the index in the procedure linkage table which
- corresponds to this symbol. This is the index of this symbol
- in all the symbols for which we are making plt entries. The
- first entry in the procedure linkage table is reserved. */
- plt_index = h->plt.offset / elf_sh_sizeof_plt (info) - 1;
-
- /* Get the offset into the .got table of the entry that
- corresponds to this function. Each .got entry is 4 bytes.
- The first three are reserved. */
- got_offset = (plt_index + 3) * 4;
-
-#ifdef GOT_BIAS
- got_offset -= GOT_BIAS;
-#endif
-
- /* Fill in the entry in the procedure linkage table. */
- if (! info->shared)
- {
- if (elf_sh_plt_entry == NULL)
- {
- elf_sh_plt_entry = (bfd_big_endian (output_bfd) ?
- elf_sh_plt_entry_be : elf_sh_plt_entry_le);
- }
- memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
- elf_sh_sizeof_plt (info));
-#ifdef INCLUDE_SHMEDIA
- movi_shori_putval (output_bfd,
- (sgot->output_section->vma
- + sgot->output_offset
- + got_offset),
- (splt->contents + h->plt.offset
- + elf_sh_plt_symbol_offset (info)));
-
- movi_shori_putval (output_bfd,
- (splt->output_section->vma + splt->output_offset),
- (splt->contents + h->plt.offset
- + elf_sh_plt_plt0_offset (info)));
-#else
- bfd_put_32 (output_bfd,
- (sgot->output_section->vma
- + sgot->output_offset
- + got_offset),
- (splt->contents + h->plt.offset
- + elf_sh_plt_symbol_offset (info)));
-
- bfd_put_32 (output_bfd,
- (splt->output_section->vma + splt->output_offset),
- (splt->contents + h->plt.offset
- + elf_sh_plt_plt0_offset (info)));
-#endif
- }
- else
- {
- if (elf_sh_pic_plt_entry == NULL)
- {
- elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
- elf_sh_pic_plt_entry_be :
- elf_sh_pic_plt_entry_le);
- }
- memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
- elf_sh_sizeof_plt (info));
-#ifdef INCLUDE_SHMEDIA
- movi_shori_putval (output_bfd, got_offset,
- (splt->contents + h->plt.offset
- + elf_sh_plt_symbol_offset (info)));
-#else
- bfd_put_32 (output_bfd, got_offset,
- (splt->contents + h->plt.offset
- + elf_sh_plt_symbol_offset (info)));
-#endif
- }
-
-#ifdef GOT_BIAS
- got_offset += GOT_BIAS;
-#endif
-
-#ifdef INCLUDE_SHMEDIA
- movi_shori_putval (output_bfd,
- plt_index * sizeof (Elf32_External_Rela),
- (splt->contents + h->plt.offset
- + elf_sh_plt_reloc_offset (info)));
-#else
- bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
- (splt->contents + h->plt.offset
- + elf_sh_plt_reloc_offset (info)));
-#endif
-
- /* Fill in the entry in the global offset table. */
- bfd_put_32 (output_bfd,
- (splt->output_section->vma
- + splt->output_offset
- + h->plt.offset
- + elf_sh_plt_temp_offset (info)),
- sgot->contents + got_offset);
-
- /* Fill in the entry in the .rela.plt section. */
- rel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + got_offset);
- rel.r_info = ELF32_R_INFO (h->dynindx, R_SH_JMP_SLOT);
- rel.r_addend = 0;
-#ifdef GOT_BIAS
- rel.r_addend = GOT_BIAS;
-#endif
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- ((Elf32_External_Rela *) srel->contents
- + plt_index));
-
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- {
- /* Mark the symbol as undefined, rather than as defined in
- the .plt section. Leave the value alone. */
- sym->st_shndx = SHN_UNDEF;
- }
- }
-
- if (h->got.offset != (bfd_vma) -1)
- {
- asection *sgot;
- asection *srel;
- Elf_Internal_Rela rel;
-
- /* This symbol has an entry in the global offset table. Set it
- up. */
-
- sgot = htab->sgot;
- srel = htab->srelgot;
- BFD_ASSERT (sgot != NULL && srel != NULL);
-
- rel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + (h->got.offset &~ (bfd_vma) 1));
-
- /* If this is a static link, or it is a -Bsymbolic link and the
- symbol is defined locally or was forced to be local because
- of a version file, we just want to emit a RELATIVE reloc.
- The entry in the global offset table will already have been
- initialized in the relocate_section function. */
- if (info->shared
- && (info->symbolic
- || h->dynindx == -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
- {
- rel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
- rel.r_addend = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
- else
- {
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
- rel.r_info = ELF32_R_INFO (h->dynindx, R_SH_GLOB_DAT);
- rel.r_addend = 0;
- }
-
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- ((Elf32_External_Rela *) srel->contents
- + srel->reloc_count));
- ++srel->reloc_count;
- }
-
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
- {
- asection *s;
- Elf_Internal_Rela rel;
-
- /* This symbol needs a copy reloc. Set it up. */
-
- BFD_ASSERT (h->dynindx != -1
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak));
-
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
- rel.r_offset = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- rel.r_info = ELF32_R_INFO (h->dynindx, R_SH_COPY);
- rel.r_addend = 0;
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- ((Elf32_External_Rela *) s->contents
- + s->reloc_count));
- ++s->reloc_count;
- }
-
- /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
- sym->st_shndx = SHN_ABS;
-
- return true;
-}
-
-/* Finish up the dynamic sections. */
-
-static boolean
-sh_elf_finish_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
-{
- struct elf_sh_link_hash_table *htab;
- bfd *dynobj;
- asection *sgot;
- asection *sdyn;
-
- htab = sh_elf_hash_table (info);
- dynobj = htab->root.dynobj;
-
- sgot = htab->sgotplt;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
-
- if (htab->root.dynamic_sections_created)
- {
- asection *splt;
- Elf32_External_Dyn *dyncon, *dynconend;
-
- BFD_ASSERT (sgot != NULL && sdyn != NULL);
-
- dyncon = (Elf32_External_Dyn *) sdyn->contents;
- dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
- for (; dyncon < dynconend; dyncon++)
- {
- Elf_Internal_Dyn dyn;
- asection *s;
-
- bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
-
- switch (dyn.d_tag)
- {
- default:
- break;
-
- case DT_PLTGOT:
- s = htab->sgot->output_section;
- goto get_vma;
-
- case DT_JMPREL:
- s = htab->srelplt->output_section;
- get_vma:
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
- break;
-
- case DT_PLTRELSZ:
- s = htab->srelplt->output_section;
- BFD_ASSERT (s != NULL);
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size;
- else
- dyn.d_un.d_val = s->_raw_size;
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
- break;
-
- case DT_RELASZ:
- /* My reading of the SVR4 ABI indicates that the
- procedure linkage table relocs (DT_JMPREL) should be
- included in the overall relocs (DT_RELA). This is
- what Solaris does. However, UnixWare can not handle
- that case. Therefore, we override the DT_RELASZ entry
- here to make it not include the JMPREL relocs. Since
- the linker script arranges for .rela.plt to follow all
- other relocation sections, we don't have to worry
- about changing the DT_RELA entry. */
- if (htab->srelplt != NULL)
- {
- s = htab->srelplt->output_section;
- if (s->_cooked_size != 0)
- dyn.d_un.d_val -= s->_cooked_size;
- else
- dyn.d_un.d_val -= s->_raw_size;
- }
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
- break;
- }
- }
-
- /* Fill in the first entry in the procedure linkage table. */
- splt = htab->splt;
- if (splt && splt->_raw_size > 0)
- {
- if (info->shared)
- {
- if (elf_sh_pic_plt_entry == NULL)
- {
- elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
- elf_sh_pic_plt_entry_be :
- elf_sh_pic_plt_entry_le);
- }
- memcpy (splt->contents, elf_sh_pic_plt_entry,
- elf_sh_sizeof_plt (info));
- }
- else
- {
- if (elf_sh_plt0_entry == NULL)
- {
- elf_sh_plt0_entry = (bfd_big_endian (output_bfd) ?
- elf_sh_plt0_entry_be :
- elf_sh_plt0_entry_le);
- }
- memcpy (splt->contents, elf_sh_plt0_entry, PLT_ENTRY_SIZE);
-#ifdef INCLUDE_SHMEDIA
- movi_shori_putval (output_bfd,
- sgot->output_section->vma
- + sgot->output_offset,
- splt->contents
- + elf_sh_plt0_gotplt_offset (info));
-#else
- bfd_put_32 (output_bfd,
- sgot->output_section->vma + sgot->output_offset + 4,
- splt->contents + elf_sh_plt0_gotid_offset (info));
- bfd_put_32 (output_bfd,
- sgot->output_section->vma + sgot->output_offset + 8,
- splt->contents + elf_sh_plt0_linker_offset (info));
-#endif
- }
-
- /* UnixWare sets the entsize of .plt to 4, although that doesn't
- really seem like the right value. */
- elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
- }
- }
-
- /* Fill in the first three entries in the global offset table. */
- if (sgot && sgot->_raw_size > 0)
- {
- if (sdyn == NULL)
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
- else
- bfd_put_32 (output_bfd,
- sdyn->output_section->vma + sdyn->output_offset,
- sgot->contents);
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4);
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
-
- elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
- }
-
- return true;
-}
-
-static enum elf_reloc_type_class
-sh_elf_reloc_type_class (rela)
- const Elf_Internal_Rela *rela;
-{
- switch ((int) ELF32_R_TYPE (rela->r_info))
- {
- case R_SH_RELATIVE:
- return reloc_class_relative;
- case R_SH_JMP_SLOT:
- return reloc_class_plt;
- case R_SH_COPY:
- return reloc_class_copy;
- default:
- return reloc_class_normal;
- }
-}
-
-#ifndef ELF_ARCH
-#define TARGET_BIG_SYM bfd_elf32_sh_vec
-#define TARGET_BIG_NAME "elf32-sh"
-#define TARGET_LITTLE_SYM bfd_elf32_shl_vec
-#define TARGET_LITTLE_NAME "elf32-shl"
-#define ELF_ARCH bfd_arch_sh
-#define ELF_MACHINE_CODE EM_SH
-#define ELF_MAXPAGESIZE 128
-
-#define elf_symbol_leading_char '_'
-#endif /* ELF_ARCH */
-
-#define bfd_elf32_bfd_reloc_type_lookup sh_elf_reloc_type_lookup
-#define elf_info_to_howto sh_elf_info_to_howto
-#define bfd_elf32_bfd_relax_section sh_elf_relax_section
-#define elf_backend_relocate_section sh_elf_relocate_section
-#define bfd_elf32_bfd_get_relocated_section_contents \
- sh_elf_get_relocated_section_contents
-#define elf_backend_object_p sh_elf_set_mach_from_flags
-#define bfd_elf32_bfd_set_private_bfd_flags \
- sh_elf_set_private_flags
-#define bfd_elf32_bfd_copy_private_bfd_data \
- sh_elf_copy_private_data
-#define bfd_elf32_bfd_merge_private_bfd_data \
- sh_elf_merge_private_data
-
-#define elf_backend_gc_mark_hook sh_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook sh_elf_gc_sweep_hook
-#define elf_backend_check_relocs sh_elf_check_relocs
-#define elf_backend_copy_indirect_symbol \
- sh_elf_copy_indirect_symbol
-#define elf_backend_create_dynamic_sections \
- sh_elf_create_dynamic_sections
-#define bfd_elf32_bfd_link_hash_table_create \
- sh_elf_link_hash_table_create
-#define elf_backend_adjust_dynamic_symbol \
- sh_elf_adjust_dynamic_symbol
-#define elf_backend_size_dynamic_sections \
- sh_elf_size_dynamic_sections
-#define elf_backend_finish_dynamic_symbol \
- sh_elf_finish_dynamic_symbol
-#define elf_backend_finish_dynamic_sections \
- sh_elf_finish_dynamic_sections
-#define elf_backend_reloc_type_class sh_elf_reloc_type_class
-
-#define elf_backend_can_gc_sections 1
-#define elf_backend_can_refcount 1
-#define elf_backend_want_got_plt 1
-#define elf_backend_plt_readonly 1
-#define elf_backend_want_plt_sym 0
-#define elf_backend_got_header_size 12
-#define elf_backend_plt_header_size PLT_ENTRY_SIZE
-#include "elf32-target.h"
diff --git a/contrib/binutils/bfd/elf32-v850.c b/contrib/binutils/bfd/elf32-v850.c
deleted file mode 100644
index 6762190..0000000
--- a/contrib/binutils/bfd/elf32-v850.c
+++ /dev/null
@@ -1,2220 +0,0 @@
-/* V850-specific support for 32-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
- Free Software Foundation, Inc.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char
- dependencies. As is the gas & simulator code or the v850. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "bfdlink.h"
-#include "libbfd.h"
-#include "elf-bfd.h"
-#include "elf/v850.h"
-#include "libiberty.h"
-
-/* Sign-extend a 24-bit number. */
-#define SEXT24(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000)
-
-static reloc_howto_type *v850_elf_reloc_type_lookup
- PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
-static void v850_elf_info_to_howto_rel
- PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
-static void v850_elf_info_to_howto_rela
- PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
-static bfd_reloc_status_type v850_elf_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static boolean v850_elf_is_local_label_name
- PARAMS ((bfd *, const char *));
-static boolean v850_elf_relocate_section
- PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static bfd_reloc_status_type v850_elf_perform_relocation
- PARAMS ((bfd *, unsigned int, bfd_vma, bfd_byte *));
-static boolean v850_elf_check_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
-static void remember_hi16s_reloc
- PARAMS ((bfd *, bfd_vma, bfd_byte *));
-static bfd_byte * find_remembered_hi16s_reloc
- PARAMS ((bfd_vma, boolean *));
-static bfd_reloc_status_type v850_elf_final_link_relocate
- PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma,
- bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int));
-static boolean v850_elf_object_p
- PARAMS ((bfd *));
-static boolean v850_elf_fake_sections
- PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
-static void v850_elf_final_write_processing
- PARAMS ((bfd *, boolean));
-static boolean v850_elf_set_private_flags
- PARAMS ((bfd *, flagword));
-static boolean v850_elf_merge_private_bfd_data
- PARAMS ((bfd *, bfd *));
-static boolean v850_elf_print_private_bfd_data
- PARAMS ((bfd *, PTR));
-static boolean v850_elf_section_from_bfd_section
- PARAMS ((bfd *, asection *, int *));
-static void v850_elf_symbol_processing
- PARAMS ((bfd *, asymbol *));
-static boolean v850_elf_add_symbol_hook
- PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
- const char **, flagword *, asection **, bfd_vma *));
-static boolean v850_elf_link_output_symbol_hook
- PARAMS ((bfd *, struct bfd_link_info *, const char *,
- Elf_Internal_Sym *, asection *));
-static boolean v850_elf_section_from_shdr
- PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
-static boolean v850_elf_gc_sweep_hook
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-static asection * v850_elf_gc_mark_hook
- PARAMS ((asection *, struct bfd_link_info *,
- Elf_Internal_Rela *, struct elf_link_hash_entry *,
- Elf_Internal_Sym *));
-
-/* Note: It is REQUIRED that the 'type' value of each entry
- in this array match the index of the entry in the array. */
-static reloc_howto_type v850_elf_howto_table[] =
-{
- /* This reloc does nothing. */
- HOWTO (R_V850_NONE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_V850_NONE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A PC relative 9 bit branch. */
- HOWTO (R_V850_9_PCREL, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_9_PCREL", /* name */
- false, /* partial_inplace */
- 0x00ffffff, /* src_mask */
- 0x00ffffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* A PC relative 22 bit branch. */
- HOWTO (R_V850_22_PCREL, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 22, /* bitsize */
- true, /* pc_relative */
- 7, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_22_PCREL", /* name */
- false, /* partial_inplace */
- 0x07ffff80, /* src_mask */
- 0x07ffff80, /* dst_mask */
- true), /* pcrel_offset */
-
- /* High 16 bits of symbol value. */
- HOWTO (R_V850_HI16_S, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_HI16_S", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of symbol value. */
- HOWTO (R_V850_HI16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_HI16", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of symbol value. */
- HOWTO (R_V850_LO16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_LO16", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Simple 32bit reloc. */
- HOWTO (R_V850_32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_32", /* name */
- false, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Simple 16bit reloc. */
- HOWTO (R_V850_16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_V850_16", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Simple 8bit reloc. */
- HOWTO (R_V850_8, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_V850_8", /* name */
- false, /* partial_inplace */
- 0xff, /* src_mask */
- 0xff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit offset from the short data area pointer. */
- HOWTO (R_V850_SDA_16_16_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_SDA_16_16_OFFSET", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 15 bit offset from the short data area pointer. */
- HOWTO (R_V850_SDA_15_16_OFFSET, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 1, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_SDA_15_16_OFFSET", /* name */
- false, /* partial_inplace */
- 0xfffe, /* src_mask */
- 0xfffe, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit offset from the zero data area pointer. */
- HOWTO (R_V850_ZDA_16_16_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_ZDA_16_16_OFFSET", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 15 bit offset from the zero data area pointer. */
- HOWTO (R_V850_ZDA_15_16_OFFSET, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 1, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_ZDA_15_16_OFFSET", /* name */
- false, /* partial_inplace */
- 0xfffe, /* src_mask */
- 0xfffe, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 6 bit offset from the tiny data area pointer. */
- HOWTO (R_V850_TDA_6_8_OFFSET, /* type */
- 2, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 1, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_TDA_6_8_OFFSET", /* name */
- false, /* partial_inplace */
- 0x7e, /* src_mask */
- 0x7e, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 8 bit offset from the tiny data area pointer. */
- HOWTO (R_V850_TDA_7_8_OFFSET, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_TDA_7_8_OFFSET", /* name */
- false, /* partial_inplace */
- 0x7f, /* src_mask */
- 0x7f, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 7 bit offset from the tiny data area pointer. */
- HOWTO (R_V850_TDA_7_7_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 7, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_TDA_7_7_OFFSET", /* name */
- false, /* partial_inplace */
- 0x7f, /* src_mask */
- 0x7f, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit offset from the tiny data area pointer! */
- HOWTO (R_V850_TDA_16_16_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_TDA_16_16_OFFSET", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xfff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 5 bit offset from the tiny data area pointer. */
- HOWTO (R_V850_TDA_4_5_OFFSET, /* type */
- 1, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 5, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_TDA_4_5_OFFSET", /* name */
- false, /* partial_inplace */
- 0x0f, /* src_mask */
- 0x0f, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 4 bit offset from the tiny data area pointer. */
- HOWTO (R_V850_TDA_4_4_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 4, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_TDA_4_4_OFFSET", /* name */
- false, /* partial_inplace */
- 0x0f, /* src_mask */
- 0x0f, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit offset from the short data area pointer. */
- HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_SDA_16_16_SPLIT_OFFSET",/* name */
- false, /* partial_inplace */
- 0xfffe0020, /* src_mask */
- 0xfffe0020, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit offset from the zero data area pointer. */
- HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */
- false, /* partial_inplace */
- 0xfffe0020, /* src_mask */
- 0xfffe0020, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 6 bit offset from the call table base pointer. */
- HOWTO (R_V850_CALLT_6_7_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 7, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_CALLT_6_7_OFFSET", /* name */
- false, /* partial_inplace */
- 0x3f, /* src_mask */
- 0x3f, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit offset from the call table base pointer. */
- HOWTO (R_V850_CALLT_16_16_OFFSET, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- v850_elf_reloc, /* special_function */
- "R_V850_CALLT_16_16_OFFSET", /* name */
- false, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GNU extension to record C++ vtable hierarchy */
- HOWTO (R_V850_GNU_VTINHERIT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- NULL, /* special_function */
- "R_V850_GNU_VTINHERIT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GNU extension to record C++ vtable member usage */
- HOWTO (R_V850_GNU_VTENTRY, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_elf_rel_vtable_reloc_fn, /* special_function */
- "R_V850_GNU_VTENTRY", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
-};
-
-/* Map BFD reloc types to V850 ELF reloc types. */
-
-struct v850_elf_reloc_map
-{
- /* BFD_RELOC_V850_CALLT_16_16_OFFSET is 258, which will not fix in an
- unsigned char. */
- bfd_reloc_code_real_type bfd_reloc_val;
- unsigned int elf_reloc_val;
-};
-
-static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
-{
- { BFD_RELOC_NONE, R_V850_NONE },
- { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL },
- { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL },
- { BFD_RELOC_HI16_S, R_V850_HI16_S },
- { BFD_RELOC_HI16, R_V850_HI16 },
- { BFD_RELOC_LO16, R_V850_LO16 },
- { BFD_RELOC_32, R_V850_32 },
- { BFD_RELOC_16, R_V850_16 },
- { BFD_RELOC_8, R_V850_8 },
- { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
- { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
- { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
- { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
- { BFD_RELOC_V850_TDA_6_8_OFFSET, R_V850_TDA_6_8_OFFSET },
- { BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET },
- { BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET },
- { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
- { BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET },
- { BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET },
- { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
- { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
- { BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET },
- { BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET },
- { BFD_RELOC_VTABLE_INHERIT, R_V850_GNU_VTINHERIT },
- { BFD_RELOC_VTABLE_ENTRY, R_V850_GNU_VTENTRY },
-
-};
-
-/* Map a bfd relocation into the appropriate howto structure. */
-
-static reloc_howto_type *
-v850_elf_reloc_type_lookup (abfd, code)
- bfd * abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- unsigned int i;
-
- for (i = ARRAY_SIZE (v850_elf_reloc_map); i --;)
- if (v850_elf_reloc_map[i].bfd_reloc_val == code)
- {
- unsigned int elf_reloc_val = v850_elf_reloc_map[i].elf_reloc_val;
-
- BFD_ASSERT (v850_elf_howto_table[elf_reloc_val].type == elf_reloc_val);
-
- return v850_elf_howto_table + elf_reloc_val;
- }
-
- return NULL;
-}
-
-/* Set the howto pointer for an V850 ELF reloc. */
-
-static void
-v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd * abfd ATTRIBUTE_UNUSED;
- arelent * cache_ptr;
- Elf32_Internal_Rel * dst;
-{
- unsigned int r_type;
-
- r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_V850_max);
- cache_ptr->howto = &v850_elf_howto_table[r_type];
-}
-
-/* Set the howto pointer for a V850 ELF reloc (type RELA). */
-static void
-v850_elf_info_to_howto_rela (abfd, cache_ptr, dst)
- bfd * abfd ATTRIBUTE_UNUSED;
- arelent * cache_ptr;
- Elf32_Internal_Rela *dst;
-{
- unsigned int r_type;
-
- r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_V850_max);
- cache_ptr->howto = &v850_elf_howto_table[r_type];
-}
-
-/* Look through the relocs for a section during the first phase, and
- allocate space in the global offset table or procedure linkage
- table. */
-
-static boolean
-v850_elf_check_relocs (abfd, info, sec, relocs)
- bfd * abfd;
- struct bfd_link_info * info;
- asection * sec;
- const Elf_Internal_Rela * relocs;
-{
- boolean ret = true;
- bfd *dynobj;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
- asection *sreloc;
- enum v850_reloc_type r_type;
- int other = 0;
- const char *common = (const char *)0;
-
- if (info->relocateable)
- return true;
-
-#ifdef DEBUG
- fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
- bfd_get_section_name (abfd, sec),
- bfd_archive_filename (abfd));
-#endif
-
- dynobj = elf_hash_table (info)->dynobj;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- sreloc = NULL;
-
- rel_end = relocs + sec->reloc_count;
- for (rel = relocs; rel < rel_end; rel++)
- {
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
- else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
- r_type = (enum v850_reloc_type) ELF32_R_TYPE (rel->r_info);
- switch (r_type)
- {
- default:
- case R_V850_NONE:
- case R_V850_9_PCREL:
- case R_V850_22_PCREL:
- case R_V850_HI16_S:
- case R_V850_HI16:
- case R_V850_LO16:
- case R_V850_32:
- case R_V850_16:
- case R_V850_8:
- case R_V850_CALLT_6_7_OFFSET:
- case R_V850_CALLT_16_16_OFFSET:
- break;
-
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_V850_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return false;
- break;
-
- /* This relocation describes which C++ vtable entries
- are actually used. Record for later use during GC. */
- case R_V850_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
- return false;
- break;
-
- case R_V850_SDA_16_16_SPLIT_OFFSET:
- case R_V850_SDA_16_16_OFFSET:
- case R_V850_SDA_15_16_OFFSET:
- other = V850_OTHER_SDA;
- common = ".scommon";
- goto small_data_common;
-
- case R_V850_ZDA_16_16_SPLIT_OFFSET:
- case R_V850_ZDA_16_16_OFFSET:
- case R_V850_ZDA_15_16_OFFSET:
- other = V850_OTHER_ZDA;
- common = ".zcommon";
- goto small_data_common;
-
- case R_V850_TDA_4_5_OFFSET:
- case R_V850_TDA_4_4_OFFSET:
- case R_V850_TDA_6_8_OFFSET:
- case R_V850_TDA_7_8_OFFSET:
- case R_V850_TDA_7_7_OFFSET:
- case R_V850_TDA_16_16_OFFSET:
- other = V850_OTHER_TDA;
- common = ".tcommon";
- /* fall through */
-
-#define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
-
- small_data_common:
- if (h)
- {
- /* Flag which type of relocation was used. */
- h->other |= other;
- if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
- && (h->other & V850_OTHER_ERROR) == 0)
- {
- const char * msg;
- static char buff[200]; /* XXX */
-
- switch (h->other & V850_OTHER_MASK)
- {
- default:
- msg = _("Variable `%s' cannot occupy in multiple small data regions");
- break;
- case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
- msg = _("Variable `%s' can only be in one of the small, zero, and tiny data regions");
- break;
- case V850_OTHER_SDA | V850_OTHER_ZDA:
- msg = _("Variable `%s' cannot be in both small and zero data regions simultaneously");
- break;
- case V850_OTHER_SDA | V850_OTHER_TDA:
- msg = _("Variable `%s' cannot be in both small and tiny data regions simultaneously");
- break;
- case V850_OTHER_ZDA | V850_OTHER_TDA:
- msg = _("Variable `%s' cannot be in both zero and tiny data regions simultaneously");
- break;
- }
-
- sprintf (buff, msg, h->root.root.string);
- info->callbacks->warning (info, buff, h->root.root.string,
- abfd, h->root.u.def.section,
- (bfd_vma) 0);
-
- bfd_set_error (bfd_error_bad_value);
- h->other |= V850_OTHER_ERROR;
- ret = false;
- }
- }
-
- if (h && h->root.type == bfd_link_hash_common
- && h->root.u.c.p
- && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
- {
- asection * section;
-
- section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
- section->flags |= SEC_IS_COMMON;
- }
-
-#ifdef DEBUG
- fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
- v850_elf_howto_table[ (int)r_type ].name,
- (h && h->root.root.string) ? h->root.root.string : "<unknown>",
- (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
-#endif
- break;
- }
- }
-
- return ret;
-}
-
-/* In the old version, when an entry was checked out from the table,
- it was deleted. This produced an error if the entry was needed
- more than once, as the second attempted retry failed.
-
- In the current version, the entry is not deleted, instead we set
- the field 'found' to true. If a second lookup matches the same
- entry, then we know that the hi16s reloc has already been updated
- and does not need to be updated a second time.
-
- TODO - TOFIX: If it is possible that we need to restore 2 different
- addresses from the same table entry, where the first generates an
- overflow, whilst the second do not, then this code will fail. */
-
-typedef struct hi16s_location
-{
- bfd_vma addend;
- bfd_byte * address;
- unsigned long counter;
- boolean found;
- struct hi16s_location * next;
-}
-hi16s_location;
-
-static hi16s_location * previous_hi16s;
-static hi16s_location * free_hi16s;
-static unsigned long hi16s_counter;
-
-static void
-remember_hi16s_reloc (abfd, addend, address)
- bfd * abfd;
- bfd_vma addend;
- bfd_byte * address;
-{
- hi16s_location * entry = NULL;
- bfd_size_type amt = sizeof (* free_hi16s);
-
- /* Find a free structure. */
- if (free_hi16s == NULL)
- free_hi16s = (hi16s_location *) bfd_zalloc (abfd, amt);
-
- entry = free_hi16s;
- free_hi16s = free_hi16s->next;
-
- entry->addend = addend;
- entry->address = address;
- entry->counter = hi16s_counter ++;
- entry->found = false;
- entry->next = previous_hi16s;
- previous_hi16s = entry;
-
- /* Cope with wrap around of our counter. */
- if (hi16s_counter == 0)
- {
- /* XXX - Assume that all counter entries differ only in their low 16 bits. */
- for (entry = previous_hi16s; entry != NULL; entry = entry->next)
- entry->counter &= 0xffff;
-
- hi16s_counter = 0x10000;
- }
-
- return;
-}
-
-static bfd_byte *
-find_remembered_hi16s_reloc (addend, already_found)
- bfd_vma addend;
- boolean * already_found;
-{
- hi16s_location * match = NULL;
- hi16s_location * entry;
- hi16s_location * previous = NULL;
- hi16s_location * prev;
- bfd_byte * addr;
-
- /* Search the table. Record the most recent entry that matches. */
- for (entry = previous_hi16s; entry; entry = entry->next)
- {
- if (entry->addend == addend
- && (match == NULL || match->counter < entry->counter))
- {
- previous = prev;
- match = entry;
- }
-
- prev = entry;
- }
-
- if (match == NULL)
- return NULL;
-
- /* Extract the address. */
- addr = match->address;
-
- /* Remeber if this entry has already been used before. */
- if (already_found)
- * already_found = match->found;
-
- /* Note that this entry has now been used. */
- match->found = true;
-
- return addr;
-}
-
-/* FIXME: The code here probably ought to be removed and the code in reloc.c
- allowed to do its stuff instead. At least for most of the relocs, anwyay. */
-
-static bfd_reloc_status_type
-v850_elf_perform_relocation (abfd, r_type, addend, address)
- bfd *abfd;
- unsigned int r_type;
- bfd_vma addend;
- bfd_byte *address;
-{
- unsigned long insn;
- bfd_signed_vma saddend = (bfd_signed_vma) addend;
-
- switch (r_type)
- {
- default:
- /* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */
- return bfd_reloc_notsupported;
-
- case R_V850_32:
- bfd_put_32 (abfd, addend, address);
- return bfd_reloc_ok;
-
- case R_V850_22_PCREL:
- if (saddend > 0x1fffff || saddend < -0x200000)
- return bfd_reloc_overflow;
-
- if ((addend % 2) != 0)
- return bfd_reloc_dangerous;
-
- insn = bfd_get_32 (abfd, address);
- insn &= ~0xfffe003f;
- insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
- bfd_put_32 (abfd, (bfd_vma) insn, address);
- return bfd_reloc_ok;
-
- case R_V850_9_PCREL:
- if (saddend > 0xff || saddend < -0x100)
- return bfd_reloc_overflow;
-
- if ((addend % 2) != 0)
- return bfd_reloc_dangerous;
-
- insn = bfd_get_16 (abfd, address);
- insn &= ~ 0xf870;
- insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3);
- break;
-
- case R_V850_HI16:
- addend += (bfd_get_16 (abfd, address) << 16);
- addend = (addend >> 16);
- insn = addend;
- break;
-
- case R_V850_HI16_S:
- /* Remember where this relocation took place. */
- remember_hi16s_reloc (abfd, addend, address);
-
- addend += (bfd_get_16 (abfd, address) << 16);
- addend = (addend >> 16) + ((addend & 0x8000) != 0);
-
- /* This relocation cannot overflow. */
- if (addend > 0x7fff)
- addend = 0;
-
- insn = addend;
- break;
-
- case R_V850_LO16:
- /* Calculate the sum of the value stored in the instruction and the
- addend and check for overflow from the low 16 bits into the high
- 16 bits. The assembler has already done some of this: If the
- value stored in the instruction has its 15th bit set, (counting
- from zero) then the assembler will have added 1 to the value
- stored in the associated HI16S reloc. So for example, these
- relocations:
-
- movhi hi( fred ), r0, r1
- movea lo( fred ), r1, r1
-
- will store 0 in the value fields for the MOVHI and MOVEA instructions
- and addend will be the address of fred, but for these instructions:
-
- movhi hi( fred + 0x123456), r0, r1
- movea lo( fred + 0x123456), r1, r1
-
- the value stored in the MOVHI instruction will be 0x12 and the value
- stored in the MOVEA instruction will be 0x3456. If however the
- instructions were:
-
- movhi hi( fred + 0x10ffff), r0, r1
- movea lo( fred + 0x10ffff), r1, r1
-
- then the value stored in the MOVHI instruction would be 0x11 (not
- 0x10) and the value stored in the MOVEA instruction would be 0xffff.
- Thus (assuming for the moment that the addend is 0), at run time the
- MOVHI instruction loads 0x110000 into r1, then the MOVEA instruction
- adds 0xffffffff (sign extension!) producing 0x10ffff. Similarly if
- the instructions were:
-
- movhi hi( fred - 1), r0, r1
- movea lo( fred - 1), r1, r1
-
- then 0 is stored in the MOVHI instruction and -1 is stored in the
- MOVEA instruction.
-
- Overflow can occur if the addition of the value stored in the
- instruction plus the addend sets the 15th bit when before it was clear.
- This is because the 15th bit will be sign extended into the high part,
- thus reducing its value by one, but since the 15th bit was originally
- clear, the assembler will not have added 1 to the previous HI16S reloc
- to compensate for this effect. For example:
-
- movhi hi( fred + 0x123456), r0, r1
- movea lo( fred + 0x123456), r1, r1
-
- The value stored in HI16S reloc is 0x12, the value stored in the LO16
- reloc is 0x3456. If we assume that the address of fred is 0x00007000
- then the relocations become:
-
- HI16S: 0x0012 + (0x00007000 >> 16) = 0x12
- LO16: 0x3456 + (0x00007000 & 0xffff) = 0xa456
-
- but when the instructions are executed, the MOVEA instruction's value
- is signed extended, so the sum becomes:
-
- 0x00120000
- + 0xffffa456
- ------------
- 0x0011a456 but 'fred + 0x123456' = 0x0012a456
-
- Note that if the 15th bit was set in the value stored in the LO16
- reloc, then we do not have to do anything:
-
- movhi hi( fred + 0x10ffff), r0, r1
- movea lo( fred + 0x10ffff), r1, r1
-
- HI16S: 0x0011 + (0x00007000 >> 16) = 0x11
- LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff
-
- 0x00110000
- + 0x00006fff
- ------------
- 0x00116fff = fred + 0x10ffff = 0x7000 + 0x10ffff
-
- Overflow can also occur if the computation carries into the 16th bit
- and it also results in the 15th bit having the same value as the 15th
- bit of the original value. What happens is that the HI16S reloc
- will have already examined the 15th bit of the original value and
- added 1 to the high part if the bit is set. This compensates for the
- sign extension of 15th bit of the result of the computation. But now
- there is a carry into the 16th bit, and this has not been allowed for.
-
- So, for example if fred is at address 0xf000:
-
- movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set]
- movea lo( fred + 0xffff), r1, r1
-
- HI16S: 0x0001 + (0x0000f000 >> 16) = 0x0001
- LO16: 0xffff + (0x0000f000 & 0xffff) = 0xefff (carry into bit 16 is lost)
-
- 0x00010000
- + 0xffffefff
- ------------
- 0x0000efff but 'fred + 0xffff' = 0x0001efff
-
- Similarly, if the 15th bit remains clear, but overflow occurs into
- the 16th bit then (assuming the address of fred is 0xf000):
-
- movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear]
- movea lo( fred + 0x7000), r1, r1
-
- HI16S: 0x0000 + (0x0000f000 >> 16) = 0x0000
- LO16: 0x7000 + (0x0000f000 & 0xffff) = 0x6fff (carry into bit 16 is lost)
-
- 0x00000000
- + 0x00006fff
- ------------
- 0x00006fff but 'fred + 0x7000' = 0x00016fff
-
- Note - there is no need to change anything if a carry occurs, and the
- 15th bit changes its value from being set to being clear, as the HI16S
- reloc will have already added in 1 to the high part for us:
-
- movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set]
- movea lo( fred + 0xffff), r1, r1
-
- HI16S: 0x0001 + (0x00007000 >> 16)
- LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff (carry into bit 16 is lost)
-
- 0x00010000
- + 0x00006fff (bit 15 not set, so the top half is zero)
- ------------
- 0x00016fff which is right (assuming that fred is at 0x7000)
-
- but if the 15th bit goes from being clear to being set, then we must
- once again handle overflow:
-
- movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear]
- movea lo( fred + 0x7000), r1, r1
-
- HI16S: 0x0000 + (0x0000ffff >> 16)
- LO16: 0x7000 + (0x0000ffff & 0xffff) = 0x6fff (carry into bit 16)
-
- 0x00000000
- + 0x00006fff (bit 15 not set, so the top half is zero)
- ------------
- 0x00006fff which is wrong (assuming that fred is at 0xffff). */
- {
- long result;
-
- insn = bfd_get_16 (abfd, address);
- result = insn + addend;
-
-#define BIT15_SET(x) ((x) & 0x8000)
-#define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff)
-
- if ((BIT15_SET (result) && ! BIT15_SET (addend))
- || (OVERFLOWS (addend, insn)
- && ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
- {
- boolean already_updated;
- bfd_byte * hi16s_address = find_remembered_hi16s_reloc
- (addend, & already_updated);
-
- /* Amend the matching HI16_S relocation. */
- if (hi16s_address != NULL)
- {
- if (! already_updated)
- {
- insn = bfd_get_16 (abfd, hi16s_address);
- insn += 1;
- bfd_put_16 (abfd, (bfd_vma) insn, hi16s_address);
- }
- }
- else
- {
- fprintf (stderr, _("FAILED to find previous HI16 reloc\n"));
- return bfd_reloc_overflow;
- }
- }
-
- /* Do not complain if value has top bit set, as this has been anticipated. */
- insn = result & 0xffff;
- break;
- }
-
- case R_V850_8:
- addend += (char) bfd_get_8 (abfd, address);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x7f || saddend < -0x80)
- return bfd_reloc_overflow;
-
- bfd_put_8 (abfd, addend, address);
- return bfd_reloc_ok;
-
- case R_V850_CALLT_16_16_OFFSET:
- addend += bfd_get_16 (abfd, address);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0xffff || saddend < 0)
- return bfd_reloc_overflow;
-
- insn = addend;
- break;
-
- case R_V850_16:
-
- /* drop through */
- case R_V850_SDA_16_16_OFFSET:
- case R_V850_ZDA_16_16_OFFSET:
- case R_V850_TDA_16_16_OFFSET:
- addend += bfd_get_16 (abfd, address);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x7fff || saddend < -0x8000)
- return bfd_reloc_overflow;
-
- insn = addend;
- break;
-
- case R_V850_SDA_15_16_OFFSET:
- case R_V850_ZDA_15_16_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += (insn & 0xfffe);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x7ffe || saddend < -0x8000)
- return bfd_reloc_overflow;
-
- if (addend & 1)
- return bfd_reloc_dangerous;
-
- insn = (addend &~ (bfd_vma) 1) | (insn & 1);
- break;
-
- case R_V850_TDA_6_8_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += ((insn & 0x7e) << 1);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0xfc || saddend < 0)
- return bfd_reloc_overflow;
-
- if (addend & 3)
- return bfd_reloc_dangerous;
-
- insn &= 0xff81;
- insn |= (addend >> 1);
- break;
-
- case R_V850_TDA_7_8_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += ((insn & 0x7f) << 1);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0xfe || saddend < 0)
- return bfd_reloc_overflow;
-
- if (addend & 1)
- return bfd_reloc_dangerous;
-
- insn &= 0xff80;
- insn |= (addend >> 1);
- break;
-
- case R_V850_TDA_7_7_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += insn & 0x7f;
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x7f || saddend < 0)
- return bfd_reloc_overflow;
-
- insn &= 0xff80;
- insn |= addend;
- break;
-
- case R_V850_TDA_4_5_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += ((insn & 0xf) << 1);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x1e || saddend < 0)
- return bfd_reloc_overflow;
-
- if (addend & 1)
- return bfd_reloc_dangerous;
-
- insn &= 0xfff0;
- insn |= (addend >> 1);
- break;
-
- case R_V850_TDA_4_4_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += insn & 0xf;
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0xf || saddend < 0)
- return bfd_reloc_overflow;
-
- insn &= 0xfff0;
- insn |= addend;
- break;
-
- case R_V850_ZDA_16_16_SPLIT_OFFSET:
- case R_V850_SDA_16_16_SPLIT_OFFSET:
- insn = bfd_get_32 (abfd, address);
- addend += ((insn & 0xfffe0000) >> 16) + ((insn & 0x20) >> 5);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x7fff || saddend < -0x8000)
- return bfd_reloc_overflow;
-
- insn &= 0x0001ffdf;
- insn |= (addend & 1) << 5;
- insn |= (addend &~ (bfd_vma) 1) << 16;
-
- bfd_put_32 (abfd, (bfd_vma) insn, address);
- return bfd_reloc_ok;
-
- case R_V850_CALLT_6_7_OFFSET:
- insn = bfd_get_16 (abfd, address);
- addend += ((insn & 0x3f) << 1);
-
- saddend = (bfd_signed_vma) addend;
-
- if (saddend > 0x7e || saddend < 0)
- return bfd_reloc_overflow;
-
- if (addend & 1)
- return bfd_reloc_dangerous;
-
- insn &= 0xff80;
- insn |= (addend >> 1);
- break;
-
- case R_V850_GNU_VTINHERIT:
- case R_V850_GNU_VTENTRY:
- return bfd_reloc_ok;
-
- }
-
- bfd_put_16 (abfd, (bfd_vma) insn, address);
- return bfd_reloc_ok;
-}
-
-/* Insert the addend into the instruction. */
-
-static bfd_reloc_status_type
-v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
- bfd * abfd ATTRIBUTE_UNUSED;
- arelent * reloc;
- asymbol * symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection * isection;
- bfd * obfd;
- char ** err ATTRIBUTE_UNUSED;
-{
- long relocation;
-
- /* If there is an output BFD,
- and the symbol is not a section name (which is only defined at final link time),
- and either we are not putting the addend into the instruction
- or the addend is zero, so there is nothing to add into the instruction
- then just fixup the address and return. */
- if (obfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc->howto->partial_inplace
- || reloc->addend == 0))
- {
- reloc->address += isection->output_offset;
- return bfd_reloc_ok;
- }
-#if 0
- else if (obfd != NULL)
- return bfd_reloc_continue;
-#endif
-
- /* Catch relocs involving undefined symbols. */
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0
- && obfd == NULL)
- return bfd_reloc_undefined;
-
- /* We handle final linking of some relocs ourselves. */
-
- /* Is the address of the relocation really within the section? */
- if (reloc->address > isection->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Work out which section the relocation is targetted at and the
- initial relocation command value. */
-
- /* Get symbol value. (Common symbols are special.) */
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- /* Convert input-section-relative symbol value to absolute + addend. */
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc->addend;
-
-#if 0 /* Since this reloc is going to be processed later on, we should
- not make it pc-relative here. To test this, try assembling and
- linking this program:
-
- .text
- .globl _start
- nop
- _start:
- jr foo
-
- .section ".foo","ax"
- nop
- foo:
- nop */
- if (reloc->howto->pc_relative)
- {
- /* Here the variable relocation holds the final address of the
- symbol we are relocating against, plus any addend. */
- relocation -= isection->output_section->vma + isection->output_offset;
-
- /* Deal with pcrel_offset. */
- relocation -= reloc->address;
- }
-#endif
- reloc->addend = relocation;
- return bfd_reloc_ok;
-}
-
-static boolean
-v850_elf_is_local_label_name (abfd, name)
- bfd * abfd ATTRIBUTE_UNUSED;
- const char * name;
-{
- return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
- || (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_'));
-}
-
-/* Perform a relocation as part of a final link. */
-
-static bfd_reloc_status_type
-v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
- input_section, contents, offset, value,
- addend, info, sym_sec, is_local)
- reloc_howto_type * howto;
- bfd * input_bfd;
- bfd * output_bfd ATTRIBUTE_UNUSED;
- asection * input_section;
- bfd_byte * contents;
- bfd_vma offset;
- bfd_vma value;
- bfd_vma addend;
- struct bfd_link_info * info;
- asection * sym_sec;
- int is_local ATTRIBUTE_UNUSED;
-{
- unsigned int r_type = howto->type;
- bfd_byte * hit_data = contents + offset;
-
- /* Adjust the value according to the relocation. */
- switch (r_type)
- {
- case R_V850_9_PCREL:
- value -= (input_section->output_section->vma
- + input_section->output_offset);
- value -= offset;
- break;
-
- case R_V850_22_PCREL:
- value -= (input_section->output_section->vma
- + input_section->output_offset
- + offset);
-
- /* If the sign extension will corrupt the value then we have overflowed. */
- if (((value & 0xff000000) != 0x0) && ((value & 0xff000000) != 0xff000000))
- return bfd_reloc_overflow;
-
- /* Only the bottom 24 bits of the PC are valid */
- value = SEXT24 (value);
- break;
-
- case R_V850_HI16_S:
- case R_V850_HI16:
- case R_V850_LO16:
- case R_V850_16:
- case R_V850_32:
- case R_V850_8:
- break;
-
- case R_V850_ZDA_15_16_OFFSET:
- case R_V850_ZDA_16_16_OFFSET:
- case R_V850_ZDA_16_16_SPLIT_OFFSET:
- if (sym_sec == NULL)
- return bfd_reloc_undefined;
-
- value -= sym_sec->output_section->vma;
- break;
-
- case R_V850_SDA_15_16_OFFSET:
- case R_V850_SDA_16_16_OFFSET:
- case R_V850_SDA_16_16_SPLIT_OFFSET:
- {
- unsigned long gp;
- struct bfd_link_hash_entry * h;
-
- if (sym_sec == NULL)
- return bfd_reloc_undefined;
-
- /* Get the value of __gp. */
- h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
- if (h == (struct bfd_link_hash_entry *) NULL
- || h->type != bfd_link_hash_defined)
- return bfd_reloc_other;
-
- gp = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
-
- value -= sym_sec->output_section->vma;
- value -= (gp - sym_sec->output_section->vma);
- }
- break;
-
- case R_V850_TDA_4_4_OFFSET:
- case R_V850_TDA_4_5_OFFSET:
- case R_V850_TDA_16_16_OFFSET:
- case R_V850_TDA_7_7_OFFSET:
- case R_V850_TDA_7_8_OFFSET:
- case R_V850_TDA_6_8_OFFSET:
- {
- unsigned long ep;
- struct bfd_link_hash_entry * h;
-
- /* Get the value of __ep. */
- h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
- if (h == (struct bfd_link_hash_entry *) NULL
- || h->type != bfd_link_hash_defined)
- /* Actually this indicates that __ep could not be found. */
- return bfd_reloc_continue;
-
- ep = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
-
- value -= ep;
- }
- break;
-
- case R_V850_CALLT_6_7_OFFSET:
- {
- unsigned long ctbp;
- struct bfd_link_hash_entry * h;
-
- /* Get the value of __ctbp. */
- h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
- if (h == (struct bfd_link_hash_entry *) NULL
- || h->type != bfd_link_hash_defined)
- /* Actually this indicates that __ctbp could not be found. */
- return bfd_reloc_dangerous + 1;
-
- ctbp = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
- value -= ctbp;
- }
- break;
-
- case R_V850_CALLT_16_16_OFFSET:
- {
- unsigned long ctbp;
- struct bfd_link_hash_entry * h;
-
- if (sym_sec == NULL)
- return bfd_reloc_undefined;
-
- /* Get the value of __ctbp. */
- h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
- if (h == (struct bfd_link_hash_entry *) NULL
- || h->type != bfd_link_hash_defined)
- return (bfd_reloc_dangerous + 1);
-
- ctbp = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
-
- value -= sym_sec->output_section->vma;
- value -= (ctbp - sym_sec->output_section->vma);
- }
- break;
-
- case R_V850_NONE:
- case R_V850_GNU_VTINHERIT:
- case R_V850_GNU_VTENTRY:
- return bfd_reloc_ok;
-
- default:
- return bfd_reloc_notsupported;
- }
-
- /* Perform the relocation. */
- return v850_elf_perform_relocation (input_bfd, r_type, value + addend, hit_data);
-}
-
-/* Relocate an V850 ELF section. */
-
-static boolean
-v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd * output_bfd;
- struct bfd_link_info * info;
- bfd * input_bfd;
- asection * input_section;
- bfd_byte * contents;
- Elf_Internal_Rela * relocs;
- Elf_Internal_Sym * local_syms;
- asection ** local_sections;
-{
- Elf_Internal_Shdr * symtab_hdr;
- struct elf_link_hash_entry ** sym_hashes;
- Elf_Internal_Rela * rel;
- Elf_Internal_Rela * relend;
-
- symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (input_bfd);
-
- if (sym_hashes == NULL)
- {
- info->callbacks->warning
- (info, "no hash table available",
- NULL, input_bfd, input_section, (bfd_vma) 0);
-
- return false;
- }
-
- /* Reset the list of remembered HI16S relocs to empty. */
- free_hi16s = previous_hi16s;
- previous_hi16s = NULL;
- hi16s_counter = 0;
-
- rel = relocs;
- relend = relocs + input_section->reloc_count;
- for (; rel < relend; rel++)
- {
- int r_type;
- reloc_howto_type * howto;
- unsigned long r_symndx;
- Elf_Internal_Sym * sym;
- asection * sec;
- struct elf_link_hash_entry * h;
- bfd_vma relocation;
- bfd_reloc_status_type r;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- r_type = ELF32_R_TYPE (rel->r_info);
-
- if (r_type == R_V850_GNU_VTENTRY
- || r_type == R_V850_GNU_VTINHERIT)
- continue;
-
- howto = v850_elf_howto_table + r_type;
-
- 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. */
- 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;
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- sec = local_sections[r_symndx];
- relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
-#if 0
- {
- char * name;
-
- name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
- name = (name == NULL) ? "<none>" : name;
- fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
- sec->name, name, sym->st_name,
- sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend);
- }
-#endif
- }
- else
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
- 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;
-
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- sec = h->root.u.def.section;
- relocation = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
-#if 0
- fprintf (stderr, "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
- sec->name, h->root.root.string, h->root.u.def.value, sec->output_section->vma, sec->output_offset, relocation);
-#endif
- }
- else if (h->root.type == bfd_link_hash_undefweak)
- {
-#if 0
- fprintf (stderr, "undefined: sec: %s, name: %s\n",
- sec->name, h->root.root.string);
-#endif
- relocation = 0;
- }
- else
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd,
- input_section, rel->r_offset, true)))
- return false;
-#if 0
- fprintf (stderr, "unknown: name: %s\n", h->root.root.string);
-#endif
- relocation = 0;
- }
- }
-
- /* FIXME: We should use the addend, but the COFF relocations don't. */
- r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
- input_section,
- contents, rel->r_offset,
- relocation, rel->r_addend,
- info, sec, h == NULL);
-
- if (r != bfd_reloc_ok)
- {
- const char * name;
- const char * msg = (const char *)0;
-
- if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = (bfd_elf_string_from_elf_section
- (input_bfd, symtab_hdr->sh_link, sym->st_name));
- if (name == NULL || *name == '\0')
- name = bfd_section_name (input_bfd, sec);
- }
-
- switch (r)
- {
- case bfd_reloc_overflow:
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset)))
- return false;
- break;
-
- case bfd_reloc_undefined:
- if (! ((*info->callbacks->undefined_symbol)
- (info, name, input_bfd, input_section,
- rel->r_offset, true)))
- return false;
- break;
-
- case bfd_reloc_outofrange:
- msg = _("internal error: out of range error");
- goto common_error;
-
- case bfd_reloc_notsupported:
- msg = _("internal error: unsupported relocation error");
- goto common_error;
-
- case bfd_reloc_dangerous:
- msg = _("internal error: dangerous relocation");
- goto common_error;
-
- case bfd_reloc_other:
- msg = _("could not locate special linker symbol __gp");
- goto common_error;
-
- case bfd_reloc_continue:
- msg = _("could not locate special linker symbol __ep");
- goto common_error;
-
- case (bfd_reloc_dangerous + 1):
- msg = _("could not locate special linker symbol __ctbp");
- goto common_error;
-
- default:
- msg = _("internal error: unknown error");
- /* fall through */
-
- common_error:
- if (!((*info->callbacks->warning)
- (info, msg, name, input_bfd, input_section,
- rel->r_offset)))
- return false;
- break;
- }
- }
- }
-
- return true;
-}
-
-static boolean
-v850_elf_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
-{
- /* No got and plt entries for v850-elf. */
- return true;
-}
-
-static asection *
-v850_elf_gc_mark_hook (sec, info, rel, h, sym)
- asection *sec;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_V850_GNU_VTINHERIT:
- case R_V850_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
-}
-
-/* Set the right machine number. */
-
-static boolean
-v850_elf_object_p (abfd)
- bfd *abfd;
-{
- switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
- {
- default:
- case E_V850_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
- case E_V850E_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
- case E_V850EA_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850ea); break;
- }
- return true;
-}
-
-/* Store the machine number in the flags field. */
-
-static void
-v850_elf_final_write_processing (abfd, linker)
- bfd * abfd;
- boolean linker ATTRIBUTE_UNUSED;
-{
- unsigned long val;
-
- switch (bfd_get_mach (abfd))
- {
- default:
- case 0: val = E_V850_ARCH; break;
- case bfd_mach_v850e: val = E_V850E_ARCH; break;
- case bfd_mach_v850ea: val = E_V850EA_ARCH; break;
- }
-
- elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
- elf_elfheader (abfd)->e_flags |= val;
-}
-
-/* Function to keep V850 specific file flags. */
-
-static boolean
-v850_elf_set_private_flags (abfd, flags)
- bfd * abfd;
- flagword flags;
-{
- BFD_ASSERT (!elf_flags_init (abfd)
- || elf_elfheader (abfd)->e_flags == flags);
-
- elf_elfheader (abfd)->e_flags = flags;
- elf_flags_init (abfd) = true;
- return true;
-}
-
-/* Merge backend specific data from an object file
- to the output object file when linking. */
-static boolean
-v850_elf_merge_private_bfd_data (ibfd, obfd)
- bfd * ibfd;
- bfd * obfd;
-{
- flagword out_flags;
- flagword in_flags;
-
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- in_flags = elf_elfheader (ibfd)->e_flags;
- out_flags = elf_elfheader (obfd)->e_flags;
-
- if (! elf_flags_init (obfd))
- {
- /* If the input is the default architecture then do not
- bother setting the flags for the output architecture,
- instead allow future merges to do this. If no future
- merges ever set these flags then they will retain their
- unitialised values, which surprise surprise, correspond
- to the default values. */
- if (bfd_get_arch_info (ibfd)->the_default)
- return true;
-
- elf_flags_init (obfd) = true;
- elf_elfheader (obfd)->e_flags = in_flags;
-
- if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
- && bfd_get_arch_info (obfd)->the_default)
- return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
-
- return true;
- }
-
- /* Check flag compatibility. */
- if (in_flags == out_flags)
- return true;
-
- if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH)
- && (in_flags & EF_V850_ARCH) != E_V850_ARCH)
- _bfd_error_handler (_("%s: Architecture mismatch with previous modules"),
- bfd_archive_filename (ibfd));
-
- return true;
-}
-
-/* Display the flags field. */
-
-static boolean
-v850_elf_print_private_bfd_data (abfd, ptr)
- bfd * abfd;
- PTR ptr;
-{
- FILE * file = (FILE *) ptr;
-
- BFD_ASSERT (abfd != NULL && ptr != NULL);
-
- _bfd_elf_print_private_bfd_data (abfd, ptr);
-
- /* xgettext:c-format */
- fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags);
-
- switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
- {
- default:
- case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
- case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break;
- case E_V850EA_ARCH: fprintf (file, _("v850ea architecture")); break;
- }
-
- fputc ('\n', file);
-
- return true;
-}
-
-/* V850 ELF uses four common sections. One is the usual one, and the
- others are for (small) objects in one of the special data areas:
- small, tiny and zero. All the objects are kept together, and then
- referenced via the gp register, the ep register or the r0 register
- respectively, which yields smaller, faster assembler code. This
- approach is copied from elf32-mips.c. */
-
-static asection v850_elf_scom_section;
-static asymbol v850_elf_scom_symbol;
-static asymbol * v850_elf_scom_symbol_ptr;
-static asection v850_elf_tcom_section;
-static asymbol v850_elf_tcom_symbol;
-static asymbol * v850_elf_tcom_symbol_ptr;
-static asection v850_elf_zcom_section;
-static asymbol v850_elf_zcom_symbol;
-static asymbol * v850_elf_zcom_symbol_ptr;
-
-/* Given a BFD section, try to locate the
- corresponding ELF section index. */
-
-static boolean
-v850_elf_section_from_bfd_section (abfd, sec, retval)
- bfd * abfd ATTRIBUTE_UNUSED;
- asection * sec;
- int * retval;
-{
- if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
- *retval = SHN_V850_SCOMMON;
- else if (strcmp (bfd_get_section_name (abfd, sec), ".tcommon") == 0)
- *retval = SHN_V850_TCOMMON;
- else if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0)
- *retval = SHN_V850_ZCOMMON;
- else
- return false;
-
- return true;
-}
-
-/* Handle the special V850 section numbers that a symbol may use. */
-
-static void
-v850_elf_symbol_processing (abfd, asym)
- bfd * abfd;
- asymbol * asym;
-{
- elf_symbol_type * elfsym = (elf_symbol_type *) asym;
- unsigned int indx;
-
- indx = elfsym->internal_elf_sym.st_shndx;
-
- /* If the section index is an "ordinary" index, then it may
- refer to a v850 specific section created by the assembler.
- Check the section's type and change the index it matches.
-
- FIXME: Should we alter the st_shndx field as well ? */
-
- if (indx < elf_numsections (abfd))
- switch (elf_elfsections(abfd)[indx]->sh_type)
- {
- case SHT_V850_SCOMMON:
- indx = SHN_V850_SCOMMON;
- break;
-
- case SHT_V850_TCOMMON:
- indx = SHN_V850_TCOMMON;
- break;
-
- case SHT_V850_ZCOMMON:
- indx = SHN_V850_ZCOMMON;
- break;
-
- default:
- break;
- }
-
- switch (indx)
- {
- case SHN_V850_SCOMMON:
- if (v850_elf_scom_section.name == NULL)
- {
- /* Initialize the small common section. */
- v850_elf_scom_section.name = ".scommon";
- v850_elf_scom_section.flags = SEC_IS_COMMON | SEC_ALLOC | SEC_DATA;
- v850_elf_scom_section.output_section = & v850_elf_scom_section;
- v850_elf_scom_section.symbol = & v850_elf_scom_symbol;
- v850_elf_scom_section.symbol_ptr_ptr = & v850_elf_scom_symbol_ptr;
- v850_elf_scom_symbol.name = ".scommon";
- v850_elf_scom_symbol.flags = BSF_SECTION_SYM;
- v850_elf_scom_symbol.section = & v850_elf_scom_section;
- v850_elf_scom_symbol_ptr = & v850_elf_scom_symbol;
- }
- asym->section = & v850_elf_scom_section;
- asym->value = elfsym->internal_elf_sym.st_size;
- break;
-
- case SHN_V850_TCOMMON:
- if (v850_elf_tcom_section.name == NULL)
- {
- /* Initialize the tcommon section. */
- v850_elf_tcom_section.name = ".tcommon";
- v850_elf_tcom_section.flags = SEC_IS_COMMON;
- v850_elf_tcom_section.output_section = & v850_elf_tcom_section;
- v850_elf_tcom_section.symbol = & v850_elf_tcom_symbol;
- v850_elf_tcom_section.symbol_ptr_ptr = & v850_elf_tcom_symbol_ptr;
- v850_elf_tcom_symbol.name = ".tcommon";
- v850_elf_tcom_symbol.flags = BSF_SECTION_SYM;
- v850_elf_tcom_symbol.section = & v850_elf_tcom_section;
- v850_elf_tcom_symbol_ptr = & v850_elf_tcom_symbol;
- }
- asym->section = & v850_elf_tcom_section;
- asym->value = elfsym->internal_elf_sym.st_size;
- break;
-
- case SHN_V850_ZCOMMON:
- if (v850_elf_zcom_section.name == NULL)
- {
- /* Initialize the zcommon section. */
- v850_elf_zcom_section.name = ".zcommon";
- v850_elf_zcom_section.flags = SEC_IS_COMMON;
- v850_elf_zcom_section.output_section = & v850_elf_zcom_section;
- v850_elf_zcom_section.symbol = & v850_elf_zcom_symbol;
- v850_elf_zcom_section.symbol_ptr_ptr = & v850_elf_zcom_symbol_ptr;
- v850_elf_zcom_symbol.name = ".zcommon";
- v850_elf_zcom_symbol.flags = BSF_SECTION_SYM;
- v850_elf_zcom_symbol.section = & v850_elf_zcom_section;
- v850_elf_zcom_symbol_ptr = & v850_elf_zcom_symbol;
- }
- asym->section = & v850_elf_zcom_section;
- asym->value = elfsym->internal_elf_sym.st_size;
- break;
- }
-}
-
-/* Hook called by the linker routine which adds symbols from an object
- file. We must handle the special v850 section numbers here. */
-
-static boolean
-v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
- bfd * abfd;
- struct bfd_link_info * info ATTRIBUTE_UNUSED;
- const Elf_Internal_Sym * sym;
- const char ** namep ATTRIBUTE_UNUSED;
- flagword * flagsp ATTRIBUTE_UNUSED;
- asection ** secp;
- bfd_vma * valp;
-{
- unsigned int indx = sym->st_shndx;
-
- /* If the section index is an "ordinary" index, then it may
- refer to a v850 specific section created by the assembler.
- Check the section's type and change the index it matches.
-
- FIXME: Should we alter the st_shndx field as well ? */
-
- if (indx < elf_numsections (abfd))
- switch (elf_elfsections(abfd)[indx]->sh_type)
- {
- case SHT_V850_SCOMMON:
- indx = SHN_V850_SCOMMON;
- break;
-
- case SHT_V850_TCOMMON:
- indx = SHN_V850_TCOMMON;
- break;
-
- case SHT_V850_ZCOMMON:
- indx = SHN_V850_ZCOMMON;
- break;
-
- default:
- break;
- }
-
- switch (indx)
- {
- case SHN_V850_SCOMMON:
- *secp = bfd_make_section_old_way (abfd, ".scommon");
- (*secp)->flags |= SEC_IS_COMMON;
- *valp = sym->st_size;
- break;
-
- case SHN_V850_TCOMMON:
- *secp = bfd_make_section_old_way (abfd, ".tcommon");
- (*secp)->flags |= SEC_IS_COMMON;
- *valp = sym->st_size;
- break;
-
- case SHN_V850_ZCOMMON:
- *secp = bfd_make_section_old_way (abfd, ".zcommon");
- (*secp)->flags |= SEC_IS_COMMON;
- *valp = sym->st_size;
- break;
- }
-
- return true;
-}
-
-static boolean
-v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
- bfd * abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info * info ATTRIBUTE_UNUSED;
- const char * name ATTRIBUTE_UNUSED;
- Elf_Internal_Sym * sym;
- asection * input_sec;
-{
- /* If we see a common symbol, which implies a relocatable link, then
- if a symbol was in a special common section in an input file, mark
- it as a special common in the output file. */
-
- if (sym->st_shndx == SHN_COMMON)
- {
- if (strcmp (input_sec->name, ".scommon") == 0)
- sym->st_shndx = SHN_V850_SCOMMON;
- else if (strcmp (input_sec->name, ".tcommon") == 0)
- sym->st_shndx = SHN_V850_TCOMMON;
- else if (strcmp (input_sec->name, ".zcommon") == 0)
- sym->st_shndx = SHN_V850_ZCOMMON;
- }
-
- return true;
-}
-
-static boolean
-v850_elf_section_from_shdr (abfd, hdr, name)
- bfd * abfd;
- Elf_Internal_Shdr * hdr;
- const char * name;
-{
- /* There ought to be a place to keep ELF backend specific flags, but
- at the moment there isn't one. We just keep track of the
- sections by their name, instead. */
-
- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
- return false;
-
- switch (hdr->sh_type)
- {
- case SHT_V850_SCOMMON:
- case SHT_V850_TCOMMON:
- case SHT_V850_ZCOMMON:
- if (! bfd_set_section_flags (abfd, hdr->bfd_section,
- (bfd_get_section_flags (abfd,
- hdr->bfd_section)
- | SEC_IS_COMMON)))
- return false;
- }
-
- return true;
-}
-
-/* Set the correct type for a V850 ELF section. We do this
- by the section name, which is a hack, but ought to work. */
-
-static boolean
-v850_elf_fake_sections (abfd, hdr, sec)
- bfd * abfd ATTRIBUTE_UNUSED;
- Elf32_Internal_Shdr * hdr;
- asection * sec;
-{
- register const char * name;
-
- name = bfd_get_section_name (abfd, sec);
-
- if (strcmp (name, ".scommon") == 0)
- {
- hdr->sh_type = SHT_V850_SCOMMON;
- }
- else if (strcmp (name, ".tcommon") == 0)
- {
- hdr->sh_type = SHT_V850_TCOMMON;
- }
- else if (strcmp (name, ".zcommon") == 0)
- hdr->sh_type = SHT_V850_ZCOMMON;
-
- return true;
-}
-
-#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
-#define TARGET_LITTLE_NAME "elf32-v850"
-#define ELF_ARCH bfd_arch_v850
-#define ELF_MACHINE_CODE EM_V850
-#define ELF_MACHINE_ALT1 EM_CYGNUS_V850
-#define ELF_MAXPAGESIZE 0x1000
-
-#define elf_info_to_howto v850_elf_info_to_howto_rela
-#define elf_info_to_howto_rel v850_elf_info_to_howto_rel
-
-#define elf_backend_check_relocs v850_elf_check_relocs
-#define elf_backend_relocate_section v850_elf_relocate_section
-#define elf_backend_object_p v850_elf_object_p
-#define elf_backend_final_write_processing v850_elf_final_write_processing
-#define elf_backend_section_from_bfd_section v850_elf_section_from_bfd_section
-#define elf_backend_symbol_processing v850_elf_symbol_processing
-#define elf_backend_add_symbol_hook v850_elf_add_symbol_hook
-#define elf_backend_link_output_symbol_hook v850_elf_link_output_symbol_hook
-#define elf_backend_section_from_shdr v850_elf_section_from_shdr
-#define elf_backend_fake_sections v850_elf_fake_sections
-#define elf_backend_gc_mark_hook v850_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook v850_elf_gc_sweep_hook
-
-#define elf_backend_can_gc_sections 1
-
-#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name
-#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
-#define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data
-#define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags
-#define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data
-
-#define elf_symbol_leading_char '_'
-
-#include "elf32-target.h"
diff --git a/contrib/binutils/bfd/elf64-mips.c b/contrib/binutils/bfd/elf64-mips.c
deleted file mode 100644
index f2f5dcbc..0000000
--- a/contrib/binutils/bfd/elf64-mips.c
+++ /dev/null
@@ -1,7092 +0,0 @@
-/* MIPS-specific support for 64-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
- Free Software Foundation, Inc.
- Ian Lance Taylor, Cygnus Support
- Linker support added by Mark Mitchell, CodeSourcery, LLC.
- <mark@codesourcery.com>
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* This file supports the 64-bit MIPS ELF ABI.
-
- The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
- overrides the usual ELF reloc handling, and handles reading and
- writing the relocations here. */
-
-/* TODO: Many things are unsupported, even if there is some code for it
- . (which was mostly stolen from elf32-mips.c and slightly adapted).
- .
- . - Relocation handling for REL relocs is wrong in many cases and
- . generally untested.
- . - Relocation handling for RELA relocs related to GOT support are
- . also likely to be wrong.
- . - Support for MIPS16 is only partially implemented.
- . - Embedded PIC is only partially implemented (is it needed?).
- . - Combined relocs with RSS_* entries are unsupported.
- . - The whole GOT handling for NewABI is missing, some parts of
- . the OldABI version is still lying around and shold be removed.
- */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-#include "aout/ar.h"
-#include "bfdlink.h"
-#include "genlink.h"
-#include "elf-bfd.h"
-#include "elf/mips.h"
-
-/* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
- use ECOFF. However, we support it anyhow for an easier changeover. */
-#include "coff/sym.h"
-#include "coff/symconst.h"
-#include "coff/internal.h"
-#include "coff/ecoff.h"
-/* The 64 bit versions of the mdebug data structures are in alpha.h. */
-#include "coff/alpha.h"
-#define ECOFF_SIGNED_64
-#include "ecoffswap.h"
-
-struct mips_elf64_link_hash_entry;
-
-static void mips_elf64_swap_reloc_in
- PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
- Elf64_Mips_Internal_Rel *));
-static void mips_elf64_swap_reloca_in
- PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
- Elf64_Mips_Internal_Rela *));
-static void mips_elf64_swap_reloc_out
- PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
- Elf64_Mips_External_Rel *));
-static void mips_elf64_swap_reloca_out
- PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
- Elf64_Mips_External_Rela *));
-static void mips_elf64_be_swap_reloc_in
- PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rel *));
-static void mips_elf64_be_swap_reloc_out
- PARAMS ((bfd *, const Elf_Internal_Rel *, bfd_byte *));
-static void mips_elf64_be_swap_reloca_in
- PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
-static void mips_elf64_be_swap_reloca_out
- PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
-static bfd_vma mips_elf64_high PARAMS ((bfd_vma));
-static bfd_vma mips_elf64_higher PARAMS ((bfd_vma));
-static bfd_vma mips_elf64_highest PARAMS ((bfd_vma));
-static reloc_howto_type *mips_elf64_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-static void mips_elf64_info_to_howto_rel
- PARAMS ((bfd *, arelent *, Elf64_Internal_Rel *));
-static void mips_elf64_info_to_howto_rela
- PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *));
-static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
-static boolean mips_elf64_slurp_one_reloc_table
- PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
-static boolean mips_elf64_slurp_reloc_table
- PARAMS ((bfd *, asection *, asymbol **, boolean));
-static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
-static void mips_elf64_write_rel
- PARAMS((bfd *, asection *, Elf_Internal_Shdr *, int *, PTR));
-static void mips_elf64_write_rela
- PARAMS((bfd *, asection *, Elf_Internal_Shdr *, int *, PTR));
-static struct bfd_hash_entry *mips_elf64_link_hash_newfunc
- PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static bfd_reloc_status_type mips_elf64_hi16_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_higher_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_highest_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_gprel16_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_gprel16_reloca
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_literal_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_gprel32_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_shift6_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_reloc_status_type mips_elf64_got16_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static boolean mips_elf64_assign_gp PARAMS ((bfd *, bfd_vma *));
-static bfd_reloc_status_type mips_elf64_final_gp
- PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
-static bfd_reloc_status_type gprel16_with_gp
- PARAMS ((bfd *, asymbol *, arelent *, asection *, boolean, PTR, bfd_vma));
-static int mips_elf64_additional_program_headers PARAMS ((bfd *));
-static struct bfd_link_hash_table *mips_elf64_link_hash_table_create
- PARAMS((bfd *));
-static bfd_vma mips_elf64_got_offset_from_index
- PARAMS ((bfd *, bfd *, bfd_vma));
-static struct mips_elf64_got_info *_mips_elf64_got_info
- PARAMS ((bfd *, asection **));
-static bfd_vma mips_elf64_sign_extend PARAMS ((bfd_vma, int));
-static boolean mips_elf64_overflow_p PARAMS ((bfd_vma, int));
-static bfd_vma mips_elf64_global_got_index
- PARAMS ((bfd *, struct elf_link_hash_entry *));
-static boolean mips_elf64_sort_hash_table_f
- PARAMS ((struct mips_elf64_link_hash_entry *, PTR));
-static boolean mips_elf64_sort_hash_table
- PARAMS ((struct bfd_link_info *, unsigned long));
-static void mips_elf64_swap_msym_out
- PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));
-static bfd_vma mips_elf64_create_local_got_entry
- PARAMS ((bfd *abfd, struct mips_elf64_got_info *, asection *,
- bfd_vma value));
-static bfd_vma mips_elf64_local_got_index
- PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
-static bfd_vma mips_elf64_got_page
- PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
-static bfd_vma mips_elf64_got16_entry
- PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, boolean));
-static boolean mips_elf64_local_relocation_p
- PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, boolean));
-static const Elf_Internal_Rela *mips_elf64_next_relocation
- PARAMS ((unsigned int, const Elf_Internal_Rela *,
- const Elf_Internal_Rela *));
-static boolean mips_elf64_create_dynamic_relocation
- PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
- struct mips_elf64_link_hash_entry *, asection *, bfd_vma,
- bfd_vma *, asection *));
-static bfd_reloc_status_type mips_elf64_calculate_relocation
- PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
- const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
- Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
- boolean *));
-static bfd_vma mips_elf64_obtain_contents
- PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
-static boolean mips_elf64_perform_relocation
- PARAMS ((struct bfd_link_info *, reloc_howto_type *,
- const Elf_Internal_Rela *, bfd_vma,
- bfd *, asection *, bfd_byte *, boolean));
-static boolean mips_elf64_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-boolean mips_elf64_create_dynamic_sections
- PARAMS ((bfd *, struct bfd_link_info *));
-boolean mips_elf64_adjust_dynamic_symbol
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *h));
-boolean mips_elf64_always_size_sections
- PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf64_check_mips16_stubs
- PARAMS ((struct mips_elf64_link_hash_entry *, PTR));
-boolean mips_elf64_size_dynamic_sections
- PARAMS ((bfd *, struct bfd_link_info *));
-boolean mips_elf64_finish_dynamic_symbol
- PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
- Elf_Internal_Sym *));
-boolean mips_elf64_finish_dynamic_sections
- PARAMS ((bfd *, struct bfd_link_info *info));
-asection *mips_elf64_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *));
-boolean mips_elf64_gc_sweep_hook
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-static boolean mips_elf64_create_got_section
- PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf64_record_global_got_symbol
- PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *,
- struct mips_elf64_got_info *));
-static asection *mips_elf64_create_msym_section PARAMS((bfd *));
-static void mips_elf64_allocate_dynamic_relocations
- PARAMS ((bfd *, unsigned int));
-static boolean mips_elf64_stub_section_p PARAMS ((bfd *, asection *));
-boolean mips_elf64_check_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-static boolean mips_elf64_output_extsym
- PARAMS ((struct mips_elf64_link_hash_entry *, PTR));
-static void mips_elf64_swap_gptab_in
- PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
-static void mips_elf64_swap_gptab_out
- PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
-static int gptab_compare PARAMS ((const PTR, const PTR));
-boolean mips_elf64_final_link PARAMS ((bfd *, struct bfd_link_info *));
-
-extern const bfd_target bfd_elf64_bigmips_vec;
-extern const bfd_target bfd_elf64_littlemips_vec;
-
-static bfd_vma prev_reloc_addend = 0;
-static bfd_size_type prev_reloc_address = 0;
-
-/* Whether we are trying to be compatible with IRIX6 (or little endianers
- which are otherwise IRIX-ABI compliant). */
-#define SGI_COMPAT(abfd) \
- ((abfd->xvec == &bfd_elf64_bigmips_vec) \
- || (abfd->xvec == &bfd_elf64_littlemips_vec) ? true : false)
-
-/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
- from smaller values. Start with zero, widen, *then* decrement. */
-#define MINUS_ONE (((bfd_vma)0) - 1)
-
-/* The number of local .got entries we reserve. */
-#define MIPS_RESERVED_GOTNO (2)
-
-/* Instructions which appear in a stub. */
-#define ELF_MIPS_GP_OFFSET(abfd) 0x7ff0
-#define STUB_LW 0xdf998010 /* ld t9,0x8010(gp) */
-#define STUB_MOVE 0x03e07825 /* move t7,ra */
-#define STUB_JALR 0x0320f809 /* jal t9 */
-#define STUB_LI16 0x34180000 /* ori t8,zero,0 */
-#define MIPS_FUNCTION_STUB_SIZE (16)
-
-/* The relocation table used for SHT_REL sections. */
-
-#define UNUSED_RELOC(num) { num, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-
-static reloc_howto_type mips_elf64_howto_table_rel[] =
-{
- /* No relocation. */
- HOWTO (R_MIPS_NONE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_NONE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit relocation. */
- HOWTO (R_MIPS_16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit relocation. */
- HOWTO (R_MIPS_32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit symbol relative relocation. */
- HOWTO (R_MIPS_REL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 26 bit jump address. */
- HOWTO (R_MIPS_26, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper 36
- bits must match the PC + 4. */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_26", /* name */
- true, /* partial_inplace */
- 0x03ffffff, /* src_mask */
- 0x03ffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of symbol value. */
- HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HI16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of symbol value. */
- HOWTO (R_MIPS_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_LO16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GP relative reference. */
- HOWTO (R_MIPS_GPREL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_gprel16_reloc, /* special_function */
- "R_MIPS_GPREL16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to literal section. */
- HOWTO (R_MIPS_LITERAL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_literal_reloc, /* special_function */
- "R_MIPS_LITERAL", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to global offset table. */
- HOWTO (R_MIPS_GOT16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_got16_reloc, /* special_function */
- "R_MIPS_GOT16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit PC relative reference. */
- HOWTO (R_MIPS_PC16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_PC16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 16 bit call through global offset table. */
- /* FIXME: This is not handled correctly. */
- HOWTO (R_MIPS_CALL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit GP relative reference. */
- HOWTO (R_MIPS_GPREL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_elf64_gprel32_reloc, /* special_function */
- "R_MIPS_GPREL32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- UNUSED_RELOC (13),
- UNUSED_RELOC (14),
- UNUSED_RELOC (15),
-
- /* A 5 bit shift field. */
- HOWTO (R_MIPS_SHIFT5, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 5, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SHIFT5", /* name */
- true, /* partial_inplace */
- 0x000007c0, /* src_mask */
- 0x000007c0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 6 bit shift field. */
- HOWTO (R_MIPS_SHIFT6, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 6, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- mips_elf64_shift6_reloc, /* special_function */
- "R_MIPS_SHIFT6", /* name */
- true, /* partial_inplace */
- 0x000007c4, /* src_mask */
- 0x000007c4, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit relocation. */
- HOWTO (R_MIPS_64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_64", /* name */
- true, /* partial_inplace */
- MINUS_ONE, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_DISP", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement to page pointer in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_PAGE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_PAGE", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Offset from page pointer in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_OFST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_OFST", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_HI16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_LO16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit substraction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SUB, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SUB", /* name */
- true, /* partial_inplace */
- MINUS_ONE, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Insert the addend as an instruction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_INSERT_A, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_INSERT_A", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Insert the addend as an instruction, and change all relocations
- to refer to the old instruction at the address. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_INSERT_B, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_INSERT_B", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Delete a 32 bit instruction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_DELETE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_DELETE", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the higher value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHER, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_elf64_higher_reloc, /* special_function */
- "R_MIPS_HIGHER", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the highest value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHEST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_elf64_highest_reloc, /* special_function */
- "R_MIPS_HIGHEST", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_CALL_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_HI16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_CALL_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_LO16", /* name */
- true, /* partial_inplace */
- 0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Section displacement, used by an associated event location section. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SCN_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SCN_DISP", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_MIPS_REL16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL16", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* These two are obsolete. */
- EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
- EMPTY_HOWTO (R_MIPS_PJUMP),
-
- /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
- It must be used for multigot GOT's (and only there). */
- HOWTO (R_MIPS_RELGOT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_RELGOT", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Protected jump conversion. This is an optimization hint. No
- relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x00000000, /* dst_mask */
- false), /* pcrel_offset */
-};
-
-/* The relocation table used for SHT_RELA sections. */
-
-static reloc_howto_type mips_elf64_howto_table_rela[] =
-{
- /* No relocation. */
- HOWTO (R_MIPS_NONE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_NONE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit relocation. */
- HOWTO (R_MIPS_16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit relocation. */
- HOWTO (R_MIPS_32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit symbol relative relocation. */
- HOWTO (R_MIPS_REL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 26 bit jump address. */
- HOWTO (R_MIPS_26, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper 36
- bits must match the PC + 4. */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_26", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x03ffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* R_MIPS_HI16 and R_MIPS_LO16 are unsupported for 64 bit REL. */
- /* High 16 bits of symbol value. */
- HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of symbol value. */
- HOWTO (R_MIPS_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_LO16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GP relative reference. */
- HOWTO (R_MIPS_GPREL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_gprel16_reloca, /* special_function */
- "R_MIPS_GPREL16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to literal section. */
- HOWTO (R_MIPS_LITERAL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_literal_reloc, /* special_function */
- "R_MIPS_LITERAL", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Reference to global offset table. */
- /* FIXME: This is not handled correctly. */
- HOWTO (R_MIPS_GOT16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 16 bit PC relative reference. */
- HOWTO (R_MIPS_PC16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_PC16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- true), /* pcrel_offset */
-
- /* 16 bit call through global offset table. */
- /* FIXME: This is not handled correctly. */
- HOWTO (R_MIPS_CALL16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 32 bit GP relative reference. */
- HOWTO (R_MIPS_GPREL32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- mips_elf64_gprel32_reloc, /* special_function */
- "R_MIPS_GPREL32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- UNUSED_RELOC (13),
- UNUSED_RELOC (14),
- UNUSED_RELOC (15),
-
- /* A 5 bit shift field. */
- HOWTO (R_MIPS_SHIFT5, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 5, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SHIFT5", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x000007c0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 6 bit shift field. */
- HOWTO (R_MIPS_SHIFT6, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 6, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- mips_elf64_shift6_reloc, /* special_function */
- "R_MIPS_SHIFT6", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x000007c4, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit relocation. */
- HOWTO (R_MIPS_64, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_64", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_DISP", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Displacement to page pointer in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_PAGE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_PAGE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Offset from page pointer in the global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_OFST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_OFST", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_GOT_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_GOT_LO16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* 64 bit substraction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SUB, /* type */
- 0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SUB", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- MINUS_ONE, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Insert the addend as an instruction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_INSERT_A, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_INSERT_A", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Insert the addend as an instruction, and change all relocations
- to refer to the old instruction at the address. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_INSERT_B, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_INSERT_B", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Delete a 32 bit instruction. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_DELETE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_DELETE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the higher value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHER, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HIGHER", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Get the highest value of a 64 bit addend. */
- HOWTO (R_MIPS_HIGHEST, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_HIGHEST", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* High 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_CALL_HI16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_HI16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Low 16 bits of displacement in global offset table. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_CALL_LO16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_CALL_LO16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x0000ffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Section displacement, used by an associated event location section. */
- /* FIXME: Not handled correctly. */
- HOWTO (R_MIPS_SCN_DISP, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_SCN_DISP", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- HOWTO (R_MIPS_REL16, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_REL16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* These two are obsolete. */
- EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
- EMPTY_HOWTO (R_MIPS_PJUMP),
-
- /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
- It must be used for multigot GOT's (and only there). */
- HOWTO (R_MIPS_RELGOT, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_RELGOT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* Protected jump conversion. This is an optimization hint. No
- relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0x00000000, /* dst_mask */
- false), /* pcrel_offset */
-};
-
-/* Swap in a MIPS 64-bit Rel reloc. */
-
-static void
-mips_elf64_swap_reloc_in (abfd, src, dst)
- bfd *abfd;
- const Elf64_Mips_External_Rel *src;
- Elf64_Mips_Internal_Rel *dst;
-{
- dst->r_offset = H_GET_64 (abfd, src->r_offset);
- dst->r_sym = H_GET_32 (abfd, src->r_sym);
- dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
- dst->r_type3 = H_GET_8 (abfd, src->r_type3);
- dst->r_type2 = H_GET_8 (abfd, src->r_type2);
- dst->r_type = H_GET_8 (abfd, src->r_type);
-}
-
-/* Swap in a MIPS 64-bit Rela reloc. */
-
-static void
-mips_elf64_swap_reloca_in (abfd, src, dst)
- bfd *abfd;
- const Elf64_Mips_External_Rela *src;
- Elf64_Mips_Internal_Rela *dst;
-{
- dst->r_offset = H_GET_64 (abfd, src->r_offset);
- dst->r_sym = H_GET_32 (abfd, src->r_sym);
- dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
- dst->r_type3 = H_GET_8 (abfd, src->r_type3);
- dst->r_type2 = H_GET_8 (abfd, src->r_type2);
- dst->r_type = H_GET_8 (abfd, src->r_type);
- dst->r_addend = H_GET_S64 (abfd, src->r_addend);
-}
-
-/* Swap out a MIPS 64-bit Rel reloc. */
-
-static void
-mips_elf64_swap_reloc_out (abfd, src, dst)
- bfd *abfd;
- const Elf64_Mips_Internal_Rel *src;
- Elf64_Mips_External_Rel *dst;
-{
- H_PUT_64 (abfd, src->r_offset, dst->r_offset);
- H_PUT_32 (abfd, src->r_sym, dst->r_sym);
- H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
- H_PUT_8 (abfd, src->r_type3, dst->r_type3);
- H_PUT_8 (abfd, src->r_type2, dst->r_type2);
- H_PUT_8 (abfd, src->r_type, dst->r_type);
-}
-
-/* Swap out a MIPS 64-bit Rela reloc. */
-
-static void
-mips_elf64_swap_reloca_out (abfd, src, dst)
- bfd *abfd;
- const Elf64_Mips_Internal_Rela *src;
- Elf64_Mips_External_Rela *dst;
-{
- H_PUT_64 (abfd, src->r_offset, dst->r_offset);
- H_PUT_32 (abfd, src->r_sym, dst->r_sym);
- H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
- H_PUT_8 (abfd, src->r_type3, dst->r_type3);
- H_PUT_8 (abfd, src->r_type2, dst->r_type2);
- H_PUT_8 (abfd, src->r_type, dst->r_type);
- H_PUT_S64 (abfd, src->r_addend, dst->r_addend);
-}
-
-/* Swap in a MIPS 64-bit Rel reloc. */
-
-static void
-mips_elf64_be_swap_reloc_in (abfd, src, dst)
- bfd *abfd;
- const bfd_byte *src;
- Elf_Internal_Rel *dst;
-{
- Elf64_Mips_Internal_Rel mirel;
-
- mips_elf64_swap_reloc_in (abfd,
- (const Elf64_Mips_External_Rel *) src,
- &mirel);
-
- dst[0].r_offset = mirel.r_offset;
- dst[0].r_info = ELF64_R_INFO (mirel.r_sym, mirel.r_type);
- dst[1].r_offset = mirel.r_offset;
- dst[1].r_info = ELF64_R_INFO (mirel.r_ssym, mirel.r_type2);
- dst[2].r_offset = mirel.r_offset;
- dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirel.r_type3);
-}
-
-/* Swap in a MIPS 64-bit Rela reloc. */
-
-static void
-mips_elf64_be_swap_reloca_in (abfd, src, dst)
- bfd *abfd;
- const bfd_byte *src;
- Elf_Internal_Rela *dst;
-{
- Elf64_Mips_Internal_Rela mirela;
-
- mips_elf64_swap_reloca_in (abfd,
- (const Elf64_Mips_External_Rela *) src,
- &mirela);
-
- dst[0].r_offset = mirela.r_offset;
- dst[0].r_info = ELF64_R_INFO (mirela.r_sym, mirela.r_type);
- dst[0].r_addend = mirela.r_addend;
- dst[1].r_offset = mirela.r_offset;
- dst[1].r_info = ELF64_R_INFO (mirela.r_ssym, mirela.r_type2);
- dst[1].r_addend = 0;
- dst[2].r_offset = mirela.r_offset;
- dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirela.r_type3);
- dst[2].r_addend = 0;
-}
-
-/* Swap out a MIPS 64-bit Rel reloc. */
-
-static void
-mips_elf64_be_swap_reloc_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Rel *src;
- bfd_byte *dst;
-{
- Elf64_Mips_Internal_Rel mirel;
-
- mirel.r_offset = src[0].r_offset;
- BFD_ASSERT(src[0].r_offset == src[1].r_offset);
- BFD_ASSERT(src[0].r_offset == src[2].r_offset);
-
- mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
- mirel.r_sym = ELF64_R_SYM (src[0].r_info);
- mirel.r_type2 = ELF64_MIPS_R_TYPE2 (src[1].r_info);
- mirel.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
- mirel.r_type3 = ELF64_MIPS_R_TYPE3 (src[2].r_info);
-
- mips_elf64_swap_reloc_out (abfd, &mirel,
- (Elf64_Mips_External_Rel *) dst);
-}
-
-/* Swap out a MIPS 64-bit Rela reloc. */
-
-static void
-mips_elf64_be_swap_reloca_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Rela *src;
- bfd_byte *dst;
-{
- Elf64_Mips_Internal_Rela mirela;
-
- mirela.r_offset = src[0].r_offset;
- BFD_ASSERT(src[0].r_offset == src[1].r_offset);
- BFD_ASSERT(src[0].r_offset == src[2].r_offset);
-
- mirela.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
- mirela.r_sym = ELF64_R_SYM (src[0].r_info);
- mirela.r_addend = src[0].r_addend;
- BFD_ASSERT(src[1].r_addend == 0);
- BFD_ASSERT(src[2].r_addend == 0);
-
- mirela.r_type2 = ELF64_MIPS_R_TYPE2 (src[1].r_info);
- mirela.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
- mirela.r_type3 = ELF64_MIPS_R_TYPE3 (src[2].r_info);
-
- mips_elf64_swap_reloca_out (abfd, &mirela,
- (Elf64_Mips_External_Rela *) dst);
-}
-
-/* Calculate the %high function. */
-
-static bfd_vma
-mips_elf64_high (value)
- bfd_vma value;
-{
- return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
-}
-
-/* Calculate the %higher function. */
-
-static bfd_vma
-mips_elf64_higher (value)
- bfd_vma value;
-{
- return ((value + (bfd_vma) 0x80008000) >> 32) & 0xffff;
-}
-
-/* Calculate the %highest function. */
-
-static bfd_vma
-mips_elf64_highest (value)
- bfd_vma value;
-{
- return ((value + (bfd_vma) 0x800080008000) >> 48) & 0xffff;
-}
-
-/* Do a R_MIPS_HI16 relocation. */
-
-bfd_reloc_status_type
-mips_elf64_hi16_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- /* If we're relocating, and this is an external symbol, we don't
- want to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc_entry->howto->partial_inplace
- || reloc_entry->addend == 0))
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
- reloc_entry->addend += 0x8000;
-
- return bfd_reloc_continue;
-}
-
-/* Do a R_MIPS_HIGHER relocation. */
-
-bfd_reloc_status_type
-mips_elf64_higher_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- /* If we're relocating, and this is an external symbol, we don't
- want to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc_entry->howto->partial_inplace
- || reloc_entry->addend == 0))
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (((reloc_entry->addend & 0xffffffff) + 0x80008000)
- & ~0xffffffff)
- reloc_entry->addend += 0x80008000;
-
- return bfd_reloc_continue;
-}
-
-/* Do a R_MIPS_HIGHEST relocation. */
-
-bfd_reloc_status_type
-mips_elf64_highest_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- /* If we're relocating, and this is an external symbol, we don't
- want to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc_entry->howto->partial_inplace
- || reloc_entry->addend == 0))
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (((reloc_entry->addend & 0xffffffffffff) + 0x800080008000)
- & ~0xffffffffffff)
- reloc_entry->addend += 0x800080008000;
-
- return bfd_reloc_continue;
-}
-
-/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
- table used for PIC code. If the symbol is an external symbol, the
- instruction is modified to contain the offset of the appropriate
- entry in the global offset table. If the symbol is a section
- symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
- addends are combined to form the real addend against the section
- symbol; the GOT16 is modified to contain the offset of an entry in
- the global offset table, and the LO16 is modified to offset it
- appropriately. Thus an offset larger than 16 bits requires a
- modified value in the global offset table.
-
- This implementation suffices for the assembler, but the linker does
- not yet know how to create global offset tables. */
-
-bfd_reloc_status_type
-mips_elf64_got16_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- /* If we're relocating, and this an external symbol, we don't want
- to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* If we're relocating, and this is a local symbol, we can handle it
- just like HI16. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) != 0)
- return mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
-
- abort ();
-}
-
-/* Set the GP value for OUTPUT_BFD. Returns false if this is a
- dangerous relocation. */
-
-static boolean
-mips_elf64_assign_gp (output_bfd, pgp)
- bfd *output_bfd;
- bfd_vma *pgp;
-{
- unsigned int count;
- asymbol **sym;
- unsigned int i;
-
- /* If we've already figured out what GP will be, just return it. */
- *pgp = _bfd_get_gp_value (output_bfd);
- if (*pgp)
- return true;
-
- count = bfd_get_symcount (output_bfd);
- sym = bfd_get_outsymbols (output_bfd);
-
- /* The linker script will have created a symbol named `_gp' with the
- appropriate value. */
- if (sym == (asymbol **) NULL)
- i = count;
- else
- {
- for (i = 0; i < count; i++, sym++)
- {
- register CONST char *name;
-
- name = bfd_asymbol_name (*sym);
- if (*name == '_' && strcmp (name, "_gp") == 0)
- {
- *pgp = bfd_asymbol_value (*sym);
- _bfd_set_gp_value (output_bfd, *pgp);
- break;
- }
- }
- }
-
- if (i >= count)
- {
- /* Only get the error once. */
- *pgp = 4;
- _bfd_set_gp_value (output_bfd, *pgp);
- return false;
- }
-
- return true;
-}
-
-/* We have to figure out the gp value, so that we can adjust the
- symbol value correctly. We look up the symbol _gp in the output
- BFD. If we can't find it, we're stuck. We cache it in the ELF
- target data. We don't need to adjust the symbol value for an
- external symbol if we are producing relocateable output. */
-
-static bfd_reloc_status_type
-mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
- bfd *output_bfd;
- asymbol *symbol;
- boolean relocateable;
- char **error_message;
- bfd_vma *pgp;
-{
- if (bfd_is_und_section (symbol->section)
- && ! relocateable)
- {
- *pgp = 0;
- return bfd_reloc_undefined;
- }
-
- *pgp = _bfd_get_gp_value (output_bfd);
- if (*pgp == 0
- && (! relocateable
- || (symbol->flags & BSF_SECTION_SYM) != 0))
- {
- if (relocateable)
- {
- /* Make up a value. */
- *pgp = symbol->section->output_section->vma + 0x4000;
- _bfd_set_gp_value (output_bfd, *pgp);
- }
- else if (!mips_elf64_assign_gp (output_bfd, pgp))
- {
- *error_message =
- (char *) _("GP relative relocation when _gp not defined");
- return bfd_reloc_dangerous;
- }
- }
-
- return bfd_reloc_ok;
-}
-
-/* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
- become the offset from the gp register. */
-
-bfd_reloc_status_type
-mips_elf64_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_reloc_status_type ret;
- bfd_vma gp;
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ELF
- file. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (output_bfd != (bfd *) NULL)
- relocateable = true;
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
- }
-
- ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
- &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- return gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
- relocateable, data, gp);
-}
-
-static bfd_reloc_status_type
-gprel16_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
- gp)
- bfd *abfd;
- asymbol *symbol;
- arelent *reloc_entry;
- asection *input_section;
- boolean relocateable;
- PTR data;
- bfd_vma gp;
-{
- bfd_vma relocation;
- unsigned long insn;
- unsigned long val;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* Set val to the offset into the section or symbol. */
- if (reloc_entry->howto->src_mask == 0)
- {
- /* This case occurs with the 64-bit MIPS ELF ABI. */
- val = reloc_entry->addend;
- }
- else
- {
- val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
- if (val & 0x8000)
- val -= 0x10000;
- }
-
- /* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
- an external symbol. */
- if (! relocateable
- || (symbol->flags & BSF_SECTION_SYM) != 0)
- val += relocation - gp;
-
- insn = (insn & ~0xffff) | (val & 0xffff);
- bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
-
- if (relocateable)
- reloc_entry->address += input_section->output_offset;
-
- else if ((long) val >= 0x8000 || (long) val < -0x8000)
- return bfd_reloc_overflow;
-
- return bfd_reloc_ok;
-}
-
-/* Do a R_MIPS_GPREL16 RELA relocation. */
-
-bfd_reloc_status_type
-mips_elf64_gprel16_reloca (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_vma gp;
-
- /* This works only for NewABI. */
- BFD_ASSERT (reloc_entry->howto->src_mask == 0);
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ELF
- file. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (output_bfd != (bfd *) NULL)
- relocateable = true;
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
- }
-
- if (prev_reloc_address != reloc_entry->address)
- prev_reloc_address = reloc_entry->address;
- else
- {
- mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
- &gp);
- prev_reloc_addend = reloc_entry->addend + reloc_entry->address - gp;
- if (symbol->flags & BSF_LOCAL)
- prev_reloc_addend += _bfd_get_gp_value (abfd);
-/*fprintf(stderr, "Addend: %lx, Next Addend: %lx\n", reloc_entry->addend, prev_reloc_addend);*/
- }
-
- return bfd_reloc_ok;
-}
-
-/* Do a R_MIPS_LITERAL relocation. */
-
-bfd_reloc_status_type
-mips_elf64_literal_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- /* If we're relocating, and this is an external symbol, we don't
- want to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc_entry->howto->partial_inplace
- || reloc_entry->addend == 0))
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* FIXME: The entries in the .lit8 and .lit4 sections should be merged.
- Currently we simply call mips_elf64_gprel16_reloc. */
- return mips_elf64_gprel16_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
-}
-
-/* Do a R_MIPS_GPREL32 relocation. Is this 32 bit value the offset
- from the gp register? XXX */
-
-bfd_reloc_status_type
-mips_elf64_gprel32_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
-{
- boolean relocateable;
- bfd_reloc_status_type ret;
- bfd_vma gp;
- bfd_vma relocation;
- unsigned long val;
-
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. We will only have an
- addend if this is a newly created reloc, not read from an ELF
- file. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- *error_message = (char *)
- _("32bits gp relative relocation occurs for an external symbol");
- return bfd_reloc_outofrange;
- }
-
- if (output_bfd != (bfd *) NULL)
- {
- relocateable = true;
- gp = _bfd_get_gp_value (output_bfd);
- }
- else
- {
- relocateable = false;
- output_bfd = symbol->section->output_section->owner;
-
- ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
- error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
- }
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- if (reloc_entry->howto->src_mask == 0)
- {
- /* This case arises with the 64-bit MIPS ELF ABI. */
- val = 0;
- }
- else
- val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* Set val to the offset into the section or symbol. */
- val += reloc_entry->addend;
-
- /* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
- an external symbol. */
- if (! relocateable
- || (symbol->flags & BSF_SECTION_SYM) != 0)
- val += relocation - gp;
-
- bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
-
- if (relocateable)
- reloc_entry->address += input_section->output_offset;
-
- return bfd_reloc_ok;
-}
-
-/* Do a R_MIPS_SHIFT6 relocation. The MSB of the shift is stored at bit 2,
- the rest is at bits 6-10. The bitpos alredy got right by the howto. */
-
-bfd_reloc_status_type
-mips_elf64_shift6_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- /* If we're relocating, and this is an external symbol, we don't
- want to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc_entry->howto->partial_inplace
- || reloc_entry->addend == 0))
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
- | (reloc_entry->addend & 0x00000800) >> 9;
-
- return bfd_reloc_continue;
-}
-
-static int
-mips_elf64_additional_program_headers (abfd)
- bfd *abfd;
-{
- int ret = 0;
-
- /* See if we need a PT_MIPS_OPTIONS segment. */
- if (bfd_get_section_by_name (abfd, ".MIPS.options"))
- ++ret;
-
- return ret;
-}
-
-/* Given a BFD reloc type, return a howto structure. */
-
-static reloc_howto_type *
-mips_elf64_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- /* FIXME: We default to RELA here instead of choosing the right
- relocation variant. */
- reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
-
- switch (code)
- {
- case BFD_RELOC_NONE:
- return &howto_table[R_MIPS_NONE];
- case BFD_RELOC_16:
- return &howto_table[R_MIPS_16];
- case BFD_RELOC_32:
- return &howto_table[R_MIPS_32];
- case BFD_RELOC_64:
- case BFD_RELOC_CTOR:
- /* We need to handle these specially. Select the right
- relocation (R_MIPS_32 or R_MIPS_64) based on the
- size of addresses on this architecture. */
- if (bfd_arch_bits_per_address (abfd) == 32)
- return &howto_table[R_MIPS_32];
- else
- return &howto_table[R_MIPS_64];
-
- case BFD_RELOC_16_PCREL:
- return &howto_table[R_MIPS_PC16];
- case BFD_RELOC_HI16_S:
- return &howto_table[R_MIPS_HI16];
- case BFD_RELOC_LO16:
- return &howto_table[R_MIPS_LO16];
- case BFD_RELOC_GPREL16:
- return &howto_table[R_MIPS_GPREL16];
- case BFD_RELOC_GPREL32:
- return &howto_table[R_MIPS_GPREL32];
- case BFD_RELOC_MIPS_JMP:
- return &howto_table[R_MIPS_26];
- case BFD_RELOC_MIPS_LITERAL:
- return &howto_table[R_MIPS_LITERAL];
- case BFD_RELOC_MIPS_GOT16:
- return &howto_table[R_MIPS_GOT16];
- case BFD_RELOC_MIPS_CALL16:
- return &howto_table[R_MIPS_CALL16];
- case BFD_RELOC_MIPS_SHIFT5:
- return &howto_table[R_MIPS_SHIFT5];
- case BFD_RELOC_MIPS_SHIFT6:
- return &howto_table[R_MIPS_SHIFT6];
- case BFD_RELOC_MIPS_GOT_DISP:
- return &howto_table[R_MIPS_GOT_DISP];
- case BFD_RELOC_MIPS_GOT_PAGE:
- return &howto_table[R_MIPS_GOT_PAGE];
- case BFD_RELOC_MIPS_GOT_OFST:
- return &howto_table[R_MIPS_GOT_OFST];
- case BFD_RELOC_MIPS_GOT_HI16:
- return &howto_table[R_MIPS_GOT_HI16];
- case BFD_RELOC_MIPS_GOT_LO16:
- return &howto_table[R_MIPS_GOT_LO16];
- case BFD_RELOC_MIPS_SUB:
- return &howto_table[R_MIPS_SUB];
- case BFD_RELOC_MIPS_INSERT_A:
- return &howto_table[R_MIPS_INSERT_A];
- case BFD_RELOC_MIPS_INSERT_B:
- return &howto_table[R_MIPS_INSERT_B];
- case BFD_RELOC_MIPS_DELETE:
- return &howto_table[R_MIPS_DELETE];
- case BFD_RELOC_MIPS_HIGHEST:
- return &howto_table[R_MIPS_HIGHEST];
- case BFD_RELOC_MIPS_HIGHER:
- return &howto_table[R_MIPS_HIGHER];
- case BFD_RELOC_MIPS_CALL_HI16:
- return &howto_table[R_MIPS_CALL_HI16];
- case BFD_RELOC_MIPS_CALL_LO16:
- return &howto_table[R_MIPS_CALL_LO16];
- case BFD_RELOC_MIPS_SCN_DISP:
- return &howto_table[R_MIPS_SCN_DISP];
- case BFD_RELOC_MIPS_REL16:
- return &howto_table[R_MIPS_REL16];
- /* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated. */
- case BFD_RELOC_MIPS_RELGOT:
- return &howto_table[R_MIPS_RELGOT];
- case BFD_RELOC_MIPS_JALR:
- return &howto_table[R_MIPS_JALR];
-/*
- case BFD_RELOC_MIPS16_JMP:
- return &elf_mips16_jump_howto;
- case BFD_RELOC_MIPS16_GPREL:
- return &elf_mips16_gprel_howto;
- case BFD_RELOC_VTABLE_INHERIT:
- return &elf_mips_gnu_vtinherit_howto;
- case BFD_RELOC_VTABLE_ENTRY:
- return &elf_mips_gnu_vtentry_howto;
- case BFD_RELOC_PCREL_HI16_S:
- return &elf_mips_gnu_rel_hi16;
- case BFD_RELOC_PCREL_LO16:
- return &elf_mips_gnu_rel_lo16;
- case BFD_RELOC_16_PCREL_S2:
- return &elf_mips_gnu_rel16_s2;
- case BFD_RELOC_64_PCREL:
- return &elf_mips_gnu_pcrel64;
- case BFD_RELOC_32_PCREL:
- return &elf_mips_gnu_pcrel32;
-*/
- default:
- bfd_set_error (bfd_error_bad_value);
- return NULL;
- }
-}
-
-/* Prevent relocation handling by bfd for MIPS ELF64. */
-
-static void
-mips_elf64_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *cache_ptr ATTRIBUTE_UNUSED;
- Elf64_Internal_Rel *dst ATTRIBUTE_UNUSED;
-{
- BFD_ASSERT (0);
-}
-
-static void
-mips_elf64_info_to_howto_rela (abfd, cache_ptr, dst)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *cache_ptr ATTRIBUTE_UNUSED;
- Elf64_Internal_Rela *dst ATTRIBUTE_UNUSED;
-{
- BFD_ASSERT (0);
-}
-
-/* Since each entry in an SHT_REL or SHT_RELA section can represent up
- to three relocs, we must tell the user to allocate more space. */
-
-static long
-mips_elf64_get_reloc_upper_bound (abfd, sec)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
-{
- return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
-}
-
-/* Read the relocations from one reloc section. */
-
-static boolean
-mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
- bfd *abfd;
- asection *asect;
- asymbol **symbols;
- const Elf_Internal_Shdr *rel_hdr;
-{
- PTR allocated = NULL;
- bfd_byte *native_relocs;
- arelent *relents;
- arelent *relent;
- bfd_vma count;
- bfd_vma i;
- int entsize;
- reloc_howto_type *howto_table;
-
- allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
- if (allocated == NULL)
- return false;
-
- if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
- goto error_return;
-
- native_relocs = (bfd_byte *) allocated;
-
- relents = asect->relocation + asect->reloc_count;
-
- entsize = rel_hdr->sh_entsize;
- BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
- || entsize == sizeof (Elf64_Mips_External_Rela));
-
- count = rel_hdr->sh_size / entsize;
-
- if (entsize == sizeof (Elf64_Mips_External_Rel))
- howto_table = mips_elf64_howto_table_rel;
- else
- howto_table = mips_elf64_howto_table_rela;
-
- relent = relents;
- for (i = 0; i < count; i++, native_relocs += entsize)
- {
- Elf64_Mips_Internal_Rela rela;
- boolean used_sym, used_ssym;
- int ir;
-
- if (entsize == sizeof (Elf64_Mips_External_Rela))
- mips_elf64_swap_reloca_in (abfd,
- (Elf64_Mips_External_Rela *) native_relocs,
- &rela);
- else
- {
- Elf64_Mips_Internal_Rel rel;
-
- mips_elf64_swap_reloc_in (abfd,
- (Elf64_Mips_External_Rel *) native_relocs,
- &rel);
- rela.r_offset = rel.r_offset;
- rela.r_sym = rel.r_sym;
- rela.r_ssym = rel.r_ssym;
- rela.r_type3 = rel.r_type3;
- rela.r_type2 = rel.r_type2;
- rela.r_type = rel.r_type;
- rela.r_addend = 0;
- }
-
- /* Each entry represents up to three actual relocations. */
-
- used_sym = false;
- used_ssym = false;
- for (ir = 0; ir < 3; ir++)
- {
- enum elf_mips_reloc_type type;
-
- switch (ir)
- {
- default:
- abort ();
- case 0:
- type = (enum elf_mips_reloc_type) rela.r_type;
- break;
- case 1:
- type = (enum elf_mips_reloc_type) rela.r_type2;
- break;
- case 2:
- type = (enum elf_mips_reloc_type) rela.r_type3;
- break;
- }
-
- if (type == R_MIPS_NONE)
- {
- /* There are no more relocations in this entry. If this
- is the first entry, we need to generate a dummy
- relocation so that the generic linker knows that
- there has been a break in the sequence of relocations
- applying to a particular address. */
- if (ir == 0)
- {
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- relent->address = rela.r_offset;
- else
- relent->address = rela.r_offset - asect->vma;
- relent->addend = 0;
- relent->howto = &howto_table[(int) R_MIPS_NONE];
- ++relent;
- }
- break;
- }
-
- /* Some types require symbols, whereas some do not. */
- switch (type)
- {
- case R_MIPS_NONE:
- case R_MIPS_LITERAL:
- case R_MIPS_INSERT_A:
- case R_MIPS_INSERT_B:
- case R_MIPS_DELETE:
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
- break;
-
- default:
- if (! used_sym)
- {
- if (rela.r_sym == 0)
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
- else
- {
- asymbol **ps, *s;
-
- ps = symbols + rela.r_sym - 1;
- s = *ps;
- if ((s->flags & BSF_SECTION_SYM) == 0)
- relent->sym_ptr_ptr = ps;
- else
- relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
- }
-
- used_sym = true;
- }
- else if (! used_ssym)
- {
- switch (rela.r_ssym)
- {
- case RSS_UNDEF:
- relent->sym_ptr_ptr =
- bfd_abs_section_ptr->symbol_ptr_ptr;
- break;
-
- case RSS_GP:
- case RSS_GP0:
- case RSS_LOC:
- /* FIXME: I think these need to be handled using
- special howto structures. */
- BFD_ASSERT (0);
- break;
-
- default:
- BFD_ASSERT (0);
- break;
- }
-
- used_ssym = true;
- }
- else
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
-
- break;
- }
-
- /* The address of an ELF reloc is section relative for an
- object file, and absolute for an executable file or
- shared library. The address of a BFD reloc is always
- section relative. */
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- relent->address = rela.r_offset;
- else
- relent->address = rela.r_offset - asect->vma;
-
- relent->addend = rela.r_addend;
-
- relent->howto = &howto_table[(int) type];
-
- ++relent;
- }
- }
-
- asect->reloc_count += relent - relents;
-
- if (allocated != NULL)
- free (allocated);
-
- return true;
-
- error_return:
- if (allocated != NULL)
- free (allocated);
- return false;
-}
-
-/* Read the relocations. On Irix 6, there can be two reloc sections
- associated with a single data section. */
-
-static boolean
-mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
- bfd *abfd;
- asection *asect;
- asymbol **symbols;
- boolean dynamic;
-{
- bfd_size_type amt;
- struct bfd_elf_section_data * const d = elf_section_data (asect);
-
- if (dynamic)
- {
- bfd_set_error (bfd_error_invalid_operation);
- return false;
- }
-
- if (asect->relocation != NULL
- || (asect->flags & SEC_RELOC) == 0
- || asect->reloc_count == 0)
- return true;
-
- /* Allocate space for 3 arelent structures for each Rel structure. */
- amt = asect->reloc_count;
- amt *= 3 * sizeof (arelent);
- asect->relocation = (arelent *) bfd_alloc (abfd, amt);
- if (asect->relocation == NULL)
- return false;
-
- /* The slurp_one_reloc_table routine increments reloc_count. */
- asect->reloc_count = 0;
-
- if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
- return false;
- if (d->rel_hdr2 != NULL)
- {
- if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
- d->rel_hdr2))
- return false;
- }
-
- return true;
-}
-
-/* Write out the relocations. */
-
-static void
-mips_elf64_write_relocs (abfd, sec, data)
- bfd *abfd;
- asection *sec;
- PTR data;
-{
- boolean *failedp = (boolean *) data;
- int count;
- Elf_Internal_Shdr *rel_hdr;
- unsigned int idx;
-
- /* If we have already failed, don't do anything. */
- if (*failedp)
- return;
-
- if ((sec->flags & SEC_RELOC) == 0)
- return;
-
- /* The linker backend writes the relocs out itself, and sets the
- reloc_count field to zero to inhibit writing them here. Also,
- sometimes the SEC_RELOC flag gets set even when there aren't any
- relocs. */
- if (sec->reloc_count == 0)
- return;
-
- /* We can combine up to three relocs that refer to the same address
- if the latter relocs have no associated symbol. */
- count = 0;
- for (idx = 0; idx < sec->reloc_count; idx++)
- {
- bfd_vma addr;
- unsigned int i;
-
- ++count;
-
- addr = sec->orelocation[idx]->address;
- for (i = 0; i < 2; i++)
- {
- arelent *r;
-
- if (idx + 1 >= sec->reloc_count)
- break;
- r = sec->orelocation[idx + 1];
- if (r->address != addr
- || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
- || (*r->sym_ptr_ptr)->value != 0)
- break;
-
- /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
-
- ++idx;
- }
- }
-
- rel_hdr = &elf_section_data (sec)->rel_hdr;
-
- /* Do the actual relocation. */
-
- if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rel))
- mips_elf64_write_rel (abfd, sec, rel_hdr, &count, data);
- else if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rela))
- mips_elf64_write_rela (abfd, sec, rel_hdr, &count, data);
- else
- BFD_ASSERT (0);
-}
-
-static void
-mips_elf64_write_rel (abfd, sec, rel_hdr, count, data)
- bfd *abfd;
- asection *sec;
- Elf_Internal_Shdr *rel_hdr;
- int *count;
- PTR data;
-{
- boolean *failedp = (boolean *) data;
- Elf64_Mips_External_Rel *ext_rel;
- unsigned int idx;
- asymbol *last_sym = 0;
- int last_sym_idx = 0;
-
- rel_hdr->sh_size = (bfd_vma)(rel_hdr->sh_entsize * *count);
- rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
- if (rel_hdr->contents == NULL)
- {
- *failedp = true;
- return;
- }
-
- ext_rel = (Elf64_Mips_External_Rel *) rel_hdr->contents;
- for (idx = 0; idx < sec->reloc_count; idx++, ext_rel++)
- {
- arelent *ptr;
- Elf64_Mips_Internal_Rel int_rel;
- asymbol *sym;
- int n;
- unsigned int i;
-
- ptr = sec->orelocation[idx];
-
- /* The address of an ELF reloc is section relative for an object
- file, and absolute for an executable file or shared library.
- The address of a BFD reloc is always section relative. */
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- int_rel.r_offset = ptr->address;
- else
- int_rel.r_offset = ptr->address + sec->vma;
-
- sym = *ptr->sym_ptr_ptr;
- if (sym == last_sym)
- n = last_sym_idx;
- else
- {
- last_sym = sym;
- n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
- if (n < 0)
- {
- *failedp = true;
- return;
- }
- last_sym_idx = n;
- }
-
- int_rel.r_sym = n;
- int_rel.r_ssym = RSS_UNDEF;
-
- if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
- && ! _bfd_elf_validate_reloc (abfd, ptr))
- {
- *failedp = true;
- return;
- }
-
- int_rel.r_type = ptr->howto->type;
- int_rel.r_type2 = (int) R_MIPS_NONE;
- int_rel.r_type3 = (int) R_MIPS_NONE;
-
- for (i = 0; i < 2; i++)
- {
- arelent *r;
-
- if (idx + 1 >= sec->reloc_count)
- break;
- r = sec->orelocation[idx + 1];
- if (r->address != ptr->address
- || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
- || (*r->sym_ptr_ptr)->value != 0)
- break;
-
- /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
-
- if (i == 0)
- int_rel.r_type2 = r->howto->type;
- else
- int_rel.r_type3 = r->howto->type;
-
- ++idx;
- }
-
- mips_elf64_swap_reloc_out (abfd, &int_rel, ext_rel);
- }
-
- BFD_ASSERT (ext_rel - (Elf64_Mips_External_Rel *) rel_hdr->contents
- == *count);
-}
-
-static void
-mips_elf64_write_rela (abfd, sec, rela_hdr, count, data)
- bfd *abfd;
- asection *sec;
- Elf_Internal_Shdr *rela_hdr;
- int *count;
- PTR data;
-{
- boolean *failedp = (boolean *) data;
- Elf64_Mips_External_Rela *ext_rela;
- unsigned int idx;
- asymbol *last_sym = 0;
- int last_sym_idx = 0;
-
- rela_hdr->sh_size = (bfd_vma)(rela_hdr->sh_entsize * *count);
- rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
- if (rela_hdr->contents == NULL)
- {
- *failedp = true;
- return;
- }
-
- ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
- for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
- {
- arelent *ptr;
- Elf64_Mips_Internal_Rela int_rela;
- asymbol *sym;
- int n;
- unsigned int i;
-
- ptr = sec->orelocation[idx];
-
- /* The address of an ELF reloc is section relative for an object
- file, and absolute for an executable file or shared library.
- The address of a BFD reloc is always section relative. */
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- int_rela.r_offset = ptr->address;
- else
- int_rela.r_offset = ptr->address + sec->vma;
-
- sym = *ptr->sym_ptr_ptr;
- if (sym == last_sym)
- n = last_sym_idx;
- else
- {
- last_sym = sym;
- n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
- if (n < 0)
- {
- *failedp = true;
- return;
- }
- last_sym_idx = n;
- }
-
- int_rela.r_sym = n;
- int_rela.r_addend = ptr->addend;
- int_rela.r_ssym = RSS_UNDEF;
-
- if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
- && ! _bfd_elf_validate_reloc (abfd, ptr))
- {
- *failedp = true;
- return;
- }
-
- int_rela.r_type = ptr->howto->type;
- int_rela.r_type2 = (int) R_MIPS_NONE;
- int_rela.r_type3 = (int) R_MIPS_NONE;
-
- for (i = 0; i < 2; i++)
- {
- arelent *r;
-
- if (idx + 1 >= sec->reloc_count)
- break;
- r = sec->orelocation[idx + 1];
- if (r->address != ptr->address
- || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
- || (*r->sym_ptr_ptr)->value != 0)
- break;
-
- /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
-
- if (i == 0)
- int_rela.r_type2 = r->howto->type;
- else
- int_rela.r_type3 = r->howto->type;
-
- ++idx;
- }
-
- mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
- }
-
- BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
- == *count);
-}
-
-/* This structure is used to hold .got information when linking. It
- is stored in the tdata field of the bfd_elf_section_data structure. */
-
-struct mips_elf64_got_info
-{
- /* The global symbol in the GOT with the lowest index in the dynamic
- symbol table. */
- struct elf_link_hash_entry *global_gotsym;
- /* The number of global .got entries. */
- unsigned int global_gotno;
- /* The number of local .got entries. */
- unsigned int local_gotno;
- /* The number of local .got entries we have used. */
- unsigned int assigned_gotno;
-};
-
-/* The MIPS ELF64 linker needs additional information for each symbol in
- the global hash table. */
-
-struct mips_elf64_link_hash_entry
-{
- struct elf_link_hash_entry root;
-
- /* External symbol information. */
- EXTR esym;
-
- /* Number of R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 relocs against
- this symbol. */
- unsigned int possibly_dynamic_relocs;
-
- /* If the R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 reloc is against
- a readonly section. */
- boolean readonly_reloc;
-
- /* The index of the first dynamic relocation (in the .rel.dyn
- section) against this symbol. */
- unsigned int min_dyn_reloc_index;
-
- /* We must not create a stub for a symbol that has relocations
- related to taking the function's address, i.e. any but
- R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
- p. 4-20. */
- boolean no_fn_stub;
-
- /* If there is a stub that 32 bit functions should use to call this
- 16 bit function, this points to the section containing the stub. */
- asection *fn_stub;
-
- /* Whether we need the fn_stub; this is set if this symbol appears
- in any relocs other than a 16 bit call. */
- boolean need_fn_stub;
-
- /* If there is a stub that 16 bit functions should use to call this
- 32 bit function, this points to the section containing the stub. */
- asection *call_stub;
-
- /* This is like the call_stub field, but it is used if the function
- being called returns a floating point value. */
- asection *call_fp_stub;
-};
-
- /* The mips16 compiler uses a couple of special sections to handle
- floating point arguments.
-
- Section names that look like .mips16.fn.FNNAME contain stubs that
- copy floating point arguments from the fp regs to the gp regs and
- then jump to FNNAME. If any 32 bit function calls FNNAME, the
- call should be redirected to the stub instead. If no 32 bit
- function calls FNNAME, the stub should be discarded. We need to
- consider any reference to the function, not just a call, because
- if the address of the function is taken we will need the stub,
- since the address might be passed to a 32 bit function.
-
- Section names that look like .mips16.call.FNNAME contain stubs
- that copy floating point arguments from the gp regs to the fp
- regs and then jump to FNNAME. If FNNAME is a 32 bit function,
- then any 16 bit function that calls FNNAME should be redirected
- to the stub instead. If FNNAME is not a 32 bit function, the
- stub should be discarded.
-
- .mips16.call.fp.FNNAME sections are similar, but contain stubs
- which call FNNAME and then copy the return value from the fp regs
- to the gp regs. These stubs store the return value in $18 while
- calling FNNAME; any function which might call one of these stubs
- must arrange to save $18 around the call. (This case is not
- needed for 32 bit functions that call 16 bit functions, because
- 16 bit functions always return floating point values in both
- $f0/$f1 and $2/$3.)
-
- Note that in all cases FNNAME might be defined statically.
- Therefore, FNNAME is not used literally. Instead, the relocation
- information will indicate which symbol the section is for.
-
- We record any stubs that we find in the symbol table. */
-
-#define FN_STUB ".mips16.fn."
-#define CALL_STUB ".mips16.call."
-#define CALL_FP_STUB ".mips16.call.fp."
-
-/* MIPS ELF64 linker hash table. */
-
-struct mips_elf64_link_hash_table
-{
- struct elf_link_hash_table root;
- /* This is set if we see any mips16 stub sections. */
- boolean mips16_stubs_seen;
-};
-
-/* Look up an entry in a MIPS ELF64 linker hash table. */
-
-#define mips_elf64_link_hash_lookup(table, string, create, copy, follow) \
- ((struct mips_elf64_link_hash_entry *) \
- elf_link_hash_lookup (&(table)->root, (string), (create), \
- (copy), (follow)))
-
-/* Traverse a MIPS ELF linker hash table. */
-
-#define mips_elf64_link_hash_traverse(table, func, info) \
- (elf_link_hash_traverse \
- (&(table)->root, \
- (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
- (info)))
-
-/* Get the MIPS ELF64 linker hash table from a link_info structure. */
-
-#define mips_elf64_hash_table(p) \
- ((struct mips_elf64_link_hash_table *) ((p)->hash))
-
-/* Create an entry in a MIPS ELF64 linker hash table. */
-
-static struct bfd_hash_entry *
-mips_elf64_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
-{
- struct mips_elf64_link_hash_entry *ret =
- (struct mips_elf64_link_hash_entry *) entry;
-
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (ret == (struct mips_elf64_link_hash_entry *) NULL)
- ret = ((struct mips_elf64_link_hash_entry *)
- bfd_hash_allocate (table,
- sizeof (struct mips_elf64_link_hash_entry)));
- if (ret == (struct mips_elf64_link_hash_entry *) NULL)
- return (struct bfd_hash_entry *) ret;
-
- /* Call the allocation method of the superclass. */
- ret = ((struct mips_elf64_link_hash_entry *)
- _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
- table, string));
- if (ret != (struct mips_elf64_link_hash_entry *) NULL)
- {
- /* Set local fields. */
- memset (&ret->esym, 0, sizeof (EXTR));
- /* We use -2 as a marker to indicate that the information has
- not been set. -1 means there is no associated ifd. */
- ret->esym.ifd = -2;
- ret->possibly_dynamic_relocs = 0;
- ret->readonly_reloc = false;
- ret->min_dyn_reloc_index = 0;
- ret->no_fn_stub = false;
- ret->fn_stub = NULL;
- ret->need_fn_stub = false;
- ret->call_stub = NULL;
- ret->call_fp_stub = NULL;
- }
-
- return (struct bfd_hash_entry *) ret;
-}
-
-/* Create a MIPS ELF64 linker hash table. */
-
-struct bfd_link_hash_table *
-mips_elf64_link_hash_table_create (abfd)
- bfd *abfd;
-{
- struct mips_elf64_link_hash_table *ret;
-
- ret = ((struct mips_elf64_link_hash_table *)
- bfd_alloc (abfd, sizeof (struct mips_elf64_link_hash_table)));
- if (ret == (struct mips_elf64_link_hash_table *) NULL)
- return NULL;
-
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- mips_elf64_link_hash_newfunc))
- {
- bfd_release (abfd, ret);
- return NULL;
- }
-
- ret->mips16_stubs_seen = false;
-
- return &ret->root.root;
-}
-
-/* Returns the offset for the entry at the INDEXth position
- in the GOT. */
-
-static bfd_vma
-mips_elf64_got_offset_from_index (dynobj, output_bfd, index)
- bfd *dynobj;
- bfd *output_bfd;
- bfd_vma index;
-{
- asection *sgot;
- bfd_vma gp;
-
- sgot = bfd_get_section_by_name (dynobj, ".got");
- gp = _bfd_get_gp_value (output_bfd);
- return (sgot->output_section->vma + sgot->output_offset + index -
- gp);
-}
-
-/* Returns the GOT information associated with the link indicated by
- INFO. If SGOTP is non-NULL, it is filled in with the GOT
- section. */
-
-static struct mips_elf64_got_info *
-_mips_elf64_got_info (abfd, sgotp)
- bfd *abfd;
- asection **sgotp;
-{
- asection *sgot;
- struct mips_elf64_got_info *g;
-
- sgot = bfd_get_section_by_name (abfd, ".got");
- BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_elf64_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
-
- if (sgotp)
- *sgotp = sgot;
- return g;
-}
-
-/* Sign-extend VALUE, which has the indicated number of BITS. */
-
-static bfd_vma
-mips_elf64_sign_extend (value, bits)
- bfd_vma value;
- int bits;
-{
- if (value & ((bfd_vma)1 << (bits - 1)))
- /* VALUE is negative. */
- value |= ((bfd_vma) - 1) << bits;
-
- return value;
-}
-
-/* Return non-zero if the indicated VALUE has overflowed the maximum
- range expressable by a signed number with the indicated number of
- BITS. */
-
-static boolean
-mips_elf64_overflow_p (value, bits)
- bfd_vma value;
- int bits;
-{
- bfd_signed_vma svalue = (bfd_signed_vma) value;
-
- if (svalue > (1 << (bits - 1)) - 1)
- /* The value is too big. */
- return true;
- else if (svalue < -(1 << (bits - 1)))
- /* The value is too small. */
- return true;
-
- /* All is well. */
- return false;
-}
-
-/* Returns the GOT index for the global symbol indicated by H. */
-
-static bfd_vma
-mips_elf64_global_got_index (abfd, h)
- bfd *abfd;
- struct elf_link_hash_entry *h;
-{
- bfd_vma index;
- asection *sgot;
- struct mips_elf64_got_info *g;
-
- g = _mips_elf64_got_info (abfd, &sgot);
-
- /* Once we determine the global GOT entry with the lowest dynamic
- symbol table index, we must put all dynamic symbols with greater
- indices into the GOT. That makes it easy to calculate the GOT
- offset. */
- BFD_ASSERT (h->dynindx >= g->global_gotsym->dynindx);
- index = ((h->dynindx - g->global_gotsym->dynindx + g->local_gotno)
- * (get_elf_backend_data (abfd)->s->arch_size / 8));
- BFD_ASSERT (index < sgot->_raw_size);
-
- return index;
-}
-
-struct mips_elf64_hash_sort_data
-{
- /* The symbol in the global GOT with the lowest dynamic symbol table
- index. */
- struct elf_link_hash_entry *low;
- /* The least dynamic symbol table index corresponding to a symbol
- with a GOT entry. */
- long min_got_dynindx;
- /* The greatest dynamic symbol table index not corresponding to a
- symbol without a GOT entry. */
- long max_non_got_dynindx;
-};
-
-/* If H needs a GOT entry, assign it the highest available dynamic
- index. Otherwise, assign it the lowest available dynamic
- index. */
-
-static boolean
-mips_elf64_sort_hash_table_f (h, data)
- struct mips_elf64_link_hash_entry *h;
- PTR data;
-{
- struct mips_elf64_hash_sort_data *hsd
- = (struct mips_elf64_hash_sort_data *) data;
-
- if (h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf64_link_hash_entry *) h->root.root.u.i.link;
-
- /* Symbols without dynamic symbol table entries aren't interesting
- at all. */
- if (h->root.dynindx == -1)
- return true;
-
- if (h->root.got.offset != 1)
- h->root.dynindx = hsd->max_non_got_dynindx++;
- else
- {
- h->root.dynindx = --hsd->min_got_dynindx;
- hsd->low = (struct elf_link_hash_entry *) h;
- }
-
- return true;
-}
-
-/* Sort the dynamic symbol table so that symbols that need GOT entries
- appear towards the end. This reduces the amount of GOT space
- required. MAX_LOCAL is used to set the number of local symbols
- known to be in the dynamic symbol table. During
- mips_elf64_size_dynamic_sections, this value is 1. Afterward, the
- section symbols are added and the count is higher. */
-
-static boolean
-mips_elf64_sort_hash_table (info, max_local)
- struct bfd_link_info *info;
- unsigned long max_local;
-{
- struct mips_elf64_hash_sort_data hsd;
- struct mips_elf64_got_info *g;
- bfd *dynobj;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- hsd.low = NULL;
- hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount;
- hsd.max_non_got_dynindx = max_local;
- mips_elf64_link_hash_traverse (((struct mips_elf64_link_hash_table *)
- elf_hash_table (info)),
- mips_elf64_sort_hash_table_f,
- &hsd);
-
- /* There shoud have been enough room in the symbol table to
- accomodate both the GOT and non-GOT symbols. */
- BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
-
- /* Now we know which dynamic symbol has the lowest dynamic symbol
- table index in the GOT. */
- g = _mips_elf64_got_info (dynobj, NULL);
- g->global_gotsym = hsd.low;
-
- return true;
-}
-
-#if 0
-/* Swap in an MSYM entry. */
-
-static void
-mips_elf64_swap_msym_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_Msym *ex;
- Elf32_Internal_Msym *in;
-{
- in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value);
- in->ms_info = H_GET_32 (abfd, ex->ms_info);
-}
-#endif
-/* Swap out an MSYM entry. */
-
-static void
-mips_elf64_swap_msym_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_Internal_Msym *in;
- Elf32_External_Msym *ex;
-{
- H_PUT_32 (abfd, in->ms_hash_value, ex->ms_hash_value);
- H_PUT_32 (abfd, in->ms_info, ex->ms_info);
-}
-
-/* Create a local GOT entry for VALUE. Return the index of the entry,
- or -1 if it could not be created. */
-
-static bfd_vma
-mips_elf64_create_local_got_entry (abfd, g, sgot, value)
- bfd *abfd;
- struct mips_elf64_got_info *g;
- asection *sgot;
- bfd_vma value;
-{
- CONST bfd_vma got_size = get_elf_backend_data (abfd)->s->arch_size / 8;
-
- if (g->assigned_gotno >= g->local_gotno)
- {
- /* We didn't allocate enough space in the GOT. */
- (*_bfd_error_handler)
- (_("not enough GOT space for local GOT entries"));
- bfd_set_error (bfd_error_bad_value);
- return (bfd_vma) -1;
- }
-
- bfd_put_64 (abfd, value, (sgot->contents + got_size * g->assigned_gotno));
- return got_size * g->assigned_gotno++;
-}
-
-/* Returns the GOT offset at which the indicated address can be found.
- If there is not yet a GOT entry for this value, create one. Returns
- -1 if no satisfactory GOT offset can be found. */
-
-static bfd_vma
-mips_elf64_local_got_index (abfd, info, value)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_vma value;
-{
- CONST bfd_vma got_size = get_elf_backend_data (abfd)->s->arch_size / 8;
- asection *sgot;
- struct mips_elf64_got_info *g;
- bfd_byte *entry;
-
- g = _mips_elf64_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- /* Look to see if we already have an appropriate entry. */
- for (entry = (sgot->contents + got_size * MIPS_RESERVED_GOTNO);
- entry != sgot->contents + got_size * g->assigned_gotno;
- entry += got_size)
- {
- bfd_vma address = bfd_get_64 (abfd, entry);
- if (address == value)
- return entry - sgot->contents;
- }
-
- return mips_elf64_create_local_got_entry (abfd, g, sgot, value);
-}
-
-/* Find a GOT entry that is within 32KB of the VALUE. These entries
- are supposed to be placed at small offsets in the GOT, i.e.,
- within 32KB of GP. Return the index into the GOT for this page,
- and store the offset from this entry to the desired address in
- OFFSETP, if it is non-NULL. */
-
-static bfd_vma
-mips_elf64_got_page (abfd, info, value, offsetp)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_vma value;
- bfd_vma *offsetp;
-{
- CONST bfd_vma got_size = get_elf_backend_data (abfd)->s->arch_size / 8;
- asection *sgot;
- struct mips_elf64_got_info *g;
- bfd_byte *entry;
- bfd_byte *last_entry;
- bfd_vma index = 0;
- bfd_vma address;
-
- g = _mips_elf64_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- /* Look to see if we aleady have an appropriate entry. */
- last_entry = sgot->contents + got_size * g->assigned_gotno;
- for (entry = (sgot->contents + got_size * MIPS_RESERVED_GOTNO);
- entry != last_entry;
- entry += got_size)
- {
- address = bfd_get_64 (abfd, entry);
-
- if (!mips_elf64_overflow_p (value - address, 16))
- {
- /* This entry will serve as the page pointer. We can add a
- 16-bit number to it to get the actual address. */
- index = entry - sgot->contents;
- break;
- }
- }
-
- /* If we didn't have an appropriate entry, we create one now. */
- if (entry == last_entry)
- index = mips_elf64_create_local_got_entry (abfd, g, sgot, value);
-
- if (offsetp)
- {
- address = bfd_get_64 (abfd, entry);
- *offsetp = value - address;
- }
-
- return index;
-}
-
-/* Find a GOT entry whose higher-order 16 bits are the same as those
- for value. Return the index into the GOT for this entry. */
-
-static bfd_vma
-mips_elf64_got16_entry (abfd, info, value, external)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_vma value;
- boolean external;
-{
- CONST bfd_vma got_size = get_elf_backend_data (abfd)->s->arch_size / 8;
- asection *sgot;
- struct mips_elf64_got_info *g;
- bfd_byte *entry;
- bfd_byte *last_entry;
- bfd_vma index = 0;
- bfd_vma address;
-
- if (! external)
- {
- /* Although the ABI says that it is "the high-order 16 bits" that we
- want, it is really the %high value. The complete value is
- calculated with a `addiu' of a LO16 relocation, just as with a
- HI16/LO16 pair. */
- value = mips_elf64_high (value) << 16;
- }
-
- g = _mips_elf64_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- /* Look to see if we already have an appropriate entry. */
- last_entry = sgot->contents + got_size * g->assigned_gotno;
- for (entry = (sgot->contents + got_size * MIPS_RESERVED_GOTNO);
- entry != last_entry;
- entry += got_size)
- {
- address = bfd_get_64 (abfd, entry);
- if (address == value)
- {
- /* This entry has the right high-order 16 bits, and the low-order
- 16 bits are set to zero. */
- index = entry - sgot->contents;
- break;
- }
- }
-
- /* If we didn't have an appropriate entry, we create one now. */
- if (entry == last_entry)
- index = mips_elf64_create_local_got_entry (abfd, g, sgot, value);
-
- return index;
-}
-
-/* Return whether a relocation is against a local symbol. */
-
-static boolean
-mips_elf64_local_relocation_p (input_bfd, relocation, local_sections,
- check_forced)
- bfd *input_bfd;
- const Elf_Internal_Rela *relocation;
- asection **local_sections;
- boolean check_forced;
-{
- unsigned long r_symndx;
- Elf_Internal_Shdr *symtab_hdr;
- struct mips_elf64_link_hash_entry* h;
- size_t extsymoff;
-
- r_symndx = ELF64_R_SYM (relocation->r_info);
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
-
- if (r_symndx < extsymoff)
- return true;
- if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL)
- return true;
-
- if (check_forced)
- {
- /* Look up the hash table to check whether the symbol
- was forced local. */
- h = (struct mips_elf64_link_hash_entry *)
- elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
- /* Find the real hash-table entry for this symbol. */
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf64_link_hash_entry *) h->root.root.u.i.link;
- if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
- return true;
- }
-
- return false;
-}
-
-/* Returns the first relocation of type r_type found, beginning with
- RELOCATION. RELEND is one-past-the-end of the relocation table. */
-
-static const Elf_Internal_Rela *
-mips_elf64_next_relocation (r_type, relocation, relend)
- unsigned int r_type;
- const Elf_Internal_Rela *relocation;
- const Elf_Internal_Rela *relend;
-{
- /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
- immediately following. However, for the IRIX6 ABI, the next
- relocation may be a composed relocation consisting of several
- relocations for the same address. In that case, the R_MIPS_LO16
- relocation may occur as one of these. We permit a similar
- extension in general, as that is useful for GCC. */
- while (relocation < relend)
- {
- if (ELF64_MIPS_R_TYPE (relocation->r_info) == r_type)
- return relocation;
-
- ++relocation;
- }
-
- /* We didn't find it. */
- bfd_set_error (bfd_error_bad_value);
- return NULL;
-}
-
-/* Create a rel.dyn relocation for the dynamic linker to resolve. REL
- is the original relocation, which is now being transformed into a
- dynamic relocation. The ADDENDP is adjusted if necessary; the
- caller should store the result in place of the original addend. */
-
-static boolean
-mips_elf64_create_dynamic_relocation (output_bfd, info, rel, h, sec,
- symbol, addendp, input_section)
- bfd *output_bfd;
- struct bfd_link_info *info;
- const Elf_Internal_Rela *rel;
- struct mips_elf64_link_hash_entry *h;
- asection *sec;
- bfd_vma symbol;
- bfd_vma *addendp;
- asection *input_section;
-{
- Elf_Internal_Rel outrel[3];
- boolean skip;
- asection *sreloc;
- bfd *dynobj;
- int r_type;
-
- r_type = ELF64_MIPS_R_TYPE (rel->r_info);
- dynobj = elf_hash_table (info)->dynobj;
- sreloc = bfd_get_section_by_name (dynobj, ".rel.dyn");
- BFD_ASSERT (sreloc != NULL);
- BFD_ASSERT (sreloc->contents != NULL);
- BFD_ASSERT ((sreloc->reloc_count
- * get_elf_backend_data (output_bfd)->s->sizeof_rel)
- < sreloc->_raw_size);
-
- skip = false;
- outrel[0].r_offset = _bfd_elf_section_offset (output_bfd, info,
- input_section,
- rel[0].r_offset);
- /* FIXME: For -2 runtime relocation needs to be skipped, but
- properly resolved statically and installed. */
- BFD_ASSERT (outrel[0].r_offset != (bfd_vma) -2);
-
- /* We begin by assuming that the offset for the dynamic relocation
- is the same as for the original relocation. We'll adjust this
- later to reflect the correct output offsets. */
- if (elf_section_data (input_section)->sec_info_type != ELF_INFO_TYPE_STABS)
- {
- outrel[1].r_offset = rel[1].r_offset;
- outrel[2].r_offset = rel[2].r_offset;
- }
- else
- {
- /* Except that in a stab section things are more complex.
- Because we compress stab information, the offset given in the
- relocation may not be the one we want; we must let the stabs
- machinery tell us the offset. */
- outrel[1].r_offset = outrel[0].r_offset;
- outrel[2].r_offset = outrel[0].r_offset;
- /* If we didn't need the relocation at all, this value will be
- -1. */
- if (outrel[0].r_offset == (bfd_vma) -1)
- skip = true;
- }
-
- /* If we've decided to skip this relocation, just output an empty
- record. Note that R_MIPS_NONE == 0, so that this call to memset
- is a way of setting R_TYPE to R_MIPS_NONE. */
- if (skip)
- memset (outrel, 0, sizeof (Elf_Internal_Rel) * 3);
- else
- {
- long indx;
- bfd_vma section_offset;
-
- /* We must now calculate the dynamic symbol table index to use
- in the relocation. */
- if (h != NULL
- && (! info->symbolic || (h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- {
- indx = h->root.dynindx;
- /* h->root.dynindx may be -1 if this symbol was marked to
- become local. */
- if (indx == -1)
- indx = 0;
- }
- else
- {
- if (sec != NULL && bfd_is_abs_section (sec))
- indx = 0;
- else if (sec == NULL || sec->owner == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- else
- {
- indx = elf_section_data (sec->output_section)->dynindx;
- if (indx == 0)
- abort ();
- }
-
- /* Figure out how far the target of the relocation is from
- the beginning of its section. */
- section_offset = symbol - sec->output_section->vma;
- /* The relocation we're building is section-relative.
- Therefore, the original addend must be adjusted by the
- section offset. */
- *addendp += section_offset;
- /* Now, the relocation is just against the section. */
- symbol = sec->output_section->vma;
- }
-
- /* If the relocation was previously an absolute relocation and
- this symbol will not be referred to by the relocation, we must
- adjust it by the value we give it in the dynamic symbol table.
- Otherwise leave the job up to the dynamic linker. */
- if (!indx && r_type != R_MIPS_REL32)
- *addendp += symbol;
-
- /* The relocation is always an REL32 relocation because we don't
- know where the shared library will wind up at load-time. */
- outrel[0].r_info = ELF64_R_INFO (indx, R_MIPS_REL32);
-
- /* Adjust the output offset of the relocation to reference the
- correct location in the output file. */
- outrel[0].r_offset += (input_section->output_section->vma
- + input_section->output_offset);
- outrel[1].r_offset += (input_section->output_section->vma
- + input_section->output_offset);
- outrel[2].r_offset += (input_section->output_section->vma
- + input_section->output_offset);
- }
-
- /* Put the relocation back out. */
- mips_elf64_be_swap_reloc_out (output_bfd, outrel,
- (sreloc->contents
- + sreloc->reloc_count
- * sizeof (Elf64_Mips_External_Rel)));
-
- /* Record the index of the first relocation referencing H. This
- information is later emitted in the .msym section. */
- if (h != NULL
- && (h->min_dyn_reloc_index == 0
- || sreloc->reloc_count < h->min_dyn_reloc_index))
- h->min_dyn_reloc_index = sreloc->reloc_count;
-
- /* We've now added another relocation. */
- ++sreloc->reloc_count;
-
- /* Make sure the output section is writable. The dynamic linker
- will be writing to it. */
- elf_section_data (input_section->output_section)->this_hdr.sh_flags
- |= SHF_WRITE;
-
- return true;
-}
-
-/* Calculate the value produced by the RELOCATION (which comes from
- the INPUT_BFD). The ADDEND is the addend to use for this
- RELOCATION; RELOCATION->R_ADDEND is ignored.
-
- The result of the relocation calculation is stored in VALUEP.
- REQUIRE_JALXP indicates whether or not the opcode used with this
- relocation must be JALX.
-
- This function returns bfd_reloc_continue if the caller need take no
- further action regarding this relocation, bfd_reloc_notsupported if
- something goes dramatically wrong, bfd_reloc_overflow if an
- overflow occurs, and bfd_reloc_ok to indicate success. */
-
-static bfd_reloc_status_type
-mips_elf64_calculate_relocation (abfd, input_bfd, input_section, info,
- relocation, addend, howto, local_syms,
- local_sections, valuep, namep, require_jalxp)
- bfd *abfd;
- bfd *input_bfd;
- asection *input_section;
- struct bfd_link_info *info;
- const Elf_Internal_Rela *relocation;
- bfd_vma addend;
- reloc_howto_type *howto;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
- bfd_vma *valuep;
- const char **namep;
- boolean *require_jalxp;
-{
- /* The eventual value we will return. */
- bfd_vma value;
- /* The address of the symbol against which the relocation is
- occurring. */
- bfd_vma symbol = 0;
- /* The final GP value to be used for the relocatable, executable, or
- shared object file being produced. */
- bfd_vma gp = (bfd_vma) - 1;
- /* The place (section offset or address) of the storage unit being
- relocated. */
- bfd_vma p;
- /* The value of GP used to create the relocatable object. */
- bfd_vma gp0 = (bfd_vma) - 1;
- /* The offset into the global offset table at which the address of
- the relocation entry symbol, adjusted by the addend, resides
- during execution. */
- bfd_vma g = (bfd_vma) - 1;
- /* The section in which the symbol referenced by the relocation is
- located. */
- asection *sec = NULL;
- struct mips_elf64_link_hash_entry* h = NULL;
- /* True if the symbol referred to by this relocation is a local
- symbol. */
- boolean local_p;
- Elf_Internal_Shdr *symtab_hdr;
- size_t extsymoff;
- unsigned long r_symndx;
- int r_type;
- /* True if overflow occurred during the calculation of the
- relocation value. */
- boolean overflowed_p;
- /* True if this relocation refers to a MIPS16 function. */
- boolean target_is_16_bit_code_p = false;
-
- /* Parse the relocation. */
- r_symndx = ELF64_R_SYM (relocation->r_info);
- r_type = ELF64_MIPS_R_TYPE (relocation->r_info);
- p = (input_section->output_section->vma
- + input_section->output_offset
- + relocation->r_offset);
-
- /* Assume that there will be no overflow. */
- overflowed_p = false;
-
- /* Figure out whether or not the symbol is local, and get the offset
- used in the array of hash table entries. */
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- local_p = mips_elf64_local_relocation_p (input_bfd, relocation,
- local_sections, false);
- if (! elf_bad_symtab (input_bfd))
- extsymoff = symtab_hdr->sh_info;
- else
- {
- /* The symbol table does not follow the rule that local symbols
- must come before globals. */
- extsymoff = 0;
- }
-
- /* Figure out the value of the symbol. */
- if (local_p)
- {
- Elf_Internal_Sym *sym;
-
- sym = local_syms + r_symndx;
- sec = local_sections[r_symndx];
-
- symbol = sec->output_section->vma + sec->output_offset;
- if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
- symbol += sym->st_value;
-
- /* MIPS16 text labels should be treated as odd. */
- if (sym->st_other == STO_MIPS16)
- ++symbol;
-
- /* Record the name of this symbol, for our caller. */
- *namep = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (*namep == '\0')
- *namep = bfd_section_name (input_bfd, sec);
-
- target_is_16_bit_code_p = (sym->st_other == STO_MIPS16);
- }
- else
- {
- /* For global symbols we look up the symbol in the hash-table. */
- h = ((struct mips_elf64_link_hash_entry *)
- elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
- /* Find the real hash-table entry for this symbol. */
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf64_link_hash_entry *) h->root.root.u.i.link;
-
- /* Record the name of this symbol, for our caller. */
- *namep = h->root.root.root.string;
-
- /* If this symbol is defined, calculate its address. */
- if ((h->root.root.type == bfd_link_hash_defined
- || h->root.root.type == bfd_link_hash_defweak)
- && h->root.root.u.def.section)
- {
- sec = h->root.root.u.def.section;
- if (sec->output_section)
- symbol = (h->root.root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- else
- symbol = h->root.root.u.def.value;
- }
- else if (h->root.root.type == bfd_link_hash_undefweak)
- /* We allow relocations against undefined weak symbols, giving
- it the value zero, so that you can undefined weak functions
- and check to see if they exist by looking at their
- addresses. */
- symbol = 0;
- else if (info->shared
- && (!info->symbolic || info->allow_shlib_undefined)
- && !info->no_undefined
- && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
- symbol = 0;
- else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0 ||
- strcmp (h->root.root.root.string, "_DYNAMIC_LINKING") == 0)
- {
- /* If this is a dynamic link, we should have created a
- _DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol
- in in mips_elf64_create_dynamic_sections.
- Otherwise, we should define the symbol with a value of 0.
- FIXME: It should probably get into the symbol table
- somehow as well. */
- BFD_ASSERT (! info->shared);
- BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
- symbol = 0;
- }
- else
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.root.string, input_bfd,
- input_section, relocation->r_offset,
- (!info->shared || info->no_undefined
- || ELF_ST_VISIBILITY (h->root.other)))))
- return bfd_reloc_undefined;
- symbol = 0;
- }
-
- target_is_16_bit_code_p = (h->root.other == STO_MIPS16);
- }
-
- /* If this is a 64-bit call to a 16-bit function with a stub, we
- need to redirect the call to the stub, unless we're already *in*
- a stub. */
- if (r_type != R_MIPS16_26 && !info->relocateable
- && ((h != NULL && h->fn_stub != NULL)
- || (local_p && elf_tdata (input_bfd)->local_stubs != NULL
- && elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
- && !mips_elf64_stub_section_p (input_bfd, input_section))
- {
- /* This is a 64-bit call to a 16-bit function. We should
- have already noticed that we were going to need the
- stub. */
- if (local_p)
- sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
- else
- {
- BFD_ASSERT (h->need_fn_stub);
- sec = h->fn_stub;
- }
-
- symbol = sec->output_section->vma + sec->output_offset;
- }
- /* If this is a 16-bit call to a 64-bit function with a stub, we
- need to redirect the call to the stub. */
- else if (r_type == R_MIPS16_26 && !info->relocateable
- && h != NULL
- && (h->call_stub != NULL || h->call_fp_stub != NULL)
- && !target_is_16_bit_code_p)
- {
- /* If both call_stub and call_fp_stub are defined, we can figure
- out which one to use by seeing which one appears in the input
- file. */
- if (h->call_stub != NULL && h->call_fp_stub != NULL)
- {
- asection *o;
-
- sec = NULL;
- for (o = input_bfd->sections; o != NULL; o = o->next)
- {
- if (strncmp (bfd_get_section_name (input_bfd, o),
- CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
- {
- sec = h->call_fp_stub;
- break;
- }
- }
- if (sec == NULL)
- sec = h->call_stub;
- }
- else if (h->call_stub != NULL)
- sec = h->call_stub;
- else
- sec = h->call_fp_stub;
-
- BFD_ASSERT (sec->_raw_size > 0);
- symbol = sec->output_section->vma + sec->output_offset;
- }
-
- /* Calls from 16-bit code to 32-bit code and vice versa require the
- special jalx instruction. */
- *require_jalxp = (!info->relocateable
- && ((r_type == R_MIPS16_26) != target_is_16_bit_code_p));
-
- local_p = mips_elf64_local_relocation_p (input_bfd, relocation,
- local_sections, true);
-
- /* If we haven't already determined the GOT offset, or the GP value,
- and we're going to need it, get it now. */
- switch (r_type)
- {
- case R_MIPS_CALL16:
- case R_MIPS_GOT16:
- case R_MIPS_GOT_DISP:
- case R_MIPS_GOT_HI16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_CALL_LO16:
- /* Find the index into the GOT where this value is located. */
- if (!local_p)
- {
- BFD_ASSERT (addend == 0);
- g = mips_elf64_global_got_index (elf_hash_table (info)->dynobj,
- (struct elf_link_hash_entry*) h);
- if (! elf_hash_table(info)->dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->root.dynindx == -1)
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
- {
- /* This is a static link or a -Bsymbolic link. The
- symbol is defined locally, or was forced to be local.
- We must initialize this entry in the GOT. */
- bfd *tmpbfd = elf_hash_table (info)->dynobj;
-
- asection *sgot = bfd_get_section_by_name (tmpbfd, ".got");
- bfd_put_64 (tmpbfd, symbol + addend, sgot->contents + g);
- }
- }
- else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
- /* There's no need to create a local GOT entry here; the
- calculation for a local GOT16 entry does not involve G. */
- break;
- else
- {
- g = mips_elf64_local_got_index (abfd, info, symbol + addend);
- if (g == (bfd_vma) -1)
- return false;
- }
-
- /* Convert GOT indices to actual offsets. */
- g = mips_elf64_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd, g);
- break;
-
- case R_MIPS_HI16:
- case R_MIPS_LO16:
- case R_MIPS_GPREL16:
- case R_MIPS_GPREL32:
- case R_MIPS_LITERAL:
- gp0 = _bfd_get_gp_value (input_bfd);
- gp = _bfd_get_gp_value (abfd);
- break;
-
- default:
- break;
- }
-
- /* Figure out what kind of relocation is being performed. */
- switch (r_type)
- {
- case R_MIPS_NONE:
- return bfd_reloc_continue;
-
- case R_MIPS_16:
- value = symbol + mips_elf64_sign_extend (addend, 16);
- overflowed_p = mips_elf64_overflow_p (value, 16);
- break;
-
- case R_MIPS_32:
- case R_MIPS_REL32:
- case R_MIPS_64:
- if ((info->shared
- || (elf_hash_table (info)->dynamic_sections_created
- && h != NULL
- && ((h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
- && ((h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
- && r_symndx != 0
- && (input_section->flags & SEC_ALLOC) != 0)
- {
- /* If we're creating a shared library, or this relocation is
- against a symbol in a shared library, then we can't know
- where the symbol will end up. So, we create a relocation
- record in the output, and leave the job up to the dynamic
- linker. */
- value = addend;
- if (!mips_elf64_create_dynamic_relocation (abfd, info, relocation,
- h, sec, symbol, &value,
- input_section))
- return false;
- }
- else
- {
- if (r_type != R_MIPS_REL32)
- value = symbol + addend;
- else
- value = addend;
- }
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_PC32:
- case R_MIPS_PC64:
- case R_MIPS_GNU_REL_LO16:
- value = symbol + addend - p;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_GNU_REL16_S2:
- value = symbol + mips_elf64_sign_extend (addend << 2, 18) - p;
- overflowed_p = mips_elf64_overflow_p (value, 18);
- value = (value >> 2) & howto->dst_mask;
- break;
-
- case R_MIPS_GNU_REL_HI16:
- value = mips_elf64_high (addend + symbol - p);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS16_26:
- /* The calculation for R_MIPS16_26 is just the same as for an
- R_MIPS_26. It's only the storage of the relocated field into
- the output file that's different. That's handled in
- mips_elf_perform_relocation. So, we just fall through to the
- R_MIPS_26 case here. */
- case R_MIPS_26:
- if (local_p)
- value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
- else
- value = (mips_elf64_sign_extend (addend << 2, 28) + symbol) >> 2;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_HI16:
- value = mips_elf64_high (addend + symbol);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_LO16:
- value = (addend + symbol) & 0xffff;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_LITERAL:
- /* Because we don't merge literal sections, we can handle this
- just like R_MIPS_GPREL16. In the long run, we should merge
- shared literals, and then we will need to additional work
- here. */
-
- /* Fall through. */
-
- case R_MIPS_GPREL16:
- if (local_p)
- value = mips_elf64_sign_extend (addend, 16) + symbol + gp0 - gp;
- else
- value = mips_elf64_sign_extend (addend, 16) + symbol - gp;
- overflowed_p = mips_elf64_overflow_p (value, 16);
- break;
-
- case R_MIPS_PC16:
- value = mips_elf64_sign_extend (addend, 16) + symbol - p;
- overflowed_p = mips_elf64_overflow_p (value, 16);
- value = (bfd_vma) ((bfd_signed_vma) value / 4);
- break;
-
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- if (local_p)
- {
- boolean forced;
-
- /* The special case is when the symbol is forced to be local. We
- need the full address in the GOT since no R_MIPS_LO16 relocation
- follows. */
- forced = ! mips_elf64_local_relocation_p (input_bfd, relocation,
- local_sections, false);
- value = mips_elf64_got16_entry (abfd, info, symbol + addend, forced);
- if (value == (bfd_vma) -1)
- return false;
- value
- = mips_elf64_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd,
- value);
- overflowed_p = mips_elf64_overflow_p (value, 16);
- break;
- }
-
- /* Fall through. */
-
- case R_MIPS_GOT_DISP:
- value = g;
- overflowed_p = mips_elf64_overflow_p (value, 16);
- break;
-
- case R_MIPS_GPREL32:
- value = (addend + symbol + gp0 - gp) & howto->dst_mask;
- break;
-
- case R_MIPS_GOT_HI16:
- case R_MIPS_CALL_HI16:
- /* We're allowed to handle these two relocations identically.
- The dynamic linker is allowed to handle the CALL relocations
- differently by creating a lazy evaluation stub. */
- value = g;
- value = mips_elf64_high (value);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_GOT_LO16:
- case R_MIPS_CALL_LO16:
- value = g & howto->dst_mask;
- break;
-
- case R_MIPS_GOT_PAGE:
- value = mips_elf64_got_page (abfd, info, symbol + addend, NULL);
- if (value == (bfd_vma) -1)
- return false;
- value = mips_elf64_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd,
- value);
- overflowed_p = mips_elf64_overflow_p (value, 16);
- break;
-
- case R_MIPS_GOT_OFST:
- mips_elf64_got_page (abfd, info, symbol + addend, &value);
- overflowed_p = mips_elf64_overflow_p (value, 16);
- break;
-
- case R_MIPS_SUB:
- value = symbol - addend;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_HIGHER:
- value = mips_elf64_higher (addend + symbol);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_HIGHEST:
- value = mips_elf64_highest (addend + symbol);
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_SCN_DISP:
- value = symbol + addend - sec->output_offset;
- value &= howto->dst_mask;
- break;
-
- case R_MIPS_PJUMP:
- case R_MIPS_JALR:
- /* Both of these may be ignored. R_MIPS_JALR is an optimization
- hint; we could improve performance by honoring that hint. */
- return bfd_reloc_continue;
-
- case R_MIPS_GNU_VTINHERIT:
- case R_MIPS_GNU_VTENTRY:
- /* We don't do anything with these at present. */
- return bfd_reloc_continue;
-
- default:
- /* An unrecognized relocation type. */
- return bfd_reloc_notsupported;
- }
-
- /* Store the VALUE for our caller. */
- *valuep = value;
- return overflowed_p ? bfd_reloc_overflow : bfd_reloc_ok;
-}
-
-/* Obtain the field relocated by RELOCATION. */
-
-static bfd_vma
-mips_elf64_obtain_contents (howto, relocation, input_bfd, contents)
- reloc_howto_type *howto;
- const Elf_Internal_Rela *relocation;
- bfd *input_bfd;
- bfd_byte *contents;
-{
- bfd_byte *location = contents + relocation->r_offset;
-
- /* Obtain the bytes. */
- return bfd_get (8 * bfd_get_reloc_size (howto), input_bfd, location);
-}
-
-/* It has been determined that the result of the RELOCATION is the
- VALUE. Use HOWTO to place VALUE into the output file at the
- appropriate position. The SECTION is the section to which the
- relocation applies. If REQUIRE_JALX is true, then the opcode used
- for the relocation must be either JAL or JALX, and it is
- unconditionally converted to JALX.
-
- Returns false if anything goes wrong. */
-
-static boolean
-mips_elf64_perform_relocation (info, howto, relocation, value,
- input_bfd, input_section,
- contents, require_jalx)
- struct bfd_link_info *info;
- reloc_howto_type *howto;
- const Elf_Internal_Rela *relocation;
- bfd_vma value;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- boolean require_jalx;
-{
- bfd_vma x;
- bfd_byte *location;
- int r_type = ELF32_R_TYPE (relocation->r_info);
-
- /* Figure out where the relocation is occurring. */
- location = contents + relocation->r_offset;
-
- /* Obtain the current value. */
- x = mips_elf64_obtain_contents (howto, relocation, input_bfd, contents);
-
- /* Clear the field we are setting. */
- x &= ~howto->dst_mask;
-
- /* If this is the R_MIPS16_26 relocation, we must store the
- value in a funny way. */
- if (r_type == R_MIPS16_26)
- {
- /* R_MIPS16_26 is used for the mips16 jal and jalx instructions.
- Most mips16 instructions are 16 bits, but these instructions
- are 32 bits.
-
- The format of these instructions is:
-
- +--------------+--------------------------------+
- ! JALX ! X! Imm 20:16 ! Imm 25:21 !
- +--------------+--------------------------------+
- ! Immediate 15:0 !
- +-----------------------------------------------+
-
- JALX is the 5-bit value 00011. X is 0 for jal, 1 for jalx.
- Note that the immediate value in the first word is swapped.
-
- When producing a relocateable object file, R_MIPS16_26 is
- handled mostly like R_MIPS_26. In particular, the addend is
- stored as a straight 26-bit value in a 32-bit instruction.
- (gas makes life simpler for itself by never adjusting a
- R_MIPS16_26 reloc to be against a section, so the addend is
- always zero). However, the 32 bit instruction is stored as 2
- 16-bit values, rather than a single 32-bit value. In a
- big-endian file, the result is the same; in a little-endian
- file, the two 16-bit halves of the 32 bit value are swapped.
- This is so that a disassembler can recognize the jal
- instruction.
-
- When doing a final link, R_MIPS16_26 is treated as a 32 bit
- instruction stored as two 16-bit values. The addend A is the
- contents of the targ26 field. The calculation is the same as
- R_MIPS_26. When storing the calculated value, reorder the
- immediate value as shown above, and don't forget to store the
- value as two 16-bit values.
-
- To put it in MIPS ABI terms, the relocation field is T-targ26-16,
- defined as
-
- big-endian:
- +--------+----------------------+
- | | |
- | | targ26-16 |
- |31 26|25 0|
- +--------+----------------------+
-
- little-endian:
- +----------+------+-------------+
- | | | |
- | sub1 | | sub2 |
- |0 9|10 15|16 31|
- +----------+--------------------+
- where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
- ((sub1 << 16) | sub2)).
-
- When producing a relocateable object file, the calculation is
- (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
- When producing a fully linked file, the calculation is
- let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
- ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */
-
- if (!info->relocateable)
- /* Shuffle the bits according to the formula above. */
- value = (((value & 0x1f0000) << 5)
- | ((value & 0x3e00000) >> 5)
- | (value & 0xffff));
- }
- else if (r_type == R_MIPS16_GPREL)
- {
- /* R_MIPS16_GPREL is used for GP-relative addressing in mips16
- mode. A typical instruction will have a format like this:
-
- +--------------+--------------------------------+
- ! EXTEND ! Imm 10:5 ! Imm 15:11 !
- +--------------+--------------------------------+
- ! Major ! rx ! ry ! Imm 4:0 !
- +--------------+--------------------------------+
-
- EXTEND is the five bit value 11110. Major is the instruction
- opcode.
-
- This is handled exactly like R_MIPS_GPREL16, except that the
- addend is retrieved and stored as shown in this diagram; that
- is, the Imm fields above replace the V-rel16 field.
-
- All we need to do here is shuffle the bits appropriately. As
- above, the two 16-bit halves must be swapped on a
- little-endian system. */
- value = (((value & 0x7e0) << 16)
- | ((value & 0xf800) << 5)
- | (value & 0x1f));
- }
-
- /* Set the field. */
- x |= (value & howto->dst_mask);
-
- /* If required, turn JAL into JALX. */
- if (require_jalx)
- {
- boolean ok;
- bfd_vma opcode = x >> 26;
- bfd_vma jalx_opcode;
-
- /* Check to see if the opcode is already JAL or JALX. */
- if (r_type == R_MIPS16_26)
- {
- ok = ((opcode == 0x6) || (opcode == 0x7));
- jalx_opcode = 0x7;
- }
- else
- {
- ok = ((opcode == 0x3) || (opcode == 0x1d));
- jalx_opcode = 0x1d;
- }
-
- /* If the opcode is not JAL or JALX, there's a problem. */
- if (!ok)
- {
- (*_bfd_error_handler)
- (_("%s: %s+0x%lx: jump to stub routine which is not jal"),
- bfd_archive_filename (input_bfd),
- input_section->name,
- (unsigned long) relocation->r_offset);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- /* Make this the JALX opcode. */
- x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
- }
-
- /* Swap the high- and low-order 16 bits on little-endian systems
- when doing a MIPS16 relocation. */
- if ((r_type == R_MIPS16_GPREL || r_type == R_MIPS16_26)
- && bfd_little_endian (input_bfd))
- x = (((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
-
- /* Put the value into the output. */
- bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
- return true;
-}
-
-/* Returns true if SECTION is a MIPS16 stub section. */
-
-static boolean
-mips_elf64_stub_section_p (abfd, section)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *section;
-{
- const char *name = bfd_get_section_name (abfd, section);
-
- return (strncmp (name, FN_STUB, sizeof FN_STUB - 1) == 0
- || strncmp (name, CALL_STUB, sizeof CALL_STUB - 1) == 0
- || strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0);
-}
-
-/* Relocate a MIPS ELF64 section. */
-
-static boolean
-mips_elf64_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- Elf_Internal_Rela *relocs;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
-{
- Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *relend;
- bfd_vma addend = 0;
- boolean use_saved_addend_p = false;
- struct elf_backend_data *bed;
-
- bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
- for (rel = relocs; rel < relend; ++rel)
- {
- const char *name;
- bfd_vma value;
- reloc_howto_type *howto;
- boolean require_jalx;
- /* True if the relocation is a RELA relocation, rather than a
- REL relocation. */
- boolean rela_relocation_p = true;
- int r_type = ELF64_MIPS_R_TYPE (rel->r_info);
- const char *msg = (const char *) NULL;
-
- /* Find the relocation howto for this relocation. */
- howto = &mips_elf64_howto_table_rela[r_type];
-
- if (!use_saved_addend_p)
- {
- Elf_Internal_Shdr *rel_hdr;
-
- /* If these relocations were originally of the REL variety,
- we must pull the addend out of the field that will be
- relocated. Otherwise, we simply use the contents of the
- RELA relocation. To determine which flavor or relocation
- this is, we depend on the fact that the INPUT_SECTION's
- REL_HDR is read before its REL_HDR2. */
- rel_hdr = &elf_section_data (input_section)->rel_hdr;
- if ((size_t) (rel - relocs)
- >= (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel))
- rel_hdr = elf_section_data (input_section)->rel_hdr2;
- if (rel_hdr->sh_entsize
- == (get_elf_backend_data (input_bfd)->s->sizeof_rel))
- {
- /* Note that this is a REL relocation. */
- rela_relocation_p = false;
-
- /* Find the relocation howto for this relocation. */
- howto = &mips_elf64_howto_table_rel[r_type];
-
- /* Get the addend, which is stored in the input file. */
- addend = mips_elf64_obtain_contents (howto,
- rel,
- input_bfd,
- contents);
- addend &= howto->src_mask;
-
- /* For some kinds of relocations, the ADDEND is a
- combination of the addend stored in two different
- relocations. */
- if (r_type == R_MIPS_HI16
- || r_type == R_MIPS_GNU_REL_HI16
- || (r_type == R_MIPS_GOT16
- && mips_elf64_local_relocation_p (input_bfd, rel,
- local_sections, false)))
- {
- bfd_vma l;
- const Elf_Internal_Rela *lo16_relocation;
- reloc_howto_type *lo16_howto;
- int lo;
-
- /* The combined value is the sum of the HI16 addend,
- left-shifted by sixteen bits, and the LO16
- addend, sign extended. (Usually, the code does
- a `lui' of the HI16 value, and then an `addiu' of
- the LO16 value.)
-
- Scan ahead to find a matching LO16 relocation. */
- if (r_type == R_MIPS_GNU_REL_HI16)
- lo = R_MIPS_GNU_REL_LO16;
- else
- lo = R_MIPS_LO16;
- lo16_relocation
- = mips_elf64_next_relocation (lo, rel, relend);
- if (lo16_relocation == NULL)
- return false;
-
- /* Obtain the addend kept there. */
- if (rela_relocation_p == false)
- lo16_howto = &mips_elf64_howto_table_rel[lo];
- else
- lo16_howto = &mips_elf64_howto_table_rela[lo];
- l = mips_elf64_obtain_contents (lo16_howto,
- lo16_relocation,
- input_bfd, contents);
- l &= lo16_howto->src_mask;
- l = mips_elf64_sign_extend (l, 16);
-
- addend <<= 16;
-
- /* Compute the combined addend. */
- addend += l;
- }
- }
- else
- addend = rel->r_addend;
- }
-
- if (info->relocateable)
- {
- Elf_Internal_Sym *sym;
- unsigned long r_symndx;
-
- /* Since we're just relocating, all we need to do is copy
- the relocations back out to the object file, unless
- they're against a section symbol, in which case we need
- to adjust by the section offset, or unless they're GP
- relative in which case we need to adjust by the amount
- that we're adjusting GP in this relocateable object. */
-
- if (!mips_elf64_local_relocation_p (input_bfd, rel, local_sections,
- false))
- /* There's nothing to do for non-local relocations. */
- continue;
-
- if (r_type == R_MIPS_GPREL16
- || r_type == R_MIPS_GPREL32
- || r_type == R_MIPS_LITERAL)
- addend -= (_bfd_get_gp_value (output_bfd)
- - _bfd_get_gp_value (input_bfd));
- else if (r_type == R_MIPS_26 || r_type == R_MIPS_GNU_REL16_S2)
- /* The addend is stored without its two least
- significant bits (which are always zero.) In a
- non-relocateable link, calculate_relocation will do
- this shift; here, we must do it ourselves. */
- addend <<= 2;
-
- r_symndx = ELF64_R_SYM (rel->r_info);
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- /* Adjust the addend appropriately. */
- addend += local_sections[r_symndx]->output_offset;
-
-#if 0
- /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
- then we only want to write out the high-order 16 bits.
- The subsequent R_MIPS_LO16 will handle the low-order bits. */
- if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16
- || r_type == R_MIPS_GNU_REL_HI16)
- addend = mips_elf64_high (addend);
- else if (r_type == R_MIPS_HIGHER)
- addend = mips_elf64_higher (addend);
- else if (r_type == R_MIPS_HIGHEST)
- addend = mips_elf64_highest (addend);
-#endif
- /* If the relocation is for an R_MIPS_26 relocation, then
- the two low-order bits are not stored in the object file;
- they are implicitly zero. */
- if (r_type == R_MIPS_26 || r_type == R_MIPS_GNU_REL16_S2)
- addend >>= 2;
-
- if (rela_relocation_p)
- /* If this is a RELA relocation, just update the addend.
- We have to cast away constness for REL. */
- rel->r_addend = addend;
- else
- {
- /* Otherwise, we have to write the value back out. Note
- that we use the source mask, rather than the
- destination mask because the place to which we are
- writing will be source of the addend in the final
- link. */
- addend &= howto->src_mask;
-
- if (!mips_elf64_perform_relocation (info, howto, rel, addend,
- input_bfd, input_section,
- contents, false))
- return false;
- }
-
- /* Go on to the next relocation. */
- continue;
- }
-
- /* In the N32 and 64-bit ABIs there may be multiple consecutive
- relocations for the same offset. In that case we are
- supposed to treat the output of each relocation as the addend
- for the next. */
- if (rel + 1 < relend
- && rel->r_offset == rel[1].r_offset
- && ELF64_MIPS_R_TYPE (rel[1].r_info) != R_MIPS_NONE)
- use_saved_addend_p = true;
- else
- use_saved_addend_p = false;
-
- /* Figure out what value we are supposed to relocate. */
- switch (mips_elf64_calculate_relocation (output_bfd, input_bfd,
- input_section, info, rel,
- addend, howto, local_syms,
- local_sections, &value, &name,
- &require_jalx))
- {
- case bfd_reloc_continue:
- /* There's nothing to do. */
- continue;
-
- case bfd_reloc_undefined:
- /* mips_elf64_calculate_relocation already called the
- undefined_symbol callback. There's no real point in
- trying to perform the relocation at this point, so we
- just skip ahead to the next relocation. */
- continue;
-
- case bfd_reloc_notsupported:
- msg = _("internal error: unsupported relocation error");
- info->callbacks->warning
- (info, msg, name, input_bfd, input_section, rel->r_offset);
- return false;
-
- case bfd_reloc_overflow:
- if (use_saved_addend_p)
- /* Ignore overflow until we reach the last relocation for
- a given location. */
- ;
- else
- {
- BFD_ASSERT (name != NULL);
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset)))
- return false;
- }
- break;
-
- case bfd_reloc_ok:
- break;
-
- default:
- abort ();
- break;
- }
-
- /* If we've got another relocation for the address, keep going
- until we reach the last one. */
- if (use_saved_addend_p)
- {
- addend = value;
- continue;
- }
-
- /* Actually perform the relocation. */
- if (!mips_elf64_perform_relocation (info, howto, rel, value, input_bfd,
- input_section, contents,
- require_jalx))
- return false;
- }
-
- return true;
-}
-
-/* Create dynamic sections when linking against a dynamic object. */
-
-boolean
-mips_elf64_create_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- flagword flags;
- register asection *s;
-
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED | SEC_READONLY);
-
- /* Mips ABI requests the .dynamic section to be read only. */
- s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s != NULL)
- {
- if (! bfd_set_section_flags (abfd, s, flags))
- return false;
- }
-
- /* We need to create .got section. */
- if (! mips_elf64_create_got_section (abfd, info))
- return false;
-
- /* Create the .msym section on IRIX6. It is used by the dynamic
- linker to speed up dynamic relocations, and to avoid computing
- the ELF hash for symbols. */
- if (!mips_elf64_create_msym_section (abfd))
- return false;
-
- /* Create .stub section. */
- if (bfd_get_section_by_name (abfd, ".MIPS.stubs") == NULL)
- {
- s = bfd_make_section (abfd, ".MIPS.stubs");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE)
- || ! bfd_set_section_alignment (abfd, s, 3))
- return false;
- }
-
- return true;
-}
-
-/* Adjust a symbol defined by a dynamic object and referenced by a
- regular object. The current definition is in some section of the
- dynamic object, but we're not including those sections. We have to
- change the definition to something the rest of the link can
- understand. */
-
-boolean
-mips_elf64_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
-{
- bfd *dynobj;
- struct mips_elf64_link_hash_entry *hmips;
- asection *s;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- /* Make sure we know what is going on here. */
- BFD_ASSERT (dynobj != NULL
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
- || h->weakdef != NULL
- || ((h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)));
-
- /* If this symbol is defined in a dynamic object, we need to copy
- any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
- file. */
- hmips = (struct mips_elf64_link_hash_entry *) h;
- if (! info->relocateable
- && hmips->possibly_dynamic_relocs != 0
- && (h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- {
- mips_elf64_allocate_dynamic_relocations (dynobj,
- hmips->possibly_dynamic_relocs);
- if (hmips->readonly_reloc)
- /* We tell the dynamic linker that there are relocations
- against the text segment. */
- info->flags |= DF_TEXTREL;
- }
-
- /* For a function, create a stub, if allowed. */
- if (! hmips->no_fn_stub
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
- {
- if (! elf_hash_table (info)->dynamic_sections_created)
- return true;
-
- /* If this symbol is not defined in a regular file, then set
- the symbol to the stub location. This is required to make
- function pointers compare as equal between the normal
- executable and the shared library. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- {
- /* We need .stub section. */
- s = bfd_get_section_by_name (dynobj, ".MIPS.stubs");
- BFD_ASSERT (s != NULL);
-
- h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
-
- /* XXX Write this stub address somewhere. */
- h->plt.offset = s->_raw_size;
-
- /* Make room for this stub code. */
- s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
-
- /* The last half word of the stub will be filled with the index
- of this symbol in .dynsym section. */
- return true;
- }
- }
- else if ((h->type == STT_FUNC)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
- {
- /* This will set the entry for this symbol in the GOT to 0, and
- the dynamic linker will take care of this. */
- h->root.u.def.value = 0;
- return true;
- }
-
- /* If this is a weak symbol, and there is a real definition, the
- processor independent code will have arranged for us to see the
- real definition first, and we can just use the same value. */
- if (h->weakdef != NULL)
- {
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
- return true;
- }
-
- /* This is a reference to a symbol defined by a dynamic object which
- is not a function. */
-
- return true;
-}
-
-/* This function is called after all the input files have been read,
- and the input sections have been assigned to output sections. */
-
-boolean
-mips_elf64_always_size_sections (output_bfd, info)
- bfd *output_bfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
-{
- if (info->relocateable
- || ! mips_elf64_hash_table (info)->mips16_stubs_seen)
- return true;
-
- mips_elf64_link_hash_traverse (mips_elf64_hash_table (info),
- mips_elf64_check_mips16_stubs,
- (PTR) NULL);
-
- return true;
-}
-
-/* Check the mips16 stubs for a particular symbol, and see if we can
- discard them. */
-
-static boolean
-mips_elf64_check_mips16_stubs (h, data)
- struct mips_elf64_link_hash_entry *h;
- PTR data ATTRIBUTE_UNUSED;
-{
- if (h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf64_link_hash_entry *) h->root.root.u.i.link;
-
- if (h->fn_stub != NULL
- && ! h->need_fn_stub)
- {
- /* We don't need the fn_stub; the only references to this symbol
- are 16 bit calls. Clobber the size to 0 to prevent it from
- being included in the link. */
- h->fn_stub->_raw_size = 0;
- h->fn_stub->_cooked_size = 0;
- h->fn_stub->flags &= ~SEC_RELOC;
- h->fn_stub->reloc_count = 0;
- h->fn_stub->flags |= SEC_EXCLUDE;
- }
-
- if (h->call_stub != NULL
- && h->root.other == STO_MIPS16)
- {
- /* We don't need the call_stub; this is a 16 bit function, so
- calls from other 16 bit functions are OK. Clobber the size
- to 0 to prevent it from being included in the link. */
- h->call_stub->_raw_size = 0;
- h->call_stub->_cooked_size = 0;
- h->call_stub->flags &= ~SEC_RELOC;
- h->call_stub->reloc_count = 0;
- h->call_stub->flags |= SEC_EXCLUDE;
- }
-
- if (h->call_fp_stub != NULL
- && h->root.other == STO_MIPS16)
- {
- /* We don't need the call_stub; this is a 16 bit function, so
- calls from other 16 bit functions are OK. Clobber the size
- to 0 to prevent it from being included in the link. */
- h->call_fp_stub->_raw_size = 0;
- h->call_fp_stub->_cooked_size = 0;
- h->call_fp_stub->flags &= ~SEC_RELOC;
- h->call_fp_stub->reloc_count = 0;
- h->call_fp_stub->flags |= SEC_EXCLUDE;
- }
-
- return true;
-}
-
-/* Set the sizes of the dynamic sections. */
-
-boolean
-mips_elf64_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
-{
- bfd *dynobj;
- asection *s;
- boolean reltext;
- struct mips_elf64_got_info *g = NULL;
-
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- /* Set the contents of the .interp section to the interpreter. */
- if (! info->shared)
- {
- s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
- s->_raw_size = strlen ("/usr/lib64/libc.so.1") + 1;
- s->contents = (bfd_byte *) "/usr/lib64/libc.so.1";
- }
- }
-
- /* The check_relocs and adjust_dynamic_symbol entry points have
- determined the sizes of the various dynamic sections. Allocate
- memory for them. */
- reltext = false;
- for (s = dynobj->sections; s != NULL; s = s->next)
- {
- const char *name;
- boolean strip;
-
- /* It's OK to base decisions on the section name, because none
- of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
-
- if ((s->flags & SEC_LINKER_CREATED) == 0)
- continue;
-
- strip = false;
-
- if (strncmp (name, ".rel", 4) == 0)
- {
- if (s->_raw_size == 0)
- {
- /* We only strip the section if the output section name
- has the same name. Otherwise, there might be several
- input sections for this output section. FIXME: This
- code is probably not needed these days anyhow, since
- the linker now does not create empty output sections. */
- if (s->output_section != NULL
- && strcmp (name,
- bfd_get_section_name (s->output_section->owner,
- s->output_section)) == 0)
- strip = true;
- }
- else
- {
- const char *outname;
- asection *target;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL entry.
- If the relocation section is .rel.dyn, we always
- assert a DT_TEXTREL entry rather than testing whether
- there exists a relocation to a read only section or
- not. */
- outname = bfd_get_section_name (output_bfd,
- s->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 4);
- if ((target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0)
- || strcmp (outname, "rel.dyn") == 0)
- reltext = true;
-
- /* We use the reloc_count field as a counter if we need
- to copy relocs into the output file. */
- if (strcmp (name, "rel.dyn") != 0)
- s->reloc_count = 0;
- }
- }
- else if (strncmp (name, ".got", 4) == 0)
- {
- int i;
- bfd_size_type loadable_size = 0;
- bfd_size_type local_gotno;
- bfd *sub;
-
- BFD_ASSERT (elf_section_data (s) != NULL);
- g = (struct mips_elf64_got_info *) elf_section_data (s)->tdata;
- BFD_ASSERT (g != NULL);
-
- /* Calculate the total loadable size of the output. That
- will give us the maximum number of GOT_PAGE entries
- required. */
- for (sub = info->input_bfds; sub; sub = sub->link_next)
- {
- asection *subsection;
-
- for (subsection = sub->sections;
- subsection;
- subsection = subsection->next)
- {
- if ((subsection->flags & SEC_ALLOC) == 0)
- continue;
- loadable_size += (subsection->_raw_size + 0xf) & ~0xf;
- }
- }
- loadable_size += MIPS_FUNCTION_STUB_SIZE;
-
- /* Assume there are two loadable segments consisting of
- contiguous sections. Is 5 enough? */
- local_gotno = (loadable_size >> 16) + 5;
- /* It's possible we will need GOT_PAGE entries as well as
- GOT16 entries. Often, these will be able to share GOT
- entries, but not always. */
- local_gotno *= 2;
-
- g->local_gotno += local_gotno;
- s->_raw_size += local_gotno * 8;
-
- /* There has to be a global GOT entry for every symbol with
- a dynamic symbol table index of DT_MIPS_GOTSYM or
- higher. Therefore, it make sense to put those symbols
- that need GOT entries at the end of the symbol table. We
- do that here. */
- if (!mips_elf64_sort_hash_table (info, 1))
- return false;
-
- if (g->global_gotsym != NULL)
- i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
- else
- /* If there are no global symbols, or none requiring
- relocations, then GLOBAL_GOTSYM will be NULL. */
- i = 0;
- g->global_gotno = i;
- s->_raw_size += i * 8;
- }
- else if (strcmp (name, ".MIPS.stubs") == 0)
- {
- /* Irix rld assumes that the function stub isn't at the end
- of .text section. So put a dummy. XXX */
- s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
- }
- else if (strcmp (name, ".msym")
- == 0)
- s->_raw_size = (sizeof (Elf32_External_Msym)
- * (elf_hash_table (info)->dynsymcount
- + bfd_count_sections (output_bfd)));
- else if (strncmp (name, ".init", 5) != 0)
- {
- /* It's not one of our sections, so don't allocate space. */
- continue;
- }
-
- if (strip)
- {
- _bfd_strip_section_from_output (info, s);
- continue;
- }
-
- /* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- }
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- /* Add some entries to the .dynamic section. We fill in the
- values later, in elf_mips_finish_dynamic_sections, but we
- must add the entries now so that we get the correct size for
- the .dynamic section. The DT_DEBUG entry is filled in by the
- dynamic linker and used by the debugger. */
- if (! info->shared)
- {
- /* SGI object has the equivalence of DT_DEBUG in the
- DT_MIPS_RLD_MAP entry. */
- if (!bfd_elf64_add_dynamic_entry (info, DT_MIPS_RLD_MAP, 0))
- return false;
- if (!SGI_COMPAT (output_bfd))
- {
- if (!bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
- return false;
- }
- }
- else
- {
- /* Shared libraries on traditional mips have DT_DEBUG. */
- if (!SGI_COMPAT (output_bfd))
- {
- if (!bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
- return false;
- }
- }
-
- if (reltext && SGI_COMPAT (output_bfd))
- info->flags |= DF_TEXTREL;
-
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
- return false;
- }
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0))
- return false;
-
- if (bfd_get_section_by_name (dynobj, "rel.dyn"))
- {
- if (! bfd_elf64_add_dynamic_entry (info, DT_REL, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_RELSZ, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_RELENT, 0))
- return false;
- }
-
- if (SGI_COMPAT (output_bfd))
- {
- if (!bfd_elf64_add_dynamic_entry (info, DT_MIPS_CONFLICTNO, 0))
- return false;
- }
-
- if (SGI_COMPAT (output_bfd))
- {
- if (!bfd_elf64_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0))
- return false;
- }
-
- if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
- {
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0))
- return false;
-
- s = bfd_get_section_by_name (dynobj, ".liblist");
- BFD_ASSERT (s != NULL);
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_LIBLIST, 0))
- return false;
- }
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_RLD_VERSION, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_FLAGS, 0))
- return false;
-
-#if 0
- /* Time stamps in executable files are a bad idea. */
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0))
- return false;
-#endif
-
-#if 0 /* FIXME */
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0))
- return false;
-#endif
-
-#if 0 /* FIXME */
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_IVERSION, 0))
- return false;
-#endif
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_BASE_ADDRESS, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_LOCAL_GOTNO, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_SYMTABNO, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_UNREFEXTNO, 0))
- return false;
-
- if (! bfd_elf64_add_dynamic_entry (info, DT_MIPS_GOTSYM, 0))
- return false;
-
- if ((bfd_get_section_by_name(dynobj, ".MIPS.options"))
- && !bfd_elf64_add_dynamic_entry (info, DT_MIPS_OPTIONS, 0))
- return false;
-
- if (bfd_get_section_by_name (dynobj, ".msym")
- && !bfd_elf64_add_dynamic_entry (info, DT_MIPS_MSYM, 0))
- return false;
- }
-
- return true;
-}
-
-/* Finish up dynamic symbol handling. We set the contents of various
- dynamic sections here. */
-
-boolean
-mips_elf64_finish_dynamic_symbol (output_bfd, info, h, sym)
- bfd *output_bfd;
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- bfd *dynobj;
- bfd_vma gval;
- asection *sgot;
- asection *smsym;
- struct mips_elf64_got_info *g;
- const char *name;
- struct mips_elf64_link_hash_entry *mh;
-
- dynobj = elf_hash_table (info)->dynobj;
- gval = sym->st_value;
- mh = (struct mips_elf64_link_hash_entry *) h;
-
- if (h->plt.offset != (bfd_vma) -1)
- {
- asection *s;
- bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
-
- /* This symbol has a stub. Set it up. */
-
- BFD_ASSERT (h->dynindx != -1);
-
- s = bfd_get_section_by_name (dynobj, ".MIPS.stubs");
- BFD_ASSERT (s != NULL);
-
- /* FIXME: Can h->dynindex be more than 64K? */
- if (h->dynindx & 0xffff0000)
- return false;
-
- /* Fill the stub. */
- bfd_put_32 (output_bfd, STUB_LW, stub);
- bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
- bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
- bfd_put_32 (output_bfd, STUB_LI16 + h->dynindx, stub + 12);
-
- BFD_ASSERT (h->plt.offset <= s->_raw_size);
- memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
-
- /* Mark the symbol as undefined. plt.offset != -1 occurs
- only for the referenced symbol. */
- sym->st_shndx = SHN_UNDEF;
-
- /* The run-time linker uses the st_value field of the symbol
- to reset the global offset table entry for this external
- to its stub address when unlinking a shared object. */
- gval = s->output_section->vma + s->output_offset + h->plt.offset;
- sym->st_value = gval;
- }
-
- BFD_ASSERT (h->dynindx != -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
-
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_elf64_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
-
- /* Run through the global symbol table, creating GOT entries for all
- the symbols that need them. */
- if (g->global_gotsym != NULL
- && h->dynindx >= g->global_gotsym->dynindx)
- {
- bfd_vma offset;
- bfd_vma value;
-
- if (sym->st_value)
- value = sym->st_value;
- else
- {
- /* For an entity defined in a shared object, this will be
- NULL. (For functions in shared objects for
- which we have created stubs, ST_VALUE will be non-NULL.
- That's because such the functions are now no longer defined
- in a shared object.) */
-
- if (info->shared && h->root.type == bfd_link_hash_undefined)
- value = 0;
- else
- value = h->root.u.def.value;
- }
- offset = mips_elf64_global_got_index (dynobj, h);
- bfd_put_64 (output_bfd, value, sgot->contents + offset);
- }
-
- /* Create a .msym entry, if appropriate. */
- smsym = bfd_get_section_by_name (dynobj, ".msym");
- if (smsym)
- {
- Elf32_Internal_Msym msym;
-
- msym.ms_hash_value = bfd_elf_hash (h->root.root.string);
- /* It is undocumented what the `1' indicates, but IRIX6 uses
- this value. */
- msym.ms_info = ELF32_MS_INFO (mh->min_dyn_reloc_index, 1);
- mips_elf64_swap_msym_out
- (dynobj, &msym,
- ((Elf32_External_Msym *) smsym->contents) + h->dynindx);
- }
-
- /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
- name = h->root.root.string;
- if (strcmp (name, "_DYNAMIC") == 0
- || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
- sym->st_shndx = SHN_ABS;
- else if (strcmp (name, "_DYNAMIC_LINK") == 0
- || strcmp (name, "_DYNAMIC_LINKING") == 0)
- {
- sym->st_shndx = SHN_ABS;
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
- sym->st_value = 1;
- }
- else if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS)
- {
- if (h->type == STT_FUNC)
- sym->st_shndx = SHN_MIPS_TEXT;
- else if (h->type == STT_OBJECT)
- sym->st_shndx = SHN_MIPS_DATA;
- }
-
- /* Handle the IRIX6-specific symbols. */
-
- {
- /* The linker script takes care of providing names and values for
- these, but we must place them into the right sections. */
- static const char* const text_section_symbols[] = {
- "_ftext",
- "_etext",
- "__dso_displacement",
- "__elf_header",
- "__program_header_table",
- NULL
- };
-
- static const char* const data_section_symbols[] = {
- "_fdata",
- "_edata",
- "_end",
- "_fbss",
- NULL
- };
-
- const char* const *p;
- int i;
-
- for (i = 0; i < 2; ++i)
- for (p = (i == 0) ? text_section_symbols : data_section_symbols;
- *p;
- ++p)
- if (strcmp (*p, name) == 0)
- {
- /* All of these symbols are given type STT_SECTION by the
- IRIX6 linker. */
- sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
-
- /* The IRIX linker puts these symbols in special sections. */
- if (i == 0)
- sym->st_shndx = SHN_MIPS_TEXT;
- else
- sym->st_shndx = SHN_MIPS_DATA;
-
- break;
- }
- }
-
- return true;
-}
-
-/* Finish up the dynamic sections. */
-
-boolean
-mips_elf64_finish_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
-{
- bfd *dynobj;
- asection *sdyn;
- asection *sgot;
- struct mips_elf64_got_info *g;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
-
- sgot = bfd_get_section_by_name (dynobj, ".got");
- if (sgot == NULL)
- g = NULL;
- else
- {
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_elf64_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
- }
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- bfd_byte *b;
-
- BFD_ASSERT (sdyn != NULL);
- BFD_ASSERT (g != NULL);
-
- for (b = sdyn->contents;
- b < sdyn->contents + sdyn->_raw_size;
- b += get_elf_backend_data (dynobj)->s->sizeof_dyn)
- {
- Elf_Internal_Dyn dyn;
- const char *name;
- size_t elemsize;
- asection *s;
- boolean swap_out_p;
-
- /* Read in the current dynamic entry. */
- (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
-
- /* Assume that we're going to modify it and write it out. */
- swap_out_p = true;
-
- switch (dyn.d_tag)
- {
- case DT_RELENT:
- s = bfd_get_section_by_name(dynobj, "rel.dyn");
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_val = get_elf_backend_data (dynobj)->s->sizeof_rel;
- break;
-
- case DT_STRSZ:
- /* Rewrite DT_STRSZ. */
- dyn.d_un.d_val =
- _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
- break;
-
- case DT_PLTGOT:
- name = ".got";
- goto get_vma;
- case DT_MIPS_CONFLICT:
- name = ".conflict";
- goto get_vma;
- case DT_MIPS_LIBLIST:
- name = ".liblist";
- get_vma:
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
- break;
-
- case DT_MIPS_RLD_VERSION:
- dyn.d_un.d_val = 1; /* XXX */
- break;
-
- case DT_MIPS_FLAGS:
- dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
- break;
-
- case DT_MIPS_CONFLICTNO:
- name = ".conflict";
- elemsize = sizeof (Elf32_Conflict);
- goto set_elemno;
-
- case DT_MIPS_LIBLISTNO:
- name = ".liblist";
- elemsize = sizeof (Elf32_Lib);
- set_elemno:
- s = bfd_get_section_by_name (output_bfd, name);
- if (s != NULL)
- {
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size / elemsize;
- else
- dyn.d_un.d_val = s->_raw_size / elemsize;
- }
- else
- dyn.d_un.d_val = 0;
- break;
-
- case DT_MIPS_TIME_STAMP:
- time ((time_t *) &dyn.d_un.d_val);
- break;
-
- case DT_MIPS_ICHECKSUM:
- /* XXX FIXME: */
- swap_out_p = false;
- break;
-
- case DT_MIPS_IVERSION:
- /* XXX FIXME: */
- swap_out_p = false;
- break;
-
- case DT_MIPS_BASE_ADDRESS:
- s = output_bfd->sections;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma & ~(0xffff);
- break;
-
- case DT_MIPS_LOCAL_GOTNO:
- dyn.d_un.d_val = g->local_gotno;
- break;
-
- case DT_MIPS_UNREFEXTNO:
- /* The index into the dynamic symbol table which is the
- entry of the first external symbol that is not
- referenced within the same object. */
- dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
- break;
-
- case DT_MIPS_GOTSYM:
- if (g->global_gotsym)
- {
- dyn.d_un.d_val = g->global_gotsym->dynindx;
- break;
- }
- /* In case if we don't have global got symbols we default
- to setting DT_MIPS_GOTSYM to the same value as
- DT_MIPS_SYMTABNO, so we just fall through. */
-
- case DT_MIPS_SYMTABNO:
- name = ".dynsym";
- elemsize = get_elf_backend_data (output_bfd)->s->sizeof_sym;
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
-
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size / elemsize;
- else
- dyn.d_un.d_val = s->_raw_size / elemsize;
- break;
-
- case DT_MIPS_HIPAGENO:
- dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO;
- break;
-
- case DT_MIPS_OPTIONS:
- s = bfd_get_section_by_name(output_bfd, ".MIPS.options");
- dyn.d_un.d_ptr = s->vma;
- break;
-
- case DT_MIPS_MSYM:
- s = bfd_get_section_by_name(output_bfd, ".msym");
- dyn.d_un.d_ptr = s->vma;
- break;
-
- default:
- swap_out_p = false;
- break;
- }
-
- if (swap_out_p)
- (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
- (dynobj, &dyn, b);
- }
- }
-
- /* The first entry of the global offset table will be filled at
- runtime. The second entry will be used by some runtime loaders.
- This isn't the case of Irix rld. */
- if (sgot != NULL && sgot->_raw_size > 0)
- {
- bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents);
- bfd_put_64 (output_bfd, (bfd_vma) 0x80000000, sgot->contents + 8);
- }
-
- if (sgot != NULL)
- elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8;
-
- {
- asection *smsym;
- asection *s;
-
- /* ??? The section symbols for the output sections were set up in
- _bfd_elf_final_link. SGI sets the STT_NOTYPE attribute for these
- symbols. Should we do so? */
-
- smsym = bfd_get_section_by_name (dynobj, ".msym");
- if (smsym != NULL)
- {
- Elf32_Internal_Msym msym;
-
- msym.ms_hash_value = 0;
- msym.ms_info = ELF32_MS_INFO (0, 1);
-
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- long dynindx = elf_section_data (s)->dynindx;
-
- mips_elf64_swap_msym_out
- (output_bfd, &msym,
- (((Elf32_External_Msym *) smsym->contents)
- + dynindx));
- }
- }
-
- /* Clean up a first relocation in .rel.dyn. */
- s = bfd_get_section_by_name (dynobj, "rel.dyn");
- if (s != NULL && s->_raw_size > 0)
- memset (s->contents, 0, get_elf_backend_data (dynobj)->s->sizeof_rel);
- }
-
- return true;
-}
-
-/* Return the section that should be marked against GC for a given
- relocation. */
-
-asection *
-mips_elf64_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
-{
- if (h != NULL)
- {
- switch (ELF64_R_TYPE (rel->r_info))
- {
- case R_MIPS_GNU_VTINHERIT:
- case R_MIPS_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
-
- return NULL;
-}
-
-/* Update the got entry reference counts for the section being removed. */
-
-boolean
-mips_elf64_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
-{
-#if 0
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel, *relend;
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- switch (ELF64_R_TYPE (rel->r_info))
- {
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- /* ??? It would seem that the existing MIPS code does no sort
- of reference counting or whatnot on its GOT and PLT entries,
- so it is not possible to garbage collect them at this time. */
- break;
-
- default:
- break;
- }
-#endif
-
- return true;
-}
-
-/* Create the .got section to hold the global offset table. */
-
-static boolean
-mips_elf64_create_got_section (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- flagword flags;
- register asection *s;
- struct elf_link_hash_entry *h;
- struct mips_elf64_got_info *g;
-
- /* This function may be called more than once. */
- if (bfd_get_section_by_name (abfd, ".got"))
- return true;
-
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED);
-
- s = bfd_make_section (abfd, ".got");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags)
- || ! bfd_set_section_alignment (abfd, s, 4))
- return false;
-
- /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
- linker script because we don't want to define the symbol if we
- are not creating a global offset table. */
- h = NULL;
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (info->shared
- && ! bfd_elf64_link_record_dynamic_symbol (info, h))
- return false;
-
- /* The first several global offset table entries are reserved. */
- s->_raw_size = MIPS_RESERVED_GOTNO * (get_elf_backend_data (abfd)->s->arch_size / 8);
-
- g = (struct mips_elf64_got_info *) bfd_alloc (abfd,
- sizeof (struct mips_elf64_got_info));
- if (g == NULL)
- return false;
- g->global_gotsym = NULL;
- g->local_gotno = MIPS_RESERVED_GOTNO;
- g->assigned_gotno = MIPS_RESERVED_GOTNO;
- if (elf_section_data (s) == NULL)
- {
- s->used_by_bfd =
- (PTR) bfd_zalloc (abfd, sizeof (struct bfd_elf_section_data));
- if (elf_section_data (s) == NULL)
- return false;
- }
- elf_section_data (s)->tdata = (PTR) g;
- elf_section_data (s)->this_hdr.sh_flags
- |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
-
- return true;
-}
-
-/* If H is a symbol that needs a global GOT entry, but has a dynamic
- symbol table index lower than any we've seen to date, record it for
- posterity. */
-
-static boolean
-mips_elf64_record_global_got_symbol (h, info, g)
- struct elf_link_hash_entry *h;
- struct bfd_link_info *info;
- struct mips_elf64_got_info *g ATTRIBUTE_UNUSED;
-{
- /* A global symbol in the GOT must also be in the dynamic symbol
- table. */
- if (h->dynindx == -1
- && !bfd_elf64_link_record_dynamic_symbol (info, h))
- return false;
-
- /* If we've already marked this entry as needing GOT space, we don't
- need to do it again. */
- if (h->got.offset != (bfd_vma) - 1)
- return true;
-
- /* By setting this to a value other than -1, we are indicating that
- there needs to be a GOT entry for H. Avoid using zero, as the
- generic ELF copy_indirect_symbol tests for <= 0. */
- h->got.offset = 1;
-
- return true;
-}
-
-/* Returns the .msym section for ABFD, creating it if it does not
- already exist. Returns NULL to indicate error. */
-
-static asection *
-mips_elf64_create_msym_section (abfd)
- bfd *abfd;
-{
- asection *s;
-
- s = bfd_get_section_by_name (abfd, ".msym");
- if (!s)
- {
- s = bfd_make_section (abfd, ".msym");
- if (!s
- || !bfd_set_section_flags (abfd, s,
- SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_LINKER_CREATED
- | SEC_READONLY)
- || !bfd_set_section_alignment (abfd, s, 3))
- return NULL;
- }
-
- return s;
-}
-
-/* Add room for N relocations to the .rel.dyn section in ABFD. */
-
-static void
-mips_elf64_allocate_dynamic_relocations (abfd, n)
- bfd *abfd;
- unsigned int n;
-{
- asection *s;
-
- s = bfd_get_section_by_name (abfd, ".rel.dyn");
- BFD_ASSERT (s != NULL);
-
- if (s->_raw_size == 0)
- {
- /* Make room for a null element. */
- s->_raw_size += get_elf_backend_data (abfd)->s->sizeof_rel;
- ++s->reloc_count;
- }
- s->_raw_size += n * get_elf_backend_data (abfd)->s->sizeof_rel;
-}
-
-/* Look through the relocs for a section during the first phase, and
- allocate space in the global offset table. */
-
-boolean
-mips_elf64_check_relocs (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
-{
- const char *name;
- bfd *dynobj;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- struct mips_elf64_got_info *g;
- size_t extsymoff;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
- asection *sgot;
- asection *sreloc;
- struct elf_backend_data *bed;
-
- if (info->relocateable)
- return true;
-
- dynobj = elf_hash_table (info)->dynobj;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
-
- /* Check for the mips16 stub sections. */
-
- name = bfd_get_section_name (abfd, sec);
- if (strncmp (name, FN_STUB, sizeof FN_STUB - 1) == 0)
- {
- unsigned long r_symndx;
-
- /* Look at the relocation information to figure out which symbol
- this is for. */
-
- r_symndx = ELF64_R_SYM (relocs->r_info);
-
- if (r_symndx < extsymoff
- || sym_hashes[r_symndx - extsymoff] == NULL)
- {
- asection *o;
-
- /* This stub is for a local symbol. This stub will only be
- needed if there is some relocation in this BFD, other
- than a 16 bit function call, which refers to this symbol. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- Elf_Internal_Rela *sec_relocs;
- const Elf_Internal_Rela *r, *rend;
-
- /* We can ignore stub sections when looking for relocs. */
- if ((o->flags & SEC_RELOC) == 0
- || o->reloc_count == 0
- || strncmp (bfd_get_section_name (abfd, o), FN_STUB,
- sizeof FN_STUB - 1) == 0
- || strncmp (bfd_get_section_name (abfd, o), CALL_STUB,
- sizeof CALL_STUB - 1) == 0
- || strncmp (bfd_get_section_name (abfd, o), CALL_FP_STUB,
- sizeof CALL_FP_STUB - 1) == 0)
- continue;
-
- sec_relocs = (_bfd_elf64_link_read_relocs
- (abfd, o, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory));
- if (sec_relocs == NULL)
- return false;
-
- rend = sec_relocs + o->reloc_count;
- for (r = sec_relocs; r < rend; r++)
- if (ELF64_R_SYM (r->r_info) == r_symndx
- && ELF64_R_TYPE (r->r_info) != R_MIPS16_26)
- break;
-
- if (! info->keep_memory)
- free (sec_relocs);
-
- if (r < rend)
- break;
- }
-
- if (o == NULL)
- {
- /* There is no non-call reloc for this stub, so we do
- not need it. Since this function is called before
- the linker maps input sections to output sections, we
- can easily discard it by setting the SEC_EXCLUDE
- flag. */
- sec->flags |= SEC_EXCLUDE;
- return true;
- }
-
- /* Record this stub in an array of local symbol stubs for
- this BFD. */
- if (elf_tdata (abfd)->local_stubs == NULL)
- {
- unsigned long symcount;
- asection **n;
- bfd_size_type amt;
-
- if (elf_bad_symtab (abfd))
- symcount = NUM_SHDR_ENTRIES (symtab_hdr);
- else
- symcount = symtab_hdr->sh_info;
- amt = symcount * sizeof (asection *);
- n = (asection **) bfd_zalloc (abfd, amt);
- if (n == NULL)
- return false;
- elf_tdata (abfd)->local_stubs = n;
- }
-
- elf_tdata (abfd)->local_stubs[r_symndx] = sec;
-
- /* We don't need to set mips16_stubs_seen in this case.
- That flag is used to see whether we need to look through
- the global symbol table for stubs. We don't need to set
- it here, because we just have a local stub. */
- }
- else
- {
- struct mips_elf64_link_hash_entry *h;
-
- h = ((struct mips_elf64_link_hash_entry *)
- sym_hashes[r_symndx - extsymoff]);
-
- /* H is the symbol this stub is for. */
-
- h->fn_stub = sec;
- mips_elf64_hash_table (info)->mips16_stubs_seen = true;
- }
- }
- else if (strncmp (name, CALL_STUB, sizeof CALL_STUB - 1) == 0
- || strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
- {
- unsigned long r_symndx;
- struct mips_elf64_link_hash_entry *h;
- asection **loc;
-
- /* Look at the relocation information to figure out which symbol
- this is for. */
-
- r_symndx = ELF64_R_SYM (relocs->r_info);
-
- if (r_symndx < extsymoff
- || sym_hashes[r_symndx - extsymoff] == NULL)
- {
- /* This stub was actually built for a static symbol defined
- in the same file. We assume that all static symbols in
- mips16 code are themselves mips16, so we can simply
- discard this stub. Since this function is called before
- the linker maps input sections to output sections, we can
- easily discard it by setting the SEC_EXCLUDE flag. */
- sec->flags |= SEC_EXCLUDE;
- return true;
- }
-
- h = ((struct mips_elf64_link_hash_entry *)
- sym_hashes[r_symndx - extsymoff]);
-
- /* H is the symbol this stub is for. */
-
- if (strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
- loc = &h->call_fp_stub;
- else
- loc = &h->call_stub;
-
- /* If we already have an appropriate stub for this function, we
- don't need another one, so we can discard this one. Since
- this function is called before the linker maps input sections
- to output sections, we can easily discard it by setting the
- SEC_EXCLUDE flag. We can also discard this section if we
- happen to already know that this is a mips16 function; it is
- not necessary to check this here, as it is checked later, but
- it is slightly faster to check now. */
- if (*loc != NULL || h->root.other == STO_MIPS16)
- {
- sec->flags |= SEC_EXCLUDE;
- return true;
- }
-
- *loc = sec;
- mips_elf64_hash_table (info)->mips16_stubs_seen = true;
- }
-
- if (dynobj == NULL)
- {
- sgot = NULL;
- g = NULL;
- }
- else
- {
- sgot = bfd_get_section_by_name (dynobj, ".got");
- if (sgot == NULL)
- g = NULL;
- else
- {
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_elf64_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
- }
- }
-
- sreloc = NULL;
- bed = get_elf_backend_data (abfd);
- rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
- for (rel = relocs; rel < rel_end; ++rel)
- {
- unsigned long r_symndx;
- int r_type;
- struct elf_link_hash_entry *h;
-
- r_symndx = ELF64_R_SYM (rel->r_info);
- r_type = ELF64_MIPS_R_TYPE (rel->r_info);
-
- if (r_symndx < extsymoff)
- h = NULL;
- else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
- {
- (*_bfd_error_handler)
- (_("%s: Malformed reloc detected for section %s"),
- bfd_archive_filename (abfd), name);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- else
- {
- h = sym_hashes[r_symndx - extsymoff];
-
- /* This may be an indirect symbol created because of a version. */
- if (h != NULL)
- {
- while (h->root.type == bfd_link_hash_indirect)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
- }
-
- /* Some relocs require a global offset table. */
- if (dynobj == NULL || sgot == NULL)
- {
- switch (r_type)
- {
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_GOT_PAGE:
- case R_MIPS_GOT_OFST:
- case R_MIPS_GOT_DISP:
- if (dynobj == NULL)
- elf_hash_table (info)->dynobj = dynobj = abfd;
- if (! mips_elf64_create_got_section (dynobj, info))
- return false;
- g = _mips_elf64_got_info (dynobj, &sgot);
- break;
-
- case R_MIPS_32:
- case R_MIPS_REL32:
- case R_MIPS_64:
- if (dynobj == NULL
- && (info->shared || h != NULL)
- && (sec->flags & SEC_ALLOC) != 0)
- elf_hash_table (info)->dynobj = dynobj = abfd;
- break;
-
- default:
- break;
- }
- }
-
- if (!h && (r_type == R_MIPS_CALL_LO16
- || r_type == R_MIPS_GOT_LO16
- || r_type == R_MIPS_GOT_DISP))
- {
- /* We may need a local GOT entry for this relocation. We
- don't count R_MIPS_GOT_PAGE because we can estimate the
- maximum number of pages needed by looking at the size of
- the segment. Similar comments apply to R_MIPS_GOT16 and
- R_MIPS_CALL16. We don't count R_MIPS_GOT_HI16, or
- R_MIPS_CALL_HI16 because these are always followed by an
- R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.
-
- This estimation is very conservative since we can merge
- duplicate entries in the GOT. In order to be less
- conservative, we could actually build the GOT here,
- rather than in relocate_section. */
- g->local_gotno++;
- sgot->_raw_size += get_elf_backend_data (dynobj)->s->arch_size / 8;
- }
-
- switch (r_type)
- {
- case R_MIPS_CALL16:
- if (h == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: CALL16 reloc at 0x%lx not against global symbol"),
- bfd_archive_filename (abfd), (unsigned long) rel->r_offset);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- /* Fall through. */
-
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- if (h != NULL)
- {
- /* This symbol requires a global offset table entry. */
- if (!mips_elf64_record_global_got_symbol (h, info, g))
- return false;
-
- /* We need a stub, not a plt entry for the undefined
- function. But we record it as if it needs plt. See
- elf_adjust_dynamic_symbol in elflink.h. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->type = STT_FUNC;
- }
- break;
-
- case R_MIPS_GOT16:
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_GOT_DISP:
- /* This symbol requires a global offset table entry. */
- if (h && !mips_elf64_record_global_got_symbol (h, info, g))
- return false;
- break;
-
- case R_MIPS_32:
- case R_MIPS_REL32:
- case R_MIPS_64:
- if ((info->shared || h != NULL)
- && (sec->flags & SEC_ALLOC) != 0)
- {
- if (sreloc == NULL)
- {
- const char *name = ".rel.dyn";
-
- sreloc = bfd_get_section_by_name (dynobj, name);
- if (sreloc == NULL)
- {
- sreloc = bfd_make_section (dynobj, name);
- if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY))
- || ! bfd_set_section_alignment (dynobj, sreloc,
- 4))
- return false;
- }
- }
-#define MIPS_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
- if (info->shared)
- {
- /* When creating a shared object, we must copy these
- reloc types into the output file as R_MIPS_REL32
- relocs. We make room for this reloc in the
- .rel.dyn reloc section. */
- mips_elf64_allocate_dynamic_relocations (dynobj, 1);
- if ((sec->flags & MIPS_READONLY_SECTION)
- == MIPS_READONLY_SECTION)
- /* We tell the dynamic linker that there are
- relocations against the text segment. */
- info->flags |= DF_TEXTREL;
- }
- else
- {
- struct mips_elf64_link_hash_entry *hmips;
-
- /* We only need to copy this reloc if the symbol is
- defined in a dynamic object. */
- hmips = (struct mips_elf64_link_hash_entry *) h;
- ++hmips->possibly_dynamic_relocs;
- if ((sec->flags & MIPS_READONLY_SECTION)
- == MIPS_READONLY_SECTION)
- /* We need it to tell the dynamic linker if there
- are relocations against the text segment. */
- hmips->readonly_reloc = true;
- }
-
- /* Even though we don't directly need a GOT entry for
- this symbol, a symbol must have a dynamic symbol
- table index greater that DT_MIPS_GOTSYM if there are
- dynamic relocations against it. */
- if (h != NULL
- && !mips_elf64_record_global_got_symbol (h, info, g))
- return false;
- }
- break;
-
- case R_MIPS_26:
- case R_MIPS_GPREL16:
- case R_MIPS_LITERAL:
- case R_MIPS_GPREL32:
- break;
-
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_MIPS_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return false;
- break;
-
- /* This relocation describes which C++ vtable entries are actually
- used. Record for later use during GC. */
- case R_MIPS_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_offset))
- return false;
- break;
-
- default:
- break;
- }
- }
-
- return true;
-}
-
-/* Structure used to pass information to mips_elf64_output_extsym. */
-
-struct extsym_info
-{
- bfd *abfd;
- struct bfd_link_info *info;
- struct ecoff_debug_info *debug;
- const struct ecoff_debug_swap *swap;
- boolean failed;
-};
-
-/* This routine is used to write out ECOFF debugging external symbol
- information. It is called via mips_elf64_link_hash_traverse. The
- ECOFF external symbol information must match the ELF external
- symbol information. Unfortunately, at this point we don't know
- whether a symbol is required by reloc information, so the two
- tables may wind up being different. We must sort out the external
- symbol information before we can set the final size of the .mdebug
- section, and we must set the size of the .mdebug section before we
- can relocate any sections, and we can't know which symbols are
- required by relocation until we relocate the sections.
- Fortunately, it is relatively unlikely that any symbol will be
- stripped but required by a reloc. In particular, it can not happen
- when generating a final executable. */
-
-static boolean
-mips_elf64_output_extsym (h, data)
- struct mips_elf64_link_hash_entry *h;
- PTR data;
-{
- struct extsym_info *einfo = (struct extsym_info *) data;
- boolean strip;
- asection *sec, *output_section;
-
- if (h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf64_link_hash_entry *) h->root.root.u.i.link;
-
- if (h->root.indx == -2)
- strip = false;
- else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
- strip = true;
- else if (einfo->info->strip == strip_all
- || (einfo->info->strip == strip_some
- && bfd_hash_lookup (einfo->info->keep_hash,
- h->root.root.root.string,
- false, false) == NULL))
- strip = true;
- else
- strip = false;
-
- if (strip)
- return true;
-
- if (h->esym.ifd == -2)
- {
- h->esym.jmptbl = 0;
- h->esym.cobol_main = 0;
- h->esym.weakext = 0;
- h->esym.reserved = 0;
- h->esym.ifd = ifdNil;
- h->esym.asym.value = 0;
- h->esym.asym.st = stGlobal;
-
- if (h->root.root.type == bfd_link_hash_undefined
- || h->root.root.type == bfd_link_hash_undefweak)
- {
- const char *name;
-
- /* Use undefined class. Also, set class and type for some
- special symbols. */
- name = h->root.root.root.string;
- h->esym.asym.sc = scUndefined;
- }
- else if (h->root.root.type != bfd_link_hash_defined
- && h->root.root.type != bfd_link_hash_defweak)
- h->esym.asym.sc = scAbs;
- else
- {
- const char *name;
-
- sec = h->root.root.u.def.section;
- output_section = sec->output_section;
-
- /* When making a shared library and symbol h is the one from
- the another shared library, OUTPUT_SECTION may be null. */
- if (output_section == NULL)
- h->esym.asym.sc = scUndefined;
- else
- {
- name = bfd_section_name (output_section->owner, output_section);
-
- if (strcmp (name, ".text") == 0)
- h->esym.asym.sc = scText;
- else if (strcmp (name, ".data") == 0)
- h->esym.asym.sc = scData;
- else if (strcmp (name, ".sdata") == 0)
- h->esym.asym.sc = scSData;
- else if (strcmp (name, ".rodata") == 0
- || strcmp (name, ".rdata") == 0)
- h->esym.asym.sc = scRData;
- else if (strcmp (name, ".bss") == 0)
- h->esym.asym.sc = scBss;
- else if (strcmp (name, ".sbss") == 0)
- h->esym.asym.sc = scSBss;
- else if (strcmp (name, ".init") == 0)
- h->esym.asym.sc = scInit;
- else if (strcmp (name, ".fini") == 0)
- h->esym.asym.sc = scFini;
- else
- h->esym.asym.sc = scAbs;
- }
- }
-
- h->esym.asym.reserved = 0;
- h->esym.asym.index = indexNil;
- }
-
- if (h->root.root.type == bfd_link_hash_common)
- h->esym.asym.value = h->root.root.u.c.size;
- else if (h->root.root.type == bfd_link_hash_defined
- || h->root.root.type == bfd_link_hash_defweak)
- {
- if (h->esym.asym.sc == scCommon)
- h->esym.asym.sc = scBss;
- else if (h->esym.asym.sc == scSCommon)
- h->esym.asym.sc = scSBss;
-
- sec = h->root.root.u.def.section;
- output_section = sec->output_section;
- if (output_section != NULL)
- h->esym.asym.value = (h->root.root.u.def.value
- + sec->output_offset
- + output_section->vma);
- else
- h->esym.asym.value = 0;
- }
- else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
- {
- struct mips_elf64_link_hash_entry *hd = h;
- boolean no_fn_stub = h->no_fn_stub;
-
- while (hd->root.root.type == bfd_link_hash_indirect)
- {
- hd = (struct mips_elf64_link_hash_entry *)h->root.root.u.i.link;
- no_fn_stub = no_fn_stub || hd->no_fn_stub;
- }
-
- if (!no_fn_stub)
- {
- /* Set type and value for a symbol with a function stub. */
- h->esym.asym.st = stProc;
- sec = hd->root.root.u.def.section;
- if (sec == NULL)
- h->esym.asym.value = 0;
- else
- {
- output_section = sec->output_section;
- if (output_section != NULL)
- h->esym.asym.value = (hd->root.plt.offset
- + sec->output_offset
- + output_section->vma);
- else
- h->esym.asym.value = 0;
- }
-#if 0 /* FIXME? */
- h->esym.ifd = 0;
-#endif
- }
- }
-
- if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
- h->root.root.root.string,
- &h->esym))
- {
- einfo->failed = true;
- return false;
- }
-
- return true;
-}
-
-/* Swap an entry in a .gptab section. Note that these routines rely
- on the equivalence of the two elements of the union. */
-
-static void
-mips_elf64_swap_gptab_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_gptab *ex;
- Elf32_gptab *in;
-{
- in->gt_entry.gt_g_value = H_GET_32 (abfd, ex->gt_entry.gt_g_value);
- in->gt_entry.gt_bytes = H_GET_32 (abfd, ex->gt_entry.gt_bytes);
-}
-
-static void
-mips_elf64_swap_gptab_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_gptab *in;
- Elf32_External_gptab *ex;
-{
- H_PUT_32 (abfd, (bfd_vma) in->gt_entry.gt_g_value,
- ex->gt_entry.gt_g_value);
- H_PUT_32 (abfd, (bfd_vma) in->gt_entry.gt_bytes,
- ex->gt_entry.gt_bytes);
-}
-
-/* A comparison routine used to sort .gptab entries. */
-
-static int
-gptab_compare (p1, p2)
- const PTR p1;
- const PTR p2;
-{
- const Elf32_gptab *a1 = (const Elf32_gptab *) p1;
- const Elf32_gptab *a2 = (const Elf32_gptab *) p2;
-
- return a1->gt_entry.gt_g_value - a2->gt_entry.gt_g_value;
-}
-
-/* We need to use a special link routine to handle the .mdebug section.
- We need to merge all instances of this section together, not write
- them all out sequentially. */
-
-boolean
-mips_elf64_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- asection **secpp;
- asection *o;
- struct bfd_link_order *p;
- asection *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
- struct ecoff_debug_info debug;
- const struct ecoff_debug_swap *swap
- = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
- HDRR *symhdr = &debug.symbolic_header;
- PTR mdebug_handle = NULL;
- asection *s;
- EXTR esym;
- unsigned int i;
- static const char * const secname[] =
- { ".text", ".init", ".fini", ".data",
- ".rodata", ".sdata", ".sbss", ".bss" };
- static const int sc[] = { scText, scInit, scFini, scData,
- scRData, scSData, scSBss, scBss };
-
- /* If all the things we linked together were PIC, but we're
- producing an executable (rather than a shared object), then the
- resulting file is CPIC (i.e., it calls PIC code.) */
- if (!info->shared
- && !info->relocateable
- && elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
- {
- elf_elfheader (abfd)->e_flags &= ~EF_MIPS_PIC;
- elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
- }
-
- /* We'd carefully arranged the dynamic symbol indices, and then the
- generic size_dynamic_sections renumbered them out from under us.
- Rather than trying somehow to prevent the renumbering, just do
- the sort again. */
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- bfd *dynobj;
- asection *got;
- struct mips_elf64_got_info *g;
-
- /* When we resort, we must tell mips_elf64_sort_hash_table what
- the lowest index it may use is. That's the number of section
- symbols we're going to add. The generic ELF linker only
- adds these symbols when building a shared object. Note that
- we count the sections after (possibly) removing the .options
- section above. */
- if (!mips_elf64_sort_hash_table (info, (info->shared
- ? bfd_count_sections (abfd) + 1
- : 1)))
- return false;
-
- /* Make sure we didn't grow the global .got region. */
- dynobj = elf_hash_table (info)->dynobj;
- got = bfd_get_section_by_name (dynobj, ".got");
- g = (struct mips_elf64_got_info *) elf_section_data (got)->tdata;
-
- if (g->global_gotsym != NULL)
- BFD_ASSERT ((elf_hash_table (info)->dynsymcount
- - g->global_gotsym->dynindx)
- <= g->global_gotno);
- }
-
- /* We include .MIPS.options, even though we don't process it quite right.
- (Some entries are supposed to be merged.) At IRIX6 empirically we seem
- to be better off including it than not. */
- for (secpp = &abfd->sections; *secpp != NULL; secpp = &(*secpp)->next)
- {
- if (strcmp ((*secpp)->name, ".MIPS.options") == 0)
- {
- for (p = (*secpp)->link_order_head; p != NULL; p = p->next)
- if (p->type == bfd_indirect_link_order)
- p->u.indirect.section->flags &=~ SEC_HAS_CONTENTS;
- (*secpp)->link_order_head = NULL;
- bfd_section_list_remove (abfd, secpp);
- --abfd->section_count;
-
- break;
- }
- }
-
- /* Get a value for the GP register. */
- if (elf_gp (abfd) == 0)
- {
- struct bfd_link_hash_entry *h;
-
- h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true);
- if (h != (struct bfd_link_hash_entry *) NULL
- && h->type == bfd_link_hash_defined)
- elf_gp (abfd) = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
- else if (info->relocateable)
- {
- bfd_vma lo = MINUS_ONE;
-
- /* Find the GP-relative section with the lowest offset. */
- for (o = abfd->sections; o != NULL; o = o->next)
- if (o->vma < lo
- && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
- lo = o->vma;
-
- /* And calculate GP relative to that. */
- elf_gp (abfd) = (lo + 0x7ff0);
- }
- else
- {
- /* If the relocate_section function needs to do a reloc
- involving the GP value, it should make a reloc_dangerous
- callback to warn that GP is not defined. */
- }
- }
-
- /* Go through the sections and collect the .mdebug information. */
- mdebug_sec = NULL;
- gptab_data_sec = NULL;
- gptab_bss_sec = NULL;
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- {
- if (strcmp (o->name, ".mdebug") == 0)
- {
- struct extsym_info einfo;
- bfd_vma last;
-
- /* We have found the .mdebug section in the output file.
- Look through all the link_orders comprising it and merge
- the information together. */
- symhdr->magic = swap->sym_magic;
- /* FIXME: What should the version stamp be? */
- symhdr->vstamp = 0;
- symhdr->ilineMax = 0;
- symhdr->cbLine = 0;
- symhdr->idnMax = 0;
- symhdr->ipdMax = 0;
- symhdr->isymMax = 0;
- symhdr->ioptMax = 0;
- symhdr->iauxMax = 0;
- symhdr->issMax = 0;
- symhdr->issExtMax = 0;
- symhdr->ifdMax = 0;
- symhdr->crfd = 0;
- symhdr->iextMax = 0;
-
- /* We accumulate the debugging information itself in the
- debug_info structure. */
- debug.line = NULL;
- debug.external_dnr = NULL;
- debug.external_pdr = NULL;
- debug.external_sym = NULL;
- debug.external_opt = NULL;
- debug.external_aux = NULL;
- debug.ss = NULL;
- debug.ssext = debug.ssext_end = NULL;
- debug.external_fdr = NULL;
- debug.external_rfd = NULL;
- debug.external_ext = debug.external_ext_end = NULL;
-
- mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
- if (mdebug_handle == (PTR) NULL)
- return false;
-
- esym.jmptbl = 0;
- esym.cobol_main = 0;
- esym.weakext = 0;
- esym.reserved = 0;
- esym.ifd = ifdNil;
- esym.asym.iss = issNil;
- esym.asym.st = stLocal;
- esym.asym.reserved = 0;
- esym.asym.index = indexNil;
- last = 0;
- for (i = 0; i < sizeof (secname) / sizeof (secname[0]); i++)
- {
- esym.asym.sc = sc[i];
- s = bfd_get_section_by_name (abfd, secname[i]);
- if (s != NULL)
- {
- esym.asym.value = s->vma;
- last = s->vma + s->_raw_size;
- }
- else
- esym.asym.value = last;
- if (!bfd_ecoff_debug_one_external (abfd, &debug, swap,
- secname[i], &esym))
- return false;
- }
-
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
- bfd *input_bfd;
- const struct ecoff_debug_swap *input_swap;
- struct ecoff_debug_info input_debug;
- char *eraw_src;
- char *eraw_end;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
- input_bfd = input_section->owner;
-
- if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
- || (get_elf_backend_data (input_bfd)
- ->elf_backend_ecoff_debug_swap) == NULL)
- {
- /* I don't know what a non MIPS ELF bfd would be
- doing with a .mdebug section, but I don't really
- want to deal with it. */
- continue;
- }
-
- input_swap = (get_elf_backend_data (input_bfd)
- ->elf_backend_ecoff_debug_swap);
-
- BFD_ASSERT (p->size == input_section->_raw_size);
-
- /* The ECOFF linking code expects that we have already
- read in the debugging information and set up an
- ecoff_debug_info structure, so we do that now. */
- if (! _bfd_mips_elf_read_ecoff_info (input_bfd, input_section,
- &input_debug))
- return false;
-
- if (! (bfd_ecoff_debug_accumulate
- (mdebug_handle, abfd, &debug, swap, input_bfd,
- &input_debug, input_swap, info)))
- return false;
-
- /* Loop through the external symbols. For each one with
- interesting information, try to find the symbol in
- the linker global hash table and save the information
- for the output external symbols. */
- eraw_src = input_debug.external_ext;
- eraw_end = (eraw_src
- + (input_debug.symbolic_header.iextMax
- * input_swap->external_ext_size));
- for (;
- eraw_src < eraw_end;
- eraw_src += input_swap->external_ext_size)
- {
- EXTR ext;
- const char *name;
- struct mips_elf64_link_hash_entry *h;
-
- (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
- if (ext.asym.sc == scNil
- || ext.asym.sc == scUndefined
- || ext.asym.sc == scSUndefined)
- continue;
-
- name = input_debug.ssext + ext.asym.iss;
- h = mips_elf64_link_hash_lookup (mips_elf64_hash_table (info),
- name, false, false, true);
- if (h == NULL || h->esym.ifd != -2)
- continue;
-
- if (ext.ifd != -1)
- {
- BFD_ASSERT (ext.ifd
- < input_debug.symbolic_header.ifdMax);
- ext.ifd = input_debug.ifdmap[ext.ifd];
- }
-
- h->esym = ext;
- }
-
- /* Free up the information we just read. */
- free (input_debug.line);
- free (input_debug.external_dnr);
- free (input_debug.external_pdr);
- free (input_debug.external_sym);
- free (input_debug.external_opt);
- free (input_debug.external_aux);
- free (input_debug.ss);
- free (input_debug.ssext);
- free (input_debug.external_fdr);
- free (input_debug.external_rfd);
- free (input_debug.external_ext);
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &=~ SEC_HAS_CONTENTS;
- }
-
- /* Build the external symbol information. */
- einfo.abfd = abfd;
- einfo.info = info;
- einfo.debug = &debug;
- einfo.swap = swap;
- einfo.failed = false;
- mips_elf64_link_hash_traverse (mips_elf64_hash_table (info),
- mips_elf64_output_extsym,
- (PTR) &einfo);
- if (einfo.failed)
- return false;
-
- /* Set the size of the .mdebug section. */
- o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
-
- /* Skip this section later on (I don't think this currently
- matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
-
- mdebug_sec = o;
- }
-
- if (strncmp (o->name, ".gptab.", sizeof ".gptab." - 1) == 0)
- {
- const char *subname;
- unsigned int c;
- Elf32_gptab *tab;
- Elf32_External_gptab *ext_tab;
- unsigned int i;
-
- /* The .gptab.sdata and .gptab.sbss sections hold
- information describing how the small data area would
- change depending upon the -G switch. These sections
- not used in executables files. */
- if (! info->relocateable)
- {
- asection **secpp;
-
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &=~ SEC_HAS_CONTENTS;
- }
-
- /* Skip this section later on (I don't think this
- currently matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
-
- /* Really remove the section. */
- for (secpp = &abfd->sections;
- *secpp != o;
- secpp = &(*secpp)->next)
- ;
- bfd_section_list_remove (abfd, secpp);
- --abfd->section_count;
-
- continue;
- }
-
- /* There is one gptab for initialized data, and one for
- uninitialized data. */
- if (strcmp (o->name, ".gptab.sdata") == 0)
- gptab_data_sec = o;
- else if (strcmp (o->name, ".gptab.sbss") == 0)
- gptab_bss_sec = o;
- else
- {
- (*_bfd_error_handler)
- (_("%s: illegal section name `%s'"),
- bfd_archive_filename (abfd), o->name);
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
-
- /* The linker script always combines .gptab.data and
- .gptab.sdata into .gptab.sdata, and likewise for
- .gptab.bss and .gptab.sbss. It is possible that there is
- no .sdata or .sbss section in the output file, in which
- case we must change the name of the output section. */
- subname = o->name + sizeof ".gptab" - 1;
- if (bfd_get_section_by_name (abfd, subname) == NULL)
- {
- if (o == gptab_data_sec)
- o->name = ".gptab.data";
- else
- o->name = ".gptab.bss";
- subname = o->name + sizeof ".gptab" - 1;
- BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL);
- }
-
- /* Set up the first entry. */
- c = 1;
- tab = (Elf32_gptab *) bfd_malloc (c * sizeof (Elf32_gptab));
- if (tab == NULL)
- return false;
- tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
- tab[0].gt_header.gt_unused = 0;
-
- /* Combine the input sections. */
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- {
- asection *input_section;
- bfd *input_bfd;
- bfd_size_type size;
- unsigned long last;
- bfd_size_type gpentry;
-
- if (p->type != bfd_indirect_link_order)
- {
- if (p->type == bfd_fill_link_order)
- continue;
- abort ();
- }
-
- input_section = p->u.indirect.section;
- input_bfd = input_section->owner;
-
- /* Combine the gptab entries for this input section one
- by one. We know that the input gptab entries are
- sorted by ascending -G value. */
- size = bfd_section_size (input_bfd, input_section);
- last = 0;
- for (gpentry = sizeof (Elf32_External_gptab);
- gpentry < size;
- gpentry += sizeof (Elf32_External_gptab))
- {
- Elf32_External_gptab ext_gptab;
- Elf32_gptab int_gptab;
- unsigned long val;
- unsigned long add;
- boolean exact;
- unsigned int look;
-
- if (! (bfd_get_section_contents
- (input_bfd, input_section, (PTR) &ext_gptab,
- gpentry, sizeof (Elf32_External_gptab))))
- {
- free (tab);
- return false;
- }
-
- mips_elf64_swap_gptab_in (input_bfd, &ext_gptab,
- &int_gptab);
- val = int_gptab.gt_entry.gt_g_value;
- add = int_gptab.gt_entry.gt_bytes - last;
-
- exact = false;
- for (look = 1; look < c; look++)
- {
- if (tab[look].gt_entry.gt_g_value >= val)
- tab[look].gt_entry.gt_bytes += add;
-
- if (tab[look].gt_entry.gt_g_value == val)
- exact = true;
- }
-
- if (! exact)
- {
- Elf32_gptab *new_tab;
- unsigned int max;
-
- /* We need a new table entry. */
- new_tab = ((Elf32_gptab *)
- bfd_realloc ((PTR) tab,
- (c + 1) * sizeof (Elf32_gptab)));
- if (new_tab == NULL)
- {
- free (tab);
- return false;
- }
- tab = new_tab;
- tab[c].gt_entry.gt_g_value = val;
- tab[c].gt_entry.gt_bytes = add;
-
- /* Merge in the size for the next smallest -G
- value, since that will be implied by this new
- value. */
- max = 0;
- for (look = 1; look < c; look++)
- {
- if (tab[look].gt_entry.gt_g_value < val
- && (max == 0
- || (tab[look].gt_entry.gt_g_value
- > tab[max].gt_entry.gt_g_value)))
- max = look;
- }
- if (max != 0)
- tab[c].gt_entry.gt_bytes +=
- tab[max].gt_entry.gt_bytes;
-
- ++c;
- }
-
- last = int_gptab.gt_entry.gt_bytes;
- }
-
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &=~ SEC_HAS_CONTENTS;
- }
-
- /* The table must be sorted by -G value. */
- if (c > 2)
- qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare);
-
- /* Swap out the table. */
- ext_tab = ((Elf32_External_gptab *)
- bfd_alloc (abfd, c * sizeof (Elf32_External_gptab)));
- if (ext_tab == NULL)
- {
- free (tab);
- return false;
- }
-
- for (i = 0; i < c; i++)
- mips_elf64_swap_gptab_out (abfd, tab + i, ext_tab + i);
- free (tab);
-
- o->_raw_size = c * sizeof (Elf32_External_gptab);
- o->contents = (bfd_byte *) ext_tab;
-
- /* Skip this section later on (I don't think this currently
- matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
- }
- }
-
- /* Invoke the regular ELF backend linker to do all the work. */
- if (!bfd_elf64_bfd_final_link (abfd, info))
- return false;
-
- /* Now write out the computed sections. */
- if (mdebug_sec != (asection *) NULL)
- {
- BFD_ASSERT (abfd->output_has_begun);
- if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
- swap, info,
- mdebug_sec->filepos))
- return false;
-
- bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
- }
- if (gptab_data_sec != (asection *) NULL)
- {
- if (! bfd_set_section_contents (abfd, gptab_data_sec,
- gptab_data_sec->contents,
- (file_ptr) 0,
- gptab_data_sec->_raw_size))
- return false;
- }
-
- if (gptab_bss_sec != (asection *) NULL)
- {
- if (! bfd_set_section_contents (abfd, gptab_bss_sec,
- gptab_bss_sec->contents,
- (file_ptr) 0,
- gptab_bss_sec->_raw_size))
- return false;
- }
-
- return true;
-}
-
-/* ECOFF swapping routines. These are used when dealing with the
- .mdebug section, which is in the ECOFF debugging format. */
-static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
-{
- /* Symbol table magic number. */
- magicSym2,
- /* Alignment of debugging information. E.g., 4. */
- 8,
- /* Sizes of external symbolic information. */
- sizeof (struct hdr_ext),
- sizeof (struct dnr_ext),
- sizeof (struct pdr_ext),
- sizeof (struct sym_ext),
- sizeof (struct opt_ext),
- sizeof (struct fdr_ext),
- sizeof (struct rfd_ext),
- sizeof (struct ext_ext),
- /* Functions to swap in external symbolic data. */
- ecoff_swap_hdr_in,
- ecoff_swap_dnr_in,
- ecoff_swap_pdr_in,
- ecoff_swap_sym_in,
- ecoff_swap_opt_in,
- ecoff_swap_fdr_in,
- ecoff_swap_rfd_in,
- ecoff_swap_ext_in,
- _bfd_ecoff_swap_tir_in,
- _bfd_ecoff_swap_rndx_in,
- /* Functions to swap out external symbolic data. */
- ecoff_swap_hdr_out,
- ecoff_swap_dnr_out,
- ecoff_swap_pdr_out,
- ecoff_swap_sym_out,
- ecoff_swap_opt_out,
- ecoff_swap_fdr_out,
- ecoff_swap_rfd_out,
- ecoff_swap_ext_out,
- _bfd_ecoff_swap_tir_out,
- _bfd_ecoff_swap_rndx_out,
- /* Function to read in symbolic data. */
- _bfd_mips_elf_read_ecoff_info
-};
-
-/* Relocations in the 64 bit MIPS ELF ABI are more complex than in
- standard ELF. This structure is used to redirect the relocation
- handling routines. */
-
-const struct elf_size_info mips_elf64_size_info =
-{
- sizeof (Elf64_External_Ehdr),
- sizeof (Elf64_External_Phdr),
- sizeof (Elf64_External_Shdr),
- sizeof (Elf64_Mips_External_Rel),
- sizeof (Elf64_Mips_External_Rela),
- sizeof (Elf64_External_Sym),
- sizeof (Elf64_External_Dyn),
- sizeof (Elf_External_Note),
- 4, /* hash-table entry size */
- 3, /* internal relocations per external relocations */
- 64, /* arch_size */
- 8, /* file_align */
- ELFCLASS64,
- EV_CURRENT,
- bfd_elf64_write_out_phdrs,
- bfd_elf64_write_shdrs_and_ehdr,
- mips_elf64_write_relocs,
- bfd_elf64_swap_symbol_out,
- mips_elf64_slurp_reloc_table,
- bfd_elf64_slurp_symbol_table,
- bfd_elf64_swap_dyn_in,
- bfd_elf64_swap_dyn_out,
- mips_elf64_be_swap_reloc_in,
- mips_elf64_be_swap_reloc_out,
- mips_elf64_be_swap_reloca_in,
- mips_elf64_be_swap_reloca_out
-};
-
-#define ELF_ARCH bfd_arch_mips
-#define ELF_MACHINE_CODE EM_MIPS
-
-#define ELF_MAXPAGESIZE 0x1000
-
-#define elf_backend_collect true
-#define elf_backend_type_change_ok true
-#define elf_backend_can_gc_sections true
-#define elf_info_to_howto mips_elf64_info_to_howto_rela
-#define elf_info_to_howto_rel mips_elf64_info_to_howto_rel
-#define elf_backend_object_p _bfd_mips_elf_object_p
-#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
-#define elf_backend_section_processing _bfd_mips_elf_section_processing
-#define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
-#define elf_backend_fake_sections _bfd_mips_elf_fake_sections
-#define elf_backend_section_from_bfd_section \
- _bfd_mips_elf_section_from_bfd_section
-#define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
-#define elf_backend_link_output_symbol_hook \
- _bfd_mips_elf_link_output_symbol_hook
-#define elf_backend_create_dynamic_sections \
- mips_elf64_create_dynamic_sections
-#define elf_backend_check_relocs mips_elf64_check_relocs
-#define elf_backend_adjust_dynamic_symbol \
- mips_elf64_adjust_dynamic_symbol
-#define elf_backend_always_size_sections \
- mips_elf64_always_size_sections
-#define elf_backend_size_dynamic_sections \
- mips_elf64_size_dynamic_sections
-#define elf_backend_relocate_section mips_elf64_relocate_section
-#define elf_backend_finish_dynamic_symbol \
- mips_elf64_finish_dynamic_symbol
-#define elf_backend_finish_dynamic_sections \
- mips_elf64_finish_dynamic_sections
-#define elf_backend_final_write_processing \
- _bfd_mips_elf_final_write_processing
-#define elf_backend_additional_program_headers \
- mips_elf64_additional_program_headers
-#define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
-#define elf_backend_gc_mark_hook mips_elf64_gc_mark_hook
-#define elf_backend_gc_sweep_hook mips_elf64_gc_sweep_hook
-#define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
-#define elf_backend_size_info mips_elf64_size_info
-
-#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
-#define elf_backend_plt_header_size 0
-
-/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
- * work better/work only in RELA, so we default to this. */
-#define elf_backend_may_use_rel_p 1
-#define elf_backend_may_use_rela_p 1
-#define elf_backend_default_use_rela_p 1
-
-/* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
- MIPS-specific function only applies to IRIX5, which had no 64-bit
- ABI. */
-#define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
-#define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
-#define bfd_elf64_bfd_link_hash_table_create \
- mips_elf64_link_hash_table_create
-#define bfd_elf64_bfd_final_link mips_elf64_final_link
-#define bfd_elf64_bfd_merge_private_bfd_data \
- _bfd_mips_elf_merge_private_bfd_data
-#define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
-#define bfd_elf64_bfd_print_private_bfd_data \
- _bfd_mips_elf_print_private_bfd_data
-
-#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
-#define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
-#define bfd_elf64_archive_functions
-extern boolean bfd_elf64_archive_slurp_armap
- PARAMS((bfd *));
-extern boolean bfd_elf64_archive_write_armap
- PARAMS((bfd *, unsigned int, struct orl *, unsigned int, int));
-#define bfd_elf64_archive_slurp_extended_name_table \
- _bfd_archive_coff_slurp_extended_name_table
-#define bfd_elf64_archive_construct_extended_name_table \
- _bfd_archive_coff_construct_extended_name_table
-#define bfd_elf64_archive_truncate_arname \
- _bfd_archive_coff_truncate_arname
-#define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
-#define bfd_elf64_archive_openr_next_archived_file \
- _bfd_archive_coff_openr_next_archived_file
-#define bfd_elf64_archive_get_elt_at_index \
- _bfd_archive_coff_get_elt_at_index
-#define bfd_elf64_archive_generic_stat_arch_elt \
- _bfd_archive_coff_generic_stat_arch_elt
-#define bfd_elf64_archive_update_armap_timestamp \
- _bfd_archive_coff_update_armap_timestamp
-
-/* The SGI style (n)64 NewABI. */
-#define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
-#define TARGET_LITTLE_NAME "elf64-littlemips"
-#define TARGET_BIG_SYM bfd_elf64_bigmips_vec
-#define TARGET_BIG_NAME "elf64-bigmips"
-
-#include "elf64-target.h"
-
-#define INCLUDED_TARGET_FILE /* More a type of flag. */
-
-/* The SYSV-style 'traditional' (n)64 NewABI. */
-#undef TARGET_LITTLE_SYM
-#undef TARGET_LITTLE_NAME
-#undef TARGET_BIG_SYM
-#undef TARGET_BIG_NAME
-
-#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
-#define TARGET_LITTLE_NAME "elf64-tradlittlemips"
-#define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
-#define TARGET_BIG_NAME "elf64-tradbigmips"
-
-/* Include the target file again for this target. */
-#include "elf64-target.h"
diff --git a/contrib/binutils/bfd/filemode.c b/contrib/binutils/bfd/filemode.c
deleted file mode 100644
index 6f45968..0000000
--- a/contrib/binutils/bfd/filemode.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/* filemode.c -- make a string describing file modes
- Copyright (C) 1985, 1990 Free Software Foundation, Inc.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "sysdep.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-void mode_string ();
-static char ftypelet ();
-static void rwx ();
-static void setst ();
-
-/* filemodestring - fill in string STR with an ls-style ASCII
- representation of the st_mode field of file stats block STATP.
- 10 characters are stored in STR; no terminating null is added.
- The characters stored in STR are:
-
- 0 File type. 'd' for directory, 'c' for character
- special, 'b' for block special, 'm' for multiplex,
- 'l' for symbolic link, 's' for socket, 'p' for fifo,
- '-' for any other file type
-
- 1 'r' if the owner may read, '-' otherwise.
-
- 2 'w' if the owner may write, '-' otherwise.
-
- 3 'x' if the owner may execute, 's' if the file is
- set-user-id, '-' otherwise.
- 'S' if the file is set-user-id, but the execute
- bit isn't set.
-
- 4 'r' if group members may read, '-' otherwise.
-
- 5 'w' if group members may write, '-' otherwise.
-
- 6 'x' if group members may execute, 's' if the file is
- set-group-id, '-' otherwise.
- 'S' if it is set-group-id but not executable.
-
- 7 'r' if any user may read, '-' otherwise.
-
- 8 'w' if any user may write, '-' otherwise.
-
- 9 'x' if any user may execute, 't' if the file is "sticky"
- (will be retained in swap space after execution), '-'
- otherwise.
- 'T' if the file is sticky but not executable. */
-
-void
-filemodestring (statp, str)
- struct stat *statp;
- char *str;
-{
- mode_string (statp->st_mode, str);
-}
-
-/* Like filemodestring, but only the relevant part of the `struct stat'
- is given as an argument. */
-
-void
-mode_string (mode, str)
- unsigned short mode;
- char *str;
-{
- str[0] = ftypelet (mode);
- rwx ((mode & 0700) << 0, &str[1]);
- rwx ((mode & 0070) << 3, &str[4]);
- rwx ((mode & 0007) << 6, &str[7]);
- setst (mode, str);
-}
-
-/* Return a character indicating the type of file described by
- file mode BITS:
- 'd' for directories
- 'b' for block special files
- 'c' for character special files
- 'm' for multiplexor files
- 'l' for symbolic links
- 's' for sockets
- 'p' for fifos
- '-' for any other file type. */
-
-static char
-ftypelet (bits)
- unsigned short bits;
-{
- switch (bits & S_IFMT)
- {
- default:
- return '-';
- case S_IFDIR:
- return 'd';
-#ifdef S_IFLNK
- case S_IFLNK:
- return 'l';
-#endif
-#ifdef S_IFCHR
- case S_IFCHR:
- return 'c';
-#endif
-#ifdef S_IFBLK
- case S_IFBLK:
- return 'b';
-#endif
-#ifdef S_IFMPC
- case S_IFMPC:
- case S_IFMPB:
- return 'm';
-#endif
-#ifdef S_IFSOCK
- case S_IFSOCK:
- return 's';
-#endif
-#ifdef S_IFIFO
-#if S_IFIFO != S_IFSOCK
- case S_IFIFO:
- return 'p';
-#endif
-#endif
-#ifdef S_IFNWK /* HP-UX */
- case S_IFNWK:
- return 'n';
-#endif
- }
-}
-
-/* Look at read, write, and execute bits in BITS and set
- flags in CHARS accordingly. */
-
-static void
-rwx (bits, chars)
- unsigned short bits;
- char *chars;
-{
- chars[0] = (bits & S_IREAD) ? 'r' : '-';
- chars[1] = (bits & S_IWRITE) ? 'w' : '-';
- chars[2] = (bits & S_IEXEC) ? 'x' : '-';
-}
-
-/* Set the 's' and 't' flags in file attributes string CHARS,
- according to the file mode BITS. */
-
-static void
-setst (bits, chars)
- unsigned short bits;
- char *chars;
-{
-#ifdef S_ISUID
- if (bits & S_ISUID)
- {
- if (chars[3] != 'x')
- /* Set-uid, but not executable by owner. */
- chars[3] = 'S';
- else
- chars[3] = 's';
- }
-#endif
-#ifdef S_ISGID
- if (bits & S_ISGID)
- {
- if (chars[6] != 'x')
- /* Set-gid, but not executable by group. */
- chars[6] = 'S';
- else
- chars[6] = 's';
- }
-#endif
-#ifdef S_ISVTX
- if (bits & S_ISVTX)
- {
- if (chars[9] != 'x')
- /* Sticky, but not executable by others. */
- chars[9] = 'T';
- else
- chars[9] = 't';
- }
-#endif
-}
-
-
diff --git a/contrib/binutils/bfd/mipsbsd.c b/contrib/binutils/bfd/mipsbsd.c
deleted file mode 100644
index 85cf0ef..0000000
--- a/contrib/binutils/bfd/mipsbsd.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/* BFD backend for MIPS BSD (a.out) binaries.
- Copyright 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
- Written by Ralph Campbell.
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#define BYTES_IN_WORD 4
-/* #define ENTRY_CAN_BE_ZERO */
-#define N_HEADER_IN_TEXT(x) 1
-#define N_SHARED_LIB(x) 0
-#define N_TXTADDR(x) \
- (N_MAGIC(x) != ZMAGIC ? (x).a_entry : /* object file or NMAGIC */\
- TEXT_START_ADDR + EXEC_BYTES_SIZE /* no padding */\
- )
-#define N_DATADDR(x) (N_TXTADDR(x)+N_TXTSIZE(x))
-#define TEXT_START_ADDR 4096
-#define TARGET_PAGE_SIZE 4096
-#define SEGMENT_SIZE TARGET_PAGE_SIZE
-#define DEFAULT_ARCH bfd_arch_mips
-#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \
- || (mtype) == M_MIPS1 || (mtype) == M_MIPS2)
-#define MY_symbol_leading_char '\0'
-
-/* Do not "beautify" the CONCAT* macro args. Traditional C will not
- remove whitespace added here, and thus will fail to concatenate
- the tokens. */
-#define MY(OP) CONCAT2 (mipsbsd_,OP)
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-#include "libaout.h"
-
-#define SET_ARCH_MACH(ABFD, EXEC) \
- MY(set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
- MY(choose_reloc_size) (ABFD);
-static void MY(set_arch_mach) PARAMS ((bfd *abfd, unsigned long machtype));
-static void MY(choose_reloc_size) PARAMS ((bfd *abfd));
-
-#define MY_write_object_contents MY(write_object_contents)
-static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
-
-/* We can't use MY(x) here because it leads to a recursive call to CONCAT2
- when expanded inside JUMP_TABLE. */
-#define MY_bfd_reloc_type_lookup mipsbsd_reloc_howto_type_lookup
-#define MY_canonicalize_reloc mipsbsd_canonicalize_reloc
-
-#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
-#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
-#define MY_final_link_callback unused
-#define MY_bfd_final_link _bfd_generic_final_link
-
-#define MY_backend_data &MY(backend_data)
-#define MY_BFD_TARGET
-
-#include "aout-target.h"
-
-static bfd_reloc_status_type mips_fix_jmp_addr
- PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
- bfd *, char **));
-static reloc_howto_type *MY(reloc_howto_type_lookup)
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-
-long MY(canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
-
-static void
-MY(set_arch_mach) (abfd, machtype)
- bfd *abfd;
- unsigned long machtype;
-{
- enum bfd_architecture arch;
- unsigned int machine;
-
- /* Determine the architecture and machine type of the object file. */
- switch (machtype)
- {
- case M_MIPS1:
- arch = bfd_arch_mips;
- machine = 3000;
- break;
-
- case M_MIPS2:
- arch = bfd_arch_mips;
- machine = 4000;
- break;
-
- default:
- arch = bfd_arch_obscure;
- machine = 0;
- break;
- }
-
- bfd_set_arch_mach (abfd, arch, machine);
-}
-
-/* Determine the size of a relocation entry, based on the architecture */
-static void
-MY (choose_reloc_size) (abfd)
- bfd *abfd;
-{
- switch (bfd_get_arch (abfd))
- {
- case bfd_arch_sparc:
- case bfd_arch_a29k:
- case bfd_arch_mips:
- obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
- break;
- default:
- obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
- break;
- }
-}
-
-/* Write an object file in BSD a.out format.
- Section contents have already been written. We write the
- file header, symbols, and relocation. */
-
-static boolean
-MY (write_object_contents) (abfd)
- bfd *abfd;
-{
- struct external_exec exec_bytes;
- struct internal_exec *execp = exec_hdr (abfd);
-
- /* Magic number, maestro, please! */
- switch (bfd_get_arch (abfd))
- {
- case bfd_arch_m68k:
- switch (bfd_get_mach (abfd))
- {
- case bfd_mach_m68010:
- N_SET_MACHTYPE (*execp, M_68010);
- break;
- default:
- case bfd_mach_m68020:
- N_SET_MACHTYPE (*execp, M_68020);
- break;
- }
- break;
- case bfd_arch_sparc:
- N_SET_MACHTYPE (*execp, M_SPARC);
- break;
- case bfd_arch_i386:
- N_SET_MACHTYPE (*execp, M_386);
- break;
- case bfd_arch_a29k:
- N_SET_MACHTYPE (*execp, M_29K);
- break;
- case bfd_arch_mips:
- switch (bfd_get_mach (abfd))
- {
- case 4000:
- case 6000:
- N_SET_MACHTYPE (*execp, M_MIPS2);
- break;
- default:
- N_SET_MACHTYPE (*execp, M_MIPS1);
- break;
- }
- break;
- default:
- N_SET_MACHTYPE (*execp, M_UNKNOWN);
- }
-
- MY (choose_reloc_size) (abfd);
-
- WRITE_HEADERS (abfd, execp);
-
- return true;
-}
-
-/* MIPS relocation types. */
-#define MIPS_RELOC_32 0
-#define MIPS_RELOC_JMP 1
-#define MIPS_RELOC_WDISP16 2
-#define MIPS_RELOC_HI16 3
-#define MIPS_RELOC_HI16_S 4
-#define MIPS_RELOC_LO16 5
-
-/* This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
- The jump destination address is formed from the upper 4 bits of the
- "current" program counter concatenated with the jump instruction's
- 26 bit field and two trailing zeros.
- If the destination address is not in the same segment as the "current"
- program counter, then we need to signal an error. */
-
-static bfd_reloc_status_type
-mips_fix_jmp_addr (abfd, reloc_entry, symbol, data, input_section, output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- struct symbol_cache_entry *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_vma relocation, pc;
-
- /* If this is a partial relocation, just continue. */
- if (output_bfd != (bfd *)NULL)
- return bfd_reloc_continue;
-
- /* If this is an undefined symbol, return error */
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0)
- return bfd_reloc_undefined;
-
- /* Work out which section the relocation is targetted at and the
- initial relocation command value. */
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- pc = input_section->output_section->vma + input_section->output_offset +
- reloc_entry->address + 4;
-
- if ((relocation & 0xF0000000) != (pc & 0xF0000000))
- return bfd_reloc_overflow;
-
- return bfd_reloc_continue;
-}
-
-/* This is only called when performing a BFD_RELOC_HI16_S relocation.
- We need to see if bit 15 is set in the result. If it is, we add
- 0x10000 and continue normally. This will compensate for the sign extension
- when the low bits are added at run time. */
-
-static bfd_reloc_status_type
-mips_fix_hi16_s PARAMS ((bfd *, arelent *, asymbol *, PTR,
- asection *, bfd *, char **));
-
-static bfd_reloc_status_type
-mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_vma relocation;
-
- /* If this is a partial relocation, just continue. */
- if (output_bfd != (bfd *)NULL)
- return bfd_reloc_continue;
-
- /* If this is an undefined symbol, return error. */
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0)
- return bfd_reloc_undefined;
-
- /* Work out which section the relocation is targetted at and the
- initial relocation command value. */
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (relocation & 0x8000)
- reloc_entry->addend += 0x10000;
-
- return bfd_reloc_continue;
-}
-
-static reloc_howto_type mips_howto_table_ext[] = {
- {MIPS_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, 0,
- "32", false, 0, 0xffffffff, false},
- {MIPS_RELOC_JMP, 2, 2, 26, false, 0, complain_overflow_dont,
- mips_fix_jmp_addr,
- "MIPS_JMP", false, 0, 0x03ffffff, false},
- {MIPS_RELOC_WDISP16, 2, 2, 16, true, 0, complain_overflow_signed, 0,
- "WDISP16", false, 0, 0x0000ffff, false},
- {MIPS_RELOC_HI16, 16, 2, 16, false, 0, complain_overflow_bitfield, 0,
- "HI16", false, 0, 0x0000ffff, false},
- {MIPS_RELOC_HI16_S, 16, 2, 16, false, 0, complain_overflow_bitfield,
- mips_fix_hi16_s,
- "HI16_S", false, 0, 0x0000ffff, false},
- {MIPS_RELOC_LO16, 0, 2, 16, false, 0, complain_overflow_dont, 0,
- "LO16", false, 0, 0x0000ffff, false},
-};
-
-static reloc_howto_type *
-MY(reloc_howto_type_lookup) (abfd, code)
- bfd *abfd;
- bfd_reloc_code_real_type code;
-{
-
- if (bfd_get_arch (abfd) != bfd_arch_mips)
- return 0;
-
- switch (code)
- {
- case BFD_RELOC_CTOR:
- case BFD_RELOC_32:
- return (&mips_howto_table_ext[MIPS_RELOC_32]);
- case BFD_RELOC_MIPS_JMP:
- return (&mips_howto_table_ext[MIPS_RELOC_JMP]);
- case BFD_RELOC_16_PCREL_S2:
- return (&mips_howto_table_ext[MIPS_RELOC_WDISP16]);
- case BFD_RELOC_HI16:
- return (&mips_howto_table_ext[MIPS_RELOC_HI16]);
- case BFD_RELOC_HI16_S:
- return (&mips_howto_table_ext[MIPS_RELOC_HI16_S]);
- case BFD_RELOC_LO16:
- return (&mips_howto_table_ext[MIPS_RELOC_LO16]);
- default:
- return 0;
- }
-}
-
-/* This is just like the standard aoutx.h version but we need to do our
- own mapping of external reloc type values to howto entries. */
-long
-MY(canonicalize_reloc) (abfd, section, relptr, symbols)
- bfd *abfd;
- sec_ptr section;
- arelent **relptr;
- asymbol **symbols;
-{
- arelent *tblptr = section->relocation;
- unsigned int count, c;
- extern reloc_howto_type NAME(aout,ext_howto_table)[];
-
- /* If we have already read in the relocation table, return the values. */
- if (section->flags & SEC_CONSTRUCTOR)
- {
- arelent_chain *chain = section->constructor_chain;
-
- for (count = 0; count < section->reloc_count; count++)
- {
- *relptr++ = &chain->relent;
- chain = chain->next;
- }
- *relptr = 0;
- return section->reloc_count;
- }
-
- if (tblptr && section->reloc_count)
- {
- for (count = 0; count++ < section->reloc_count;)
- *relptr++ = tblptr++;
- *relptr = 0;
- return section->reloc_count;
- }
-
- if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
- return -1;
- tblptr = section->relocation;
-
- /* fix up howto entries. */
- for (count = 0; count++ < section->reloc_count;)
- {
- c = tblptr->howto - NAME(aout,ext_howto_table);
- tblptr->howto = &mips_howto_table_ext[c];
-
- *relptr++ = tblptr++;
- }
- *relptr = 0;
- return section->reloc_count;
-}
-
-static const struct aout_backend_data MY(backend_data) = {
- 0, /* zmagic contiguous */
- 1, /* text incl header */
- 0, /* entry is text address */
- 0, /* exec_hdr_flags */
- TARGET_PAGE_SIZE, /* text vma */
- MY_set_sizes,
- 0, /* text size includes exec header */
- 0, /* add_dynamic_symbols */
- 0, /* add_one_symbol */
- 0, /* link_dynamic_object */
- 0, /* write_dynamic_symbol */
- 0, /* check_dynamic_reloc */
- 0 /* finish_dynamic_link */
-};
-
-extern const bfd_target aout_mips_big_vec;
-
-const bfd_target aout_mips_little_vec =
- {
- "a.out-mips-little", /* name */
- bfd_target_aout_flavour,
- BFD_ENDIAN_LITTLE, /* target byte order (little) */
- BFD_ENDIAN_LITTLE, /* target headers byte order (little) */
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
- MY_symbol_leading_char,
- ' ', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
- {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
- bfd_generic_archive_p, MY_core_file_p},
- {bfd_false, MY_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, MY_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (MY),
- BFD_JUMP_TABLE_COPY (MY),
- BFD_JUMP_TABLE_CORE (MY),
- BFD_JUMP_TABLE_ARCHIVE (MY),
- BFD_JUMP_TABLE_SYMBOLS (MY),
- BFD_JUMP_TABLE_RELOCS (MY),
- BFD_JUMP_TABLE_WRITE (MY),
- BFD_JUMP_TABLE_LINK (MY),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- & aout_mips_big_vec,
-
- (PTR) MY_backend_data
- };
-
-const bfd_target aout_mips_big_vec =
- {
- "a.out-mips-big", /* name */
- bfd_target_aout_flavour,
- BFD_ENDIAN_BIG, /* target byte order (big) */
- BFD_ENDIAN_BIG, /* target headers byte order (big) */
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
- MY_symbol_leading_char,
- ' ', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64,
- bfd_getb32, bfd_getb_signed_32, bfd_putb32,
- bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
- {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
- bfd_generic_archive_p, MY_core_file_p},
- {bfd_false, MY_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, MY_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (MY),
- BFD_JUMP_TABLE_COPY (MY),
- BFD_JUMP_TABLE_CORE (MY),
- BFD_JUMP_TABLE_ARCHIVE (MY),
- BFD_JUMP_TABLE_SYMBOLS (MY),
- BFD_JUMP_TABLE_RELOCS (MY),
- BFD_JUMP_TABLE_WRITE (MY),
- BFD_JUMP_TABLE_LINK (MY),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- & aout_mips_little_vec,
-
- (PTR) MY_backend_data
- };
diff --git a/contrib/binutils/bfd/pe-mips.c b/contrib/binutils/bfd/pe-mips.c
deleted file mode 100644
index c78726d..0000000
--- a/contrib/binutils/bfd/pe-mips.c
+++ /dev/null
@@ -1,998 +0,0 @@
-/* BFD back-end for MIPS PE COFF files.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001 Free Software Foundation, Inc.
- Modified from coff-i386.c by DJ Delorie, dj@cygnus.com
-
-This file is part of BFD, the Binary File Descriptor library.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#define COFF_WITH_PE
-#define COFF_LONG_SECTION_NAMES
-#define PCRELOFFSET true
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "libbfd.h"
-
-#include "coff/mipspe.h"
-
-#include "coff/internal.h"
-
-#include "coff/pe.h"
-
-#include "libcoff.h"
-
-static bfd_reloc_status_type coff_mips_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static reloc_howto_type *coff_mips_rtype_to_howto
- PARAMS ((bfd *, asection *, struct internal_reloc *,
- struct coff_link_hash_entry *, struct internal_syment *,
-
- bfd_vma *));
-#if 0
-static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
- struct internal_reloc *));
-static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
- const struct internal_reloc *,
- PTR));
-static void mips_adjust_reloc_in PARAMS ((bfd *,
- const struct internal_reloc *,
- arelent *));
-static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
- struct internal_reloc *));
-#endif
-
-static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
-static reloc_howto_type * coff_mips_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
-static void mips_swap_reloc_in PARAMS ((bfd *, PTR, PTR));
-static unsigned int mips_swap_reloc_out PARAMS ((bfd *, PTR, PTR));
-static boolean coff_pe_mips_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- struct internal_reloc *, struct internal_syment *, asection **));
-
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
-/* The page size is a guess based on ELF. */
-
-#define COFF_PAGE_SIZE 0x1000
-
-/* For some reason when using mips COFF the value stored in the .text
- section for a reference to a common symbol is the value itself plus
- any desired offset. Ian Taylor, Cygnus Support. */
-
-/* If we are producing relocateable output, we need to do some
- adjustments to the object file that are not done by the
- bfd_perform_relocation function. This function is called by every
- reloc type to make any required adjustments. */
-
-static bfd_reloc_status_type
-coff_mips_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
- error_message)
- bfd *abfd;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- symvalue diff;
-
- if (output_bfd == (bfd *) NULL)
- return bfd_reloc_continue;
-
- if (bfd_is_com_section (symbol->section))
- {
-#ifndef COFF_WITH_PE
- /* We are relocating a common symbol. The current value in the
- object file is ORIG + OFFSET, where ORIG is the value of the
- common symbol as seen by the object file when it was compiled
- (this may be zero if the symbol was undefined) and OFFSET is
- the offset into the common symbol (normally zero, but may be
- non-zero when referring to a field in a common structure).
- ORIG is the negative of reloc_entry->addend, which is set by
- the CALC_ADDEND macro below. We want to replace the value in
- the object file with NEW + OFFSET, where NEW is the value of
- the common symbol which we are going to put in the final
- object file. NEW is symbol->value. */
- diff = symbol->value + reloc_entry->addend;
-#else
- /* In PE mode, we do not offset the common symbol. */
- diff = reloc_entry->addend;
-#endif
- }
- else
- {
- /* For some reason bfd_perform_relocation always effectively
- ignores the addend for a COFF target when producing
- relocateable output. This seems to be always wrong for 386
- COFF, so we handle the addend here instead. */
- diff = reloc_entry->addend;
- }
-
-#ifdef COFF_WITH_PE
-#if 0
- /* dj - handle it like any other reloc? */
- /* FIXME: How should this case be handled? */
- if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0)
- abort ();
-#endif
-#endif
-
-#define DOIT(x) \
- x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask))
-
- if (diff != 0)
- {
- reloc_howto_type *howto = reloc_entry->howto;
- unsigned char *addr = (unsigned char *) data + reloc_entry->address;
-
- switch (howto->size)
- {
- case 0:
- {
- char x = bfd_get_8 (abfd, addr);
- DOIT (x);
- bfd_put_8 (abfd, x, addr);
- }
- break;
-
- case 1:
- {
- short x = bfd_get_16 (abfd, addr);
- DOIT (x);
- bfd_put_16 (abfd, (bfd_vma) x, addr);
- }
- break;
-
- case 2:
- {
- long x = bfd_get_32 (abfd, addr);
- DOIT (x);
- bfd_put_32 (abfd, (bfd_vma) x, addr);
- }
- break;
-
- default:
- abort ();
- }
- }
-
- /* Now let bfd_perform_relocation finish everything up. */
- return bfd_reloc_continue;
-}
-
-#ifdef COFF_WITH_PE
-/* Return true if this relocation should
- appear in the output .reloc section. */
-
-static boolean
-in_reloc_p (abfd, howto)
- bfd * abfd ATTRIBUTE_UNUSED;
- reloc_howto_type *howto;
-{
- return ! howto->pc_relative && howto->type != MIPS_R_RVA;
-}
-#endif
-
-#ifndef PCRELOFFSET
-#define PCRELOFFSET false
-#endif
-
-static reloc_howto_type howto_table[] =
-{
- /* Reloc type 0 is ignored. The reloc reading code ensures that
- this is a reference to the .abs section, which will cause
- bfd_perform_relocation to do nothing. */
- HOWTO (MIPS_R_ABSOLUTE, /* type */
- 0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- 0, /* special_function */
- "IGNORE", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 16 bit reference to a symbol, normally from a data section. */
- HOWTO (MIPS_R_REFHALF, /* type */
- 0, /* rightshift */
- 1, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "REFHALF", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 32 bit reference to a symbol, normally from a data section. */
- HOWTO (MIPS_R_REFWORD, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "REFWORD", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A 26 bit absolute jump address. */
- HOWTO (MIPS_R_JMPADDR, /* type */
- 2, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 26, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
- detection, because the upper four
- bits must match the PC. */
- coff_mips_reloc, /* special_function */
- "JMPADDR", /* name */
- true, /* partial_inplace */
- 0x3ffffff, /* src_mask */
- 0x3ffffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* The high 16 bits of a symbol value. Handled by the function
- mips_refhi_reloc. */
- HOWTO (MIPS_R_REFHI, /* type */
- 16, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "REFHI", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* The low 16 bits of a symbol value. */
- HOWTO (MIPS_R_REFLO, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "REFLO", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A reference to an offset from the gp register. Handled by the
- function mips_gprel_reloc. */
- HOWTO (MIPS_R_GPREL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "GPREL", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- /* A reference to a literal using an offset from the gp register.
- Handled by the function mips_gprel_reloc. */
- HOWTO (MIPS_R_LITERAL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 16, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "LITERAL", /* name */
- true, /* partial_inplace */
- 0xffff, /* src_mask */
- 0xffff, /* dst_mask */
- false), /* pcrel_offset */
-
- EMPTY_HOWTO (8),
- EMPTY_HOWTO (9),
- EMPTY_HOWTO (10),
- EMPTY_HOWTO (11),
- EMPTY_HOWTO (12),
- EMPTY_HOWTO (13),
- EMPTY_HOWTO (14),
- EMPTY_HOWTO (15),
- EMPTY_HOWTO (16),
- EMPTY_HOWTO (17),
- EMPTY_HOWTO (18),
- EMPTY_HOWTO (19),
- EMPTY_HOWTO (20),
- EMPTY_HOWTO (21),
- EMPTY_HOWTO (22),
- EMPTY_HOWTO (23),
- EMPTY_HOWTO (24),
- EMPTY_HOWTO (25),
- EMPTY_HOWTO (26),
- EMPTY_HOWTO (27),
- EMPTY_HOWTO (28),
- EMPTY_HOWTO (29),
- EMPTY_HOWTO (30),
- EMPTY_HOWTO (31),
- EMPTY_HOWTO (32),
- EMPTY_HOWTO (33),
- HOWTO (MIPS_R_RVA, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "rva32", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
- EMPTY_HOWTO (35),
- EMPTY_HOWTO (36),
- HOWTO (MIPS_R_PAIR, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- coff_mips_reloc, /* special_function */
- "PAIR", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
-};
-
-/* Turn a howto into a reloc nunmber */
-
-#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
-#define BADMAG(x) MIPSBADMAG(x)
-#define MIPS 1 /* Customize coffcode.h */
-
-#define RTYPE2HOWTO(cache_ptr, dst) \
- (cache_ptr)->howto = howto_table + (dst)->r_type;
-
-/* Compute the addend of a reloc. If the reloc is to a common symbol,
- the object file contains the value of the common symbol. By the
- time this is called, the linker may be using a different symbol
- from a different object file with a different value. Therefore, we
- hack wildly to locate the original symbol from this file so that we
- can make the correct adjustment. This macro sets coffsym to the
- symbol from the original file, and uses it to set the addend value
- correctly. If this is not a common symbol, the usual addend
- calculation is done, except that an additional tweak is needed for
- PC relative relocs.
- FIXME: This macro refers to symbols and asect; these are from the
- calling function, not the macro arguments. */
-
-#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
- { \
- coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
- if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
- coffsym = (obj_symbols (abfd) \
- + (cache_ptr->sym_ptr_ptr - symbols)); \
- else if (ptr) \
- coffsym = coff_symbol_from (abfd, ptr); \
- if (coffsym != (coff_symbol_type *) NULL \
- && coffsym->native->u.syment.n_scnum == 0) \
- cache_ptr->addend = - coffsym->native->u.syment.n_value; \
- else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
- && ptr->section != (asection *) NULL) \
- cache_ptr->addend = - (ptr->section->vma + ptr->value); \
- else \
- cache_ptr->addend = 0; \
- if (ptr && howto_table[reloc.r_type].pc_relative) \
- cache_ptr->addend += asect->vma; \
- }
-
-/* Convert an rtype to howto for the COFF backend linker. */
-
-static reloc_howto_type *
-coff_mips_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
- struct internal_reloc *rel;
- struct coff_link_hash_entry *h;
- struct internal_syment *sym;
- bfd_vma *addendp;
-{
-
- reloc_howto_type *howto;
-
- howto = howto_table + rel->r_type;
-
-#ifdef COFF_WITH_PE
- *addendp = 0;
-#endif
-
- if (howto->pc_relative)
- *addendp += sec->vma;
-
- if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
- {
- /* This is a common symbol. The section contents include the
- size (sym->n_value) as an addend. The relocate_section
- function will be adding in the final value of the symbol. We
- need to subtract out the current size in order to get the
- correct result. */
-
- BFD_ASSERT (h != NULL);
-
-#ifndef COFF_WITH_PE
- /* I think we *do* want to bypass this. If we don't, I have
- seen some data parameters get the wrong relocation address.
- If I link two versions with and without this section bypassed
- and then do a binary comparison, the addresses which are
- different can be looked up in the map. The case in which
- this section has been bypassed has addresses which correspond
- to values I can find in the map. */
- *addendp -= sym->n_value;
-#endif
- }
-
-#ifndef COFF_WITH_PE
- /* If the output symbol is common (in which case this must be a
- relocateable link), we need to add in the final size of the
- common symbol. */
- if (h != NULL && h->root.type == bfd_link_hash_common)
- *addendp += h->root.u.c.size;
-#endif
-
-#ifdef COFF_WITH_PE
- if (howto->pc_relative)
- {
- *addendp -= 4;
-
- /* If the symbol is defined, then the generic code is going to
- add back the symbol value in order to cancel out an
- adjustment it made to the addend. However, we set the addend
- to 0 at the start of this function. We need to adjust here,
- to avoid the adjustment the generic code will make. FIXME:
- This is getting a bit hackish. */
- if (sym != NULL && sym->n_scnum != 0)
- *addendp -= sym->n_value;
- }
-
- if (rel->r_type == MIPS_R_RVA)
- {
- *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
- }
-#endif
-
- return howto;
-}
-
-#define coff_rtype_to_howto coff_mips_rtype_to_howto
-
-#define coff_bfd_reloc_type_lookup coff_mips_reloc_type_lookup
-
-/* Get the howto structure for a generic reloc type. */
-
-static reloc_howto_type *
-coff_mips_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
-{
- int mips_type;
-
- switch (code)
- {
- case BFD_RELOC_16:
- mips_type = MIPS_R_REFHALF;
- break;
- case BFD_RELOC_32:
- case BFD_RELOC_CTOR:
- mips_type = MIPS_R_REFWORD;
- break;
- case BFD_RELOC_MIPS_JMP:
- mips_type = MIPS_R_JMPADDR;
- break;
- case BFD_RELOC_HI16_S:
- mips_type = MIPS_R_REFHI;
- break;
- case BFD_RELOC_LO16:
- mips_type = MIPS_R_REFLO;
- break;
- case BFD_RELOC_GPREL16:
- mips_type = MIPS_R_GPREL;
- break;
- case BFD_RELOC_MIPS_LITERAL:
- mips_type = MIPS_R_LITERAL;
- break;
-/* FIXME?
- case BFD_RELOC_16_PCREL_S2:
- mips_type = MIPS_R_PCREL16;
- break;
- case BFD_RELOC_PCREL_HI16_S:
- mips_type = MIPS_R_RELHI;
- break;
- case BFD_RELOC_PCREL_LO16:
- mips_type = MIPS_R_RELLO;
- break;
- case BFD_RELOC_GPREL32:
- mips_type = MIPS_R_SWITCH;
- break;
-*/
- case BFD_RELOC_RVA:
- mips_type = MIPS_R_RVA;
- break;
- default:
- return (reloc_howto_type *) NULL;
- }
-
- return &howto_table[mips_type];
-}
-
-static void
-mips_swap_reloc_in (abfd, src, dst)
- bfd *abfd;
- PTR src;
- PTR dst;
-{
- static struct internal_reloc pair_prev;
- RELOC *reloc_src = (RELOC *) src;
- struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
-
- reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr);
- reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
- reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type);
- reloc_dst->r_size = 0;
- reloc_dst->r_extern = 0;
- reloc_dst->r_offset = 0;
-
- switch (reloc_dst->r_type)
- {
- case MIPS_R_REFHI:
- pair_prev = *reloc_dst;
- break;
- case MIPS_R_PAIR:
- reloc_dst->r_offset = reloc_dst->r_symndx;
- if (reloc_dst->r_offset & 0x8000)
- reloc_dst->r_offset -= 0x10000;
- /*printf ("dj: pair offset is %08x\n", reloc_dst->r_offset);*/
- reloc_dst->r_symndx = pair_prev.r_symndx;
- break;
- }
-}
-
-static unsigned int
-mips_swap_reloc_out (abfd, src, dst)
- bfd *abfd;
- PTR src;
- PTR dst;
-{
- static int prev_offset = 1;
- static bfd_vma prev_addr = 0;
- struct internal_reloc *reloc_src = (struct internal_reloc *)src;
- struct external_reloc *reloc_dst = (struct external_reloc *)dst;
-
- switch (reloc_src->r_type)
- {
- case MIPS_R_REFHI:
- prev_addr = reloc_src->r_vaddr;
- prev_offset = reloc_src->r_offset;
- break;
- case MIPS_R_REFLO:
- if (reloc_src->r_vaddr == prev_addr)
- {
- /* FIXME: only slightly hackish. If we see a REFLO pointing to
- the same address as a REFHI, we assume this is the matching
- PAIR reloc and output it accordingly. The symndx is really
- the low 16 bits of the addend */
- H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
- H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
- H_PUT_16 (abfd, MIPS_R_PAIR, reloc_dst->r_type);
- return RELSZ;
- }
- break;
- }
-
- H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
- H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
-
- H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
- return RELSZ;
-}
-
-#define coff_swap_reloc_in mips_swap_reloc_in
-#define coff_swap_reloc_out mips_swap_reloc_out
-#define NO_COFF_RELOCS
-
-static boolean
-coff_pe_mips_relocate_section (output_bfd, info, input_bfd,
- input_section, contents, relocs, syms,
- sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- struct internal_reloc *relocs;
- struct internal_syment *syms;
- asection **sections;
-{
- bfd_vma gp;
- boolean gp_undefined;
- size_t adjust;
- struct internal_reloc *rel;
- struct internal_reloc *rel_end;
- unsigned int i;
- boolean got_lo;
-
- if (info->relocateable)
- {
- (*_bfd_error_handler) (_("\
-%s: `ld -r' not supported with PE MIPS objects\n"),
- bfd_archive_filename (input_bfd));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- BFD_ASSERT (input_bfd->xvec->byteorder
- == output_bfd->xvec->byteorder);
-
-#if 0
- printf ("dj: relocate %s(%s) %08x\n",
- input_bfd->filename, input_section->name,
- input_section->output_section->vma + input_section->output_offset);
-#endif
-
- gp = _bfd_get_gp_value (output_bfd);
- if (gp == 0)
- gp_undefined = true;
- else
- gp_undefined = false;
-
- got_lo = false;
-
- adjust = 0;
-
- rel = relocs;
- rel_end = rel + input_section->reloc_count;
- for (i = 0; rel < rel_end; rel++, i++)
- {
- long symndx;
- struct coff_link_hash_entry *h;
- struct internal_syment *sym;
- bfd_vma addend = 0;
- bfd_vma val, tmp, targ, src, low;
- reloc_howto_type *howto;
- unsigned char *mem = contents + rel->r_vaddr;
-
- symndx = rel->r_symndx;
-
- if (symndx == -1)
- {
- h = NULL;
- sym = NULL;
- }
- else
- {
- h = obj_coff_sym_hashes (input_bfd)[symndx];
- sym = syms + symndx;
- }
-
- /* COFF treats common symbols in one of two ways. Either the
- size of the symbol is included in the section contents, or it
- is not. We assume that the size is not included, and force
- the rtype_to_howto function to adjust the addend as needed. */
-
- if (sym != NULL && sym->n_scnum != 0)
- addend = - sym->n_value;
- else
- addend = 0;
-
- howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
- sym, &addend);
- if (howto == NULL)
- return false;
-
- /* If we are doing a relocateable link, then we can just ignore
- a PC relative reloc that is pcrel_offset. It will already
- have the correct value. If this is not a relocateable link,
- then we should ignore the symbol value. */
- if (howto->pc_relative && howto->pcrel_offset)
- {
- if (info->relocateable)
- continue;
- if (sym != NULL && sym->n_scnum != 0)
- addend += sym->n_value;
- }
-
- val = 0;
-
- if (h == NULL)
- {
- asection *sec;
-
- if (symndx == -1)
- {
- sec = bfd_abs_section_ptr;
- val = 0;
- }
- else
- {
- sec = sections[symndx];
- val = (sec->output_section->vma
- + sec->output_offset
- + sym->n_value);
- if (! obj_pe (input_bfd))
- val -= sec->vma;
- }
- }
- else
- {
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- asection *sec;
-
- sec = h->root.u.def.section;
- val = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
-
- else if (! info->relocateable)
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma, true)))
- return false;
- }
- }
-
- src = rel->r_vaddr + input_section->output_section->vma
- + input_section->output_offset;
-#if 0
- printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n",
- rel->r_type, howto_table[rel->r_type].name,
- src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset,
- h?h->root.root.string:"(none)");
-#endif
-
- /* OK, at this point the following variables are set up:
- src = VMA of the memory we're fixing up
- mem = pointer to memory we're fixing up
- val = VMA of what we need to refer to
- */
-
-#define UI(x) (*_bfd_error_handler) (_("%s: unimplemented %s\n"), \
- bfd_archive_filename (input_bfd), x); \
- bfd_set_error (bfd_error_bad_value);
-
- switch (rel->r_type)
- {
- case MIPS_R_ABSOLUTE:
- /* ignore these */
- break;
-
- case MIPS_R_REFHALF:
- UI("refhalf");
- break;
-
- case MIPS_R_REFWORD:
- tmp = bfd_get_32(input_bfd, mem);
- /* printf ("refword: src=%08x targ=%08x+%08x\n", src, tmp, val); */
- tmp += val;
- bfd_put_32(input_bfd, tmp, mem);
- break;
-
- case MIPS_R_JMPADDR:
- tmp = bfd_get_32(input_bfd, mem);
- targ = val + (tmp&0x03ffffff)*4;
- if ((src & 0xf0000000) != (targ & 0xf0000000))
- {
- (*_bfd_error_handler) (_("%s: jump too far away\n"),
- bfd_archive_filename (input_bfd));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- tmp &= 0xfc000000;
- tmp |= (targ/4) & 0x3ffffff;
- bfd_put_32(input_bfd, tmp, mem);
- break;
-
- case MIPS_R_REFHI:
- tmp = bfd_get_32(input_bfd, mem);
- switch (rel[1].r_type)
- {
- case MIPS_R_PAIR:
- /* MS PE object */
- targ = val + rel[1].r_offset + ((tmp & 0xffff) << 16);
- break;
- case MIPS_R_REFLO:
- /* GNU COFF object */
- low = bfd_get_32(input_bfd, contents + rel[1].r_vaddr);
- low &= 0xffff;
- if (low & 0x8000)
- low -= 0x10000;
- targ = val + low + ((tmp & 0xffff) << 16);
- break;
- default:
- (*_bfd_error_handler) (_("%s: bad pair/reflo after refhi\n"),
- bfd_archive_filename (input_bfd));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- tmp &= 0xffff0000;
- tmp |= (targ >> 16) & 0xffff;
- bfd_put_32(input_bfd, tmp, mem);
- break;
-
- case MIPS_R_REFLO:
- tmp = bfd_get_32(input_bfd, mem);
- targ = val + (tmp & 0xffff);
- /* printf ("refword: src=%08x targ=%08x\n", src, targ); */
- tmp &= 0xffff0000;
- tmp |= targ & 0xffff;
- bfd_put_32(input_bfd, tmp, mem);
- break;
-
- case MIPS_R_GPREL:
- case MIPS_R_LITERAL:
- UI("gprel");
- break;
-
- case MIPS_R_SECTION:
- UI("section");
- break;
-
- case MIPS_R_SECREL:
- UI("secrel");
- break;
-
- case MIPS_R_SECRELLO:
- UI("secrello");
- break;
-
- case MIPS_R_SECRELHI:
- UI("secrelhi");
- break;
-
- case MIPS_R_RVA:
- tmp = bfd_get_32 (input_bfd, mem);
- /* printf ("rva: src=%08x targ=%08x+%08x\n", src, tmp, val); */
- tmp += val
- - pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
- bfd_put_32 (input_bfd, tmp, mem);
- break;
-
- case MIPS_R_PAIR:
- /* ignore these */
- break;
- }
- }
-
- return true;
-}
-
-#define coff_relocate_section coff_pe_mips_relocate_section
-
-#ifdef TARGET_UNDERSCORE
-
-/* If mips gcc uses underscores for symbol names, then it does not use
- a leading dot for local labels, so if TARGET_UNDERSCORE is defined
- we treat all symbols starting with L as local. */
-
-static boolean coff_mips_is_local_label_name PARAMS ((bfd *, const char *));
-
-static boolean
-coff_mips_is_local_label_name (abfd, name)
- bfd *abfd;
- const char *name;
-{
- if (name[0] == 'L')
- return true;
-
- return _bfd_coff_is_local_label_name (abfd, name);
-}
-
-#define coff_bfd_is_local_label_name coff_mips_is_local_label_name
-
-#endif /* TARGET_UNDERSCORE */
-
-#define COFF_NO_HACK_SCNHDR_SIZE
-
-#include "coffcode.h"
-
-const bfd_target
-#ifdef TARGET_SYM
- TARGET_SYM =
-#else
- mipslpe_vec =
-#endif
-{
-#ifdef TARGET_NAME
- TARGET_NAME,
-#else
- "pe-mips", /* name */
-#endif
- bfd_target_coff_flavour,
- BFD_ENDIAN_LITTLE, /* data byte order is little */
- BFD_ENDIAN_LITTLE, /* header byte order is little */
-
- (HAS_RELOC | EXEC_P | /* object flags */
- HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
-
-#ifndef COFF_WITH_PE
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
- | SEC_CODE | SEC_DATA),
-#else
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
- | SEC_CODE | SEC_DATA
- | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
-#endif
-
-#ifdef TARGET_UNDERSCORE
- TARGET_UNDERSCORE, /* leading underscore */
-#else
- 0, /* leading underscore */
-#endif
- '/', /* ar_pad_char */
- 15, /* ar_max_namelen */
-
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
-
-/* Note that we allow an object file to be treated as a core file as well. */
- {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- bfd_generic_archive_p, coff_object_p},
- {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
- bfd_false},
- {bfd_false, coff_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (coff),
- BFD_JUMP_TABLE_COPY (coff),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
- BFD_JUMP_TABLE_SYMBOLS (coff),
- BFD_JUMP_TABLE_RELOCS (coff),
- BFD_JUMP_TABLE_WRITE (coff),
- BFD_JUMP_TABLE_LINK (coff),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- NULL,
-
- COFF_SWAP_TABLE
-};
OpenPOWER on IntegriCloud