Line 1... |
Line 1... |
/* OR32-specific support for 32-bit ELF
|
/* OR32-specific support for 32-bit ELF
|
Copyright 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
|
Copyright 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
|
|
Copyright (C) 2010 Embecosm Limited
|
Contributed by Ivan Guzvinec <ivang@opencores.org>
|
Contributed by Ivan Guzvinec <ivang@opencores.org>
|
Modified by Gyorgy Jeney <nog@sdf.lonestar.org> and
|
Modified by Gyorgy Jeney <nog@sdf.lonestar.org> and
|
Balint Cristian <rezso@rdsor.ro>
|
Balint Cristian <rezso@rdsor.ro>
|
|
Changed from Rel to Rela by Joern Rennecke <joern.rennecke@embecosm.com>.
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
Line 27... |
Line 29... |
#include "elf-bfd.h"
|
#include "elf-bfd.h"
|
#include "elf/or32.h"
|
#include "elf/or32.h"
|
#include "elf/common.h"
|
#include "elf/common.h"
|
#include "libiberty.h"
|
#include "libiberty.h"
|
|
|
|
/* We need RELA in order to handle highpart relocations independent of
|
|
the presence and/or location and/or value of a lowpart relocation. */
|
|
#if 0
|
/* Try to minimize the amount of space occupied by relocation tables
|
/* Try to minimize the amount of space occupied by relocation tables
|
on the ROM (not that the ROM won't be swamped by other ELF overhead). */
|
on the ROM (not that the ROM won't be swamped by other ELF overhead). */
|
#define USE_REL 1
|
#define USE_REL 1
|
|
#endif
|
|
|
/* Set the right machine number for an OR32 ELF file. */
|
/* Set the right machine number for an OR32 ELF file. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
or32_elf_object_p (bfd *abfd)
|
or32_elf_object_p (bfd *abfd)
|
Line 57... |
Line 63... |
(*_bfd_error_handler) (_("%B: failed to ensure that reloc sections aren't outside file"), abfd);
|
(*_bfd_error_handler) (_("%B: failed to ensure that reloc sections aren't outside file"), abfd);
|
|
|
elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
|
elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
|
}
|
}
|
|
|
|
#if 0 /* Not needed for RELA. */
|
static bfd_reloc_status_type
|
static bfd_reloc_status_type
|
or32_elf_generic_reloc (bfd *abfd,
|
or32_elf_generic_reloc (bfd *abfd,
|
arelent *reloc_entry,
|
arelent *reloc_entry,
|
asymbol *symbol,
|
asymbol *symbol,
|
void * data,
|
void * data,
|
Line 218... |
Line 225... |
}
|
}
|
return or32_elf_generic_reloc (abfd, reloc_entry, symbol, data,
|
return or32_elf_generic_reloc (abfd, reloc_entry, symbol, data,
|
input_section, output_bfd,
|
input_section, output_bfd,
|
error_message);
|
error_message);
|
}
|
}
|
|
#endif
|
|
|
|
|
static reloc_howto_type elf_or32_howto_table[] =
|
static reloc_howto_type elf_or32_howto_table[] =
|
{
|
{
|
/* This reloc does nothing. */
|
/* This reloc does nothing. */
|
Line 247... |
Line 255... |
FALSE, /* pc_relative */
|
FALSE, /* pc_relative */
|
0, /* bitpos */
|
0, /* bitpos */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
bfd_elf_generic_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
"R_OR32_32", /* name */
|
"R_OR32_32", /* name */
|
TRUE, /* partial_inplace */
|
FALSE, /* partial_inplace */
|
0xffffffff, /* src_mask */
|
0, /* src_mask */
|
0xffffffff, /* dst_mask */
|
0xffffffff, /* dst_mask */
|
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
|
|
/* A standard 16 bit relocation. */
|
/* A standard 16 bit relocation. */
|
HOWTO (R_OR32_16, /* type */
|
HOWTO (R_OR32_16, /* type */
|
Line 262... |
Line 270... |
FALSE, /* pc_relative */
|
FALSE, /* pc_relative */
|
0, /* bitpos */
|
0, /* bitpos */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
bfd_elf_generic_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
"R_OR32_16", /* name */
|
"R_OR32_16", /* name */
|
TRUE, /* partial_inplace */
|
FALSE, /* partial_inplace */
|
0x0000ffff, /* src_mask */
|
0, /* src_mask */
|
0x0000ffff, /* dst_mask */
|
0x0000ffff, /* dst_mask */
|
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
|
|
/* A standard 8 bit relocation. */
|
/* A standard 8 bit relocation. */
|
HOWTO (R_OR32_8, /* type */
|
HOWTO (R_OR32_8, /* type */
|
Line 277... |
Line 285... |
FALSE, /* pc_relative */
|
FALSE, /* pc_relative */
|
0, /* bitpos */
|
0, /* bitpos */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
bfd_elf_generic_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
"R_OR32_8", /* name */
|
"R_OR32_8", /* name */
|
TRUE, /* partial_inplace */
|
FALSE, /* partial_inplace */
|
0x000000ff, /* src_mask */
|
0, /* src_mask */
|
0x000000ff, /* dst_mask */
|
0x000000ff, /* dst_mask */
|
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
|
|
/* A standard low 16 bit relocation. */
|
/* A standard low 16 bit relocation. */
|
HOWTO (R_OR32_CONST, /* type */
|
HOWTO (R_OR32_CONST, /* type */
|
Line 290... |
Line 298... |
2, /* size (0 = byte, 1 = short, 2 = long) */
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
16, /* bitsize */
|
16, /* bitsize */
|
FALSE, /* pc_relative */
|
FALSE, /* pc_relative */
|
0, /* bitpos */
|
0, /* bitpos */
|
complain_overflow_dont, /* complain_on_overflow */
|
complain_overflow_dont, /* complain_on_overflow */
|
or32_elf_const_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
"R_OR32_CONST", /* name */
|
"R_OR32_CONST", /* name */
|
TRUE, /* partial_inplace */
|
FALSE, /* partial_inplace */
|
0x0000ffff, /* src_mask */
|
0, /* src_mask */
|
0x0000ffff, /* dst_mask */
|
0x0000ffff, /* dst_mask */
|
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
|
|
/* A standard high 16 bit relocation. */
|
/* A standard high 16 bit relocation. */
|
HOWTO (R_OR32_CONSTH, /* type */
|
HOWTO (R_OR32_CONSTH, /* type */
|
Line 305... |
Line 313... |
2, /* size (0 = byte, 1 = short, 2 = long) */
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
16, /* bitsize */
|
16, /* bitsize */
|
FALSE, /* pc_relative */
|
FALSE, /* pc_relative */
|
0, /* bitpos */
|
0, /* bitpos */
|
complain_overflow_dont, /* complain_on_overflow */
|
complain_overflow_dont, /* complain_on_overflow */
|
or32_elf_consth_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
"R_OR32_CONSTH", /* name */
|
"R_OR32_CONSTH", /* name */
|
TRUE, /* partial_inplace */
|
FALSE, /* partial_inplace */
|
0x0000ffff, /* src_mask */
|
0, /* src_mask */
|
0x0000ffff, /* dst_mask */
|
0x0000ffff, /* dst_mask */
|
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
|
|
/* A standard branch relocation. */
|
/* A standard branch relocation. */
|
HOWTO (R_OR32_JUMPTARG, /* type */
|
HOWTO (R_OR32_JUMPTARG, /* type */
|
Line 320... |
Line 328... |
2, /* size (0 = byte, 1 = short, 2 = long) */
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
28, /* bitsize */
|
28, /* bitsize */
|
TRUE, /* pc_relative */
|
TRUE, /* pc_relative */
|
0, /* bitpos */
|
0, /* bitpos */
|
complain_overflow_dont, /* complain_on_overflow */
|
complain_overflow_dont, /* complain_on_overflow */
|
or32_elf_generic_reloc,/* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
"R_OR32_JUMPTARG", /* name */
|
"R_OR32_JUMPTARG", /* name */
|
TRUE, /* partial_inplace */
|
FALSE, /* partial_inplace */
|
0x03ffffff, /* src_mask */
|
0, /* src_mask */
|
0x03ffffff, /* dst_mask */
|
0x03ffffff, /* dst_mask */
|
TRUE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
|
|
/* GNU extension to record C++ vtable hierarchy. */
|
/* GNU extension to record C++ vtable hierarchy. */
|
HOWTO (R_OR32_GNU_VTINHERIT, /* type */
|
HOWTO (R_OR32_GNU_VTINHERIT, /* type */
|
0, /* rightshift */
|
0, /* rightshift */
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
Line 358... |
Line 366... |
0, /* src_mask */
|
0, /* src_mask */
|
0, /* dst_mask */
|
0, /* dst_mask */
|
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
};
|
};
|
|
|
|
static bfd_boolean
|
|
or32_relocate_section (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 = &elf_tdata (input_bfd)->symtab_hdr;
|
|
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
|
|
Elf_Internal_Rela *rel= rel = relocs;
|
|
Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
|
|
|
|
for (; rel < relend; rel++)
|
|
{
|
|
int r_type = ELF32_R_TYPE (rel->r_info);
|
|
reloc_howto_type *howto;
|
|
unsigned long r_symndx;
|
|
struct elf_link_hash_entry *h = NULL;
|
|
Elf_Internal_Sym *sym = NULL;
|
|
asection *sec = NULL;
|
|
bfd_vma relocation = 0;
|
|
bfd_reloc_status_type r;
|
|
const char *name = NULL;
|
|
|
|
if ((unsigned) r_type >= ARRAY_SIZE (elf_or32_howto_table))
|
|
{
|
|
bfd_set_error (bfd_error_bad_value);
|
|
return FALSE;
|
|
}
|
|
|
|
if (r_type == R_OR32_GNU_VTENTRY
|
|
|| r_type == R_OR32_GNU_VTINHERIT)
|
|
continue;
|
|
|
|
howto = &elf_or32_howto_table[r_type];
|
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
|
|
|
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);
|
|
|
|
name = bfd_elf_string_from_elf_section
|
|
(input_bfd, symtab_hdr->sh_link, sym->st_name);
|
|
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
|
|
}
|
|
else
|
|
{
|
|
bfd_boolean unresolved_reloc, warned;
|
|
|
|
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
|
|
r_symndx, symtab_hdr, sym_hashes,
|
|
h, sec, relocation,
|
|
unresolved_reloc, warned);
|
|
}
|
|
|
|
if (sec != NULL && elf_discarded_section (sec))
|
|
{
|
|
/* For relocs against symbols from removed linkonce sections,
|
|
or sections discarded by a linker script, we just want the
|
|
section contents zeroed. Avoid any special processing. */
|
|
_bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
|
|
rel->r_info = 0;
|
|
rel->r_addend = 0;
|
|
continue;
|
|
}
|
|
|
|
if (info->relocatable)
|
|
continue;
|
|
|
|
r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
|
|
rel->r_offset, relocation, rel->r_addend);
|
|
if (r != bfd_reloc_ok)
|
|
{
|
|
const char *msg = NULL;
|
|
|
|
switch (r)
|
|
{
|
|
/* FIXME: give useful messages for possible errors. */
|
|
default:
|
|
msg = _("internal error: unknown error");
|
|
break;
|
|
}
|
|
if (msg)
|
|
r = info->callbacks->warning
|
|
(info, msg, name, input_bfd, input_section, rel->r_offset);
|
|
|
|
if (!r)
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
/* Map BFD reloc types to OR32 ELF reloc types. */
|
/* Map BFD reloc types to OR32 ELF reloc types. */
|
|
|
struct or32_reloc_map
|
struct or32_reloc_map
|
{
|
{
|
bfd_reloc_code_real_type bfd_reloc_val;
|
bfd_reloc_code_real_type bfd_reloc_val;
|
Line 440... |
Line 546... |
#define elf_info_to_howto 0
|
#define elf_info_to_howto 0
|
#define elf_info_to_howto_rel or32_info_to_howto_rel
|
#define elf_info_to_howto_rel or32_info_to_howto_rel
|
#define elf_backend_object_p or32_elf_object_p
|
#define elf_backend_object_p or32_elf_object_p
|
#define elf_backend_final_write_processing \
|
#define elf_backend_final_write_processing \
|
or32_elf_final_write_processing
|
or32_elf_final_write_processing
|
|
#define elf_backend_rela_normal 1
|
|
#define elf_backend_relocate_section or32_relocate_section
|
|
|
#include "elf32-target.h"
|
#include "elf32-target.h"
|
|
|
No newline at end of file
|
No newline at end of file
|