/* ADI Blackfin BFD support for 32-bit ELF.
- Copyright 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005-2017 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
bfd *abfd ATTRIBUTE_UNUSED,
arelent *reloc_entry ATTRIBUTE_UNUSED,
asymbol *symbol ATTRIBUTE_UNUSED,
- PTR data ATTRIBUTE_UNUSED,
+ void * data ATTRIBUTE_UNUSED,
asection *input_section ATTRIBUTE_UNUSED,
bfd *output_bfd ATTRIBUTE_UNUSED,
char **error_message ATTRIBUTE_UNUSED)
bfin_pcrel24_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
/* if rightshift is 1 and the number odd, return error. */
if (howto->rightshift && (relocation & 0x01))
{
- fprintf(stderr, "relocation should be even number\n");
+ _bfd_error_handler (_("relocation should be even number"));
return bfd_reloc_overflow;
}
bfin_imm16_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
bfin_byte4_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
bfin_bfd_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
/* Here the variable relocation holds the final address of the
symbol we are relocating against, plus any addend. */
- if (howto->pc_relative == TRUE)
+ if (howto->pc_relative)
{
relocation -= input_section->output_section->vma + input_section->output_offset;
- if (howto->pcrel_offset == TRUE)
+ if (howto->pcrel_offset)
relocation -= reloc_entry->address;
}
/* If rightshift is 1 and the number odd, return error. */
if (howto->rightshift && (relocation & 0x01))
{
- fprintf(stderr, "relocation should be even number\n");
+ _bfd_error_handler (_("relocation should be even number"));
return bfd_reloc_overflow;
}
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. */
+ 3, /* size (0 = byte, 1 = short, 2 = long). */
+ 0, /* bitsize. */
FALSE, /* pc_relative. */
0, /* bitpos. */
- complain_overflow_bitfield, /* complain_on_overflow. */
+ complain_overflow_dont, /* 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. */
+ 3, /* size (0 = byte, 1 = short, 2 = long). */
+ 0, /* bitsize. */
FALSE, /* pc_relative. */
0, /* bitpos. */
- complain_overflow_bitfield, /* complain_on_overflow. */
+ complain_overflow_dont, /* 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. */
+ 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_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. */
+ 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_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. */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
- "R_BFIN_GOT12", /* name */
+ "R_BFIN_GOT17M4", /* name */
FALSE, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* 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 },
bfd_reloc_code_real_type code)
{
unsigned int i;
- unsigned int r_type = BFIN_RELOC_MIN;
+ unsigned int r_type = (unsigned int) -1;
- for (i = sizeof (bfin_reloc_map) / sizeof (bfin_reloc_map[0]); --i;)
+ for (i = sizeof (bfin_reloc_map) / sizeof (bfin_reloc_map[0]); i--;)
if (bfin_reloc_map[i].bfd_reloc_val == code)
r_type = bfin_reloc_map[i].bfin_reloc_val;
- if (r_type <= BFIN_RELOC_MAX && r_type > BFIN_RELOC_MIN)
+ if (r_type <= BFIN_RELOC_MAX)
return &bfin_howto_table [r_type];
else if (r_type >= BFIN_GNUEXT_RELOC_MIN && r_type <= BFIN_GNUEXT_RELOC_MAX)
/* Given a bfin relocation type, return the howto. */
static reloc_howto_type *
bfin_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
- unsigned int r_type)
+ unsigned int r_type)
{
if (r_type <= BFIN_RELOC_MAX)
return &bfin_howto_table [r_type];
return (reloc_howto_type *) NULL;
}
+/* Set by ld emulation if --code-in-l1. */
+bfd_boolean elf32_bfin_code_in_l1 = 0;
+
+/* Set by ld emulation if --data-in-l1. */
+bfd_boolean elf32_bfin_data_in_l1 = 0;
+
+static void
+elf32_bfin_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
+{
+ if (elf32_bfin_code_in_l1)
+ elf_elfheader (abfd)->e_flags |= EF_BFIN_CODE_IN_L1;
+ if (elf32_bfin_data_in_l1)
+ elf_elfheader (abfd)->e_flags |= EF_BFIN_DATA_IN_L1;
+}
+
/* Return TRUE if the name is a local label.
bfin local labels begin with L$. */
static bfd_boolean
-bfin_is_local_label_name (
- bfd *abfd ATTRIBUTE_UNUSED,
- const char *label)
+bfin_is_local_label_name (bfd *abfd, const char *label)
{
if (label[0] == 'L' && label[1] == '$' )
return TRUE;
return _bfd_elf_is_local_label_name (abfd, label);
}
+\f
+/* Look through the relocs for a section during the first phase, and
+ allocate space in the global offset table or procedure linkage
+ table. */
-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. */
-struct bfinfdpic_elf_link_hash_table
+static bfd_boolean
+bfin_check_relocs (bfd * abfd,
+ struct bfd_link_info *info,
+ asection *sec,
+ const Elf_Internal_Rela *relocs)
{
- struct elf_link_hash_table elf;
-
- /* A pointer to the .got section. */
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_signed_vma *local_got_refcounts;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
asection *sgot;
- /* A pointer to the .rel.got section. */
- asection *sgotrel;
- /* A pointer to the .rofixup section. */
- asection *sgotfixup;
- /* A pointer to the .plt section. */
- asection *splt;
- /* A pointer to the .rel.plt section. */
- asection *spltrel;
- /* GOT base offset. */
- bfd_vma got0;
- /* Location of the first non-lazy PLT entry, i.e., the number of
- bytes taken by lazy PLT entries. */
- bfd_vma plt0;
- /* A hash table holding information about which symbols were
- referenced with which PIC-related relocations. */
- struct htab *relocs_info;
-};
+ asection *srelgot;
-/* Get the Blackfin ELF linker hash table from a link_info structure. */
+ if (bfd_link_relocatable (info))
+ return TRUE;
-#define bfinfdpic_hash_table(info) \
- ((struct bfinfdpic_elf_link_hash_table *) ((info)->hash))
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_refcounts = elf_local_got_refcounts (abfd);
-#define bfinfdpic_got_section(info) \
- (bfinfdpic_hash_table (info)->sgot)
-#define bfinfdpic_gotrel_section(info) \
- (bfinfdpic_hash_table (info)->sgotrel)
-#define bfinfdpic_gotfixup_section(info) \
- (bfinfdpic_hash_table (info)->sgotfixup)
-#define bfinfdpic_plt_section(info) \
- (bfinfdpic_hash_table (info)->splt)
-#define bfinfdpic_pltrel_section(info) \
- (bfinfdpic_hash_table (info)->spltrel)
-#define bfinfdpic_relocs_info(info) \
- (bfinfdpic_hash_table (info)->relocs_info)
-#define bfinfdpic_got_initial_offset(info) \
- (bfinfdpic_hash_table (info)->got0)
-#define bfinfdpic_plt_initial_offset(info) \
- (bfinfdpic_hash_table (info)->plt0)
+ sgot = NULL;
+ srelgot = NULL;
-/* Create a Blackfin ELF linker hash table. */
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
-static struct bfd_link_hash_table *
-bfinfdpic_elf_link_hash_table_create (bfd *abfd)
-{
- struct bfinfdpic_elf_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct bfinfdpic_elf_link_hash_table);
+ 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];
- ret = bfd_zalloc (abfd, amt);
- if (ret == NULL)
- return NULL;
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref_regular = 1;
+ }
- if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
- _bfd_elf_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
- {
- free (ret);
- return NULL;
- }
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_BFIN_GNU_VTINHERIT:
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ return FALSE;
+ break;
- return &ret->elf.root;
-}
+ /* This relocation describes which C++ vtable entries
+ are actually used. Record for later use during GC. */
+ case R_BFIN_GNU_VTENTRY:
+ BFD_ASSERT (h != NULL);
+ if (h != NULL
+ && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ return FALSE;
+ break;
-/* Decide whether a reference to a symbol can be resolved locally or
- not. If the symbol is protected, we want the local address, but
- its function descriptor must be assigned by the dynamic linker. */
-#define BFINFDPIC_SYM_LOCAL(INFO, H) \
- (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
- || ! elf_hash_table (INFO)->dynamic_sections_created)
-#define BFINFDPIC_FUNCDESC_LOCAL(INFO, H) \
- ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
+ case R_BFIN_GOT:
+ if (h != NULL
+ && strcmp (h->root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
-/* This structure collects information on what kind of GOT, PLT or
- function descriptors are required by relocations that reference a
- certain symbol. */
-struct bfinfdpic_relocs_info
-{
- /* The index of the symbol, as stored in the relocation r_info, if
- we have a local symbol; -1 otherwise. */
- long symndx;
- union
- {
- /* The input bfd in which the symbol is defined, if it's a local
- symbol. */
- bfd *abfd;
- /* If symndx == -1, the hash table entry corresponding to a global
- symbol (even if it turns out to bind locally, in which case it
- should ideally be replaced with section's symndx + addend). */
- struct elf_link_hash_entry *h;
- } d;
- /* The addend of the relocation that references the symbol. */
- bfd_vma addend;
+ if (dynobj == NULL)
+ {
+ /* Create the .got section. */
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (!_bfd_elf_create_got_section (dynobj, info))
+ return FALSE;
+ }
- /* The fields above are used to identify an entry. The fields below
- contain information on how an entry is used and, later on, which
- locations it was assigned. */
- /* The following 2 fields record whether the symbol+addend above was
- ever referenced with a GOT relocation. The 17M4 suffix indicates a
- GOT17M4 relocation; hilo is used for GOTLO/GOTHI pairs. */
- unsigned got17m4:1;
- unsigned gothilo:1;
- /* Whether a FUNCDESC relocation references symbol+addend. */
- unsigned fd:1;
- /* Whether a FUNCDESC_GOT relocation references symbol+addend. */
- unsigned fdgot17m4:1;
- unsigned fdgothilo:1;
- /* Whether a FUNCDESC_GOTOFF relocation references symbol+addend. */
- unsigned fdgoff17m4:1;
- unsigned fdgoffhilo:1;
- /* Whether symbol+addend is referenced with GOTOFF17M4, GOTOFFLO or
- GOTOFFHI relocations. The addend doesn't really matter, since we
- envision that this will only be used to check whether the symbol
- is mapped to the same segment as the got. */
- unsigned gotoff:1;
- /* Whether symbol+addend is referenced by a LABEL24 relocation. */
- unsigned call:1;
- /* Whether symbol+addend is referenced by a 32 or FUNCDESC_VALUE
- relocation. */
- unsigned sym:1;
- /* Whether we need a PLT entry for a symbol. Should be implied by
- something like:
- (call && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)) */
- unsigned plt:1;
- /* Whether a function descriptor should be created in this link unit
- for symbol+addend. Should be implied by something like:
- (plt || fdgotoff17m4 || fdgotofflohi
- || ((fd || fdgot17m4 || fdgothilo)
- && (symndx != -1 || BFINFDPIC_FUNCDESC_LOCAL (info, d.h)))) */
- unsigned privfd:1;
- /* Whether a lazy PLT entry is needed for this symbol+addend.
- Should be implied by something like:
- (privfd && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)
- && ! (info->flags & DF_BIND_NOW)) */
- unsigned lazyplt:1;
- /* Whether we've already emitted GOT relocations and PLT entries as
- needed for this symbol. */
- unsigned done:1;
+ sgot = elf_hash_table (info)->sgot;
+ srelgot = elf_hash_table (info)->srelgot;
+ BFD_ASSERT (sgot != NULL);
- /* The number of R_byte4_data, R_BFIN_FUNCDESC and R_BFIN_FUNCDESC_VALUE
- relocations referencing the symbol. */
- unsigned relocs32, relocsfd, relocsfdv;
+ if (h != NULL)
+ {
+ if (h->got.refcount == 0)
+ {
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1 && !h->forced_local)
+ {
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
- /* The number of .rofixups entries and dynamic relocations allocated
- for this symbol, minus any that might have already been used. */
- unsigned fixups, dynrelocs;
+ /* Allocate space in the .got section. */
+ sgot->size += 4;
+ /* Allocate relocation space. */
+ srelgot->size += sizeof (Elf32_External_Rela);
+ }
+ h->got.refcount++;
+ }
+ else
+ {
+ /* This is a global offset table entry for a local symbol. */
+ if (local_got_refcounts == NULL)
+ {
+ bfd_size_type size;
- /* The offsets of the GOT entries assigned to symbol+addend, to the
- function descriptor's address, and to a function descriptor,
- respectively. Should be zero if unassigned. The offsets are
- counted from the value that will be assigned to the PIC register,
- not from the beginning of the .got section. */
- bfd_signed_vma got_entry, fdgot_entry, fd_entry;
- /* The offsets of the PLT entries assigned to symbol+addend,
- non-lazy and lazy, respectively. If unassigned, should be
- (bfd_vma)-1. */
- bfd_vma plt_entry, lzplt_entry;
-};
+ size = symtab_hdr->sh_info;
+ size *= sizeof (bfd_signed_vma);
+ local_got_refcounts = ((bfd_signed_vma *)
+ bfd_zalloc (abfd, size));
+ if (local_got_refcounts == NULL)
+ return FALSE;
+ elf_local_got_refcounts (abfd) = local_got_refcounts;
+ }
+ if (local_got_refcounts[r_symndx] == 0)
+ {
+ sgot->size += 4;
+ if (bfd_link_pic (info))
+ {
+ /* If we are generating a shared object, we need to
+ output a R_68K_RELATIVE reloc so that the dynamic
+ linker can adjust this GOT entry. */
+ srelgot->size += sizeof (Elf32_External_Rela);
+ }
+ }
+ local_got_refcounts[r_symndx]++;
+ }
+ break;
-/* Compute a hash with the key fields of an bfinfdpic_relocs_info entry. */
-static hashval_t
-bfinfdpic_relocs_info_hash (const void *entry_)
-{
- const struct bfinfdpic_relocs_info *entry = entry_;
+ default:
+ break;
+ }
+ }
- return (entry->symndx == -1
- ? (long) entry->d.h->root.root.hash
+ return TRUE;
+}
+
+static enum elf_reloc_type_class
+elf32_bfin_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela * rela)
+{
+ switch ((int) ELF32_R_TYPE (rela->r_info))
+ {
+ default:
+ return reloc_class_normal;
+ }
+}
+\f
+static bfd_reloc_status_type
+bfin_final_link_relocate (Elf_Internal_Rela *rel, reloc_howto_type *howto,
+ bfd *input_bfd, asection *input_section,
+ bfd_byte *contents, bfd_vma address,
+ bfd_vma value, bfd_vma addend)
+{
+ int r_type = ELF32_R_TYPE (rel->r_info);
+
+ if (r_type == R_BFIN_PCREL24 || r_type == R_BFIN_PCREL24_JUMP_L)
+ {
+ bfd_reloc_status_type r = bfd_reloc_ok;
+ bfd_vma x;
+
+ if (address > bfd_get_section_limit (input_bfd, input_section))
+ return bfd_reloc_outofrange;
+
+ value += addend;
+
+ /* Perform usual pc-relative correction. */
+ value -= input_section->output_section->vma + input_section->output_offset;
+ value -= address;
+
+ /* We are getting reloc_entry->address 2 byte off from
+ the start of instruction. Assuming absolute postion
+ of the reloc data. But, following code had been written assuming
+ reloc address is starting at begining of instruction.
+ To compensate that I have increased the value of
+ relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
+
+ value += 2;
+ address -= 2;
+
+ if ((value & 0xFF000000) != 0
+ && (value & 0xFF000000) != 0xFF000000)
+ r = bfd_reloc_overflow;
+
+ value >>= 1;
+
+ x = bfd_get_16 (input_bfd, contents + address);
+ x = (x & 0xff00) | ((value >> 16) & 0xff);
+ bfd_put_16 (input_bfd, x, contents + address);
+
+ x = bfd_get_16 (input_bfd, contents + address + 2);
+ x = value & 0xFFFF;
+ bfd_put_16 (input_bfd, x, contents + address + 2);
+ return r;
+ }
+
+ return _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
+ rel->r_offset, value, addend);
+
+}
+
+static bfd_boolean
+bfin_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)
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ asection *sgot;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+ int i = 0;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+ local_got_offsets = elf_local_got_offsets (input_bfd);
+
+ sgot = NULL;
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++, i++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ bfd_vma relocation = 0;
+ bfd_boolean unresolved_reloc;
+ bfd_reloc_status_type r;
+ bfd_vma address;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= 243)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ if (r_type == R_BFIN_GNU_VTENTRY
+ || r_type == R_BFIN_GNU_VTINHERIT)
+ continue;
+
+ howto = bfin_reloc_type_lookup (input_bfd, r_type);
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ unresolved_reloc = FALSE;
+
+ 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);
+ }
+ else
+ {
+ bfd_boolean warned, ignored;
+
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned, ignored);
+ }
+
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
+
+ if (bfd_link_relocatable (info))
+ continue;
+
+ address = rel->r_offset;
+
+ /* Then, process normally. */
+ switch (r_type)
+ {
+ case R_BFIN_GNU_VTINHERIT:
+ case R_BFIN_GNU_VTENTRY:
+ return bfd_reloc_ok;
+
+ case R_BFIN_GOT:
+ /* Relocation is to the address of the entry for this symbol
+ in the global offset table. */
+ if (h != NULL
+ && strcmp (h->root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
+ goto do_default;
+ /* Fall through. */
+ /* Relocation is the offset of the entry for this symbol in
+ the global offset table. */
+
+ {
+ bfd_vma off;
+
+ if (dynobj == NULL)
+ {
+ /* Create the .got section. */
+ elf_hash_table (info)->dynobj = dynobj = output_bfd;
+ if (!_bfd_elf_create_got_section (dynobj, info))
+ return FALSE;
+ }
+
+ sgot = elf_hash_table (info)->sgot;
+ BFD_ASSERT (sgot != NULL);
+
+ if (h != NULL)
+ {
+ bfd_boolean dyn;
+
+ off = h->got.offset;
+ BFD_ASSERT (off != (bfd_vma) - 1);
+ dyn = elf_hash_table (info)->dynamic_sections_created;
+
+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+ bfd_link_pic (info),
+ h)
+ || (bfd_link_pic (info)
+ && (info->symbolic
+ || h->dynindx == -1
+ || h->forced_local)
+ && h->def_regular))
+ {
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally, or the symbol was forced to be local
+ because of a version file.. We must initialize
+ this entry in the global offset table. Since
+ the offset must always be a multiple of 4, we
+ use the least significant bit to record whether
+ we have initialized it already.
+
+ When doing a dynamic link, we create a .rela.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation,
+ sgot->contents + off);
+ h->got.offset |= 1;
+ }
+ }
+ else
+ unresolved_reloc = FALSE;
+ }
+ else
+ {
+ BFD_ASSERT (local_got_offsets != NULL);
+ off = local_got_offsets[r_symndx];
+ BFD_ASSERT (off != (bfd_vma) - 1);
+
+ /* The offset must always be a multiple of 4. We use
+ the least significant bit to record whether we have
+ already generated the necessary reloc. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation, sgot->contents + off);
+
+ if (bfd_link_pic (info))
+ {
+ asection *s;
+ Elf_Internal_Rela outrel;
+ bfd_byte *loc;
+
+ s = elf_hash_table (info)->srelgot;
+ BFD_ASSERT (s != NULL);
+
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset + off);
+ outrel.r_info =
+ ELF32_R_INFO (0, R_BFIN_PCREL24);
+ outrel.r_addend = relocation;
+ loc = s->contents;
+ loc +=
+ s->reloc_count++ * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+ }
+
+ local_got_offsets[r_symndx] |= 1;
+ }
+ }
+
+ relocation = sgot->output_offset + off;
+ rel->r_addend = 0;
+ /* bfin : preg = [preg + 17bitdiv4offset] relocation is div by 4. */
+ relocation /= 4;
+ }
+ goto do_default;
+
+ default:
+ do_default:
+ r = bfin_final_link_relocate (rel, howto, input_bfd, input_section,
+ contents, address,
+ relocation, rel->r_addend);
+
+ break;
+ }
+
+ /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
+ because such sections are not SEC_ALLOC and thus ld.so will
+ not process them. */
+ if (unresolved_reloc
+ && !((input_section->flags & SEC_DEBUGGING) != 0 && h->def_dynamic)
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%A+%#Lx): unresolvable relocation against symbol `%s'"),
+ input_bfd,
+ input_section, rel->r_offset, h->root.root.string);
+ return FALSE;
+ }
+
+ if (r != bfd_reloc_ok)
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ return FALSE;
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+
+ if (r == bfd_reloc_overflow)
+ (*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
+ else
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%A+%#Lx): reloc against `%s': error %d"),
+ input_bfd, input_section, rel->r_offset, name, (int) r);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static asection *
+bfin_gc_mark_hook (asection * sec,
+ struct bfd_link_info *info,
+ Elf_Internal_Rela * rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym * sym)
+{
+ if (h != NULL)
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_BFIN_GNU_VTINHERIT:
+ case R_BFIN_GNU_VTENTRY:
+ return NULL;
+ }
+
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
+}
+
+/* Update the got entry reference counts for the section being removed. */
+
+static bfd_boolean
+bfin_gc_sweep_hook (bfd * abfd,
+ struct bfd_link_info *info,
+ asection * sec,
+ const Elf_Internal_Rela * relocs)
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_signed_vma *local_got_refcounts;
+ const Elf_Internal_Rela *rel, *relend;
+ bfd *dynobj;
+ asection *sgot;
+ asection *srelgot;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ if (dynobj == NULL)
+ return TRUE;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_refcounts = elf_local_got_refcounts (abfd);
+
+ sgot = elf_hash_table (info)->sgot;
+ srelgot = elf_hash_table (info)->srelgot;
+
+ relend = relocs + sec->reloc_count;
+ for (rel = relocs; rel < relend; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_BFIN_GOT:
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ if (h->got.refcount > 0)
+ {
+ --h->got.refcount;
+ if (h->got.refcount == 0)
+ {
+ /* We don't need the .got entry any more. */
+ sgot->size -= 4;
+ srelgot->size -= sizeof (Elf32_External_Rela);
+ }
+ }
+ }
+ else if (local_got_refcounts != NULL)
+ {
+ if (local_got_refcounts[r_symndx] > 0)
+ {
+ --local_got_refcounts[r_symndx];
+ if (local_got_refcounts[r_symndx] == 0)
+ {
+ /* We don't need the .got entry any more. */
+ sgot->size -= 4;
+ if (bfd_link_pic (info))
+ srelgot->size -= sizeof (Elf32_External_Rela);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+\f
+extern const bfd_target bfin_elf32_fdpic_vec;
+#define IS_FDPIC(bfd) ((bfd)->xvec == &bfin_elf32_fdpic_vec)
+
+/* 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 pointer to the .rofixup section. */
+ asection *sgotfixup;
+ /* GOT base offset. */
+ bfd_vma got0;
+ /* Location of the first non-lazy PLT entry, i.e., the number of
+ bytes taken by lazy PLT entries. */
+ bfd_vma plt0;
+ /* 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) \
+ (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)->elf.sgot)
+#define bfinfdpic_gotrel_section(info) \
+ (bfinfdpic_hash_table (info)->elf.srelgot)
+#define bfinfdpic_gotfixup_section(info) \
+ (bfinfdpic_hash_table (info)->sgotfixup)
+#define bfinfdpic_plt_section(info) \
+ (bfinfdpic_hash_table (info)->elf.splt)
+#define bfinfdpic_pltrel_section(info) \
+ (bfinfdpic_hash_table (info)->elf.srelplt)
+#define bfinfdpic_relocs_info(info) \
+ (bfinfdpic_hash_table (info)->relocs_info)
+#define bfinfdpic_got_initial_offset(info) \
+ (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. */
+
+#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
+
+#define DEFAULT_STACK_SIZE 0x20000
+
+/* This structure is used to collect the number of entries present in
+ each addressable range of the got. */
+struct _bfinfdpic_dynamic_got_info
+{
+ /* Several bits of information about the current link. */
+ struct bfd_link_info *info;
+ /* Total size needed for GOT entries within the 18- or 32-bit
+ ranges. */
+ bfd_vma got17m4, gothilo;
+ /* Total size needed for function descriptor entries within the 18-
+ or 32-bit ranges. */
+ bfd_vma fd17m4, fdhilo;
+ /* Total size needed function descriptor entries referenced in PLT
+ entries, that would be profitable to place in offsets close to
+ the PIC register. */
+ bfd_vma fdplt;
+ /* Total size needed by lazy PLT entries. */
+ bfd_vma lzplt;
+ /* Number of relocations carried over from input object files. */
+ unsigned long relocs;
+ /* Number of fixups introduced by relocations in input object files. */
+ unsigned long fixups;
+};
+
+/* Create a Blackfin ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+bfinfdpic_elf_link_hash_table_create (bfd *abfd)
+{
+ struct bfinfdpic_elf_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct bfinfdpic_elf_link_hash_table);
+
+ ret = bfd_zmalloc (amt);
+ if (ret == NULL)
+ return NULL;
+
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry),
+ BFIN_ELF_DATA))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ return &ret->elf.root;
+}
+
+/* Decide whether a reference to a symbol can be resolved locally or
+ not. If the symbol is protected, we want the local address, but
+ its function descriptor must be assigned by the dynamic linker. */
+#define BFINFDPIC_SYM_LOCAL(INFO, H) \
+ (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
+ || ! elf_hash_table (INFO)->dynamic_sections_created)
+#define BFINFDPIC_FUNCDESC_LOCAL(INFO, H) \
+ ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
+
+/* This structure collects information on what kind of GOT, PLT or
+ function descriptors are required by relocations that reference a
+ certain symbol. */
+struct bfinfdpic_relocs_info
+{
+ /* The index of the symbol, as stored in the relocation r_info, if
+ we have a local symbol; -1 otherwise. */
+ long symndx;
+ union
+ {
+ /* The input bfd in which the symbol is defined, if it's a local
+ symbol. */
+ bfd *abfd;
+ /* If symndx == -1, the hash table entry corresponding to a global
+ symbol (even if it turns out to bind locally, in which case it
+ should ideally be replaced with section's symndx + addend). */
+ struct elf_link_hash_entry *h;
+ } d;
+ /* The addend of the relocation that references the symbol. */
+ bfd_vma addend;
+
+ /* The fields above are used to identify an entry. The fields below
+ contain information on how an entry is used and, later on, which
+ locations it was assigned. */
+ /* The following 2 fields record whether the symbol+addend above was
+ ever referenced with a GOT relocation. The 17M4 suffix indicates a
+ GOT17M4 relocation; hilo is used for GOTLO/GOTHI pairs. */
+ unsigned got17m4;
+ unsigned gothilo;
+ /* Whether a FUNCDESC relocation references symbol+addend. */
+ unsigned fd;
+ /* Whether a FUNCDESC_GOT relocation references symbol+addend. */
+ unsigned fdgot17m4;
+ unsigned fdgothilo;
+ /* Whether a FUNCDESC_GOTOFF relocation references symbol+addend. */
+ unsigned fdgoff17m4;
+ unsigned fdgoffhilo;
+ /* Whether symbol+addend is referenced with GOTOFF17M4, GOTOFFLO or
+ GOTOFFHI relocations. The addend doesn't really matter, since we
+ envision that this will only be used to check whether the symbol
+ is mapped to the same segment as the got. */
+ unsigned gotoff;
+ /* Whether symbol+addend is referenced by a LABEL24 relocation. */
+ unsigned call;
+ /* Whether symbol+addend is referenced by a 32 or FUNCDESC_VALUE
+ relocation. */
+ unsigned sym;
+ /* Whether we need a PLT entry for a symbol. Should be implied by
+ something like:
+ (call && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)) */
+ unsigned plt:1;
+ /* Whether a function descriptor should be created in this link unit
+ for symbol+addend. Should be implied by something like:
+ (plt || fdgotoff17m4 || fdgotofflohi
+ || ((fd || fdgot17m4 || fdgothilo)
+ && (symndx != -1 || BFINFDPIC_FUNCDESC_LOCAL (info, d.h)))) */
+ unsigned privfd:1;
+ /* Whether a lazy PLT entry is needed for this symbol+addend.
+ Should be implied by something like:
+ (privfd && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)
+ && ! (info->flags & DF_BIND_NOW)) */
+ unsigned lazyplt:1;
+ /* Whether we've already emitted GOT relocations and PLT entries as
+ needed for this symbol. */
+ unsigned done:1;
+
+ /* The number of R_BFIN_BYTE4_DATA, R_BFIN_FUNCDESC and R_BFIN_FUNCDESC_VALUE
+ relocations referencing the symbol. */
+ unsigned relocs32, relocsfd, relocsfdv;
+
+ /* The number of .rofixups entries and dynamic relocations allocated
+ for this symbol, minus any that might have already been used. */
+ unsigned fixups, dynrelocs;
+
+ /* The offsets of the GOT entries assigned to symbol+addend, to the
+ function descriptor's address, and to a function descriptor,
+ respectively. Should be zero if unassigned. The offsets are
+ counted from the value that will be assigned to the PIC register,
+ not from the beginning of the .got section. */
+ bfd_signed_vma got_entry, fdgot_entry, fd_entry;
+ /* The offsets of the PLT entries assigned to symbol+addend,
+ non-lazy and lazy, respectively. If unassigned, should be
+ (bfd_vma)-1. */
+ bfd_vma plt_entry, lzplt_entry;
+};
+
+/* Compute a hash with the key fields of an bfinfdpic_relocs_info entry. */
+static hashval_t
+bfinfdpic_relocs_info_hash (const void *entry_)
+{
+ const struct bfinfdpic_relocs_info *entry = entry_;
+
+ return (entry->symndx == -1
+ ? (long) entry->d.h->root.root.hash
: entry->symndx + (long) entry->d.abfd->id * 257) + entry->addend;
}
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;
for memory allocation purposes. */
inline static struct bfinfdpic_relocs_info *
bfinfdpic_relocs_info_for_global (struct htab *ht,
- bfd *abfd,
- struct elf_link_hash_entry *h,
- bfd_vma addend,
- enum insert_option insert)
+ bfd *abfd,
+ struct elf_link_hash_entry *h,
+ bfd_vma addend,
+ enum insert_option insert)
{
struct bfinfdpic_relocs_info entry;
inline static void
bfinfdpic_pic_merge_early_relocs_info (struct bfinfdpic_relocs_info *e2,
- struct bfinfdpic_relocs_info const *e1)
+ struct bfinfdpic_relocs_info const *e1)
{
e2->got17m4 |= e1->got17m4;
e2->gothilo |= e1->gothilo;
static bfd_vma
_bfinfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
- struct bfinfdpic_relocs_info *entry)
+ struct bfinfdpic_relocs_info *entry)
{
bfd_vma fixup_offset;
static unsigned
_bfinfdpic_osec_to_segment (bfd *output_bfd, asection *osec)
{
- struct elf_segment_map *m;
- Elf_Internal_Phdr *p;
-
- /* Find the segment that contains the output_section. */
- for (m = elf_tdata (output_bfd)->segment_map,
- p = elf_tdata (output_bfd)->phdr;
- m != NULL;
- m = m->next, p++)
- {
- int i;
+ Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section (output_bfd, osec);
- for (i = m->count - 1; i >= 0; i--)
- if (m->sections[i] == osec)
- break;
-
- if (i >= 0)
- break;
- }
-
- return p - elf_tdata (output_bfd)->phdr;
+ return (p != NULL) ? p - elf_tdata (output_bfd)->phdr : -1;
}
inline static bfd_boolean
asection *sec,
Elf_Internal_Sym *sym,
bfd_vma addend)
-
{
- bfd_vma fd_lazy_rel_offset = (bfd_vma)-1;
+ bfd_vma fd_lazy_rel_offset = (bfd_vma) -1;
int dynindx = -1;
if (entry->done)
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;
/* If we're linking an executable at a fixed address, we can
omit the dynamic relocation as long as the symbol is local to
this module. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (entry->symndx != -1
|| BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
{
+ 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
if (entry->symndx == -1
&& ! BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h)
&& BFINFDPIC_SYM_LOCAL (info, entry->d.h)
- && !(info->executable && !info->pie))
+ && !bfd_link_pde (info))
{
reloc = R_BFIN_FUNCDESC;
idx = elf_section_data (entry->d.h->root.u.def.section
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
dynamic symbol entry for the got section, so idx will be
zero, which means we can and should compute the address
of the private descriptor ourselves. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (entry->symndx != -1
|| BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h)))
{
/* If we're linking an executable at a fixed address, we can
omit the dynamic relocation as long as the symbol is local to
this module. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (entry->symndx != -1 || BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
{
if (sec)
/* If we've omitted the dynamic relocation, just emit the fixed
addresses of the symbol and of the local GOT base offset. */
- if (info->executable && !info->pie && sec && sec->output_section)
+ if (bfd_link_pde (info)
+ && sec
+ && sec->output_section)
{
lowword = ad;
highword = bfinfdpic_got_section (info)->output_section->vma
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
return TRUE;
}
-
-
-/* Look through the relocs for a section during the first phase, and
- allocate space in the global offset table or procedure linkage
- table. */
-
-static bfd_boolean
-bfin_check_relocs (bfd * abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- bfd *dynobj;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
- asection *sgot;
- asection *srelgot;
- asection *sreloc;
- if (info->relocatable)
- return TRUE;
-
- dynobj = elf_hash_table (info)->dynobj;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
-
- sgot = NULL;
- srelgot = NULL;
- sreloc = NULL;
-
- rel_end = relocs + sec->reloc_count;
- for (rel = relocs; rel < rel_end; rel++)
- {
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
- else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
- switch (ELF32_R_TYPE (rel->r_info))
- {
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_BFIN_GNU_VTINHERIT:
- if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return FALSE;
- break;
-
- /* This relocation describes which C++ vtable entries
- are actually used. Record for later use during GC. */
- case R_BFIN_GNU_VTENTRY:
- if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
- return FALSE;
- break;
-
- case R_got:
- if (h != NULL
- && strcmp (h->root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
- break;
- /* Fall through. */
-
- if (dynobj == NULL)
- {
- /* Create the .got section. */
- elf_hash_table (info)->dynobj = dynobj = abfd;
- if (!_bfd_elf_create_got_section (dynobj, info))
- return FALSE;
- }
-
- if (sgot == NULL)
- {
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
- }
-
- if (srelgot == NULL && (h != NULL || info->shared))
- {
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- if (srelgot == NULL)
- {
- flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_READONLY);
- srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
- flags);
- if (srelgot == NULL
- || !bfd_set_section_alignment (dynobj, srelgot, 2))
- return FALSE;
- }
- }
-
- if (h != NULL)
- {
- if (h->got.refcount == 0)
- {
- /* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1 && !h->forced_local)
- {
- if (!bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
-
- /* Allocate space in the .got section. */
- sgot->size += 4;
- /* Allocate relocation space. */
- srelgot->size += sizeof (Elf32_External_Rela);
- }
- h->got.refcount++;
- }
- else
- {
- /* This is a global offset table entry for a local symbol. */
- if (local_got_refcounts == NULL)
- {
- bfd_size_type size;
-
- size = symtab_hdr->sh_info;
- size *= sizeof (bfd_signed_vma);
- local_got_refcounts = ((bfd_signed_vma *)
- bfd_zalloc (abfd, size));
- if (local_got_refcounts == NULL)
- return FALSE;
- elf_local_got_refcounts (abfd) = local_got_refcounts;
- }
- if (local_got_refcounts[r_symndx] == 0)
- {
- sgot->size += 4;
- if (info->shared)
- {
- /* If we are generating a shared object, we need to
- output a R_68K_RELATIVE reloc so that the dynamic
- linker can adjust this GOT entry. */
- srelgot->size += sizeof (Elf32_External_Rela);
- }
- }
- local_got_refcounts[r_symndx]++;
- }
- break;
-
- default:
- break;
- }
- }
-
- return TRUE;
-}
-
-static enum elf_reloc_type_class
-elf32_bfin_reloc_type_class (const Elf_Internal_Rela * rela)
-{
- switch ((int) ELF32_R_TYPE (rela->r_info))
- {
- default:
- return reloc_class_normal;
- }
-}
\f
/* Relocate an Blackfin ELF section.
Elf_Internal_Rela *relend;
unsigned isec_segment, got_segment, plt_segment,
check_segment[2];
- int silence_segment_error = !(info->shared || info->pie);
+ int silence_segment_error = !bfd_link_pic (info);
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
osec = sec;
}
- 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 (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
continue;
if (h != NULL
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;
+ /* Fall through. */
case R_BFIN_GOT17M4:
case R_BFIN_GOTHI:
osec, sym,
rel->r_addend))
{
- (*_bfd_error_handler)
- (_("%B: relocation at `%A+0x%x' references symbol `%s' with nonzero addend"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: relocation at `%A+%#Lx' references symbol `%s' with nonzero addend"),
input_bfd, input_section, rel->r_offset, name);
return FALSE;
default:
non_fdpic:
picrel = NULL;
- if (h && ! BFINFDPIC_SYM_LOCAL (info, h))
+ if (h && ! BFINFDPIC_SYM_LOCAL (info, h)
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
{
info->callbacks->warning
(info, _("relocation references symbol not defined in the module"),
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;
section+offset. */
if (h && ! BFINFDPIC_FUNCDESC_LOCAL (info, h)
&& BFINFDPIC_SYM_LOCAL (info, h)
- && !(info->executable && !info->pie))
+ && !bfd_link_pde (info))
{
dynindx = elf_section_data (h->root.u.def.section
->output_section)->dynindx;
/* 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
dynamic symbol entry for the got section, so idx will
be zero, which means we can and should compute the
address of the private descriptor ourselves. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (!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,
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- 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
+ offset = _bfd_elf_section_offset (output_bfd, info,
+ input_section, rel->r_offset);
+
+ 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;
{
int dynindx;
bfd_vma addend = rel->r_addend;
+ bfd_vma offset;
+ offset = _bfd_elf_section_offset (output_bfd, info,
+ input_section, rel->r_offset);
/* If the symbol is dynamic but binds locally, use
section+offset. */
can omit the dynamic relocation as long as the symbol
is defined in the current link unit (which is implied
by its output section not being NULL). */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (!h || BFINFDPIC_SYM_LOCAL (info, h)))
{
if (osec)
}
if (!h || h->root.type != bfd_link_hash_undefweak)
{
- _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);
- if (r_type == R_BFIN_FUNCDESC_VALUE)
- _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 + 4, picrel);
+ 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);
+
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
+ _bfinfdpic_add_rofixup
+ (output_bfd,
+ bfinfdpic_gotfixup_section (info),
+ offset + input_section->output_section->vma
+ + input_section->output_offset + 4, picrel);
+ }
}
}
}
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- _bfinfdpic_add_dyn_reloc (output_bfd,
- bfinfdpic_gotrel_section (info),
- _bfd_elf_section_offset
- (output_bfd, info,
- input_section, rel->r_offset)
- + input_section
- ->output_section->vma
- + input_section->output_offset,
- r_type, dynindx, addend, picrel);
+
+ if (offset != (bfd_vma)-1)
+ _bfinfdpic_add_dyn_reloc (output_bfd,
+ bfinfdpic_gotrel_section (info),
+ offset
+ + input_section->output_section->vma
+ + input_section->output_offset,
+ r_type, dynindx, addend, picrel);
}
else if (osec)
addend += osec->output_section->vma;
/* If we've omitted the dynamic relocation, just emit
the fixed addresses of the symbol and of the local
GOT base offset. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (!h || BFINFDPIC_SYM_LOCAL (info, h)))
bfd_put_32 (output_bfd,
bfinfdpic_got_section (info)->output_section->vma
if (silence_segment_error == 1)
silence_segment_error =
(strlen (input_bfd->filename) == 6
- && strcmp (input_bfd->filename, "crt0.o") == 0)
+ && filename_cmp (input_bfd->filename, "crt0.o") == 0)
|| (strlen (input_bfd->filename) > 6
- && strcmp (input_bfd->filename
- + strlen (input_bfd->filename) - 7,
+ && filename_cmp (input_bfd->filename
+ + strlen (input_bfd->filename) - 7,
"/crt0.o") == 0)
? -1 : 0;
#endif
&& picrel->d.h->root.type == bfd_link_hash_undefined))
info->callbacks->warning
(info,
- (info->shared || info->pie)
+ bfd_link_pic (info)
? _("relocations between different segments are not supported")
: _("warning: relocation references a different segment"),
name, input_bfd, input_section, rel->r_offset);
- if (!silence_segment_error && (info->shared || info->pie))
+ if (!silence_segment_error && bfd_link_pic (info))
return FALSE;
elf_elfheader (output_bfd)->e_flags |= EF_BFIN_PIC;
}
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. */
break;
}
- if (r_type == R_pcrel24
- || r_type == R_pcrel24_jump_l)
- {
- bfd_vma x;
- bfd_vma address = rel->r_offset;
-
- relocation += rel->r_addend;
-
- /* Perform usual pc-relative correction. */
- relocation -= input_section->output_section->vma + input_section->output_offset;
- relocation -= address;
-
- /* We are getting reloc_entry->address 2 byte off from
- the start of instruction. Assuming absolute postion
- of the reloc data. But, following code had been written assuming
- reloc address is starting at begining of instruction.
- To compensate that I have increased the value of
- relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
-
- relocation += 2;
- address -= 2;
-
- relocation >>= 1;
-
- x = bfd_get_16 (input_bfd, contents + address);
- x = (x & 0xff00) | ((relocation >> 16) & 0xff);
- bfd_put_16 (input_bfd, x, contents + address);
-
- x = bfd_get_16 (input_bfd, contents + address + 2);
- x = relocation & 0xFFFF;
- bfd_put_16 (input_bfd, x, contents + address + 2);
- r = bfd_reloc_ok;
- }
- else
- r = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, rel->r_offset,
- relocation, rel->r_addend);
+ r = bfin_final_link_relocate (rel, howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, rel->r_addend);
if (r != bfd_reloc_ok)
{
switch (r)
{
case bfd_reloc_overflow:
- r = info->callbacks->reloc_overflow
+ (*info->callbacks->reloc_overflow)
(info, (h ? &h->root : NULL), name, howto->name,
(bfd_vma) 0, input_bfd, input_section, rel->r_offset);
break;
case bfd_reloc_undefined:
- r = info->callbacks->undefined_symbol
+ (*info->callbacks->undefined_symbol)
(info, name, input_bfd, input_section, rel->r_offset, TRUE);
break;
case bfd_reloc_notsupported:
msg = _("internal error: unsupported relocation error");
- break;
-
- case bfd_reloc_dangerous:
- msg = _("internal error: dangerous relocation");
- break;
-
- 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;
-}
-
-static bfd_boolean
-bfin_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)
-{
- bfd *dynobj;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_vma *local_got_offsets;
- asection *sgot;
- asection *sreloc;
- Elf_Internal_Rela *rel;
- Elf_Internal_Rela *relend;
- int i = 0;
-
- dynobj = elf_hash_table (info)->dynobj;
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (input_bfd);
- local_got_offsets = elf_local_got_offsets (input_bfd);
-
- sgot = NULL;
- sreloc = NULL;
-
- rel = relocs;
- relend = relocs + input_section->reloc_count;
- for (; rel < relend; rel++, i++)
- {
- int r_type;
- reloc_howto_type *howto;
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
- asection *sec;
- bfd_vma relocation = 0;
- bfd_boolean unresolved_reloc;
- bfd_reloc_status_type r;
- bfd_vma address;
-
- r_type = ELF32_R_TYPE (rel->r_info);
- if (r_type < 0 || r_type >= 243)
- {
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
-
- if (r_type == R_BFIN_GNU_VTENTRY
- || r_type == R_BFIN_GNU_VTINHERIT)
- continue;
-
- howto = bfin_reloc_type_lookup (input_bfd, r_type);
- if (howto == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- r_symndx = ELF32_R_SYM (rel->r_info);
-
- h = NULL;
- sym = NULL;
- sec = NULL;
- unresolved_reloc = FALSE;
-
- 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);
- }
- else
- {
- bfd_boolean 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;
-
- address = rel->r_offset;
-
- /* Then, process normally. */
- switch (r_type)
- {
- case R_BFIN_GNU_VTINHERIT:
- case R_BFIN_GNU_VTENTRY:
- return bfd_reloc_ok;
-
- case R_got:
- /* Relocation is to the address of the entry for this symbol
- in the global offset table. */
- if (h != NULL
- && strcmp (h->root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
- goto do_default;
- /* Fall through. */
- /* Relocation is the offset of the entry for this symbol in
- the global offset table. */
-
- {
- bfd_vma off;
-
- if (sgot == NULL)
- {
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
- }
-
- if (h != NULL)
- {
- bfd_boolean dyn;
-
- off = h->got.offset;
- BFD_ASSERT (off != (bfd_vma) - 1);
- dyn = elf_hash_table (info)->dynamic_sections_created;
-
- if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
- || (info->shared
- && (info->symbolic
- || h->dynindx == -1
- || h->forced_local)
- && h->def_regular))
- {
- /* This is actually a static link, or it is a
- -Bsymbolic link and the symbol is defined
- locally, or the symbol was forced to be local
- because of a version file.. We must initialize
- this entry in the global offset table. Since
- the offset must always be a multiple of 4, we
- use the least significant bit to record whether
- we have initialized it already.
-
- When doing a dynamic link, we create a .rela.got
- relocation entry to initialize the value. This
- is done in the finish_dynamic_symbol routine. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation,
- sgot->contents + off);
- h->got.offset |= 1;
- }
- }
- else
- unresolved_reloc = FALSE;
- }
- else
- {
- BFD_ASSERT (local_got_offsets != NULL);
- off = local_got_offsets[r_symndx];
- BFD_ASSERT (off != (bfd_vma) - 1);
-
- /* The offset must always be a multiple of 4. We use
- the least significant bit to record whether we have
- already generated the necessary reloc. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation, sgot->contents + off);
-
- if (info->shared)
- {
- asection *s;
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
-
- s = bfd_get_section_by_name (dynobj, ".rela.got");
- BFD_ASSERT (s != NULL);
-
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset + off);
- outrel.r_info =
- ELF32_R_INFO (0, R_pcrel24);
- outrel.r_addend = relocation;
- loc = s->contents;
- loc +=
- s->reloc_count++ * sizeof (Elf32_External_Rela);
- bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
- }
-
- local_got_offsets[r_symndx] |= 1;
- }
- }
-
- relocation = sgot->output_offset + off;
- rel->r_addend = 0;
- /* bfin : preg = [preg + 17bitdiv4offset] relocation is div by 4. */
- relocation /= 4;
- }
- goto do_default;
-
- case R_pcrel24:
- case R_pcrel24_jump_l:
- {
- bfd_vma x;
-
- relocation += rel->r_addend;
-
- /* Perform usual pc-relative correction. */
- relocation -= input_section->output_section->vma + input_section->output_offset;
- relocation -= address;
-
- /* We are getting reloc_entry->address 2 byte off from
- the start of instruction. Assuming absolute postion
- of the reloc data. But, following code had been written assuming
- reloc address is starting at begining of instruction.
- To compensate that I have increased the value of
- relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
-
- relocation += 2;
- address -= 2;
-
- relocation >>= 1;
-
- x = bfd_get_16 (input_bfd, contents + address);
- x = (x & 0xff00) | ((relocation >> 16) & 0xff);
- bfd_put_16 (input_bfd, x, contents + address);
-
- x = bfd_get_16 (input_bfd, contents + address + 2);
- x = relocation & 0xFFFF;
- bfd_put_16 (input_bfd, x, contents + address + 2);
- r = bfd_reloc_ok;
- }
- break;
-
- default:
- do_default:
- r = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, address,
- relocation, rel->r_addend);
-
- break;
- }
-
- /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
- because such sections are not SEC_ALLOC and thus ld.so will
- not process them. */
- if (unresolved_reloc
- && !((input_section->flags & SEC_DEBUGGING) != 0 && h->def_dynamic))
- {
- (*_bfd_error_handler)
- (_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"),
- input_bfd,
- input_section, (long) rel->r_offset, h->root.root.string);
- return FALSE;
- }
+ break;
- if (r != bfd_reloc_ok)
- {
- const char *name;
+ case bfd_reloc_dangerous:
+ msg = _("internal error: dangerous relocation");
+ break;
- if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (name == NULL)
- return FALSE;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, sec);
+ default:
+ msg = _("internal error: unknown error");
+ break;
}
- if (r == bfd_reloc_overflow)
- {
- if (!(info->callbacks->reloc_overflow
- (info, (h ? &h->root : NULL), name, howto->name,
- (bfd_vma) 0, input_bfd, input_section, rel->r_offset)))
- return FALSE;
- }
- else
- {
- (*_bfd_error_handler)
- (_("%B(%A+0x%lx): reloc against `%s': error %d"),
- input_bfd, input_section,
- (long) rel->r_offset, name, (int) r);
- return FALSE;
- }
+ if (msg)
+ (*info->callbacks->warning) (info, msg, name, input_bfd,
+ input_section, rel->r_offset);
}
}
return TRUE;
}
-static asection *
-bfin_gc_mark_hook (asection * sec,
- struct bfd_link_info *info,
- Elf_Internal_Rela * rel,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym * sym)
-{
- if (h != NULL)
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_BFIN_GNU_VTINHERIT:
- case R_BFIN_GNU_VTENTRY:
- return NULL;
- }
-
- return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
-}
-
-/* Update the got entry reference counts for the section being removed. */
+/* Update the relocation information for the relocations of the section
+ being removed. */
static bfd_boolean
-bfin_gc_sweep_hook (bfd * abfd,
- struct bfd_link_info *info,
- asection * sec,
- const Elf_Internal_Rela * relocs)
+bfinfdpic_gc_sweep_hook (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *sec,
+ const Elf_Internal_Rela *relocs)
{
Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel, *relend;
- bfd *dynobj;
- asection *sgot;
- asection *srelgot;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ struct bfinfdpic_relocs_info *picrel;
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- return TRUE;
+ BFD_ASSERT (IS_FDPIC (abfd));
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
-
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ 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;
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
{
- unsigned long r_symndx;
struct elf_link_hash_entry *h;
+ unsigned long r_symndx;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ 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 TRUE;
switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_got:
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h->got.refcount > 0)
- {
- --h->got.refcount;
- if (h->got.refcount == 0)
- {
- /* We don't need the .got entry any more. */
- sgot->size -= 4;
- srelgot->size -= sizeof (Elf32_External_Rela);
- }
- }
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- {
- --local_got_refcounts[r_symndx];
- if (local_got_refcounts[r_symndx] == 0)
- {
- /* We don't need the .got entry any more. */
- sgot->size -= 4;
- if (info->shared)
- srelgot->size -= sizeof (Elf32_External_Rela);
- }
- }
- }
+ {
+ case R_BFIN_PCREL24:
+ case R_BFIN_PCREL24_JUMP_L:
+ picrel->call--;
+ break;
+
+ case R_BFIN_FUNCDESC_VALUE:
+ picrel->relocsfdv--;
+ if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ picrel->relocs32++;
+ /* Fall through. */
+
+ case R_BFIN_BYTE4_DATA:
+ picrel->sym--;
+ if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ picrel->relocs32--;
+ break;
+
+ case R_BFIN_GOT17M4:
+ picrel->got17m4--;
+ break;
+
+ case R_BFIN_GOTHI:
+ case R_BFIN_GOTLO:
+ picrel->gothilo--;
+ break;
+
+ case R_BFIN_FUNCDESC_GOT17M4:
+ picrel->fdgot17m4--;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTLO:
+ picrel->fdgothilo--;
+ break;
+
+ case R_BFIN_GOTOFF17M4:
+ case R_BFIN_GOTOFFHI:
+ case R_BFIN_GOTOFFLO:
+ picrel->gotoff--;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTOFF17M4:
+ picrel->fdgoff17m4--;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ picrel->fdgoffhilo--;
break;
+
+ case R_BFIN_FUNCDESC:
+ picrel->fd--;
+ picrel->relocsfd--;
+ break;
+
default:
break;
- }
+ }
}
+
return TRUE;
}
relocate independently. */
static bfd_boolean
_bfinfdpic_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info
- ATTRIBUTE_UNUSED,
- asection *p ATTRIBUTE_UNUSED)
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *p)
{
switch (elf_section_data (p)->this_hdr.sh_type)
{
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");
- if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
+ s = elf_hash_table (info)->sgot;
+ if (s != NULL)
return TRUE;
/* Machine specific: although pointers are 32-bits wide, we want the
| SEC_LINKER_CREATED);
pltflags = flags;
- s = bfd_make_section_with_flags (abfd, ".got", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
+ elf_hash_table (info)->sgot = s;
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
- if (bed->want_got_plt)
- {
- s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
- if (s == NULL
- || !bfd_set_section_alignment (abfd, s, ptralign))
- return FALSE;
- }
-
if (bed->want_got_sym)
{
/* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
data for the got. */
if (IS_FDPIC (abfd))
{
- bfinfdpic_got_section (info) = s;
bfinfdpic_relocs_info (info) = htab_try_create (1,
bfinfdpic_relocs_info_hash,
bfinfdpic_relocs_info_eq,
if (! bfinfdpic_relocs_info (info))
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".rel.got",
- (flags | SEC_READONLY));
+ s = bfd_make_section_anyway_with_flags (abfd, ".rel.got",
+ (flags | SEC_READONLY));
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 2))
return FALSE;
bfinfdpic_gotrel_section (info) = s;
/* Machine-specific. */
- s = bfd_make_section_with_flags (abfd, ".rofixup",
- (flags | SEC_READONLY));
+ s = bfd_make_section_anyway_with_flags (abfd, ".rofixup",
+ (flags | SEC_READONLY));
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 2))
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;
pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
- s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
{
/* 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
h->def_regular = 1;
h->type = STT_OBJECT;
- if (! info->executable
+ if (! bfd_link_executable (info)
&& ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Blackfin-specific: we want rel relocations for the plt. */
- s = bfd_make_section_with_flags (abfd, ".rel.plt", flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".rel.plt",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
/* 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;
not functions. We must allocate space for them in the process
image and use a R_*_COPY reloc to tell the dynamic linker to
initialize them at run time. The linker script puts the .dynbss
- section into the .bss section of the final image. */
- s = bfd_make_section_with_flags (abfd, ".dynbss",
- SEC_ALLOC | SEC_LINKER_CREATED);
- if (s == NULL)
- return FALSE;
-
- /* The .rel[a].bss section holds copy relocs. This section is not
- normally needed. We need to create it here, though, so that the
- linker will map it to an output section. We can't just create it
- only if we need it, because we will not know whether we need it
- until we have seen all the input files, and the first time the
- main linker code calls BFD after examining all the input files
- (size_dynamic_sections) the input sections have already been
- mapped to the output sections. If the section turns out not to
- be needed, we can discard it later. We will never need this
- section when generating a shared object, since they do not use
- copy relocs. */
- if (! info->shared)
- {
- s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"),
- flags | SEC_READONLY);
- if (s == NULL
- || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* The name of the dynamic interpreter. This is put in the .interp
- section. */
-
-#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
-
-#define DEFAULT_STACK_SIZE 0x20000
-
-/* This structure is used to collect the number of entries present in
- each addressable range of the got. */
-struct _bfinfdpic_dynamic_got_info
-{
- /* Several bits of information about the current link. */
- struct bfd_link_info *info;
- /* Total size needed for GOT entries within the 18- or 32-bit
- ranges. */
- bfd_vma got17m4, gothilo;
- /* Total size needed for function descriptor entries within the 18-
- or 32-bit ranges. */
- bfd_vma fd17m4, fdhilo;
- /* Total size needed function descriptor entries referenced in PLT
- entries, that would be profitable to place in offsets close to
- the PIC register. */
- bfd_vma fdplt;
- /* Total size needed by lazy PLT entries. */
- bfd_vma lzplt;
- /* Number of relocations carried over from input object files. */
- unsigned long relocs;
- /* Number of fixups introduced by relocations in input object files. */
- unsigned long fixups;
-};
+ section into the .bss section of the final image. */
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
+ if (s == NULL)
+ return FALSE;
+
+ /* The .rel[a].bss section holds copy relocs. This section is not
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! bfd_link_pic (info))
+ {
+ s = bfd_make_section_anyway_with_flags (abfd,
+ ".rela.bss",
+ flags | SEC_READONLY);
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
/* Compute the total GOT 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_)
+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)
+ if (!bfd_link_pde (dinfo->info))
relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
else
{
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 (bfd_link_executable (info) && !info->nointerp)
{
- 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_linker_section (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_linker_section (dynobj, ".dynbss");
+ if (s && s->size == 0)
+ s->flags |= SEC_EXCLUDE;
+
+ s = bfd_get_linker_section (dynobj, ".rela.bss");
+ if (s && s->size == 0)
+ s->flags |= SEC_EXCLUDE;
+
return TRUE;
}
elf32_bfinfdpic_always_size_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
- if (!info->relocatable)
- {
- struct elf_link_hash_entry *h;
-
- /* Force a PT_GNU_STACK segment to be created. */
- if (! elf_tdata (output_bfd)->stack_flags)
- elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
-
- /* Define __stacksize if it's not defined yet. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (! h || h->root.type != bfd_link_hash_defined
- || h->type != STT_OBJECT
- || !h->def_regular)
- {
- struct bfd_link_hash_entry *bh = NULL;
-
- if (!(_bfd_generic_link_add_one_symbol
- (info, output_bfd, "__stacksize",
- BSF_GLOBAL, bfd_abs_section_ptr, DEFAULT_STACK_SIZE,
- (const char *) NULL, FALSE,
- get_elf_backend_data (output_bfd)->collect, &bh)))
- return FALSE;
-
- h = (struct elf_link_hash_entry *) bh;
- h->def_regular = 1;
- h->type = STT_OBJECT;
- }
- }
+ if (!bfd_link_relocatable (info)
+ && !bfd_elf_stack_segment_size (output_bfd, info,
+ "__stacksize", DEFAULT_STACK_SIZE))
+ return FALSE;
return TRUE;
}
+/* Check whether any of the relocations was optimized away, and
+ subtract it from the relocation or fixup count. */
static bfd_boolean
-elf32_bfinfdpic_modify_program_headers (bfd *output_bfd,
- struct bfd_link_info *info)
+_bfinfdpic_check_discarded_relocs (bfd *abfd, asection *sec,
+ struct bfd_link_info *info,
+ bfd_boolean *changed)
{
- struct elf_obj_tdata *tdata = elf_tdata (output_bfd);
- struct elf_segment_map *m;
- Elf_Internal_Phdr *p;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ Elf_Internal_Rela *rel, *erel;
- /* objcopy and strip preserve what's already there using
- elf32_bfinfdpic_copy_private_bfd_data (). */
- if (! info)
+ if ((sec->flags & SEC_RELOC) == 0
+ || sec->reloc_count == 0)
return TRUE;
- for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
- if (m->p_type == PT_GNU_STACK)
- break;
+ 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;
- if (m)
+ 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;
- /* Obtain the pointer to the __stacksize symbol. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (h)
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
{
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
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;
- BFD_ASSERT (h->root.type == bfd_link_hash_defined);
+ h = (struct elf_link_hash_entry *)h->root.u.i.link;
}
- /* Set the header p_memsz from the symbol value. We
- intentionally ignore the symbol section. */
- if (h && h->root.type == bfd_link_hash_defined)
- p->p_memsz = h->root.u.def.value;
+ if (h != NULL)
+ picrel = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info (info),
+ abfd, h,
+ rel->r_addend, NO_INSERT);
else
- p->p_memsz = DEFAULT_STACK_SIZE;
+ 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);
+ }
- p->p_align = 8;
+ 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 == SEC_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;
if (bfinfdpic_got_section (info))
{
BFD_ASSERT (bfinfdpic_gotrel_section (info)->size
- == (bfinfdpic_gotrel_section (info)->reloc_count
+ /* PR 17334: It appears that the GOT section can end up
+ being bigger than the number of relocs. Presumably
+ because some relocs have been deleted. A test case has
+ yet to be generated for verify this, but in the meantime
+ the test below has been changed from == to >= so that
+ applications can continue to be built. */
+ >= (bfinfdpic_gotrel_section (info)->reloc_count
* sizeof (Elf32_External_Rel)));
if (bfinfdpic_gotfixup_section (info))
if (bfinfdpic_gotfixup_section (info)->size
!= (bfinfdpic_gotfixup_section (info)->reloc_count * 4))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
("LINKER BUG: .rofixup section size mismatch");
return FALSE;
}
* sizeof (Elf32_External_Rel)));
}
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created)
{
regular object. */
static bfd_boolean
-elf32_bfinfdpic_adjust_dynamic_symbol
-(struct bfd_link_info *info ATTRIBUTE_UNUSED,
- struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
+elf32_bfinfdpic_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
bfd * dynobj;
asection *sec, const Elf_Internal_Rela *relocs)
{
Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
bfd *dynobj;
struct bfinfdpic_relocs_info *picrel;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
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;
dynobj = elf_hash_table (info)->dynobj;
rel_end = relocs + sec->reloc_count;
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 = 1;
+ picrel->call++;
break;
case R_BFIN_FUNCDESC_VALUE:
picrel->relocs32--;
/* Fall through. */
- case R_byte4_data:
+ case R_BFIN_BYTE4_DATA:
if (! IS_FDPIC (abfd))
break;
- picrel->sym = 1;
+ picrel->sym++;
if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
picrel->relocs32++;
break;
case R_BFIN_GOT17M4:
- picrel->got17m4 = 1;
+ picrel->got17m4++;
break;
case R_BFIN_GOTHI:
case R_BFIN_GOTLO:
- picrel->gothilo = 1;
+ picrel->gothilo++;
break;
case R_BFIN_FUNCDESC_GOT17M4:
- picrel->fdgot17m4 = 1;
+ picrel->fdgot17m4++;
break;
case R_BFIN_FUNCDESC_GOTHI:
case R_BFIN_FUNCDESC_GOTLO:
- picrel->fdgothilo = 1;
+ picrel->fdgothilo++;
break;
case R_BFIN_GOTOFF17M4:
case R_BFIN_GOTOFFHI:
case R_BFIN_GOTOFFLO:
- picrel->gotoff = 1;
+ picrel->gotoff++;
break;
case R_BFIN_FUNCDESC_GOTOFF17M4:
- picrel->fdgoff17m4 = 1;
+ picrel->fdgoff17m4++;
break;
case R_BFIN_FUNCDESC_GOTOFFHI:
case R_BFIN_FUNCDESC_GOTOFFLO:
- picrel->fdgoffhilo = 1;
+ picrel->fdgoffhilo++;
break;
case R_BFIN_FUNCDESC:
- picrel->fd = 1;
+ picrel->fd++;
picrel->relocsfd++;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_BFIN_GNU_VTENTRY:
- if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ BFD_ASSERT (h != NULL);
+ if (h != NULL
+ && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
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:
bad_reloc:
- (*_bfd_error_handler)
- (_("%B: unsupported relocation type %i"),
- abfd, ELF32_R_TYPE (rel->r_info));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unsupported relocation type %d"),
+ abfd, (int) ELF32_R_TYPE (rel->r_info));
return FALSE;
}
}
return TRUE;
}
-/* Copy backend specific data from one object module to another. */
-
-static bfd_boolean
-bfin_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
-{
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- BFD_ASSERT (!elf_flags_init (obfd)
- || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
-
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = TRUE;
-
- /* Copy object attributes. */
- _bfd_elf_copy_obj_attributes (ibfd, obfd);
-
- return TRUE;
-}
-
-static bfd_boolean
-elf32_bfinfdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
-{
- unsigned i;
-
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- if (! bfin_elf_copy_private_bfd_data (ibfd, obfd))
- return FALSE;
-
- if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr
- || ! elf_tdata (obfd) || ! elf_tdata (obfd)->phdr)
- return TRUE;
-
- /* Copy the stack size. */
- for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++)
- if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK)
- {
- Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i];
-
- for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++)
- if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK)
- {
- memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr));
-
- /* Rewrite the phdrs, since we're only called after they
- were first written. */
- if (bfd_seek (obfd, (bfd_signed_vma) get_elf_backend_data (obfd)
- ->s->sizeof_ehdr, SEEK_SET) != 0
- || get_elf_backend_data (obfd)->s
- ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr,
- elf_elfheader (obfd)->e_phnum) != 0)
- return FALSE;
- break;
- }
-
- break;
- }
-
- return TRUE;
-}
-
-
/* Display the flags field. */
static bfd_boolean
-elf32_bfin_print_private_bfd_data (bfd * abfd, PTR ptr)
+elf32_bfin_print_private_bfd_data (bfd * abfd, void * ptr)
{
FILE *file = (FILE *) ptr;
flagword flags;
object file when linking. */
static bfd_boolean
-elf32_bfin_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+elf32_bfin_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
{
- flagword old_flags, old_partial;
- flagword new_flags, new_partial;
+ bfd *obfd = info->output_bfd;
+ flagword old_flags, new_flags;
bfd_boolean error = FALSE;
new_flags = elf_elfheader (ibfd)->e_flags;
if (new_flags & EF_BFIN_FDPIC)
new_flags &= ~EF_BFIN_PIC;
-#ifdef DEBUG
- (*_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));
+#ifndef DEBUG
+ if (0)
#endif
+ _bfd_error_handler
+ ("old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s, filename = %B",
+ old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no", ibfd);
if (!elf_flags_init (obfd)) /* First call, no flags set. */
{
elf_flags_init (obfd) = TRUE;
- old_flags = new_flags;
- }
-
- else if (new_flags == old_flags) /* Compatible flags are ok. */
- ;
-
- else /* Possibly incompatible flags. */
- {
- /* We don't have to do anything if the pic flags are the same, or the new
- module(s) were compiled with -mlibrary-pic. */
- new_partial = (new_flags & EF_BFIN_PIC_FLAGS);
- old_partial = (old_flags & EF_BFIN_PIC_FLAGS);
- if (new_partial == old_partial)
- ;
-
- /* If we have mixtures of -fpic and -fPIC, or in both bits. */
- else if (new_partial != 0 && old_partial != 0)
- old_flags |= new_partial;
-
- /* One module was compiled for pic and the other was not, see if we have
- had any relocations that are not pic-safe. */
- else
- old_flags |= new_partial;
-
+ elf_elfheader (obfd)->e_flags = new_flags;
}
- /* Update the old flags now with changes made above. */
- elf_elfheader (obfd)->e_flags = old_flags;
-
- if (((new_flags & EF_BFIN_FDPIC) == 0)
- != (! IS_FDPIC (ibfd)))
+ if (((new_flags & EF_BFIN_FDPIC) == 0) != (! IS_FDPIC (obfd)))
{
error = TRUE;
if (IS_FDPIC (obfd))
- (*_bfd_error_handler)
- (_("%s: cannot link non-fdpic object file into fdpic executable"),
- bfd_get_filename (ibfd));
+ _bfd_error_handler
+ (_("%B: cannot link non-fdpic object file into fdpic executable"),
+ ibfd);
else
- (*_bfd_error_handler)
- (_("%s: cannot link fdpic object file into non-fdpic executable"),
- bfd_get_filename (ibfd));
+ _bfd_error_handler
+ (_("%B: cannot link fdpic object file into non-fdpic executable"),
+ ibfd);
}
if (error)
{
struct elf_link_hash_table root;
- /* Small local sym to section mapping cache. */
- struct sym_sec_cache sym_sec;
+ /* Small local sym cache. */
+ struct sym_cache sym_cache;
};
#define bfin_hash_entry(ent) ((struct bfin_link_hash_entry *) (ent))
struct bfin_link_hash_table *ret;
bfd_size_type amt = sizeof (struct bfin_link_hash_table);
- ret = bfd_zalloc (abfd, amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
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;
}
- ret->sym_sec.abfd = NULL;
+ ret->sym_cache.abfd = NULL;
return &ret->root.root;
}
static bfd_boolean
bfin_finish_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info)
+ struct bfd_link_info *info)
{
bfd *dynobj;
asection *sdyn;
dynobj = elf_hash_table (info)->dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created)
{
static bfd_boolean
bfin_finish_dynamic_symbol (bfd * output_bfd,
- struct bfd_link_info *info,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym * sym)
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym * sym)
{
- bfd *dynobj;
-
- dynobj = elf_hash_table (info)->dynobj;
-
if (h->got.offset != (bfd_vma) - 1)
{
asection *sgot;
/* This symbol has an entry in the global offset table.
Set it up. */
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srela = bfd_get_section_by_name (dynobj, ".rela.got");
+ sgot = elf_hash_table (info)->sgot;
+ srela = elf_hash_table (info)->srelgot;
BFD_ASSERT (sgot != NULL && srela != NULL);
rela.r_offset = (sgot->output_section->vma
the symbol was forced to be local because of a version file.
The entry in the global offset table will already have been
initialized in the relocate_section function. */
- if (info->shared
+ if (bfd_link_pic (info)
&& (info->symbolic
|| 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);
+ _bfd_error_handler (_("*** check this relocation %s"),
+ __FUNCTION__);
+ 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;
}
static bfd_boolean
bfin_adjust_dynamic_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+ struct elf_link_hash_entry *h)
{
bfd *dynobj;
asection *s;
only references to the symbol are via the global offset table.
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
- if (info->shared)
+ if (bfd_link_pic (info))
return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = bfd_get_section_by_name (dynobj, ".dynbss");
+ s = bfd_get_linker_section (dynobj, ".dynbss");
BFD_ASSERT (s != NULL);
- /* We must generate a R_68K_COPY reloc to tell the dynamic linker to
+#if 0 /* Bfin does not currently have a COPY reloc. */
+ /* We must generate a R_BFIN_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
{
asection *srel;
- srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+ srel = bfd_get_linker_section (dynobj, ".rela.bss");
BFD_ASSERT (srel != NULL);
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
-
+#else
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
+ _bfd_error_handler (_("the bfin target does not currently support the generation of copy relocations"));
+ return FALSE;
+ }
+#endif
/* We need to figure out the alignment required for this symbol. I
have no idea how ELF linkers handle this. */
power_of_two = bfd_log2 (h->size);
case. */
static bfd_boolean
-bfin_discard_copies (struct elf_link_hash_entry *h, PTR inf)
+bfin_discard_copies (struct elf_link_hash_entry *h, void * inf)
{
struct bfd_link_info *info = (struct bfd_link_info *) inf;
struct bfin_pcrel_relocs_copied *s;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
if (!h->def_regular || (!info->symbolic && !h->forced_local))
{
if ((info->flags & DF_TEXTREL) == 0)
static bfd_boolean
bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info)
+ struct bfd_link_info *info)
{
bfd *dynobj;
asection *s;
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
+ if (bfd_link_executable (info))
{
- s = bfd_get_section_by_name (dynobj, ".interp");
+ s = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
not actually use these entries. Reset the size of .rela.got,
which will cause it to get stripped from the output file
below. */
- s = bfd_get_section_by_name (dynobj, ".rela.got");
+ s = elf_hash_table (info)->srelgot;
if (s != NULL)
s->size = 0;
}
against symbols that have become local due to visibility changes.
We allocated space for them in the check_relocs routine, but we
will not fill them in in the relocate_section routine. */
- if (info->shared)
+ if (bfd_link_pic (info))
elf_link_hash_traverse (elf_hash_table (info),
- bfin_discard_copies, (PTR) info);
+ bfin_discard_copies, info);
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (!info->shared)
+ if (!bfd_link_pic (info))
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
after the add_symbols entry point has been called for all the
objects, and before the final_link entry point is called. */
-bfd_boolean bfd_bfin_elf32_create_embedded_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *, char **));
-
bfd_boolean
-bfd_bfin_elf32_create_embedded_relocs (
- bfd *abfd,
- struct bfd_link_info *info,
- asection *datasec,
- asection *relsec,
- char **errmsg)
+bfd_bfin_elf32_create_embedded_relocs (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *datasec,
+ asection *relsec,
+ char **errmsg)
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *isymbuf = NULL;
bfd_byte *p;
bfd_size_type amt;
- BFD_ASSERT (! info->relocatable);
+ BFD_ASSERT (! bfd_link_relocatable (info));
*errmsg = NULL;
/* Get a copy of the native relocations. */
internal_relocs = (_bfd_elf_link_read_relocs
- (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ (abfd, datasec, NULL, (Elf_Internal_Rela *) NULL,
info->keep_memory));
if (internal_relocs == NULL)
goto error_return;
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);
free (internal_relocs);
return FALSE;
}
+
+struct bfd_elf_special_section const elf32_bfin_special_sections[] =
+{
+ { ".l1.text", 8, -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".l1.data", 8, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { NULL, 0, 0, 0, 0 }
+};
+
\f
-#define TARGET_LITTLE_SYM bfd_elf32_bfin_vec
+#define TARGET_LITTLE_SYM bfin_elf32_vec
#define TARGET_LITTLE_NAME "elf32-bfin"
#define ELF_ARCH bfd_arch_bfin
+#define ELF_TARGET_ID BFIN_ELF_DATA
#define ELF_MACHINE_CODE EM_BLACKFIN
#define ELF_MAXPAGESIZE 0x1000
#define elf_symbol_leading_char '_'
elf32_bfin_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data \
elf32_bfin_print_private_bfd_data
+#define elf_backend_final_write_processing \
+ elf32_bfin_final_write_processing
#define elf_backend_reloc_type_class elf32_bfin_reloc_type_class
+#define elf_backend_stack_align 8
#define elf_backend_can_gc_sections 1
+#define elf_backend_special_sections elf32_bfin_special_sections
#define elf_backend_can_refcount 1
#define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 1
#include "elf32-target.h"
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_bfinfdpic_vec
+#define TARGET_LITTLE_SYM bfin_elf32_fdpic_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-bfinfdpic"
#undef elf32_bed
#define elf32_bed elf32_bfinfdpic_bed
#undef elf_backend_gc_sweep_hook
+#define elf_backend_gc_sweep_hook bfinfdpic_gc_sweep_hook
#undef elf_backend_got_header_size
#define elf_backend_got_header_size 0
#undef elf_backend_always_size_sections
#define elf_backend_always_size_sections \
elf32_bfinfdpic_always_size_sections
-#undef elf_backend_modify_program_headers
-#define elf_backend_modify_program_headers \
- elf32_bfinfdpic_modify_program_headers
-#undef bfd_elf32_bfd_copy_private_bfd_data
-#define bfd_elf32_bfd_copy_private_bfd_data \
- elf32_bfinfdpic_copy_private_bfd_data
#undef elf_backend_create_dynamic_sections
#define elf_backend_create_dynamic_sections \
#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