mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-14 12:04:04 +08:00
1555 lines
46 KiB
C
1555 lines
46 KiB
C
|
/* MIPS-specific support for 64-bit ELF
|
|||
|
Copyright 1996 Free Software Foundation, Inc.
|
|||
|
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 "libbfd.h"
|
|||
|
#include "bfdlink.h"
|
|||
|
#include "genlink.h"
|
|||
|
#include "elf-bfd.h"
|
|||
|
#include "elf/mips.h"
|
|||
|
|
|||
|
/* 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. */
|
|||
|
|
|||
|
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 reloc_howto_type *mips_elf64_reloc_type_lookup
|
|||
|
PARAMS ((bfd *, bfd_reloc_code_real_type));
|
|||
|
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 **));
|
|||
|
static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
|
|||
|
static boolean mips_elf64_section_from_shdr
|
|||
|
PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
|
|||
|
|
|||
|
/* The relocation types. */
|
|||
|
|
|||
|
enum mips_elf64_reloc_type
|
|||
|
{
|
|||
|
R_MIPS_NONE = 0,
|
|||
|
R_MIPS_16 = 1,
|
|||
|
R_MIPS_32 = 2,
|
|||
|
R_MIPS_ADD = 2,
|
|||
|
R_MIPS_REL32 = 3,
|
|||
|
R_MIPS_REL = 3,
|
|||
|
R_MIPS_26 = 4,
|
|||
|
R_MIPS_HI16 = 5,
|
|||
|
R_MIPS_LO16 = 6,
|
|||
|
R_MIPS_GPREL16 = 7,
|
|||
|
R_MIPS_GPREL = 7,
|
|||
|
R_MIPS_LITERAL = 8,
|
|||
|
R_MIPS_GOT16 = 9,
|
|||
|
R_MIPS_GOT = 9,
|
|||
|
R_MIPS_PC16 = 10,
|
|||
|
R_MIPS_CALL16 = 11,
|
|||
|
R_MIPS_CALL = 11,
|
|||
|
R_MIPS_GPREL32 = 12,
|
|||
|
R_MIPS_SHIFT5 = 16,
|
|||
|
R_MIPS_SHIFT6 = 17,
|
|||
|
R_MIPS_64 = 18,
|
|||
|
R_MIPS_GOT_DISP = 19,
|
|||
|
R_MIPS_GOT_PAGE = 20,
|
|||
|
R_MIPS_GOT_OFST = 21,
|
|||
|
R_MIPS_GOT_HI16 = 22,
|
|||
|
R_MIPS_GOT_LO16 = 23,
|
|||
|
R_MIPS_SUB = 24,
|
|||
|
R_MIPS_INSERT_A = 25,
|
|||
|
R_MIPS_INSERT_B = 26,
|
|||
|
R_MIPS_DELETE = 27,
|
|||
|
R_MIPS_HIGHER = 28,
|
|||
|
R_MIPS_HIGHEST = 29,
|
|||
|
R_MIPS_CALL_HI16 = 30,
|
|||
|
R_MIPS_CALL_LO16 = 31,
|
|||
|
R_MIPS_SCN_DISP = 32,
|
|||
|
R_MIPS_REL16 = 33,
|
|||
|
R_MIPS_ADD_IMMEDIATE = 34
|
|||
|
};
|
|||
|
|
|||
|
/* 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)
|
|||
|
|
|||
|
/* FIXME: These need to be rewritten, or we need to use the versions
|
|||
|
in elf32-mips.c. */
|
|||
|
#define mips_elf_hi16_reloc bfd_elf_generic_reloc
|
|||
|
#define mips_elf_lo16_reloc bfd_elf_generic_reloc
|
|||
|
#define mips_elf_gprel16_reloc bfd_elf_generic_reloc
|
|||
|
#define mips_elf_got16_reloc bfd_elf_generic_reloc
|
|||
|
#define mips_elf_gprel32_reloc bfd_elf_generic_reloc
|
|||
|
|
|||
|
/* The relocation table used for SHT_REL sections. */
|
|||
|
|
|||
|
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 */
|
|||
|
1, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
16, /* bitsize */
|
|||
|
false, /* pc_relative */
|
|||
|
0, /* bitpos */
|
|||
|
complain_overflow_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_16", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* 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_bitfield, /* 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_bitfield, /* 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 branch 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. */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_26", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0x3ffffff, /* src_mask */
|
|||
|
0x3ffffff, /* 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 */
|
|||
|
mips_elf_hi16_reloc, /* special_function */
|
|||
|
"R_MIPS_HI16", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* 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 */
|
|||
|
mips_elf_lo16_reloc, /* special_function */
|
|||
|
"R_MIPS_LO16", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* 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_elf_gprel16_reloc, /* special_function */
|
|||
|
"R_MIPS_GPREL16", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* 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_elf_gprel16_reloc, /* special_function */
|
|||
|
"R_MIPS_LITERAL", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* 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_elf_got16_reloc, /* special_function */
|
|||
|
"R_MIPS_GOT16", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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 */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* dst_mask */
|
|||
|
false), /* 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 */
|
|||
|
0xffff, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
mips_elf_gprel32_reloc, /* special_function */
|
|||
|
"R_MIPS_GPREL32", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0xffffffff, /* src_mask */
|
|||
|
0xffffffff, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
{ 13 },
|
|||
|
{ 14 },
|
|||
|
{ 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 */
|
|||
|
|
|||
|
/* 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_bitfield, /* 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_bitfield, /* 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_bitfield, /* 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_bitfield, /* 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_bitfield, /* 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 */
|
|||
|
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_INSERT_A", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* 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 */
|
|||
|
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_INSERT_B", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* Delete a 32 bit instruction. */
|
|||
|
/* FIXME: Not handled correctly. */
|
|||
|
HOWTO (R_MIPS_DELETE, /* 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_DELETE", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* Get the higher value of a 64 bit addend. */
|
|||
|
/* FIXME: Not handled correctly. */
|
|||
|
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 */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* Get the highest value of a 64 bit addend. */
|
|||
|
/* FIXME: Not handled correctly. */
|
|||
|
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 */
|
|||
|
0xffff, /* src_mask */
|
|||
|
0xffff, /* 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 */
|
|||
|
|
|||
|
/* I'm not sure what the remaining relocs are, but they are defined
|
|||
|
on Irix 6. */
|
|||
|
|
|||
|
HOWTO (R_MIPS_SCN_DISP, /* 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_SCN_DISP", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
HOWTO (R_MIPS_REL16, /* 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_REL16", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
HOWTO (R_MIPS_ADD_IMMEDIATE, /* 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_ADD_IMMEDIATE", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* 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 */
|
|||
|
1, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
16, /* bitsize */
|
|||
|
false, /* pc_relative */
|
|||
|
0, /* bitpos */
|
|||
|
complain_overflow_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_16", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_32", /* name */
|
|||
|
true, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_REL32", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffffffff, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* 26 bit branch 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. */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_26", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0x3ffffff, /* 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 */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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 */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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_elf_gprel16_reloc, /* special_function */
|
|||
|
"R_MIPS_GPREL16", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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_elf_gprel16_reloc, /* special_function */
|
|||
|
"R_MIPS_LITERAL", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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_elf_got16_reloc, /* special_function */
|
|||
|
"R_MIPS_GOT16", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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 */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* dst_mask */
|
|||
|
false), /* 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 */
|
|||
|
0xffff, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
mips_elf_gprel32_reloc, /* special_function */
|
|||
|
"R_MIPS_GPREL32", /* name */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0xffffffff, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
{ 13 },
|
|||
|
{ 14 },
|
|||
|
{ 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 */
|
|||
|
0, /* 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 */
|
|||
|
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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_64", /* name */
|
|||
|
true, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_GOT_DISP", /* name */
|
|||
|
true, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_GOT_PAGE", /* name */
|
|||
|
true, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_GOT_OFST", /* name */
|
|||
|
true, /* 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 */
|
|||
|
true, /* 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 */
|
|||
|
true, /* 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_bitfield, /* complain_on_overflow */
|
|||
|
bfd_elf_generic_reloc, /* special_function */
|
|||
|
"R_MIPS_SUB", /* name */
|
|||
|
true, /* 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 */
|
|||
|
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_INSERT_A", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* 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 */
|
|||
|
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_INSERT_B", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* Delete a 32 bit instruction. */
|
|||
|
/* FIXME: Not handled correctly. */
|
|||
|
HOWTO (R_MIPS_DELETE, /* 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_DELETE", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* Get the higher value of a 64 bit addend. */
|
|||
|
/* FIXME: Not handled correctly. */
|
|||
|
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 */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* Get the highest value of a 64 bit addend. */
|
|||
|
/* FIXME: Not handled correctly. */
|
|||
|
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 */
|
|||
|
0, /* src_mask */
|
|||
|
0xffff, /* 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 */
|
|||
|
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 */
|
|||
|
true, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0x0000ffff, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
/* I'm not sure what the remaining relocs are, but they are defined
|
|||
|
on Irix 6. */
|
|||
|
|
|||
|
HOWTO (R_MIPS_SCN_DISP, /* 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_SCN_DISP", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
HOWTO (R_MIPS_REL16, /* 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_REL16", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* dst_mask */
|
|||
|
false), /* pcrel_offset */
|
|||
|
|
|||
|
HOWTO (R_MIPS_ADD_IMMEDIATE, /* 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_ADD_IMMEDIATE", /* name */
|
|||
|
false, /* partial_inplace */
|
|||
|
0, /* src_mask */
|
|||
|
0, /* 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 = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
|
|||
|
dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
|
|||
|
dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
|
|||
|
dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
|
|||
|
dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
|
|||
|
dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) 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 = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
|
|||
|
dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
|
|||
|
dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
|
|||
|
dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
|
|||
|
dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
|
|||
|
dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
|
|||
|
dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) 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;
|
|||
|
{
|
|||
|
bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
|
|||
|
bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
|
|||
|
bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
|
|||
|
bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
|
|||
|
bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
|
|||
|
bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) 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;
|
|||
|
{
|
|||
|
bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
|
|||
|
bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
|
|||
|
bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
|
|||
|
bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
|
|||
|
bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
|
|||
|
bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
|
|||
|
bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
|
|||
|
}
|
|||
|
|
|||
|
/* A mapping from BFD reloc types to MIPS ELF reloc types. */
|
|||
|
|
|||
|
struct elf_reloc_map
|
|||
|
{
|
|||
|
bfd_reloc_code_real_type bfd_reloc_val;
|
|||
|
enum mips_elf64_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_CTOR, R_MIPS_64 },
|
|||
|
{ BFD_RELOC_32_PCREL, R_MIPS_REL32 },
|
|||
|
{ BFD_RELOC_MIPS_JMP, R_MIPS_26 },
|
|||
|
{ BFD_RELOC_HI16_S, R_MIPS_HI16 },
|
|||
|
{ BFD_RELOC_LO16, R_MIPS_LO16 },
|
|||
|
{ BFD_RELOC_MIPS_GPREL, 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_MIPS_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 }
|
|||
|
};
|
|||
|
|
|||
|
/* Given a BFD reloc type, return a howto structure. */
|
|||
|
|
|||
|
static reloc_howto_type *
|
|||
|
mips_elf64_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)
|
|||
|
{
|
|||
|
int v;
|
|||
|
|
|||
|
v = (int) mips_reloc_map[i].elf_reloc_val;
|
|||
|
return &mips_elf64_howto_table_rel[v];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
/* 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;
|
|||
|
unsigned int count;
|
|||
|
unsigned int i;
|
|||
|
int entsize;
|
|||
|
reloc_howto_type *howto_table;
|
|||
|
|
|||
|
allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
|
|||
|
if (allocated == NULL)
|
|||
|
goto error_return;
|
|||
|
|
|||
|
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
|
|||
|
|| (bfd_read (allocated, 1, 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 mips_elf64_reloc_type type;
|
|||
|
|
|||
|
switch (ir)
|
|||
|
{
|
|||
|
default:
|
|||
|
abort ();
|
|||
|
case 0:
|
|||
|
type = (enum mips_elf64_reloc_type) rela.r_type;
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
type = (enum mips_elf64_reloc_type) rela.r_type2;
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
type = (enum mips_elf64_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)
|
|||
|
bfd *abfd;
|
|||
|
asection *asect;
|
|||
|
asymbol **symbols;
|
|||
|
{
|
|||
|
struct bfd_elf_section_data * const d = elf_section_data (asect);
|
|||
|
|
|||
|
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. */
|
|||
|
asect->relocation = ((arelent *)
|
|||
|
bfd_alloc (abfd,
|
|||
|
asect->reloc_count * 3 * sizeof (arelent)));
|
|||
|
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;
|
|||
|
{
|
|||
|
/* FIXME. */
|
|||
|
abort ();
|
|||
|
}
|
|||
|
|
|||
|
/* Handle a 64-bit MIPS ELF specific section. */
|
|||
|
|
|||
|
static boolean
|
|||
|
mips_elf64_section_from_shdr (abfd, hdr, name)
|
|||
|
bfd *abfd;
|
|||
|
Elf_Internal_Shdr *hdr;
|
|||
|
char *name;
|
|||
|
{
|
|||
|
if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/* 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),
|
|||
|
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
|
|||
|
};
|
|||
|
|
|||
|
#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"
|
|||
|
#define ELF_ARCH bfd_arch_mips
|
|||
|
#define ELF_MACHINE_CODE EM_MIPS
|
|||
|
#define ELF_MAXPAGESIZE 0x1000
|
|||
|
#define elf_backend_size_info mips_elf64_size_info
|
|||
|
#define elf_backend_section_from_shdr mips_elf64_section_from_shdr
|
|||
|
#define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
|
|||
|
|
|||
|
#include "elf64-target.h"
|