06f44071cc
Move setting of OSABI to final_write_processing, after symbols are written. This allows OSABI to be set based on symbols actually written to the output rather than assuming input symbols will be output. Corrects object files such as the one generated on powerpc64le-linux by ld-powerpc/pr23927.s which has a local STT_GNU_IFUNC symbol but prior to this patch the file was marked ELFOSABI_NONE. * elf-bfd.h (enum elf_gnu_osabi): Rename from elf_gnu_symbols. Remove none, any, all enums. (struct elf_obj_tdata): Rename has_gnu_symbols field to has_gnu_osabi. (_bfd_elf_final_write_processing): Declare. * elf.c (_bfd_elf_write_object_contents): Unconditionally call elf_backend_final_write_processing. (_bfd_elf_post_process_headers): Move body of function to.. (_bfd_elf_final_write_processing): ..here, but set EI_OSABI byte only when not already set. Adjust for rename. * elfxx-target.h (elf_backend_final_write_processing): Default to _bfd_elf_final_write_processing. * elf-hppa.h (elf_hppa_final_write_processing): Call _bfd_elf_final_write_processing. * elf-m10300.c (_bfd_mn10300_elf_final_write_processing): Likewise. * elf-nacl.c (nacl_final_write_processing): Likewise. * elf-vxworks.c (elf_vxworks_final_write_processing): Likewise. * elf32-arc.c (arc_elf_final_write_processing): Likewise. * elf32-avr.c (bfd_elf_avr_final_write_processing): Likewise. * elf32-bfin.c (elf32_bfin_final_write_processing): Likewise. * elf32-cr16.c (_bfd_cr16_elf_final_write_processing): Likewise. * elf32-cris.c (cris_elf_final_write_processing): Likewise. * elf32-h8300.c (elf32_h8_final_write_processing): Likewise. * elf32-lm32.c (lm32_elf_final_write_processing): Likewise. * elf32-m32r.c (m32r_elf_final_write_processing): Likewise. * elf32-m68k.c (elf_m68k_final_write_processing): Likewise. * elf32-msp430.c (bfd_elf_msp430_final_write_processing): Likewise. * elf32-nds32.c (nds32_elf_final_write_processing): Likewise. * elf32-or1k.c (or1k_elf_final_write_processing): Likewise. * elf32-pj.c (pj_elf_final_write_processing): Likewise. * elf32-v850.c (v850_elf_final_write_processing): Likewise. * elf32-xc16x.c (elf32_xc16x_final_write_processing): Likewise. * elf32-xtensa.c (elf_xtensa_final_write_processing): Likewise. * elf64-ia64-vms.c (elf64_vms_final_write_processing): Likewise. * elfnn-ia64.c (elfNN_ia64_final_write_processing): Likewise. * elf32-arm.c (arm_final_write_processing): Split out from.. (elf32_arm_final_write_processing): ..here. Call _bfd_elf_final_write_processing. (elf32_arm_nacl_final_write_processing): Adjust. * elfxx-mips.c (_bfd_mips_final_write_processing): Split out from.. (_bfd_mips_elf_final_write_processing): ..here. Call _bfd_elf_final_write_processing. * elfxx-mips.h (_bfd_mips_final_write_processing): Declare. * elf32-mips.c (mips_vxworks_final_write_processing): Adjust. * elf32-ppc.c (ppc_final_write_processing): Split out from.. (ppc_elf_final_write_processing): ..here. Call _bfd_elf_final_write_processing. (ppc_elf_vxworks_final_write_processing): Adjust. * elf32-sparc.c (sparc_final_write_processing): Split out from.. (elf32_sparc_final_write_processing): ..here. Call _bfd_elf_final_write_processing. (elf32_sparc_vxworks_final_write_processing): Adjust. * elf32-d10v.c (elf_backend_final_write_processing): Don't define. * elf32-d30v.c (elf_backend_final_write_processing): Don't define. * elf32-m68hc11.c (elf_backend_final_write_processing): Don't define. * elf32-m68hc12.c (elf_backend_final_write_processing): Don't define. * elf32-s12z.c (elf_backend_final_write_processing): Don't define. * elf32-i386.c (elf_i386_check_relocs): Don't set has_gnu_symbols. * elf64-x86-64.c (elf_x86_64_check_relocs): Likewise. * elflink.c (elf_link_add_object_symbols): Likewise. (elf_link_output_symstrtab): Set has_gnu_osabi for symbols here instead.
566 lines
17 KiB
C
566 lines
17 KiB
C
/* D30V-specific support for 32-bit ELF
|
|
Copyright (C) 1997-2019 Free Software Foundation, Inc.
|
|
Contributed by Martin Hunt (hunt@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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
#include "sysdep.h"
|
|
#include "bfd.h"
|
|
#include "libbfd.h"
|
|
#include "elf-bfd.h"
|
|
#include "elf/d30v.h"
|
|
|
|
#define MAX32 ((bfd_signed_vma) 0x7fffffff)
|
|
#define MIN32 (- MAX32 - 1)
|
|
|
|
static bfd_reloc_status_type
|
|
bfd_elf_d30v_reloc (bfd *abfd,
|
|
arelent *reloc_entry,
|
|
asymbol *symbol,
|
|
void * data,
|
|
asection *input_section,
|
|
bfd *output_bfd,
|
|
char **error_message)
|
|
{
|
|
bfd_signed_vma relocation;
|
|
bfd_vma in1, in2, num;
|
|
bfd_vma tmp_addr = 0;
|
|
bfd_reloc_status_type r;
|
|
asection *reloc_target_output_section;
|
|
bfd_size_type addr = reloc_entry->address;
|
|
bfd_reloc_status_type flag = bfd_reloc_ok;
|
|
bfd_vma output_base = 0;
|
|
reloc_howto_type *howto = reloc_entry->howto;
|
|
int make_absolute = 0;
|
|
|
|
if (output_bfd != NULL)
|
|
{
|
|
/* Partial linking -- do nothing. */
|
|
reloc_entry->address += input_section->output_offset;
|
|
return bfd_reloc_ok;
|
|
}
|
|
|
|
r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
|
|
input_section, output_bfd, error_message);
|
|
if (r != bfd_reloc_continue)
|
|
return r;
|
|
|
|
/* A hacked-up version of bfd_perform_reloc() follows. */
|
|
if (bfd_is_und_section (symbol->section)
|
|
&& (symbol->flags & BSF_WEAK) == 0
|
|
&& output_bfd == NULL)
|
|
flag = bfd_reloc_undefined;
|
|
|
|
/* Is the address of the relocation really within the section? */
|
|
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
|
|
return bfd_reloc_outofrange;
|
|
|
|
/* Work out which section the relocation is targeted 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;
|
|
|
|
reloc_target_output_section = symbol->section->output_section;
|
|
|
|
/* Convert input-section-relative symbol value to absolute. */
|
|
output_base = reloc_target_output_section->vma;
|
|
relocation += output_base + symbol->section->output_offset;
|
|
|
|
/* Add in supplied addend. */
|
|
relocation += reloc_entry->addend;
|
|
|
|
/* Here the variable relocation holds the final address of the
|
|
symbol we are relocating against, plus any addend. */
|
|
if (howto->pc_relative)
|
|
{
|
|
tmp_addr = input_section->output_section->vma
|
|
+ input_section->output_offset
|
|
+ reloc_entry->address;
|
|
relocation -= tmp_addr;
|
|
}
|
|
|
|
in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
|
|
in2 = bfd_get_32 (abfd, (bfd_byte *) data + addr + 4);
|
|
|
|
/* Extract the addend. */
|
|
num = ((in2 & 0x3FFFF)
|
|
| ((in2 & 0xFF00000) >> 2)
|
|
| ((in1 & 0x3F) << 26));
|
|
in1 &= 0xFFFFFFC0;
|
|
in2 = 0x80000000;
|
|
|
|
relocation += num;
|
|
|
|
if (howto->pc_relative && howto->bitsize == 32)
|
|
{
|
|
/* The D30V has a PC that doesn't wrap and PC-relative jumps are
|
|
signed, so a PC-relative jump can't be more than +/- 2^31 bytes.
|
|
If one exceeds this, change it to an absolute jump. */
|
|
if (relocation > MAX32 || relocation < MIN32)
|
|
{
|
|
relocation = (relocation + tmp_addr) & 0xffffffff;
|
|
make_absolute = 1;
|
|
}
|
|
}
|
|
|
|
in1 |= (relocation >> 26) & 0x3F; /* Top 6 bits. */
|
|
in2 |= ((relocation & 0x03FC0000) << 2); /* Next 8 bits. */
|
|
in2 |= relocation & 0x0003FFFF; /* Bottom 18 bits. */
|
|
|
|
/* Change a PC-relative instruction to its
|
|
absolute equivalent with this simple hack. */
|
|
if (make_absolute)
|
|
in1 |= 0x00100000;
|
|
|
|
bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
|
|
bfd_put_32 (abfd, in2, (bfd_byte *) data + addr + 4);
|
|
|
|
return flag;
|
|
}
|
|
|
|
static bfd_reloc_status_type
|
|
bfd_elf_d30v_reloc_21 (bfd *abfd,
|
|
arelent *reloc_entry,
|
|
asymbol *symbol,
|
|
void * data,
|
|
asection *input_section,
|
|
bfd *output_bfd,
|
|
char **error_message)
|
|
{
|
|
bfd_vma relocation;
|
|
bfd_vma in1, num;
|
|
bfd_reloc_status_type r;
|
|
asection *reloc_target_output_section;
|
|
bfd_size_type addr = reloc_entry->address;
|
|
bfd_reloc_status_type flag = bfd_reloc_ok;
|
|
bfd_vma output_base = 0;
|
|
reloc_howto_type *howto = reloc_entry->howto;
|
|
int mask, max;
|
|
|
|
if (output_bfd != NULL)
|
|
{
|
|
/* Partial linking -- do nothing. */
|
|
reloc_entry->address += input_section->output_offset;
|
|
return bfd_reloc_ok;
|
|
}
|
|
|
|
r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
|
|
input_section, output_bfd, error_message);
|
|
if (r != bfd_reloc_continue)
|
|
return r;
|
|
|
|
/* A hacked-up version of bfd_perform_reloc() follows. */
|
|
if (bfd_is_und_section (symbol->section)
|
|
&& (symbol->flags & BSF_WEAK) == 0
|
|
&& output_bfd == NULL)
|
|
flag = bfd_reloc_undefined;
|
|
|
|
/* Is the address of the relocation really within the section? */
|
|
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
|
|
return bfd_reloc_outofrange;
|
|
|
|
/* Work out which section the relocation is targeted 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;
|
|
|
|
reloc_target_output_section = symbol->section->output_section;
|
|
|
|
/* Convert input-section-relative symbol value to absolute. */
|
|
output_base = reloc_target_output_section->vma;
|
|
relocation += output_base + symbol->section->output_offset;
|
|
|
|
/* Add in supplied addend. */
|
|
relocation += reloc_entry->addend;
|
|
|
|
/* Here the variable relocation holds the final address of the
|
|
symbol we are relocating against, plus any addend. */
|
|
|
|
if (howto->pc_relative)
|
|
{
|
|
relocation -= (input_section->output_section->vma
|
|
+ input_section->output_offset);
|
|
if (howto->pcrel_offset)
|
|
relocation -= reloc_entry->address;
|
|
}
|
|
|
|
in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
|
|
|
|
mask = (1 << howto->bitsize) - 1;
|
|
if (howto->bitsize == 6)
|
|
mask <<= 12;
|
|
max = (1 << (howto->bitsize + 2)) - 1;
|
|
|
|
/* Extract the addend. */
|
|
num = in1 & mask; /* 18 bits. */
|
|
if (howto->bitsize == 6)
|
|
num >>= 12;
|
|
num <<= 3; /* shift left 3. */
|
|
in1 &= ~mask; /* Mask out addend. */
|
|
|
|
relocation += num;
|
|
if (howto->type == R_D30V_21_PCREL_R
|
|
|| howto->type == R_D30V_15_PCREL_R
|
|
|| howto->type == R_D30V_9_PCREL_R)
|
|
relocation += 4;
|
|
|
|
if ((int) relocation < 0)
|
|
{
|
|
if (~ (int) relocation > max)
|
|
flag = bfd_reloc_overflow;
|
|
}
|
|
else
|
|
{
|
|
if ((int) relocation > max)
|
|
flag = bfd_reloc_overflow;
|
|
}
|
|
|
|
relocation >>= 3;
|
|
if (howto->bitsize == 6)
|
|
in1 |= ((relocation & (mask >> 12)) << 12);
|
|
else
|
|
in1 |= relocation & mask;
|
|
|
|
bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
|
|
|
|
return flag;
|
|
}
|
|
|
|
static reloc_howto_type elf_d30v_howto_table[] =
|
|
{
|
|
/* This reloc does nothing. */
|
|
HOWTO (R_D30V_NONE, /* Type. */
|
|
0, /* Rightshift. */
|
|
3, /* 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_D30V_NONE", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0, /* Src_mask. */
|
|
0, /* Dst_mask. */
|
|
FALSE), /* PCrel_offset. */
|
|
|
|
/* A 6 bit absolute relocation. */
|
|
HOWTO (R_D30V_6, /* Type. */
|
|
0, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
6, /* Bitsize. */
|
|
FALSE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_bitfield, /* Complain_on_overflow. */
|
|
bfd_elf_generic_reloc, /* Special_function. */
|
|
"R_D30V_6", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0x3f, /* Src_mask. */
|
|
0x3f, /* Dst_mask. */
|
|
FALSE), /* PCrel_offset. */
|
|
|
|
/* A relative 9 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_9_PCREL, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
6, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc_21, /* Special_function. */
|
|
"R_D30V_9_PCREL", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0x3f, /* Src_mask. */
|
|
0x3f, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* A relative 9 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_9_PCREL_R, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
6, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc_21, /* Special_function. */
|
|
"R_D30V_9_PCREL_R", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0x3f, /* Src_mask. */
|
|
0x3f, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* An absolute 15 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_15, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
12, /* Bitsize. */
|
|
FALSE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_generic_reloc, /* Special_function. */
|
|
"R_D30V_15", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0xfff, /* Src_mask. */
|
|
0xfff, /* Dst_mask. */
|
|
FALSE), /* PCrel_offset. */
|
|
|
|
/* A relative 15 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_15_PCREL, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
12, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc_21, /* Special_function. */
|
|
"R_D30V_15_PCREL", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0xfff, /* Src_mask. */
|
|
0xfff, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* A relative 15 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_15_PCREL_R, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
12, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc_21, /* Special_function. */
|
|
"R_D30V_15_PCREL_R", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0xfff, /* Src_mask. */
|
|
0xfff, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* An absolute 21 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_21, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
18, /* Bitsize. */
|
|
FALSE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_generic_reloc, /* Special_function. */
|
|
"R_D30V_21", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0x3ffff, /* Src_mask. */
|
|
0x3ffff, /* Dst_mask. */
|
|
FALSE), /* PCrel_offset. */
|
|
|
|
/* A relative 21 bit relocation, right shifted by 3. */
|
|
HOWTO (R_D30V_21_PCREL, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
18, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc_21, /* Special_function. */
|
|
"R_D30V_21_PCREL", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0x3ffff, /* Src_mask. */
|
|
0x3ffff, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* A relative 21 bit relocation, right shifted by 3, in the Right container. */
|
|
HOWTO (R_D30V_21_PCREL_R, /* Type. */
|
|
3, /* Rightshift. */
|
|
2, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
18, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc_21, /* Special_function. */
|
|
"R_D30V_21_PCREL_R", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0x3ffff, /* Src_mask. */
|
|
0x3ffff, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* A D30V 32 bit absolute relocation. */
|
|
HOWTO (R_D30V_32, /* Type. */
|
|
0, /* Rightshift. */
|
|
4, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
32, /* Bitsize. */
|
|
FALSE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_bitfield, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc, /* Special_function. */
|
|
"R_D30V_32", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0xffffffff, /* Src_mask. */
|
|
0xffffffff, /* Dst_mask. */
|
|
FALSE), /* PCrel_offset. */
|
|
|
|
/* A relative 32 bit relocation. */
|
|
HOWTO (R_D30V_32_PCREL, /* Type. */
|
|
0, /* Rightshift. */
|
|
4, /* Size (0 = byte, 1 = short, 2 = long). */
|
|
32, /* Bitsize. */
|
|
TRUE, /* PC_relative. */
|
|
0, /* Bitpos. */
|
|
complain_overflow_signed, /* Complain_on_overflow. */
|
|
bfd_elf_d30v_reloc, /* Special_function. */
|
|
"R_D30V_32_PCREL", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0xffffffff, /* Src_mask. */
|
|
0xffffffff, /* Dst_mask. */
|
|
TRUE), /* PCrel_offset. */
|
|
|
|
/* A regular 32 bit absolute relocation. */
|
|
HOWTO (R_D30V_32_NORMAL, /* 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_D30V_32_NORMAL", /* Name. */
|
|
FALSE, /* Partial_inplace. */
|
|
0xffffffff, /* Src_mask. */
|
|
0xffffffff, /* Dst_mask. */
|
|
FALSE), /* PCrel_offset. */
|
|
|
|
};
|
|
|
|
/* Map BFD reloc types to D30V ELF reloc types. */
|
|
|
|
struct d30v_reloc_map
|
|
{
|
|
bfd_reloc_code_real_type bfd_reloc_val;
|
|
unsigned char elf_reloc_val;
|
|
};
|
|
|
|
static const struct d30v_reloc_map d30v_reloc_map[] =
|
|
{
|
|
{ BFD_RELOC_NONE, R_D30V_NONE, },
|
|
{ BFD_RELOC_D30V_6, R_D30V_6 },
|
|
{ BFD_RELOC_D30V_9_PCREL, R_D30V_9_PCREL },
|
|
{ BFD_RELOC_D30V_9_PCREL_R, R_D30V_9_PCREL_R },
|
|
{ BFD_RELOC_D30V_15, R_D30V_15 },
|
|
{ BFD_RELOC_D30V_15_PCREL, R_D30V_15_PCREL },
|
|
{ BFD_RELOC_D30V_15_PCREL_R, R_D30V_15_PCREL_R },
|
|
{ BFD_RELOC_D30V_21, R_D30V_21 },
|
|
{ BFD_RELOC_D30V_21_PCREL, R_D30V_21_PCREL },
|
|
{ BFD_RELOC_D30V_21_PCREL_R, R_D30V_21_PCREL_R },
|
|
{ BFD_RELOC_D30V_32, R_D30V_32 },
|
|
{ BFD_RELOC_D30V_32_PCREL, R_D30V_32_PCREL },
|
|
{ BFD_RELOC_32, R_D30V_32_NORMAL },
|
|
};
|
|
|
|
static reloc_howto_type *
|
|
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|
bfd_reloc_code_real_type code)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0;
|
|
i < sizeof (d30v_reloc_map) / sizeof (struct d30v_reloc_map);
|
|
i++)
|
|
{
|
|
if (d30v_reloc_map[i].bfd_reloc_val == code)
|
|
return &elf_d30v_howto_table[d30v_reloc_map[i].elf_reloc_val];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static reloc_howto_type *
|
|
bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|
const char *r_name)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0;
|
|
i < sizeof (elf_d30v_howto_table) / sizeof (elf_d30v_howto_table[0]);
|
|
i++)
|
|
if (elf_d30v_howto_table[i].name != NULL
|
|
&& strcasecmp (elf_d30v_howto_table[i].name, r_name) == 0)
|
|
return &elf_d30v_howto_table[i];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Set the howto pointer for an D30V ELF reloc (type REL). */
|
|
|
|
static bfd_boolean
|
|
d30v_info_to_howto_rel (bfd *abfd,
|
|
arelent *cache_ptr,
|
|
Elf_Internal_Rela *dst)
|
|
{
|
|
unsigned int r_type;
|
|
|
|
r_type = ELF32_R_TYPE (dst->r_info);
|
|
if (r_type >= (unsigned int) R_D30V_max)
|
|
{
|
|
/* xgettext:c-format */
|
|
_bfd_error_handler (_("%pB: unsupported relocation type %#x"),
|
|
abfd, r_type);
|
|
bfd_set_error (bfd_error_bad_value);
|
|
return FALSE;
|
|
}
|
|
cache_ptr->howto = &elf_d30v_howto_table[r_type];
|
|
return TRUE;
|
|
}
|
|
|
|
/* Set the howto pointer for an D30V ELF reloc (type RELA). */
|
|
|
|
static bfd_boolean
|
|
d30v_info_to_howto_rela (bfd *abfd,
|
|
arelent *cache_ptr,
|
|
Elf_Internal_Rela *dst)
|
|
{
|
|
unsigned int r_type;
|
|
|
|
r_type = ELF32_R_TYPE (dst->r_info);
|
|
if (r_type >= (unsigned int) R_D30V_max)
|
|
{
|
|
/* xgettext:c-format */
|
|
_bfd_error_handler (_("%pB: unsupported relocation type %#x"),
|
|
abfd, r_type);
|
|
bfd_set_error (bfd_error_bad_value);
|
|
return FALSE;
|
|
}
|
|
cache_ptr->howto = &elf_d30v_howto_table[r_type];
|
|
return TRUE;
|
|
}
|
|
|
|
#define ELF_ARCH bfd_arch_d30v
|
|
#define ELF_MACHINE_CODE EM_D30V
|
|
#define ELF_MACHINE_ALT1 EM_CYGNUS_D30V
|
|
#define ELF_MAXPAGESIZE 0x1000
|
|
|
|
#define TARGET_BIG_SYM d30v_elf32_vec
|
|
#define TARGET_BIG_NAME "elf32-d30v"
|
|
|
|
#define elf_info_to_howto d30v_info_to_howto_rela
|
|
#define elf_info_to_howto_rel d30v_info_to_howto_rel
|
|
#define elf_backend_object_p 0
|
|
|
|
#include "elf32-target.h"
|