/* ADI Blackfin BFD support for 32-bit ELF.
- Copyright 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/bfin.h"
-#include "elf/dwarf2.h"
+#include "dwarf2.h"
#include "hashtab.h"
/* FUNCTION : bfin_pltpc_reloc
static reloc_howto_type bfin_howto_table [] =
{
/* This reloc does nothing. . */
- HOWTO (R_unused0, /* type. */
+ HOWTO (R_BFIN_UNUSED0, /* type. */
0, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
32, /* bitsize. */
0, /* bitpos. */
complain_overflow_bitfield, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
- "R_unused0", /* name. */
+ "R_BFIN_UNUSED0", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_pcrel5m2, /* type. */
+ HOWTO (R_BFIN_PCREL5M2, /* type. */
1, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long).. */
4, /* bitsize. */
0, /* bitpos. */
complain_overflow_unsigned, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_pcrel5m2", /* name. */
+ "R_BFIN_PCREL5M2", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x0000000F, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_unused1, /* type. */
+ HOWTO (R_BFIN_UNUSED1, /* type. */
0, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
32, /* bitsize. */
0, /* bitpos. */
complain_overflow_bitfield, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
- "R_unused1", /* name. */
+ "R_BFIN_UNUSED1", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_pcrel10, /* type. */
+ HOWTO (R_BFIN_PCREL10, /* type. */
1, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
10, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_pcrel10", /* name. */
+ "R_BFIN_PCREL10", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x000003FF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_pcrel12_jump, /* type. */
+ HOWTO (R_BFIN_PCREL12_JUMP, /* type. */
1, /* rightshift. */
/* the offset is actually 13 bit
aligned on a word boundary so
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_pcrel12_jump", /* name. */
+ "R_BFIN_PCREL12_JUMP", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x0FFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_rimm16, /* type. */
+ HOWTO (R_BFIN_RIMM16, /* type. */
0, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
16, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_imm16_reloc, /* special_function. */
- "R_rimm16", /* name. */
+ "R_BFIN_RIMM16", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_luimm16, /* type. */
+ HOWTO (R_BFIN_LUIMM16, /* type. */
0, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
16, /* bitsize. */
0, /* bitpos. */
complain_overflow_dont, /* complain_on_overflow. */
bfin_imm16_reloc, /* special_function. */
- "R_luimm16", /* name. */
+ "R_BFIN_LUIMM16", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_huimm16, /* type. */
+ HOWTO (R_BFIN_HUIMM16, /* type. */
16, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
16, /* bitsize. */
0, /* bitpos. */
complain_overflow_unsigned, /* complain_on_overflow. */
bfin_imm16_reloc, /* special_function. */
- "R_huimm16", /* name. */
+ "R_BFIN_HUIMM16", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_pcrel12_jump_s, /* type. */
+ HOWTO (R_BFIN_PCREL12_JUMP_S, /* type. */
1, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
12, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_pcrel12_jump_s", /* name. */
+ "R_BFIN_PCREL12_JUMP_S", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x00000FFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_pcrel24_jump_x, /* type. */
+ HOWTO (R_BFIN_PCREL24_JUMP_X, /* type. */
1, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
24, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_pcrel24_reloc, /* special_function. */
- "R_pcrel24_jump_x", /* name. */
+ "R_BFIN_PCREL24_JUMP_X", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_pcrel24, /* type. */
+ HOWTO (R_BFIN_PCREL24, /* type. */
1, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
24, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_pcrel24_reloc, /* special_function. */
- "R_pcrel24", /* name. */
+ "R_BFIN_PCREL24", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_unusedb, /* type. */
+ HOWTO (R_BFIN_UNUSEDB, /* type. */
0, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
32, /* bitsize. */
0, /* bitpos. */
complain_overflow_dont, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
- "R_unusedb", /* name. */
+ "R_BFIN_UNUSEDB", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_unusedc, /* type. */
+ HOWTO (R_BFIN_UNUSEDC, /* type. */
0, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
32, /* bitsize. */
0, /* bitpos. */
complain_overflow_dont, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
- "R_unusedc", /* name. */
+ "R_BFIN_UNUSEDC", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_pcrel24_jump_l, /* type. */
+ HOWTO (R_BFIN_PCREL24_JUMP_L, /* type. */
1, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
24, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_pcrel24_reloc, /* special_function. */
- "R_pcrel24_jump_l", /* name. */
+ "R_BFIN_PCREL24_JUMP_L", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_pcrel24_call_x, /* type. */
+ HOWTO (R_BFIN_PCREL24_CALL_X, /* type. */
1, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
24, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_pcrel24_reloc, /* special_function. */
- "R_pcrel24_call_x", /* name. */
+ "R_BFIN_PCREL24_CALL_X", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_var_eq_symb, /* type. */
+ HOWTO (R_BFIN_VAR_EQ_SYMB, /* type. */
0, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
32, /* bitsize. */
0, /* bitpos. */
complain_overflow_bitfield, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_var_eq_symb", /* name. */
+ "R_BFIN_VAR_EQ_SYMB", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_byte_data, /* type. */
+ HOWTO (R_BFIN_BYTE_DATA, /* type. */
0, /* rightshift. */
0, /* size (0 = byte, 1 = short, 2 = long). */
8, /* bitsize. */
0, /* bitpos. */
complain_overflow_unsigned, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_byte_data", /* name. */
+ "R_BFIN_BYTE_DATA", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0xFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_byte2_data, /* type. */
+ HOWTO (R_BFIN_BYTE2_DATA, /* type. */
0, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
16, /* bitsize. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_byte2_data", /* name. */
+ "R_BFIN_BYTE2_DATA", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0xFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_byte4_data, /* type. */
+ HOWTO (R_BFIN_BYTE4_DATA, /* type. */
0, /* rightshift. */
2, /* size (0 = byte, 1 = short, 2 = long). */
32, /* bitsize. */
0, /* bitpos. */
complain_overflow_unsigned, /* complain_on_overflow. */
bfin_byte4_reloc, /* special_function. */
- "R_byte4_data", /* name. */
+ "R_BFIN_BYTE4_DATA", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0xFFFFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
- HOWTO (R_pcrel11, /* type. */
+ HOWTO (R_BFIN_PCREL11, /* type. */
1, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
10, /* bitsize. */
0, /* bitpos. */
complain_overflow_unsigned, /* complain_on_overflow. */
bfin_bfd_reloc, /* special_function. */
- "R_pcrel11", /* name. */
+ "R_BFIN_PCREL11", /* name. */
FALSE, /* partial_inplace. */
0, /* src_mask. */
0x000003FF, /* dst_mask. */
static reloc_howto_type bfin_gnuext_howto_table [] =
{
- HOWTO (R_pltpc, /* type. */
+ HOWTO (R_BFIN_PLTPC, /* type. */
0, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
16, /* bitsize. */
0, /* bitpos. */
complain_overflow_bitfield, /* complain_on_overflow. */
bfin_pltpc_reloc, /* special_function. */
- "R_pltpc", /* name. */
+ "R_BFIN_PLTPC", /* name. */
FALSE, /* partial_inplace. */
0xffff, /* src_mask. */
0xffff, /* dst_mask. */
FALSE), /* pcrel_offset. */
- HOWTO (R_got, /* type. */
+ HOWTO (R_BFIN_GOT, /* type. */
0, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
16, /* bitsize. */
0, /* bitpos. */
complain_overflow_bitfield, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
- "R_got", /* name. */
+ "R_BFIN_GOT", /* name. */
FALSE, /* partial_inplace. */
0x7fff, /* src_mask. */
0x7fff, /* dst_mask. */
static const struct bfin_reloc_map bfin_reloc_map [] =
{
- { BFD_RELOC_NONE, R_unused0 },
- { BFD_RELOC_BFIN_5_PCREL, R_pcrel5m2 },
- { BFD_RELOC_NONE, R_unused1 },
- { BFD_RELOC_BFIN_10_PCREL, R_pcrel10 },
- { BFD_RELOC_BFIN_12_PCREL_JUMP, R_pcrel12_jump },
- { BFD_RELOC_BFIN_16_IMM, R_rimm16 },
- { BFD_RELOC_BFIN_16_LOW, R_luimm16 },
- { BFD_RELOC_BFIN_16_HIGH, R_huimm16 },
- { BFD_RELOC_BFIN_12_PCREL_JUMP_S, R_pcrel12_jump_s },
- { BFD_RELOC_24_PCREL, R_pcrel24 },
- { BFD_RELOC_24_PCREL, R_pcrel24 },
- { BFD_RELOC_BFIN_24_PCREL_JUMP_L, R_pcrel24_jump_l },
- { BFD_RELOC_NONE, R_unusedb },
- { BFD_RELOC_NONE, R_unusedc },
- { BFD_RELOC_BFIN_24_PCREL_CALL_X, R_pcrel24_call_x },
- { BFD_RELOC_8, R_byte_data },
- { BFD_RELOC_16, R_byte2_data },
- { BFD_RELOC_32, R_byte4_data },
- { BFD_RELOC_BFIN_11_PCREL, R_pcrel11 },
- { BFD_RELOC_BFIN_GOT, R_got },
- { BFD_RELOC_BFIN_PLTPC, R_pltpc },
+ { BFD_RELOC_NONE, R_BFIN_UNUSED0 },
+ { BFD_RELOC_BFIN_5_PCREL, R_BFIN_PCREL5M2 },
+ { BFD_RELOC_NONE, R_BFIN_UNUSED1 },
+ { BFD_RELOC_BFIN_10_PCREL, R_BFIN_PCREL10 },
+ { BFD_RELOC_BFIN_12_PCREL_JUMP, R_BFIN_PCREL12_JUMP },
+ { BFD_RELOC_BFIN_16_IMM, R_BFIN_RIMM16 },
+ { BFD_RELOC_BFIN_16_LOW, R_BFIN_LUIMM16 },
+ { BFD_RELOC_BFIN_16_HIGH, R_BFIN_HUIMM16 },
+ { BFD_RELOC_BFIN_12_PCREL_JUMP_S, R_BFIN_PCREL12_JUMP_S },
+ { BFD_RELOC_24_PCREL, R_BFIN_PCREL24 },
+ { BFD_RELOC_24_PCREL, R_BFIN_PCREL24 },
+ { BFD_RELOC_BFIN_24_PCREL_JUMP_L, R_BFIN_PCREL24_JUMP_L },
+ { BFD_RELOC_NONE, R_BFIN_UNUSEDB },
+ { BFD_RELOC_NONE, R_BFIN_UNUSEDC },
+ { BFD_RELOC_BFIN_24_PCREL_CALL_X, R_BFIN_PCREL24_CALL_X },
+ { BFD_RELOC_8, R_BFIN_BYTE_DATA },
+ { BFD_RELOC_16, R_BFIN_BYTE2_DATA },
+ { BFD_RELOC_32, R_BFIN_BYTE4_DATA },
+ { BFD_RELOC_BFIN_11_PCREL, R_BFIN_PCREL11 },
+ { BFD_RELOC_BFIN_GOT, R_BFIN_GOT },
+ { BFD_RELOC_BFIN_PLTPC, R_BFIN_PLTPC },
{ BFD_RELOC_BFIN_GOT17M4, R_BFIN_GOT17M4 },
{ BFD_RELOC_BFIN_GOTHI, R_BFIN_GOTHI },
return FALSE;
break;
- case R_got:
+ case R_BFIN_GOT:
if (h != NULL
&& strcmp (h->root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
break;
{
int r_type = ELF32_R_TYPE (rel->r_info);
- if (r_type == R_pcrel24 || r_type == R_pcrel24_jump_l)
+ if (r_type == R_BFIN_PCREL24 || r_type == R_BFIN_PCREL24_JUMP_L)
{
bfd_reloc_status_type r = bfd_reloc_ok;
bfd_vma x;
case R_BFIN_GNU_VTENTRY:
return bfd_reloc_ok;
- case R_got:
+ case R_BFIN_GOT:
/* Relocation is to the address of the entry for this symbol
in the global offset table. */
if (h != NULL
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset + off);
outrel.r_info =
- ELF32_R_INFO (0, R_pcrel24);
+ ELF32_R_INFO (0, R_BFIN_PCREL24);
outrel.r_addend = relocation;
loc = s->contents;
loc +=
switch (ELF32_R_TYPE (rel->r_info))
{
- case R_got:
+ case R_BFIN_GOT:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
extern const bfd_target bfd_elf32_bfinfdpic_vec;
#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_bfinfdpic_vec)
-/* An extension of the elf hash table data structure, containing some
- additional Blackfin-specific data. */
+/* An extension of the elf hash table data structure,
+ containing some additional Blackfin-specific data. */
struct bfinfdpic_elf_link_hash_table
{
struct elf_link_hash_table elf;
/* A hash table holding information about which symbols were
referenced with which PIC-related relocations. */
struct htab *relocs_info;
+ /* Summary reloc information collected by
+ _bfinfdpic_count_got_plt_entries. */
+ struct _bfinfdpic_dynamic_got_info *g;
};
/* Get the Blackfin ELF linker hash table from a link_info structure. */
#define bfinfdpic_hash_table(info) \
- ((struct bfinfdpic_elf_link_hash_table *) ((info)->hash))
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((info)->hash)) \
+ == BFIN_ELF_DATA ? ((struct bfinfdpic_elf_link_hash_table *) ((info)->hash)) : NULL)
#define bfinfdpic_got_section(info) \
(bfinfdpic_hash_table (info)->sgot)
(bfinfdpic_hash_table (info)->got0)
#define bfinfdpic_plt_initial_offset(info) \
(bfinfdpic_hash_table (info)->plt0)
+#define bfinfdpic_dynamic_got_plt_info(info) \
+ (bfinfdpic_hash_table (info)->g)
/* The name of the dynamic interpreter. This is put in the .interp
section. */
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
_bfd_elf_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
+ sizeof (struct elf_link_hash_entry),
+ BFIN_ELF_DATA))
{
free (ret);
return NULL;
needed for this symbol. */
unsigned done:1;
- /* The number of R_byte4_data, R_BFIN_FUNCDESC and R_BFIN_FUNCDESC_VALUE
+ /* The number of R_BFIN_BYTE4_DATA, R_BFIN_FUNCDESC and R_BFIN_FUNCDESC_VALUE
relocations referencing the symbol. */
unsigned relocs32, relocsfd, relocsfdv;
const struct bfinfdpic_relocs_info *entry,
enum insert_option insert)
{
- struct bfinfdpic_relocs_info **loc =
- (struct bfinfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
+ struct bfinfdpic_relocs_info **loc;
+
+ if (!ht)
+ return NULL;
+
+ loc = (struct bfinfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
if (! loc)
return NULL;
dynindx = entry->d.h->dynindx;
else
{
- if (sec->output_section
+ if (sec
+ && sec->output_section
&& ! bfd_is_abs_section (sec->output_section)
&& ! bfd_is_und_section (sec->output_section))
dynindx = elf_section_data (sec->output_section)->dynindx;
+ bfinfdpic_got_section (info)
->output_section->vma
+ bfinfdpic_got_section (info)->output_offset,
- R_byte4_data, idx, ad, entry);
+ R_BFIN_BYTE4_DATA, idx, ad, entry);
bfd_put_32 (output_bfd, ad,
bfinfdpic_got_section (info)->contents
so reference it directly. */
if (elf_hash_table (info)->dynamic_sections_created)
BFD_ASSERT (entry->privfd);
- reloc = R_byte4_data;
+ reloc = R_BFIN_BYTE4_DATA;
idx = elf_section_data (bfinfdpic_got_section (info)
->output_section)->dynindx;
ad = bfinfdpic_got_section (info)->output_offset
of the section. For a non-local function, it's
disregarded. */
lowword = ad;
- if (entry->symndx == -1 && entry->d.h->dynindx != -1
- && entry->d.h->dynindx == idx)
+ if (sec == NULL
+ || (entry->symndx == -1 && entry->d.h->dynindx != -1
+ && entry->d.h->dynindx == idx))
highword = 0;
else
highword = _bfinfdpic_osec_to_segment
switch (r_type)
{
- case R_pcrel24:
- case R_pcrel24_jump_l:
- case R_byte4_data:
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
+ case R_BFIN_BYTE4_DATA:
if (! IS_FDPIC (output_bfd))
goto non_fdpic;
switch (r_type)
{
- case R_pcrel24:
- case R_pcrel24_jump_l:
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
check_segment[0] = isec_segment;
if (! IS_FDPIC (output_bfd))
check_segment[1] = isec_segment;
/* Otherwise, we know we have a private function
descriptor, so reference it directly. */
BFD_ASSERT (picrel->privfd);
- r_type = R_byte4_data;
+ r_type = R_BFIN_BYTE4_DATA;
dynindx = elf_section_data (bfinfdpic_got_section (info)
->output_section)->dynindx;
addend = bfinfdpic_got_section (info)->output_offset
if (info->executable && !info->pie
&& (!h || BFINFDPIC_FUNCDESC_LOCAL (info, h)))
{
+ bfd_vma offset;
+
addend += bfinfdpic_got_section (info)->output_section->vma;
if ((bfd_get_section_flags (output_bfd,
input_section->output_section)
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- _bfinfdpic_add_rofixup (output_bfd,
- bfinfdpic_gotfixup_section
- (info),
- _bfd_elf_section_offset
- (output_bfd, info,
- input_section, rel->r_offset)
- + input_section
- ->output_section->vma
- + input_section->output_offset,
- picrel);
+
+ offset = _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset);
+
+ if (offset != (bfd_vma)-1)
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section
+ (info),
+ offset + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ picrel);
}
}
else if ((bfd_get_section_flags (output_bfd,
}
offset = _bfd_elf_section_offset (output_bfd, info,
input_section, rel->r_offset);
- /* Only output a reloc for a not deleted entry. */
- if (offset >= (bfd_vma) -2)
- _bfinfdpic_add_dyn_reloc (output_bfd,
- bfinfdpic_gotrel_section (info),
- 0,
- R_unused0,
- dynindx, addend, picrel);
- else
+
+ if (offset != (bfd_vma)-1)
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset + input_section
check_segment[0] = check_segment[1] = got_segment;
break;
- case R_byte4_data:
+ case R_BFIN_BYTE4_DATA:
if (! IS_FDPIC (output_bfd))
{
check_segment[0] = check_segment[1] = -1;
}
if (!h || h->root.type != bfd_link_hash_undefweak)
{
- /* Only output a reloc for a not deleted entry. */
- if (offset >= (bfd_vma)-2)
- _bfinfdpic_add_rofixup (output_bfd,
- bfinfdpic_gotfixup_section
- (info), -1, picrel);
- else
- _bfinfdpic_add_rofixup (output_bfd,
- bfinfdpic_gotfixup_section
- (info),
- offset + input_section
- ->output_section->vma
- + input_section->output_offset,
- picrel);
-
- if (r_type == R_BFIN_FUNCDESC_VALUE)
+ if (offset != (bfd_vma)-1)
{
- if (offset >= (bfd_vma)-2)
- _bfinfdpic_add_rofixup
- (output_bfd,
- bfinfdpic_gotfixup_section (info),
- -1, picrel);
- else
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section
+ (info),
+ offset + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ picrel);
+
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
_bfinfdpic_add_rofixup
(output_bfd,
bfinfdpic_gotfixup_section (info),
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- /* Only output a reloc for a not deleted entry. */
- if (offset >= (bfd_vma)-2)
- _bfinfdpic_add_dyn_reloc (output_bfd,
- bfinfdpic_gotrel_section (info),
- 0, R_unused0, dynindx, addend, picrel);
- else
+
+ if (offset != (bfd_vma)-1)
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset
- + input_section
- ->output_section->vma
+ + input_section->output_section->vma
+ input_section->output_offset,
r_type, dynindx, addend, picrel);
}
relocation = addend - rel->r_addend;
}
- if (r_type == R_BFIN_FUNCDESC_VALUE && offset < (bfd_vma)-2)
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
{
/* If we've omitted the dynamic relocation, just emit
the fixed addresses of the symbol and of the local
switch (r_type)
{
- case R_pcrel24:
- case R_pcrel24_jump_l:
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
if (! IS_FDPIC (output_bfd) || ! picrel->plt)
break;
/* Fall through. */
switch (ELF32_R_TYPE (rel->r_info))
{
- case R_pcrel24:
- case R_pcrel24_jump_l:
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
picrel->call--;
break;
picrel->relocs32++;
/* Fall through. */
- case R_byte4_data:
+ case R_BFIN_BYTE4_DATA:
picrel->sym--;
if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
picrel->relocs32--;
struct elf_link_hash_entry *h;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
int ptralign;
- int offset;
/* This function may be called more than once. */
s = bfd_get_section_by_name (abfd, ".got");
return FALSE;
bfinfdpic_gotfixup_section (info) = s;
- offset = -2048;
flags = BSF_GLOBAL;
}
else
{
- offset = 2048;
flags = BSF_GLOBAL | BSF_WEAK;
}
- return TRUE;
-}
-
-/* Make sure the got and plt sections exist, and that our pointers in
- the link hash table point to them. */
-
-static bfd_boolean
-elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
-{
- /* This is mostly copied from
- elflink.c:_bfd_elf_create_dynamic_sections(). */
- flagword flags, pltflags;
- asection *s;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- /* 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;
+ flags = pltflags;
pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
{
/* 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
/* Blackfin-specific: remember it. */
bfinfdpic_pltrel_section (info) = s;
+ return TRUE;
+}
+
+/* Make sure the got and plt sections exist, and that our pointers in
+ the link hash table point to them. */
+
+static bfd_boolean
+elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+{
+ /* This is mostly copied from
+ elflink.c:_bfd_elf_create_dynamic_sections(). */
+ flagword flags;
+ asection *s;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+
/* Blackfin-specific: we want to create the GOT in the Blackfin way. */
if (! _bfin_create_got_section (abfd, info))
return FALSE;
if (! info->shared)
{
s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"),
+ ".rela.bss",
flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
the symbol, an entry pointing to its function descriptor, and a
private function descriptors taking two words. */
-static int
-_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+static void
+_bfinfdpic_count_nontls_entries (struct bfinfdpic_relocs_info *entry,
+ struct _bfinfdpic_dynamic_got_info *dinfo)
{
- struct bfinfdpic_relocs_info *entry = *entryp;
- struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
- unsigned relocs = 0, fixups = 0;
-
/* Allocate space for a GOT entry pointing to the symbol. */
if (entry->got17m4)
dinfo->got17m4 += 4;
if (entry->lazyplt)
dinfo->lzplt += LZPLT_NORMAL_SIZE;
+}
+
+/* Compute the number of dynamic relocations and fixups that a symbol
+ requires, and add (or subtract) from the grand and per-symbol
+ totals. */
+
+static void
+_bfinfdpic_count_relocs_fixups (struct bfinfdpic_relocs_info *entry,
+ struct _bfinfdpic_dynamic_got_info *dinfo,
+ bfd_boolean subtract)
+{
+ bfd_vma relocs = 0, fixups = 0;
if (!dinfo->info->executable || dinfo->info->pie)
relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
relocs += entry->relocsfd;
}
+ if (subtract)
+ {
+ relocs = - relocs;
+ fixups = - fixups;
+ }
+
entry->dynrelocs += relocs;
entry->fixups += fixups;
dinfo->relocs += relocs;
dinfo->fixups += fixups;
+}
+
+/* Compute the total GOT and PLT size required by each symbol in each range. *
+ Symbols may require up to 4 words in the GOT: an entry pointing to
+ the symbol, an entry pointing to its function descriptor, and a
+ private function descriptors taking two words. */
+
+static int
+_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+ struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
+
+ _bfinfdpic_count_nontls_entries (entry, dinfo);
+
+ _bfinfdpic_count_relocs_fixups (entry, dinfo, FALSE);
return 1;
}
return 1;
}
+/* Cancel out any effects of calling _bfinfdpic_assign_got_entries and
+ _bfinfdpic_assign_plt_entries. */
+
+static int
+_bfinfdpic_reset_got_plt_entries (void **entryp, void *ignore ATTRIBUTE_UNUSED)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+
+ entry->got_entry = 0;
+ entry->fdgot_entry = 0;
+ entry->fd_entry = 0;
+ entry->plt_entry = (bfd_vma)-1;
+ entry->lzplt_entry = (bfd_vma)-1;
+
+ return 1;
+}
+
/* Follow indirect and warning hash entries so that each got entry
points to the final symbol definition. P must point to a pointer
to the hash table we're traversing. Since this traversal may
return 1;
}
-/* Set the sizes of the dynamic sections. */
+/* Compute the total size of the GOT, the PLT, the dynamic relocations
+ section and the rofixup section. Assign locations for GOT and PLT
+ entries. */
static bfd_boolean
-elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
- struct bfd_link_info *info)
+_bfinfdpic_size_got_plt (bfd *output_bfd,
+ struct _bfinfdpic_dynamic_got_plt_info *gpinfop)
{
- bfd *dynobj;
- asection *s;
- struct _bfinfdpic_dynamic_got_plt_info gpinfo;
bfd_signed_vma odd;
bfd_vma limit;
+ struct bfd_link_info *info = gpinfop->g.info;
+ bfd *dynobj = elf_hash_table (info)->dynobj;
- 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->executable)
- {
- s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
- s->size = sizeof ELF_DYNAMIC_INTERPRETER;
- s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
- }
- }
-
- memset (&gpinfo, 0, sizeof (gpinfo));
- gpinfo.g.info = info;
-
- for (;;)
- {
- htab_t relocs = bfinfdpic_relocs_info (info);
-
- htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
-
- if (relocs == bfinfdpic_relocs_info (info))
- break;
- }
-
- htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
- &gpinfo.g);
+ memcpy (bfinfdpic_dynamic_got_plt_info (info), &gpinfop->g,
+ sizeof (gpinfop->g));
odd = 12;
/* Compute the total size taken by entries in the 18-bit range,
to tell how many PLT function descriptors we can bring into it
without causing it to overflow. */
- limit = odd + gpinfo.g.got17m4 + gpinfo.g.fd17m4;
+ limit = odd + gpinfop->g.got17m4 + gpinfop->g.fd17m4;
if (limit < (bfd_vma)1 << 18)
limit = ((bfd_vma)1 << 18) - limit;
else
limit = 0;
- if (gpinfo.g.fdplt < limit)
- limit = gpinfo.g.fdplt;
+ if (gpinfop->g.fdplt < limit)
+ limit = gpinfop->g.fdplt;
/* Determine the ranges of GOT offsets that we can use for each
range of addressing modes. */
- odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.got17m4,
+ odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->got17m4,
0,
odd,
16,
- gpinfo.g.got17m4,
- gpinfo.g.fd17m4,
+ gpinfop->g.got17m4,
+ gpinfop->g.fd17m4,
limit,
(bfd_vma)1 << (18-1));
- odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.gothilo,
- gpinfo.got17m4.min,
+ odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->gothilo,
+ gpinfop->got17m4.min,
odd,
- gpinfo.got17m4.max,
- gpinfo.g.gothilo,
- gpinfo.g.fdhilo,
- gpinfo.g.fdplt - gpinfo.got17m4.fdplt,
+ gpinfop->got17m4.max,
+ gpinfop->g.gothilo,
+ gpinfop->g.fdhilo,
+ gpinfop->g.fdplt - gpinfop->got17m4.fdplt,
(bfd_vma)1 << (32-1));
/* Now assign (most) GOT offsets. */
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
- &gpinfo);
+ gpinfop);
- bfinfdpic_got_section (info)->size = gpinfo.gothilo.max
- - gpinfo.gothilo.min
+ bfinfdpic_got_section (info)->size = gpinfop->gothilo.max
+ - gpinfop->gothilo.min
/* If an odd word is the last word of the GOT, we don't need this
word to be part of the GOT. */
- - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
+ - (odd + 4 == gpinfop->gothilo.max ? 4 : 0);
if (bfinfdpic_got_section (info)->size == 0)
bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
else if (bfinfdpic_got_section (info)->size == 12
/* Subtract the number of lzplt entries, since those will generate
relocations in the pltrel section. */
bfinfdpic_gotrel_section (info)->size =
- (gpinfo.g.relocs - gpinfo.g.lzplt / LZPLT_NORMAL_SIZE)
+ (gpinfop->g.relocs - gpinfop->g.lzplt / LZPLT_NORMAL_SIZE)
* get_elf_backend_data (output_bfd)->s->sizeof_rel;
else
- BFD_ASSERT (gpinfo.g.relocs == 0);
+ BFD_ASSERT (gpinfop->g.relocs == 0);
if (bfinfdpic_gotrel_section (info)->size == 0)
bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
else
return FALSE;
}
- bfinfdpic_gotfixup_section (info)->size = (gpinfo.g.fixups + 1) * 4;
+ bfinfdpic_gotfixup_section (info)->size = (gpinfop->g.fixups + 1) * 4;
if (bfinfdpic_gotfixup_section (info)->size == 0)
bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
else
}
if (elf_hash_table (info)->dynamic_sections_created)
+ bfinfdpic_pltrel_section (info)->size =
+ gpinfop->g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
+ if (bfinfdpic_pltrel_section (info)->size == 0)
+ bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
+ else
{
- bfinfdpic_pltrel_section (info)->size =
- gpinfo.g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
- if (bfinfdpic_pltrel_section (info)->size == 0)
- bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
- else
- {
- bfinfdpic_pltrel_section (info)->contents =
- (bfd_byte *) bfd_zalloc (dynobj,
- bfinfdpic_pltrel_section (info)->size);
- if (bfinfdpic_pltrel_section (info)->contents == NULL)
- return FALSE;
- }
+ bfinfdpic_pltrel_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_pltrel_section (info)->size);
+ if (bfinfdpic_pltrel_section (info)->contents == NULL)
+ return FALSE;
}
/* Add 4 bytes for every block of at most 65535 lazy PLT entries,
block size. */
if (elf_hash_table (info)->dynamic_sections_created)
{
- bfinfdpic_plt_section (info)->size = gpinfo.g.lzplt
- + ((gpinfo.g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
+ bfinfdpic_plt_section (info)->size = gpinfop->g.lzplt
+ + ((gpinfop->g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
/ (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
}
/* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
actually assign lazy PLT entries addresses. */
- gpinfo.g.lzplt = 0;
+ gpinfop->g.lzplt = 0;
/* Save information that we're going to need to generate GOT and PLT
entries. */
- bfinfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
+ bfinfdpic_got_initial_offset (info) = -gpinfop->gothilo.min;
if (get_elf_backend_data (output_bfd)->want_got_sym)
elf_hash_table (info)->hgot->root.u.def.value
- += bfinfdpic_got_initial_offset (info);
+ = bfinfdpic_got_initial_offset (info);
if (elf_hash_table (info)->dynamic_sections_created)
bfinfdpic_plt_initial_offset (info) =
bfinfdpic_plt_section (info)->size;
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
- &gpinfo);
+ gpinfop);
/* Allocate the PLT section contents only after
_bfinfdpic_assign_plt_entries has a chance to add the size of the
non-lazy PLT entries. */
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (bfinfdpic_plt_section (info)->size == 0)
+ bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
+ else
{
- if (bfinfdpic_plt_section (info)->size == 0)
- bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
- else
+ bfinfdpic_plt_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_plt_section (info)->size);
+ if (bfinfdpic_plt_section (info)->contents == NULL)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static bfd_boolean
+elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ struct elf_link_hash_table *htab;
+ bfd *dynobj;
+ asection *s;
+ struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+
+ htab = elf_hash_table (info);
+ dynobj = htab->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (htab->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (info->executable)
{
- bfinfdpic_plt_section (info)->contents =
- (bfd_byte *) bfd_zalloc (dynobj,
- bfinfdpic_plt_section (info)->size);
- if (bfinfdpic_plt_section (info)->contents == NULL)
- return FALSE;
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
}
}
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ gpinfo.g.info = info;
+
+ for (;;)
+ {
+ htab_t relocs = bfinfdpic_relocs_info (info);
+
+ htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
+
+ if (relocs == bfinfdpic_relocs_info (info))
+ break;
+ }
+
+ htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
+ &gpinfo.g);
+
+ /* Allocate space to save the summary information, we're going to
+ use it if we're doing relaxations. */
+ bfinfdpic_dynamic_got_plt_info (info) = bfd_alloc (dynobj, sizeof (gpinfo.g));
+
+ if (!_bfinfdpic_size_got_plt (output_bfd, &gpinfo))
+ return FALSE;
+
if (elf_hash_table (info)->dynamic_sections_created)
{
if (bfinfdpic_got_section (info)->size)
return FALSE;
}
+ s = bfd_get_section_by_name (dynobj, ".dynbss");
+ if (s && s->size == 0)
+ s->flags |= SEC_EXCLUDE;
+
+ s = bfd_get_section_by_name (dynobj, ".rela.bss");
+ if (s && s->size == 0)
+ s->flags |= SEC_EXCLUDE;
+
return TRUE;
}
return TRUE;
}
+/* Check whether any of the relocations was optimized away, and
+ subtract it from the relocation or fixup count. */
+static bfd_boolean
+_bfinfdpic_check_discarded_relocs (bfd *abfd, asection *sec,
+ struct bfd_link_info *info,
+
+ bfd_boolean *changed)
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ Elf_Internal_Rela *rel, *erel;
+
+ if ((sec->flags & SEC_RELOC) == 0
+ || sec->reloc_count == 0)
+ 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;
+
+ rel = elf_section_data (sec)->relocs;
+
+ /* Now examine each relocation. */
+ for (erel = rel + sec->reloc_count; rel < erel; rel++)
+ {
+ struct elf_link_hash_entry *h;
+ unsigned long r_symndx;
+ struct bfinfdpic_relocs_info *picrel;
+ struct _bfinfdpic_dynamic_got_info *dinfo;
+
+ if (ELF32_R_TYPE (rel->r_info) != R_BFIN_BYTE4_DATA
+ && ELF32_R_TYPE (rel->r_info) != R_BFIN_FUNCDESC)
+ continue;
+
+ if (_bfd_elf_section_offset (sec->output_section->owner,
+ info, sec, rel->r_offset)
+ != (bfd_vma)-1)
+ continue;
+
+ 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];
+ 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 != NULL)
+ picrel = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info (info),
+ abfd, h,
+ rel->r_addend, NO_INSERT);
+ else
+ picrel = bfinfdpic_relocs_info_for_local (bfinfdpic_relocs_info (info),
+ abfd, r_symndx,
+ rel->r_addend, NO_INSERT);
+
+ if (! picrel)
+ return FALSE;
+
+ *changed = TRUE;
+ dinfo = bfinfdpic_dynamic_got_plt_info (info);
+
+ _bfinfdpic_count_relocs_fixups (picrel, dinfo, TRUE);
+ if (ELF32_R_TYPE (rel->r_info) == R_BFIN_BYTE4_DATA)
+ picrel->relocs32--;
+ else /* we know (ELF32_R_TYPE (rel->r_info) == R_BFIN_FUNCDESC) */
+ picrel->relocsfd--;
+ _bfinfdpic_count_relocs_fixups (picrel, dinfo, FALSE);
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+bfinfdpic_elf_discard_info (bfd *ibfd,
+ struct elf_reloc_cookie *cookie ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
+{
+ bfd_boolean changed = FALSE;
+ asection *s;
+ bfd *obfd = NULL;
+
+ /* Account for relaxation of .eh_frame section. */
+ for (s = ibfd->sections; s; s = s->next)
+ if (s->sec_info_type == ELF_INFO_TYPE_EH_FRAME)
+ {
+ if (!_bfinfdpic_check_discarded_relocs (ibfd, s, info, &changed))
+ return FALSE;
+ obfd = s->output_section->owner;
+ }
+
+ if (changed)
+ {
+ struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ memcpy (&gpinfo.g, bfinfdpic_dynamic_got_plt_info (info),
+ sizeof (gpinfo.g));
+
+ /* Clear GOT and PLT assignments. */
+ htab_traverse (bfinfdpic_relocs_info (info),
+ _bfinfdpic_reset_got_plt_entries,
+ NULL);
+
+ if (!_bfinfdpic_size_got_plt (obfd, &gpinfo))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static bfd_boolean
elf32_bfinfdpic_modify_program_headers (bfd *output_bfd,
struct bfd_link_info *info)
if (! IS_FDPIC (abfd))
goto bad_reloc;
/* Fall through. */
- case R_pcrel24:
- case R_pcrel24_jump_l:
- case R_byte4_data:
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
+ case R_BFIN_BYTE4_DATA:
if (IS_FDPIC (abfd) && ! dynobj)
{
elf_hash_table (info)->dynobj = dynobj = abfd;
switch (ELF32_R_TYPE (rel->r_info))
{
- case R_pcrel24:
- case R_pcrel24_jump_l:
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
if (IS_FDPIC (abfd))
picrel->call++;
break;
picrel->relocs32--;
/* Fall through. */
- case R_byte4_data:
+ case R_BFIN_BYTE4_DATA:
if (! IS_FDPIC (abfd))
break;
return FALSE;
break;
- case R_huimm16:
- case R_luimm16:
- case R_pcrel12_jump_s:
- case R_pcrel10:
+ case R_BFIN_HUIMM16:
+ case R_BFIN_LUIMM16:
+ case R_BFIN_PCREL12_JUMP_S:
+ case R_BFIN_PCREL10:
break;
default:
if (new_flags & EF_BFIN_FDPIC)
new_flags &= ~EF_BFIN_PIC;
-#ifdef DEBUG
+#ifndef DEBUG
+ if (0)
+#endif
(*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
bfd_get_filename (ibfd));
-#endif
if (!elf_flags_init (obfd)) /* First call, no flags set. */
{
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
bfin_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
+ sizeof (struct elf_link_hash_entry),
+ BFIN_ELF_DATA))
{
free (ret);
return NULL;
|| h->dynindx == -1 || h->forced_local) && h->def_regular)
{
fprintf(stderr, "*** check this relocation %s\n", __FUNCTION__);
- rela.r_info = ELF32_R_INFO (0, R_pcrel24);
+ rela.r_info = ELF32_R_INFO (0, R_BFIN_PCREL24);
rela.r_addend = bfd_get_signed_32 (output_bfd,
(sgot->contents
+
{
bfd_put_32 (output_bfd, (bfd_vma) 0,
sgot->contents + (h->got.offset & ~(bfd_vma) 1));
- rela.r_info = ELF32_R_INFO (h->dynindx, R_got);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_BFIN_GOT);
rela.r_addend = 0;
}
characters. */
/* We can only relocate absolute longword relocs at run time. */
- if (ELF32_R_TYPE (irel->r_info) != (int) R_byte4_data)
+ if (ELF32_R_TYPE (irel->r_info) != (int) R_BFIN_BYTE4_DATA)
{
*errmsg = _("unsupported reloc type");
bfd_set_error (bfd_error_bad_value);
#define elf_backend_finish_dynamic_sections \
elf32_bfinfdpic_finish_dynamic_sections
+#undef elf_backend_discard_info
+#define elf_backend_discard_info \
+ bfinfdpic_elf_discard_info
#undef elf_backend_can_make_relative_eh_frame
#define elf_backend_can_make_relative_eh_frame \
bfinfdpic_elf_use_relative_eh_frame