/* Xilinx MicroBlaze-specific support for 32-bit ELF
- Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2009-2019 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
{
/* This reloc does nothing. */
HOWTO (R_MICROBLAZE_NONE, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- NULL, /* Special Function. */
- "R_MICROBLAZE_NONE", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 3, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ NULL, /* Special Function. */
+ "R_MICROBLAZE_NONE", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* A standard 32 bit relocation. */
- HOWTO (R_MICROBLAZE_32, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_32", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0xffffffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_32, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 32, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_32", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0xffffffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* A standard PCREL 32 bit relocation. */
HOWTO (R_MICROBLAZE_32_PCREL,/* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_32_PCREL", /* Name. */
- TRUE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0xffffffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 32, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_32_PCREL", /* Name. */
+ TRUE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0xffffffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* A 64 bit PCREL relocation. Table-entry not really used. */
HOWTO (R_MICROBLAZE_64_PCREL,/* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_64_PCREL", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_64_PCREL", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* The low half of a PCREL 32 bit relocation. */
- HOWTO (R_MICROBLAZE_32_PCREL_LO, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain on overflow. */
- bfd_elf_generic_reloc, /* Special Function. */
- "R_MICROBLAZE_32_PCREL_LO", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_32_PCREL_LO, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed, /* Complain on overflow. */
+ bfd_elf_generic_reloc, /* Special Function. */
+ "R_MICROBLAZE_32_PCREL_LO", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* A 64 bit relocation. Table entry not really used. */
- HOWTO (R_MICROBLAZE_64, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_64", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_64, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_64", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* The low half of a 32 bit relocation. */
- HOWTO (R_MICROBLAZE_32_LO, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_32_LO", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_32_LO, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_32_LO", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* Read-only small data section relocation. */
- HOWTO (R_MICROBLAZE_SRO32, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_SRO32", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_SRO32, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_SRO32", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* Read-write small data area relocation. */
- HOWTO (R_MICROBLAZE_SRW32, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_SRW32", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
-
- /* This reloc does nothing. Used for relaxation. */
+ HOWTO (R_MICROBLAZE_SRW32, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_SRW32", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
+
+ /* This reloc does nothing. Used for relaxation. */
HOWTO (R_MICROBLAZE_64_NONE, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- NULL, /* Special Function. */
- "R_MICROBLAZE_64_NONE",/* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 3, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ NULL, /* Special Function. */
+ "R_MICROBLAZE_64_NONE",/* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* Symbol Op Symbol relocation. */
- HOWTO (R_MICROBLAZE_32_SYM_OP_SYM, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0xffffffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_32_SYM_OP_SYM, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 32, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0xffffffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain on overflow. */
- NULL, /* Special Function. */
- "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain on overflow. */
+ NULL, /* Special Function. */
+ "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* GNU extension to record C++ vtable member usage. */
HOWTO (R_MICROBLAZE_GNU_VTENTRY, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain on overflow. */
- _bfd_elf_rel_vtable_reloc_fn, /* Special Function. */
- "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain on overflow. */
+ _bfd_elf_rel_vtable_reloc_fn, /* Special Function. */
+ "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* A 64 bit GOTPC relocation. Table-entry not really used. */
- HOWTO (R_MICROBLAZE_GOTPC_64, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc, /* Special Function. */
- "R_MICROBLAZE_GOTPC_64", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_GOTPC_64, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc, /* Special Function. */
+ "R_MICROBLAZE_GOTPC_64", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
+
+ /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */
+ HOWTO (R_MICROBLAZE_TEXTPCREL_64, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc, /* Special Function. */
+ "R_MICROBLAZE_TEXTPCREL_64", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* A 64 bit GOT relocation. Table-entry not really used. */
HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_GOT_64",/* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_GOT_64",/* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
+
+ /* A 64 bit TEXTREL relocation. Table-entry not really used. */
+ HOWTO (R_MICROBLAZE_TEXTREL_64, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_TEXTREL_64",/* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* A 64 bit PLT relocation. Table-entry not really used. */
HOWTO (R_MICROBLAZE_PLT_64, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_PLT_64",/* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_PLT_64",/* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* Table-entry not really used. */
- HOWTO (R_MICROBLAZE_REL, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_REL", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_REL, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_REL", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* Table-entry not really used. */
HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_JUMP_SLOT", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_JUMP_SLOT", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* Table-entry not really used. */
HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_GLOB_DAT", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- TRUE), /* PC relative offset? */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_GLOB_DAT", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ TRUE), /* PC relative offset? */
/* A 64 bit GOT relative relocation. Table-entry not really used. */
- HOWTO (R_MICROBLAZE_GOTOFF_64, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_GOTOFF_64", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_GOTOFF_64, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_GOTOFF_64", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* A 32 bit GOT relative relocation. Table-entry not really used. */
- HOWTO (R_MICROBLAZE_GOTOFF_32, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc, /* Special Function. */
- "R_MICROBLAZE_GOTOFF_32", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_GOTOFF_32, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc, /* Special Function. */
+ "R_MICROBLAZE_GOTOFF_32", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
/* COPY relocation. Table-entry not really used. */
- HOWTO (R_MICROBLAZE_COPY, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- FALSE, /* PC_relative. */
- 0, /* Bitpos. */
- complain_overflow_dont, /* Complain on overflow. */
- bfd_elf_generic_reloc,/* Special Function. */
- "R_MICROBLAZE_COPY", /* Name. */
- FALSE, /* Partial Inplace. */
- 0, /* Source Mask. */
- 0x0000ffff, /* Dest Mask. */
- FALSE), /* PC relative offset? */
+ HOWTO (R_MICROBLAZE_COPY, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ FALSE, /* PC_relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont, /* Complain on overflow. */
+ bfd_elf_generic_reloc,/* Special Function. */
+ "R_MICROBLAZE_COPY", /* Name. */
+ FALSE, /* Partial Inplace. */
+ 0, /* Source Mask. */
+ 0x0000ffff, /* Dest Mask. */
+ FALSE), /* PC relative offset? */
+
+ /* Marker relocs for TLS. */
+ HOWTO (R_MICROBLAZE_TLS,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MICROBLAZE_TLSGD,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSGD", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MICROBLAZE_TLSLD,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSLD", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes the load module index of the load module that contains the
+ definition of its TLS sym. */
+ HOWTO (R_MICROBLAZE_TLSDTPMOD32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSDTPMOD32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a dtv-relative displacement, the difference between the value
+ of sym+add and the base address of the thread-local storage block that
+ contains the definition of sym, minus 0x8000. Used for initializing GOT */
+ HOWTO (R_MICROBLAZE_TLSDTPREL32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSDTPREL32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a dtv-relative displacement, the difference between the value
+ of sym+add and the base address of the thread-local storage block that
+ contains the definition of sym, minus 0x8000. */
+ HOWTO (R_MICROBLAZE_TLSDTPREL64,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSDTPREL64", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a tp-relative displacement, the difference between the value of
+ sym+add and the value of the thread pointer (r13). */
+ HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSGOTTPREL32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a tp-relative displacement, the difference between the value of
+ sym+add and the value of the thread pointer (r13). */
+ HOWTO (R_MICROBLAZE_TLSTPREL32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSTPREL32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
};
#ifndef NUM_ELEM
case BFD_RELOC_MICROBLAZE_64_GOT:
microblaze_reloc = R_MICROBLAZE_GOT_64;
break;
+ case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
+ microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TEXTREL:
+ microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
+ break;
case BFD_RELOC_MICROBLAZE_64_PLT:
microblaze_reloc = R_MICROBLAZE_PLT_64;
break;
case BFD_RELOC_MICROBLAZE_32_GOTOFF:
microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
break;
+ case BFD_RELOC_MICROBLAZE_64_TLSGD:
+ microblaze_reloc = R_MICROBLAZE_TLSGD;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSLD:
+ microblaze_reloc = R_MICROBLAZE_TLSLD;
+ break;
+ case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
+ break;
+ case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
+ microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
+ break;
case BFD_RELOC_MICROBLAZE_COPY:
microblaze_reloc = R_MICROBLAZE_COPY;
break;
/* Set the howto pointer for a RCE ELF reloc. */
-static void
-microblaze_elf_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
+static bfd_boolean
+microblaze_elf_info_to_howto (bfd * abfd,
arelent * cache_ptr,
Elf_Internal_Rela * dst)
{
+ unsigned int r_type;
+
if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
/* Initialize howto table if needed. */
microblaze_elf_howto_init ();
- BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MICROBLAZE_max);
+ r_type = ELF32_R_TYPE (dst->r_info);
+ if (r_type >= R_MICROBLAZE_max)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
- cache_ptr->howto = microblaze_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
+ cache_ptr->howto = microblaze_elf_howto_table [r_type];
+ return TRUE;
}
/* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
return _bfd_elf_is_local_label_name (abfd, name);
}
-/* The microblaze linker (like many others) needs to keep track of
- the number of relocs that it decides to copy as dynamic relocs in
- check_relocs for each symbol. This is so that it can later discard
- them if they are found to be unnecessary. We store the information
- in a field extending the regular ELF linker hash table. */
-
-struct elf32_mb_dyn_relocs
-{
- struct elf32_mb_dyn_relocs *next;
-
- /* The input section of the reloc. */
- asection *sec;
-
- /* Total number of relocs copied for the input section. */
- bfd_size_type count;
-
- /* Number of pc-relative relocs copied for the input section. */
- bfd_size_type pc_count;
-};
-
/* ELF linker hash entry. */
struct elf32_mb_link_hash_entry
struct elf_link_hash_entry elf;
/* Track dynamic relocs copied for this symbol. */
- struct elf32_mb_dyn_relocs *dyn_relocs;
+ struct elf_dyn_relocs *dyn_relocs;
+
+ /* TLS Reference Types for the symbol; Updated by check_relocs */
+#define TLS_GD 1 /* GD reloc. */
+#define TLS_LD 2 /* LD reloc. */
+#define TLS_TPREL 4 /* TPREL reloc, => IE. */
+#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
+#define TLS_TLS 16 /* Any TLS reloc. */
+ unsigned char tls_mask;
};
+#define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
+#define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
+#define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
+#define IS_TLS_NONE(x) (x == 0)
+
#define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
/* ELF linker hash table. */
{
struct elf_link_hash_table elf;
- /* Short-cuts to get to dynamic linker sections. */
- asection *sgot;
- asection *sgotplt;
- asection *srelgot;
- asection *splt;
- asection *srelplt;
- asection *sdynbss;
- asection *srelbss;
-
/* Small local sym to section mapping cache. */
struct sym_cache sym_sec;
+
+ /* TLS Local Dynamic GOT Entry */
+ union {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } tlsld_got;
};
+/* Nonzero if this section has TLS related relocations. */
+#define has_tls_reloc sec_flg0
+
/* Get the ELF linker hash table from a link_info structure. */
#define elf32_mb_hash_table(p) \
eh = (struct elf32_mb_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
+ eh->tls_mask = 0;
}
return entry;
if (h != (struct bfd_link_hash_entry *) NULL
&& h->type == bfd_link_hash_defined)
ro_small_data_pointer = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
h = bfd_link_hash_lookup (info->hash, RW_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
if (h != (struct bfd_link_hash_entry *) NULL
&& h->type == bfd_link_hash_defined)
rw_small_data_pointer = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
+}
+
+static bfd_vma
+dtprel_base (struct bfd_link_info *info)
+{
+ /* If tls_sec is NULL, we should have signalled an error already. */
+ if (elf_hash_table (info)->tls_sec == NULL)
+ return 0;
+ return elf_hash_table (info)->tls_sec->vma;
+}
+
+/* The size of the thread control block. */
+#define TCB_SIZE 8
+
+/* Output a simple dynamic relocation into SRELOC. */
+
+static void
+microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
+ asection *sreloc,
+ unsigned long reloc_index,
+ unsigned long indx,
+ int r_type,
+ bfd_vma offset,
+ bfd_vma addend)
+{
+
+ Elf_Internal_Rela rel;
+
+ rel.r_info = ELF32_R_INFO (indx, r_type);
+ rel.r_offset = offset;
+ rel.r_addend = addend;
+
+ bfd_elf32_swap_reloca_out (output_bfd, &rel,
+ (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
}
/* This code is taken from elf32-m32r.c
static bfd_boolean
microblaze_elf_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)
+ 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)
{
struct elf32_mb_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
Elf_Internal_Rela *rel, *relend;
+ int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
/* Assume success. */
bfd_boolean ret = TRUE;
asection *sreloc;
bfd_vma *local_got_offsets;
+ unsigned int tls_type;
if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
microblaze_elf_howto_init ();
h = NULL;
r_type = ELF32_R_TYPE (rel->r_info);
+ tls_type = 0;
+
if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
{
- (*_bfd_error_handler) (_("%s: unknown relocation type %d"),
- bfd_get_filename (input_bfd), (int) r_type);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
continue;
howto = microblaze_elf_howto_table[r_type];
r_symndx = ELF32_R_SYM (rel->r_info);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
{
/* This is a relocatable link. We don't have to change
anything, unless the reloc is against a section symbol,
else
{
bfd_vma relocation;
+ bfd_boolean resolved_to_zero;
/* This is a final link. */
sym = NULL;
{
/* External symbol. */
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
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);
sym_name = h->root.root.string;
}
goto check_reloc;
}
+ resolved_to_zero = (h != NULL
+ && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+
switch ((int) r_type)
{
case (int) R_MICROBLAZE_SRO32 :
/* Only relocate if the symbol is defined. */
if (sec)
{
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_get_section_name (sec->owner, sec);
if (strcmp (name, ".sdata2") == 0
|| strcmp (name, ".sbss2") == 0)
}
else
{
- (*_bfd_error_handler) (_("%s: The target (%s) of an %s relocation is in the wrong section (%s)"),
- bfd_get_filename (input_bfd),
- sym_name,
- microblaze_elf_howto_table[(int) r_type]->name,
- bfd_get_section_name (abfd, sec));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: the target (%s) of an %s relocation"
+ " is in the wrong section (%pA)"),
+ input_bfd,
+ sym_name,
+ microblaze_elf_howto_table[(int) r_type]->name,
+ sec);
/*bfd_set_error (bfd_error_bad_value); ??? why? */
ret = FALSE;
continue;
/* Only relocate if the symbol is defined. */
if (sec)
{
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_get_section_name (sec->owner, sec);
if (strcmp (name, ".sdata") == 0
|| strcmp (name, ".sbss") == 0)
}
else
{
- (*_bfd_error_handler) (_("%s: The target (%s) of an %s relocation is in the wrong section (%s)"),
- bfd_get_filename (input_bfd),
- sym_name,
- microblaze_elf_howto_table[(int) r_type]->name,
- bfd_get_section_name (abfd, sec));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: the target (%s) of an %s relocation"
+ " is in the wrong section (%pA)"),
+ input_bfd,
+ sym_name,
+ microblaze_elf_howto_table[(int) r_type]->name,
+ sec);
/*bfd_set_error (bfd_error_bad_value); ??? why? */
ret = FALSE;
continue;
break; /* Do nothing. */
case (int) R_MICROBLAZE_GOTPC_64:
- relocation = htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ relocation = (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset);
relocation -= (input_section->output_section->vma
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
relocation += addend;
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
+ break;
+
+ case (int) R_MICROBLAZE_TEXTPCREL_64:
+ relocation = input_section->output_section->vma;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ + offset + INST_WORD_SIZE);
+ relocation += addend;
+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+ contents + offset + endian);
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + endian + INST_WORD_SIZE);
break;
case (int) R_MICROBLAZE_PLT_64:
{
bfd_vma immediate;
- if (htab->splt != NULL && h != NULL
+ if (htab->elf.splt != NULL && h != NULL
&& h->plt.offset != (bfd_vma) -1)
{
- relocation = (htab->splt->output_section->vma
- + htab->splt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ h->plt.offset);
unresolved_reloc = FALSE;
immediate = relocation - (input_section->output_section->vma
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, immediate & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
}
else
{
+ offset + INST_WORD_SIZE);
immediate = relocation;
bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, immediate & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
}
break;
}
+ case (int) R_MICROBLAZE_TLSGD:
+ tls_type = (TLS_TLS | TLS_GD);
+ goto dogot;
+ case (int) R_MICROBLAZE_TLSLD:
+ tls_type = (TLS_TLS | TLS_LD);
+ /* Fall through. */
+ dogot:
case (int) R_MICROBLAZE_GOT_64:
{
- if (htab->sgot == NULL)
+ bfd_vma *offp;
+ bfd_vma off, off2;
+ unsigned long indx;
+ bfd_vma static_value;
+
+ bfd_boolean need_relocs = FALSE;
+ if (htab->elf.sgot == NULL)
abort ();
- if (h == NULL)
+
+ indx = 0;
+ offp = NULL;
+
+ /* 1. Identify GOT Offset;
+ 2. Compute Static Values
+ 3. Process Module Id, Process Offset
+ 4. Fixup Relocation with GOT offset value. */
+
+ /* 1. Determine GOT Offset to use : TLS_LD, global, local */
+ if (IS_TLS_LD (tls_type))
+ offp = &htab->tlsld_got.offset;
+ else if (h != NULL)
+ {
+ if (htab->elf.sgotplt != NULL
+ && h->got.offset != (bfd_vma) -1)
+ offp = &h->got.offset;
+ else
+ abort ();
+ }
+ else
{
- bfd_vma off;
if (local_got_offsets == NULL)
abort ();
- off = local_got_offsets[r_symndx];
- /* The LSB indicates whether we've already
- created relocation. */
- if (off & 1)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation + addend,
- htab->sgot->contents + off);
+ offp = &local_got_offsets[r_symndx];
+ }
- if (info->shared)
- {
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
- if (htab->srelgot == NULL)
- abort ();
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
- + off);
- outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
- outrel.r_addend = relocation + addend;
- loc = htab->srelgot->contents;
- loc += htab->srelgot->reloc_count++
- * sizeof (Elf32_External_Rela);
- bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
- }
- local_got_offsets[r_symndx] |= 1;
- }
- relocation = htab->sgot->output_section->vma
- + htab->sgot->output_offset + off
- - htab->sgotplt->output_section->vma
- - htab->sgotplt->output_offset;
- unresolved_reloc = FALSE;
+ if (!offp)
+ abort ();
+
+ off = (*offp) & ~1;
+ off2 = off;
+
+ if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
+ off2 = off + 4;
+
+ /* Symbol index to use for relocs */
+ if (h != NULL)
+ {
+ bfd_boolean dyn =
+ elf_hash_table (info)->dynamic_sections_created;
+
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+ bfd_link_pic (info),
+ h)
+ && (!bfd_link_pic (info)
+ || !SYMBOL_REFERENCES_LOCAL (info, h)))
+ indx = h->dynindx;
}
- else
+
+ /* Need to generate relocs ? */
+ if ((bfd_link_pic (info) || indx != 0)
+ && (h == NULL
+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !resolved_to_zero)
+ || h->root.type != bfd_link_hash_undefweak))
+ need_relocs = TRUE;
+
+ /* 2. Compute/Emit Static value of r-expression */
+ static_value = relocation + addend;
+
+ /* 3. Process module-id and offset */
+ if (! ((*offp) & 1) )
{
- if (htab->sgotplt != NULL && h != NULL
- && h->got.offset != (bfd_vma) -1)
+ bfd_vma got_offset;
+
+ got_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off);
+
+ /* Process module-id */
+ if (IS_TLS_LD(tls_type))
+ {
+ if (! bfd_link_pic (info))
+ bfd_put_32 (output_bfd, 1,
+ htab->elf.sgot->contents + off);
+ else
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
+ got_offset, 0);
+ }
+ else if (IS_TLS_GD(tls_type))
+ {
+ if (! need_relocs)
+ bfd_put_32 (output_bfd, 1,
+ htab->elf.sgot->contents + off);
+ else
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
+ got_offset, indx ? 0 : static_value);
+ }
+
+ /* Process Offset */
+ if (htab->elf.srelgot == NULL)
+ abort ();
+
+ got_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off2);
+ if (IS_TLS_LD(tls_type))
+ {
+ /* For LD, offset should be 0 */
+ *offp |= 1;
+ bfd_put_32 (output_bfd, 0,
+ htab->elf.sgot->contents + off2);
+ }
+ else if (IS_TLS_GD(tls_type))
{
- bfd_put_32 (output_bfd, relocation + addend,
- htab->sgot->contents + h->got.offset);
- relocation = htab->sgot->output_section->vma
- + htab->sgot->output_offset
- + h->got.offset
- - htab->sgotplt->output_section->vma
- - htab->sgotplt->output_offset;
- unresolved_reloc = FALSE;
+ *offp |= 1;
+ static_value -= dtprel_base(info);
+ if (need_relocs)
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
+ got_offset, indx ? 0 : static_value);
+ else
+ bfd_put_32 (output_bfd, static_value,
+ htab->elf.sgot->contents + off2);
}
else
- abort (); /* ??? */
+ {
+ bfd_put_32 (output_bfd, static_value,
+ htab->elf.sgot->contents + off2);
+
+ /* Relocs for dyn symbols generated by
+ finish_dynamic_symbols */
+ if (bfd_link_pic (info) && h == NULL)
+ {
+ *offp |= 1;
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ indx, R_MICROBLAZE_REL,
+ got_offset, static_value);
+ }
+ }
}
+
+ /* 4. Fixup Relocation with GOT offset value
+ Compute relative address of GOT entry for applying
+ the current relocation */
+ relocation = htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off
+ - htab->elf.sgotplt->output_section->vma
+ - htab->elf.sgotplt->output_offset;
+
+ /* Apply Current Relocation */
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
+
+ unresolved_reloc = FALSE;
break;
}
bfd_vma immediate;
unsigned short lo, high;
relocation += addend;
- relocation -= htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ relocation -= (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset);
/* Write this value into correct location. */
immediate = relocation;
lo = immediate & 0x0000ffff;
high = (immediate >> 16) & 0x0000ffff;
- bfd_put_16 (input_bfd, high, contents + offset + 2);
- bfd_put_16 (input_bfd, lo, contents + offset + INST_WORD_SIZE + 2);
+ bfd_put_16 (input_bfd, high, contents + offset + endian);
+ bfd_put_16 (input_bfd, lo,
+ contents + offset + INST_WORD_SIZE + endian);
break;
}
case (int) R_MICROBLAZE_GOTOFF_32:
{
relocation += addend;
- relocation -= htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ relocation -= (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset);
/* Write this value into correct location. */
bfd_put_32 (input_bfd, relocation, contents + offset);
break;
}
+ case (int) R_MICROBLAZE_TLSDTPREL64:
+ relocation += addend;
+ relocation -= dtprel_base(info);
+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+ contents + offset + 2);
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + 2 + INST_WORD_SIZE);
+ break;
+ case (int) R_MICROBLAZE_TEXTREL_64:
+ case (int) R_MICROBLAZE_TEXTREL_32_LO:
case (int) R_MICROBLAZE_64_PCREL :
case (int) R_MICROBLAZE_64:
case (int) R_MICROBLAZE_32:
relocation -= (input_section->output_section->vma
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
- bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
- bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ else if (r_type == R_MICROBLAZE_TEXTREL_64
+ || r_type == R_MICROBLAZE_TEXTREL_32_LO)
+ relocation -= input_section->output_section->vma;
+
+ if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + endian);
+
+ else
+ {
+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+ contents + offset + endian);
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + endian + INST_WORD_SIZE);
}
+ }
break;
}
- if ((info->shared
+ if ((bfd_link_pic (info)
&& (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak)
&& (!howto->pc_relative
|| (h != NULL
&& h->dynindx != -1
&& (!info->symbolic
|| !h->def_regular))))
- || (!info->shared
+ || (!bfd_link_pic (info)
&& h != NULL
&& h->dynindx != -1
&& !h->non_got_ref
else
{
BFD_FAIL ();
- (*_bfd_error_handler)
- (_("%B: probably compiled without -fPIC?"),
+ _bfd_error_handler
+ (_("%pB: probably compiled without -fPIC?"),
input_bfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
relocation -= (input_section->output_section->vma
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
- bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
- bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
- }
+ else if (r_type == R_MICROBLAZE_TEXTREL_64
+ || r_type == R_MICROBLAZE_TEXTREL_32_LO)
+ relocation -= input_section->output_section->vma;
+
+ if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
+ {
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + endian);
+ }
+ else
+ {
+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+ contents + offset + endian);
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + endian
+ + INST_WORD_SIZE);
+ }
+ }
break;
}
}
switch (r)
{
case bfd_reloc_overflow:
- if (!((*info->callbacks->reloc_overflow)
- (info, (h ? &h->root : NULL), name, howto->name,
- (bfd_vma) 0, input_bfd, input_section, offset)))
- return FALSE;
+ (*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, offset);
break;
case bfd_reloc_undefined:
- if (!((*info->callbacks->undefined_symbol)
- (info, name, input_bfd, input_section, offset, TRUE)))
- return FALSE;
+ (*info->callbacks->undefined_symbol)
+ (info, name, input_bfd, input_section, offset, TRUE);
break;
case bfd_reloc_outofrange:
errmsg = _("internal error: unknown error");
/* Fall through. */
common_error:
- if (!((*info->callbacks->warning)
- (info, errmsg, name, input_bfd, input_section, offset)))
- return FALSE;
+ (*info->callbacks->warning) (info, errmsg, name, input_bfd,
+ input_section, offset);
break;
}
}
/* Calculate fixup value for reference. */
static int
-calc_fixup (bfd_vma addr, asection *sec)
+calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
{
+ bfd_vma end = start + size;
int i, fixup = 0;
if (sec == NULL || sec->relax == NULL)
/* Look for addr in relax table, total fixup value. */
for (i = 0; i < sec->relax_count; i++)
{
- if (addr <= sec->relax[i].addr)
- break;
+ if (end <= sec->relax[i].addr)
+ break;
+ if ((end != start) && (start > sec->relax[i].addr))
+ continue;
fixup += sec->relax[i].size;
}
-
return fixup;
}
+/* Read-modify-write into the bfd, an immediate value into appropriate fields of
+ a 32-bit instruction. */
+static void
+microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
+{
+ unsigned long instr = bfd_get_32 (abfd, bfd_addr);
+ instr &= ~0x0000ffff;
+ instr |= (val & 0x0000ffff);
+ bfd_put_32 (abfd, instr, bfd_addr);
+}
+
+/* Read-modify-write into the bfd, an immediate value into appropriate fields of
+ two consecutive 32-bit instructions. */
+static void
+microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
+{
+ unsigned long instr_hi;
+ unsigned long instr_lo;
+
+ instr_hi = bfd_get_32 (abfd, bfd_addr);
+ instr_hi &= ~0x0000ffff;
+ instr_hi |= ((val >> 16) & 0x0000ffff);
+ bfd_put_32 (abfd, instr_hi, bfd_addr);
+
+ instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
+ instr_lo &= ~0x0000ffff;
+ instr_lo |= (val & 0x0000ffff);
+ bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
+}
+
static bfd_boolean
microblaze_elf_relax_section (bfd *abfd,
asection *sec,
*again = FALSE;
/* Only do this for a text section. */
- if (link_info->relocatable
+ if (bfd_link_relocatable (link_info)
|| (sec->flags & SEC_RELOC) == 0
- || (sec->reloc_count == 0))
+ || (sec->reloc_count == 0)
+ || (sec->flags & SEC_CODE) == 0)
return TRUE;
BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
symcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL, NULL);
BFD_ASSERT (isymbuf != NULL);
internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
{
bfd_vma symval;
if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
- && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64 ))
+ && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
+ && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
continue; /* Can't delete this reloc. */
/* Get the section contents. */
if (!bfd_get_section_contents (abfd, sec, contents,
(file_ptr) 0, sec->size))
goto error_return;
- elf_section_data (sec)->this_hdr.contents = contents;
+ elf_section_data (sec)->this_hdr.contents = contents;
}
}
asection *sym_sec;
isym = isymbuf + ELF32_R_SYM (irel->r_info);
- if (isym->st_shndx == SHN_UNDEF)
+ if (isym->st_shndx == SHN_UNDEF)
sym_sec = bfd_und_section_ptr;
else if (isym->st_shndx == SHN_ABS)
sym_sec = bfd_abs_section_ptr;
h = elf_sym_hashes (abfd)[indx];
BFD_ASSERT (h != NULL);
- if (h->root.type != bfd_link_hash_defined
+ if (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
/* This appears to be a reference to an undefined
symbol. Just ignore it--it will be caught by the
}
/* If this is a PC-relative reloc, subtract the instr offset from
- the symbol value. */
+ the symbol value. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
{
symval = symval + irel->r_addend
- (irel->r_offset
+ sec->output_section->vma
+ sec->output_offset);
- }
+ }
+ else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
+ {
+ symval = symval + irel->r_addend - (sec->output_section->vma);
+ }
else
symval += irel->r_addend;
if ((symval & 0xffff8000) == 0
|| (symval & 0xffff8000) == 0xffff8000)
{
- /* We can delete this instruction. */
+ /* We can delete this instruction. */
sec->relax[sec->relax_count].addr = irel->r_offset;
sec->relax[sec->relax_count].size = INST_WORD_SIZE;
sec->relax_count++;
/* Rewrite relocation type. */
- switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
+ switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
{
case R_MICROBLAZE_64_PCREL:
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- (int) R_MICROBLAZE_32_PCREL_LO);
+ (int) R_MICROBLAZE_32_PCREL_LO);
break;
case R_MICROBLAZE_64:
- irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- (int) R_MICROBLAZE_32_LO);
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ (int) R_MICROBLAZE_32_LO);
+ break;
+ case R_MICROBLAZE_TEXTREL_64:
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ (int) R_MICROBLAZE_TEXTREL_32_LO);
break;
default:
/* Cannot happen. */
BFD_ASSERT (FALSE);
- }
- }
+ }
+ }
} /* Loop through all relocations. */
/* Loop through the relocs again, and see if anything needs to change. */
sec->relax[sec->relax_count].addr = sec->size;
for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
- {
+ {
bfd_vma nraddr;
- /* Get the new reloc address. */
- nraddr = irel->r_offset - calc_fixup (irel->r_offset, sec);
- switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
+ /* Get the new reloc address. */
+ nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
+ switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
{
default:
break;
case R_MICROBLAZE_64_PCREL:
break;
+ case R_MICROBLAZE_TEXTREL_64:
+ case R_MICROBLAZE_TEXTREL_32_LO:
case R_MICROBLAZE_64:
case R_MICROBLAZE_32_LO:
/* If this reloc is against a symbol defined in this
- section, we must check the addend to see it will put the value in
- range to be adjusted, and hence must be changed. */
+ section, we must check the addend to see it will put the value in
+ range to be adjusted, and hence must be changed. */
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
- {
+ {
isym = isymbuf + ELF32_R_SYM (irel->r_info);
/* Only handle relocs against .text. */
if (isym->st_shndx == shndx
&& ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
- irel->r_addend -= calc_fixup (irel->r_addend, sec);
- }
+ irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
+ }
break;
case R_MICROBLAZE_NONE:
{
- /* This was a PC-relative instruction that was
- completely resolved. */
- int sfix, efix;
- bfd_vma target_address;
- target_address = irel->r_addend + irel->r_offset;
- sfix = calc_fixup (irel->r_offset, sec);
- efix = calc_fixup (target_address, sec);
- irel->r_addend -= (efix - sfix);
- /* Should use HOWTO. */
- bfd_put_16 (abfd, irel->r_addend, contents + irel->r_offset + 2);
+ /* This was a PC-relative instruction that was
+ completely resolved. */
+ int sfix, efix;
+ bfd_vma target_address;
+ target_address = irel->r_addend + irel->r_offset;
+ sfix = calc_fixup (irel->r_offset, 0, sec);
+ efix = calc_fixup (target_address, 0, sec);
+ irel->r_addend -= (efix - sfix);
+ /* Should use HOWTO. */
+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
+ irel->r_addend);
}
break;
case R_MICROBLAZE_64_NONE:
{
- /* This was a PC-relative 64-bit instruction that was
- completely resolved. */
- int sfix, efix;
- bfd_vma target_address;
+ /* This was a PC-relative 64-bit instruction that was
+ completely resolved. */
+ int sfix, efix;
+ bfd_vma target_address;
target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
- sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, sec);
- efix = calc_fixup (target_address, sec);
+ sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
+ efix = calc_fixup (target_address, 0, sec);
irel->r_addend -= (efix - sfix);
- bfd_put_16 (abfd, irel->r_addend, contents + irel->r_offset
- + INST_WORD_SIZE + 2);
+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
+ + INST_WORD_SIZE, irel->r_addend);
}
break;
}
- irel->r_offset = nraddr;
- } /* Change all relocs in this section. */
+ irel->r_offset = nraddr;
+ } /* Change all relocs in this section. */
/* Look through all other sections. */
for (o = abfd->sections; o != NULL; o = o->next)
- {
- Elf_Internal_Rela *irelocs;
- Elf_Internal_Rela *irelscan, *irelscanend;
- bfd_byte *ocontents;
-
- if (o == sec
- || (o->flags & SEC_RELOC) == 0
- || o->reloc_count == 0)
- continue;
-
- /* We always cache the relocs. Perhaps, if info->keep_memory is
- FALSE, we should free them, if we are permitted to. */
-
- irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
- if (irelocs == NULL)
- goto error_return;
-
- ocontents = NULL;
- irelscanend = irelocs + o->reloc_count;
- for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
- {
- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
- {
- isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
-
- /* Look at the reloc only if the value has been resolved. */
- if (isym->st_shndx == shndx
- && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
- {
- if (ocontents == NULL)
- {
- if (elf_section_data (o)->this_hdr.contents != NULL)
- ocontents = elf_section_data (o)->this_hdr.contents;
- else
- {
- /* We always cache the section contents.
- Perhaps, if info->keep_memory is FALSE, we
- should free them, if we are permitted to. */
- if (o->rawsize == 0)
- o->rawsize = o->size;
- ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
- if (ocontents == NULL)
- goto error_return;
- if (!bfd_get_section_contents (abfd, o, ocontents,
- (file_ptr) 0,
+ {
+ Elf_Internal_Rela *irelocs;
+ Elf_Internal_Rela *irelscan, *irelscanend;
+ bfd_byte *ocontents;
+
+ if (o == sec
+ || (o->flags & SEC_RELOC) == 0
+ || o->reloc_count == 0)
+ continue;
+
+ /* We always cache the relocs. Perhaps, if info->keep_memory is
+ FALSE, we should free them, if we are permitted to. */
+
+ irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
+ if (irelocs == NULL)
+ goto error_return;
+
+ ocontents = NULL;
+ irelscanend = irelocs + o->reloc_count;
+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
+ {
+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
+ {
+ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+
+ /* Look at the reloc only if the value has been resolved. */
+ if (isym->st_shndx == shndx
+ && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
+ {
+ if (ocontents == NULL)
+ {
+ if (elf_section_data (o)->this_hdr.contents != NULL)
+ ocontents = elf_section_data (o)->this_hdr.contents;
+ else
+ {
+ /* We always cache the section contents.
+ Perhaps, if info->keep_memory is FALSE, we
+ should free them, if we are permitted to. */
+ if (o->rawsize == 0)
+ o->rawsize = o->size;
+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
+ if (ocontents == NULL)
+ goto error_return;
+ if (!bfd_get_section_contents (abfd, o, ocontents,
+ (file_ptr) 0,
o->rawsize))
- goto error_return;
- elf_section_data (o)->this_hdr.contents = ocontents;
- }
+ goto error_return;
+ elf_section_data (o)->this_hdr.contents = ocontents;
+ }
- }
- irelscan->r_addend -= calc_fixup (irelscan->r_addend, sec);
- }
+ }
+ irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
+ }
else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
{
isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
}
irelscan->r_addend -= calc_fixup (irel->r_addend
+ isym->st_value,
+ 0,
sec);
}
}
else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
- || (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_LO))
+ || (ELF32_R_TYPE (irelscan->r_info)
+ == (int) R_MICROBLAZE_32_LO)
+ || (ELF32_R_TYPE (irelscan->r_info)
+ == (int) R_MICROBLAZE_TEXTREL_32_LO))
{
isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
}
}
- immediate = (unsigned short) bfd_get_16 (abfd, ocontents +
- irelscan->r_offset + 2);
+ unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
+ immediate = instr & 0x0000ffff;
target_address = immediate;
- offset = calc_fixup (target_address, sec);
+ offset = calc_fixup (target_address, 0, sec);
immediate -= offset;
irelscan->r_addend -= offset;
- bfd_put_16 (abfd, immediate, ocontents + irelscan->r_offset + 2);
+ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
+ irelscan->r_addend);
}
}
- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64)
+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
+ || (ELF32_R_TYPE (irelscan->r_info)
+ == (int) R_MICROBLAZE_TEXTREL_64))
{
isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
elf_section_data (o)->this_hdr.contents = ocontents;
}
}
- immediate = (unsigned short) (bfd_get_16 (abfd, ocontents
- + irelscan->r_offset
- + 2) << 16)
- & 0xffff0000;
- immediate += (unsigned short) (bfd_get_16 (abfd, ocontents
- + irelscan->r_offset
- + INST_WORD_SIZE + 2))
- & 0x0000ffff;
-
- offset = calc_fixup (irelscan->r_addend, sec);
+ unsigned long instr_hi = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset);
+ unsigned long instr_lo = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset
+ + INST_WORD_SIZE);
+ immediate = (instr_hi & 0x0000ffff) << 16;
+ immediate |= (instr_lo & 0x0000ffff);
+ offset = calc_fixup (irelscan->r_addend, 0, sec);
immediate -= offset;
irelscan->r_addend -= offset;
}
elf_section_data (o)->this_hdr.contents = ocontents;
}
}
-
- immediate = (unsigned short)
- (bfd_get_16 (abfd, ocontents + irelscan->r_offset + 2) << 16)
- & 0xffff0000;
- immediate += (unsigned short)
- (bfd_get_16 (abfd, ocontents + irelscan->r_offset
- + INST_WORD_SIZE + 2))
- & 0x0000ffff;
+ unsigned long instr_hi = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset);
+ unsigned long instr_lo = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset
+ + INST_WORD_SIZE);
+ immediate = (instr_hi & 0x0000ffff) << 16;
+ immediate |= (instr_lo & 0x0000ffff);
target_address = immediate;
- offset = calc_fixup (target_address, sec);
+ offset = calc_fixup (target_address, 0, sec);
immediate -= offset;
irelscan->r_addend -= offset;
- bfd_put_16 (abfd, ((immediate >> 16) & 0x0000ffff),
- ocontents + irelscan->r_offset + 2);
- bfd_put_16 (abfd, (immediate & 0x0000ffff),
- ocontents + irelscan->r_offset + INST_WORD_SIZE + 2);
+ microblaze_bfd_write_imm_value_64 (abfd, ocontents
+ + irelscan->r_offset, immediate);
}
}
- }
- }
+ }
+ }
/* Adjust the local symbols defined in this section. */
isymend = isymbuf + symtab_hdr->sh_info;
for (isym = isymbuf; isym < isymend; isym++)
- {
- if (isym->st_shndx == shndx)
- isym->st_value =- calc_fixup (isym->st_value, sec);
- }
+ {
+ if (isym->st_shndx == shndx)
+ {
+ isym->st_value -= calc_fixup (isym->st_value, 0, sec);
+ if (isym->st_size)
+ isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
+ }
+ }
/* Now adjust the global symbols defined in this section. */
isym = isymbuf + symtab_hdr->sh_info;
- isymend = isymbuf + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
- for (sym_index = 0; isym < isymend; isym++, sym_index++)
- {
- sym_hash = elf_sym_hashes (abfd)[sym_index];
- if (isym->st_shndx == shndx
- && (sym_hash->root.type == bfd_link_hash_defined
- || sym_hash->root.type == bfd_link_hash_defweak)
- && sym_hash->root.u.def.section == sec)
+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
+ for (sym_index = 0; sym_index < symcount; sym_index++)
+ {
+ sym_hash = elf_sym_hashes (abfd)[sym_index];
+ if ((sym_hash->root.type == bfd_link_hash_defined
+ || sym_hash->root.type == bfd_link_hash_defweak)
+ && sym_hash->root.u.def.section == sec)
{
sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
- sec);
+ 0, sec);
+ if (sym_hash->size)
+ sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
+ sym_hash->size, sec);
}
}
/* Physically move the code and change the cooked size. */
dest = sec->relax[0].addr;
for (i = 0; i < sec->relax_count; i++)
- {
- int len;
- src = sec->relax[i].addr + sec->relax[i].size;
- len = sec->relax[i+1].addr - sec->relax[i].addr - sec->relax[i].size;
+ {
+ int len;
+ src = sec->relax[i].addr + sec->relax[i].size;
+ len = sec->relax[i+1].addr - sec->relax[i].addr - sec->relax[i].size;
- memmove (contents + dest, contents + src, len);
- sec->size -= sec->relax[i].size;
- dest += len;
- }
+ memmove (contents + dest, contents + src, len);
+ sec->size -= sec->relax[i].size;
+ dest += len;
+ }
elf_section_data (sec)->relocs = internal_relocs;
free_relocs = NULL;
if (sec->relax_count == 0)
{
+ *again = FALSE;
free (sec->relax);
sec->relax = NULL;
}
+ else
+ *again = TRUE;
return TRUE;
error_return:
static asection *
microblaze_elf_gc_mark_hook (asection *sec,
struct bfd_link_info * info,
- Elf_Internal_Rela * rel,
- struct elf_link_hash_entry * h,
- Elf_Internal_Sym * sym)
+ Elf_Internal_Rela * rel,
+ struct elf_link_hash_entry * h,
+ Elf_Internal_Sym * sym)
{
if (h != NULL)
switch (ELF32_R_TYPE (rel->r_info))
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
-microblaze_elf_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
- struct bfd_link_info * info ATTRIBUTE_UNUSED,
- asection * sec ATTRIBUTE_UNUSED,
- const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
-{
- return TRUE;
-}
-
/* PIC support. */
#define PLT_ENTRY_SIZE 16
-#define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
-#define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
-#define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
-#define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
-#define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
-
-/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
- shortcuts to them in our hash table. */
+#define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
+#define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
+#define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
+#define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
+#define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
static bfd_boolean
-create_got_section (bfd *dynobj, struct bfd_link_info *info)
+update_local_sym_info (bfd *abfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ unsigned long r_symndx,
+ unsigned int tls_type)
{
- struct elf32_mb_link_hash_table *htab;
+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
+ unsigned char *local_got_tls_masks;
- if (! _bfd_elf_create_got_section (dynobj, info))
- return FALSE;
- htab = elf32_mb_hash_table (info);
- if (htab == NULL)
- return FALSE;
+ if (local_got_refcounts == NULL)
+ {
+ bfd_size_type size = symtab_hdr->sh_info;
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- if (!htab->sgot || !htab->sgotplt)
- return FALSE;
+ size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
+ local_got_refcounts = bfd_zalloc (abfd, size);
+ if (local_got_refcounts == NULL)
+ return FALSE;
+ elf_local_got_refcounts (abfd) = local_got_refcounts;
+ }
+
+ local_got_tls_masks =
+ (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
+ local_got_tls_masks[r_symndx] |= tls_type;
+ local_got_refcounts[r_symndx] += 1;
- if (!(htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got")))
- htab->srelgot = bfd_make_section (dynobj, ".rela.got");
- if (htab->srelgot == NULL
- || ! bfd_set_section_flags (dynobj, htab->srelgot, SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY)
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return FALSE;
return TRUE;
}
-
/* Look through the relocs for a section during the first phase. */
static bfd_boolean
microblaze_elf_check_relocs (bfd * abfd,
struct bfd_link_info * info,
- asection * sec,
+ asection * sec,
const Elf_Internal_Rela * relocs)
{
- Elf_Internal_Shdr * symtab_hdr;
+ Elf_Internal_Shdr * symtab_hdr;
struct elf_link_hash_entry ** sym_hashes;
struct elf_link_hash_entry ** sym_hashes_end;
- const Elf_Internal_Rela * rel;
- const Elf_Internal_Rela * rel_end;
+ const Elf_Internal_Rela * rel;
+ const Elf_Internal_Rela * rel_end;
struct elf32_mb_link_hash_table *htab;
asection *sreloc = NULL;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
htab = elf32_mb_hash_table (info);
unsigned int r_type;
struct elf_link_hash_entry * h;
unsigned long r_symndx;
+ unsigned char tls_type = 0;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
+ h = NULL;
else
- h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+ {
+ 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;
+ }
switch (r_type)
- {
+ {
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
- case R_MICROBLAZE_GNU_VTINHERIT:
- if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return FALSE;
- break;
+ case R_MICROBLAZE_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_MICROBLAZE_GNU_VTENTRY:
- if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
- return FALSE;
- break;
+ case R_MICROBLAZE_GNU_VTENTRY:
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ return FALSE;
+ break;
/* This relocation requires .plt entry. */
- case R_MICROBLAZE_PLT_64:
- if (h != NULL)
+ case R_MICROBLAZE_PLT_64:
+ if (h != NULL)
{
h->needs_plt = 1;
h->plt.refcount += 1;
}
- break;
+ break;
/* This relocation requires .got entry. */
- case R_MICROBLAZE_GOT_64:
- if (htab->sgot == NULL)
- {
- if (htab->elf.dynobj == NULL)
- htab->elf.dynobj = abfd;
- if (!create_got_section (htab->elf.dynobj, info))
- return FALSE;
- }
- if (h != NULL)
+ case R_MICROBLAZE_TLSGD:
+ tls_type |= (TLS_TLS | TLS_GD);
+ goto dogottls;
+ case R_MICROBLAZE_TLSLD:
+ tls_type |= (TLS_TLS | TLS_LD);
+ /* Fall through. */
+ dogottls:
+ sec->has_tls_reloc = 1;
+ /* Fall through. */
+ case R_MICROBLAZE_GOT_64:
+ if (htab->elf.sgot == NULL)
+ {
+ if (htab->elf.dynobj == NULL)
+ htab->elf.dynobj = abfd;
+ if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
+ return FALSE;
+ }
+ if (h != NULL)
{
h->got.refcount += 1;
+ elf32_mb_hash_entry (h)->tls_mask |= tls_type;
}
- else
+ else
{
- bfd_signed_vma *local_got_refcounts;
+ if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
+ return FALSE;
+ }
+ break;
- /* This is a global offset table entry for a local symbol. */
- local_got_refcounts = elf_local_got_refcounts (abfd);
- if (local_got_refcounts == NULL)
- {
- bfd_size_type size;
-
- size = symtab_hdr->sh_info;
- size *= sizeof (bfd_signed_vma);
- local_got_refcounts = bfd_zalloc (abfd, size);
- if (local_got_refcounts == NULL)
- return FALSE;
- elf_local_got_refcounts (abfd) = local_got_refcounts;
- }
- local_got_refcounts[r_symndx] += 1;
+ case R_MICROBLAZE_GOTOFF_64:
+ case R_MICROBLAZE_GOTOFF_32:
+ if (htab->elf.sgot == NULL)
+ {
+ if (htab->elf.dynobj == NULL)
+ htab->elf.dynobj = abfd;
+ if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
+ return FALSE;
}
- break;
+ break;
- case R_MICROBLAZE_64:
- case R_MICROBLAZE_64_PCREL:
- case R_MICROBLAZE_32:
- {
- if (h != NULL && !info->shared)
+ case R_MICROBLAZE_64:
+ case R_MICROBLAZE_64_PCREL:
+ case R_MICROBLAZE_32:
+ {
+ if (h != NULL && !bfd_link_pic (info))
{
/* we may need a copy reloc. */
h->non_got_ref = 1;
dynamic library if we manage to avoid copy relocs for the
symbol. */
- if ((info->shared
- && (sec->flags & SEC_ALLOC) != 0
- && (r_type != R_MICROBLAZE_64_PCREL
- || (h != NULL
+ if ((bfd_link_pic (info)
+ && (sec->flags & SEC_ALLOC) != 0
+ && (r_type != R_MICROBLAZE_64_PCREL
+ || (h != NULL
&& (! info->symbolic
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
- || (!info->shared
- && (sec->flags & SEC_ALLOC) != 0
- && h != NULL
- && (h->root.type == bfd_link_hash_defweak
- || !h->def_regular)))
- {
- struct elf32_mb_dyn_relocs *p;
- struct elf32_mb_dyn_relocs **head;
-
- /* When creating a shared object, we must copy these
- relocs into the output file. We create a reloc
- section in dynobj and make room for the reloc. */
+ || (!bfd_link_pic (info)
+ && (sec->flags & SEC_ALLOC) != 0
+ && h != NULL
+ && (h->root.type == bfd_link_hash_defweak
+ || !h->def_regular)))
+ {
+ struct elf_dyn_relocs *p;
+ struct elf_dyn_relocs **head;
+
+ /* When creating a shared object, we must copy these
+ relocs into the output file. We create a reloc
+ section in dynobj and make room for the reloc. */
if (sreloc == NULL)
{
- const char *name;
bfd *dynobj;
- unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
- unsigned int shnam = _bfd_elf_single_rel_hdr (sec)->sh_name;
-
- name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
- if (name == NULL)
- return FALSE;
-
- if (strncmp (name, ".rela", 5) != 0
- || strcmp (bfd_get_section_name (abfd, sec),
- name + 5) != 0)
- {
- (*_bfd_error_handler)
- (_("%B: bad relocation section name `%s\'"),
- abfd, name);
- }
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
dynobj = htab->elf.dynobj;
- sreloc = bfd_get_section_by_name (dynobj, name);
+ sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
+ 2, abfd, 1);
if (sreloc == NULL)
- {
- flagword flags;
-
- sreloc = bfd_make_section (dynobj, name);
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc, flags)
- || ! bfd_set_section_alignment (dynobj, sreloc, 2))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
return FALSE;
vpp = &elf_section_data (s)->local_dynrel;
- head = (struct elf32_mb_dyn_relocs **) vpp;
+ head = (struct elf_dyn_relocs **) vpp;
}
p = *head;
if (p == NULL || p->sec != sec)
{
bfd_size_type amt = sizeof *p;
- p = ((struct elf32_mb_dyn_relocs *)
+ p = ((struct elf_dyn_relocs *)
bfd_alloc (htab->elf.dynobj, amt));
if (p == NULL)
return FALSE;
if (r_type == R_MICROBLAZE_64_PCREL)
p->pc_count += 1;
}
- }
- break;
- }
+ }
+ break;
+ }
}
return TRUE;
}
-static bfd_boolean
-microblaze_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
-{
- struct elf32_mb_link_hash_table *htab;
-
- htab = elf32_mb_hash_table (info);
- if (htab == NULL)
- return FALSE;
-
- if (!htab->sgot && !create_got_section (dynobj, info))
- return FALSE;
-
- if (!_bfd_elf_create_dynamic_sections (dynobj, info))
- return FALSE;
-
- htab->splt = bfd_get_section_by_name (dynobj, ".plt");
- htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
- htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
- if (!info->shared)
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
-
- if (!htab->splt || !htab->srelplt || !htab->sdynbss
- || (!info->shared && !htab->srelbss))
- abort ();
-
- return TRUE;
-}
-
/* Copy the extra info we tack onto an elf_link_hash_entry. */
static void
{
if (edir->dyn_relocs != NULL)
{
- struct elf32_mb_dyn_relocs **pp;
- struct elf32_mb_dyn_relocs *p;
+ struct elf_dyn_relocs **pp;
+ struct elf_dyn_relocs *p;
if (ind->root.type == bfd_link_hash_indirect)
abort ();
list. Merge any entries against the same section. */
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
{
- struct elf32_mb_dyn_relocs *q;
+ struct elf_dyn_relocs *q;
for (q = edir->dyn_relocs; q != NULL; q = q->next)
if (q->sec == p->sec)
eind->dyn_relocs = NULL;
}
+ edir->tls_mask |= eind->tls_mask;
+
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
+/* Find dynamic relocs for H that apply to read-only sections. */
+
+static asection *
+readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+ struct elf_dyn_relocs *p;
+
+ for (p = elf32_mb_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ return p->sec;
+ }
+ return NULL;
+}
+
static bfd_boolean
microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf32_mb_link_hash_table *htab;
- struct elf32_mb_link_hash_entry * eh;
- struct elf32_mb_dyn_relocs *p;
- asection *sdynbss, *s;
+ asection *s, *srel;
unsigned int power_of_two;
- bfd *dynobj;
htab = elf32_mb_hash_table (info);
if (htab == NULL)
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->u.weakdef != NULL)
+ if (h->is_weakalias)
{
- BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
- || h->u.weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->u.weakdef->root.u.def.section;
- h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ struct elf_link_hash_entry *def = weakdef (h);
+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+ h->root.u.def.section = def->root.u.def.section;
+ h->root.u.def.value = def->root.u.def.value;
return TRUE;
}
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;
/* If there are no references to this symbol that do not use the
return TRUE;
}
- eh = (struct elf32_mb_link_hash_entry *) h;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- s = p->sec->output_section;
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- break;
- }
-
- /* If we didn't find any dynamic relocs in read-only sections, then
+ /* If we don't find any dynamic relocs in read-only sections, then
we'll be keeping the dynamic relocs and avoiding the copy reloc. */
- if (p == NULL)
+ if (!readonly_dynrelocs (h))
{
h->non_got_ref = 0;
return TRUE;
/* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- htab->srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
if (power_of_two > 3)
power_of_two = 3;
- sdynbss = htab->sdynbss;
/* Apply the required alignment. */
- sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > s->alignment_power)
{
- if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
+ if (!bfd_set_section_alignment (s->owner, s, power_of_two))
return FALSE;
}
/* Define the symbol as being at this point in the section. */
- h->root.u.def.section = sdynbss;
- h->root.u.def.value = sdynbss->size;
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
/* Increment the section size to make room for the symbol. */
- sdynbss->size += h->size;
+ s->size += h->size;
return TRUE;
}
struct bfd_link_info *info;
struct elf32_mb_link_hash_table *htab;
struct elf32_mb_link_hash_entry *eh;
- struct elf32_mb_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
-
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
- {
- asection *s = htab->splt;
-
- /* The first entry in .plt is reserved. */
- if (s->size == 0)
- s->size = PLT_ENTRY_SIZE;
-
- h->plt.offset = s->size;
-
- /* If this symbol is not defined in a regular file, and we are
- not generating a shared library, then set the symbol to this
- location in the .plt. This is required to make function
- pointers compare as equal between the normal executable and
- the shared library. */
- if (! info->shared
- && !h->def_regular)
- {
- h->root.u.def.section = s;
- h->root.u.def.value = h->plt.offset;
- }
-
- /* Make room for this entry. */
- s->size += PLT_ENTRY_SIZE;
-
- /* We also need to make an entry in the .got.plt section, which
- will be placed in the .got section by the linker script. */
- htab->sgotplt->size += 4;
-
- /* We also need to make an entry in the .rel.plt section. */
- htab->srelplt->size += sizeof (Elf32_External_Rela);
- }
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
+ {
+ asection *s = htab->elf.splt;
+
+ /* The first entry in .plt is reserved. */
+ if (s->size == 0)
+ s->size = PLT_ENTRY_SIZE;
+
+ h->plt.offset = s->size;
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ location in the .plt. This is required to make function
+ pointers compare as equal between the normal executable and
+ the shared library. */
+ if (! bfd_link_pic (info)
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = h->plt.offset;
+ }
+
+ /* Make room for this entry. */
+ s->size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .got.plt section, which
+ will be placed in the .got section by the linker script. */
+ htab->elf.sgotplt->size += 4;
+
+ /* We also need to make an entry in the .rel.plt section. */
+ htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
+ }
else
- {
- h->plt.offset = (bfd_vma) -1;
- h->needs_plt = 0;
- }
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
}
else
{
h->needs_plt = 0;
}
+ eh = (struct elf32_mb_link_hash_entry *) h;
if (h->got.refcount > 0)
{
+ unsigned int need;
asection *s;
/* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
+ Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
-
- s = htab->sgot;
- h->got.offset = s->size;
- s->size += 4;
- htab->srelgot->size += sizeof (Elf32_External_Rela);
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ need = 0;
+ if ((eh->tls_mask & TLS_TLS) != 0)
+ {
+ /* Handle TLS Symbol */
+ if ((eh->tls_mask & TLS_LD) != 0)
+ {
+ if (!eh->elf.def_dynamic)
+ /* We'll just use htab->tlsld_got.offset. This should
+ always be the case. It's a little odd if we have
+ a local dynamic reloc against a non-local symbol. */
+ htab->tlsld_got.refcount += 1;
+ else
+ need += 8;
+ }
+ if ((eh->tls_mask & TLS_GD) != 0)
+ need += 8;
+ }
+ else
+ {
+ /* Regular (non-TLS) symbol */
+ need += 4;
+ }
+ if (need == 0)
+ {
+ h->got.offset = (bfd_vma) -1;
+ }
+ else
+ {
+ s = htab->elf.sgot;
+ h->got.offset = s->size;
+ s->size += need;
+ htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
}
else
h->got.offset = (bfd_vma) -1;
- eh = (struct elf32_mb_link_hash_entry *) h;
if (eh->dyn_relocs == NULL)
return TRUE;
space for pc-relative relocs that have become local due to symbol
visibility changes. */
- if (info->shared)
+ if (bfd_link_pic (info))
{
if (h->def_regular
&& (h->forced_local
|| info->symbolic))
{
- struct elf32_mb_dyn_relocs **pp;
+ struct elf_dyn_relocs **pp;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
{
pp = &p->next;
}
}
+ else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+ eh->dyn_relocs = NULL;
}
else
{
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
+ unsigned char *lgot_masks;
asection *srel;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
- continue;
+ continue;
for (s = ibfd->sections; s != NULL; s = s->next)
{
- struct elf32_mb_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
- for (p = ((struct elf32_mb_dyn_relocs *)
+ for (p = ((struct elf_dyn_relocs *)
elf_section_data (s)->local_dynrel);
p != NULL;
p = p->next)
local_got = elf_local_got_refcounts (ibfd);
if (!local_got)
- continue;
+ continue;
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
- s = htab->sgot;
- srel = htab->srelgot;
-
- for (; local_got < end_local_got; ++local_got)
- {
- if (*local_got > 0)
- {
- *local_got = s->size;
- s->size += 4;
- if (info->shared)
- srel->size += sizeof (Elf32_External_Rela);
- }
- else
- *local_got = (bfd_vma) -1;
- }
+ lgot_masks = (unsigned char *) end_local_got;
+ s = htab->elf.sgot;
+ srel = htab->elf.srelgot;
+
+ for (; local_got < end_local_got; ++local_got, ++lgot_masks)
+ {
+ if (*local_got > 0)
+ {
+ unsigned int need = 0;
+ if ((*lgot_masks & TLS_TLS) != 0)
+ {
+ if ((*lgot_masks & TLS_GD) != 0)
+ need += 8;
+ if ((*lgot_masks & TLS_LD) != 0)
+ htab->tlsld_got.refcount += 1;
+ }
+ else
+ need += 4;
+
+ if (need == 0)
+ {
+ *local_got = (bfd_vma) -1;
+ }
+ else
+ {
+ *local_got = s->size;
+ s->size += need;
+ if (bfd_link_pic (info))
+ srel->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
+ }
+ else
+ *local_got = (bfd_vma) -1;
+ }
}
/* Allocate global sym .plt and .got entries, and space for global
sym dynamic relocs. */
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
+ if (htab->tlsld_got.refcount > 0)
+ {
+ htab->tlsld_got.offset = htab->elf.sgot->size;
+ htab->elf.sgot->size += 8;
+ if (bfd_link_pic (info))
+ htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ htab->tlsld_got.offset = (bfd_vma) -1;
+
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Make space for the trailing nop in .plt. */
- if (htab->splt->size > 0)
- htab->splt->size += 4;
+ if (htab->elf.splt->size > 0)
+ htab->elf.splt->size += 4;
}
/* The check_relocs and adjust_dynamic_symbol entry points have
bfd_boolean strip = FALSE;
if ((s->flags & SEC_LINKER_CREATED) == 0)
- continue;
+ continue;
/* It's OK to base decisions on the section name, because none
- of the dynobj section names depend upon the input files. */
+ of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);
if (strncmp (name, ".rela", 5) == 0)
- {
- if (s->size == 0)
- {
- /* If we don't need this section, strip it from the
- output file. This is to handle .rela.bss and
- .rela.plt. We must create it in
- create_dynamic_sections, because it must be created
- before the linker maps input sections to output
- sections. The linker does that before
- adjust_dynamic_symbol is called, and it is that
- function which decides whether anything needs to go
- into these sections. */
- strip = TRUE;
- }
- else
- {
- /* We use the reloc_count field as a counter if we need
- to copy relocs into the output file. */
- s->reloc_count = 0;
- }
- }
- else if (s != htab->splt && s != htab->sgot && s != htab->sgotplt)
- {
- /* It's not one of our sections, so don't allocate space. */
- continue;
- }
+ {
+ if (s->size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is to handle .rela.bss and
+ .rela.plt. We must create it in
+ create_dynamic_sections, because it must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ strip = TRUE;
+ }
+ else
+ {
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ }
+ else if (s != htab->elf.splt
+ && s != htab->elf.sgot
+ && s != htab->elf.sgotplt
+ && s != htab->elf.sdynbss
+ && s != htab->elf.sdynrelro)
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
if (strip)
- {
- s->flags |= SEC_EXCLUDE;
- continue;
- }
+ {
+ s->flags |= SEC_EXCLUDE;
+ continue;
+ }
/* Allocate memory for the section contents. */
/* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
- Unused entries should be reclaimed before the section's contents
- are written out, but at the moment this does not happen. Thus in
- order to prevent writing out garbage, we initialise the section's
- contents to zero. */
+ Unused entries should be reclaimed before the section's contents
+ are written out, but at the moment this does not happen. Thus in
+ order to prevent writing out garbage, we initialise the section's
+ contents to zero. */
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
if (s->contents == NULL && s->size != 0)
- return FALSE;
+ return FALSE;
}
if (elf_hash_table (info)->dynamic_sections_created)
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (info->executable)
- {
- if (!add_dynamic_entry (DT_DEBUG, 0))
- return FALSE;
- }
+ if (bfd_link_executable (info))
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+ }
if (!add_dynamic_entry (DT_RELA, 0)
- || !add_dynamic_entry (DT_RELASZ, 0)
- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
return FALSE;
- if (htab->splt->size != 0)
- {
- if (!add_dynamic_entry (DT_PLTGOT, 0)
- || !add_dynamic_entry (DT_PLTRELSZ, 0)
- || !add_dynamic_entry (DT_PLTREL, DT_RELA)
- || !add_dynamic_entry (DT_JMPREL, 0)
- || !add_dynamic_entry (DT_BIND_NOW, 1))
- return FALSE;
- }
+ if (htab->elf.splt->size != 0)
+ {
+ if (!add_dynamic_entry (DT_PLTGOT, 0)
+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+ || !add_dynamic_entry (DT_JMPREL, 0)
+ || !add_dynamic_entry (DT_BIND_NOW, 1))
+ return FALSE;
+ }
if (info->flags & DF_TEXTREL)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
- }
+ {
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
+ return FALSE;
+ }
}
#undef add_dynamic_entry
return TRUE;
Elf_Internal_Sym *sym)
{
struct elf32_mb_link_hash_table *htab;
+ struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
htab = elf32_mb_hash_table (info);
if (htab == NULL)
bfd_vma got_addr;
/* This symbol has an entry in the procedure linkage table. Set
- it up. */
+ it up. */
BFD_ASSERT (h->dynindx != -1);
- splt = htab->splt;
- srela = htab->srelplt;
- sgotplt = htab->sgotplt;
+ splt = htab->elf.splt;
+ srela = htab->elf.srelplt;
+ sgotplt = htab->elf.sgotplt;
BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved. */
got_addr = got_offset;
/* For non-PIC objects we need absolute address of the GOT entry. */
- if (!info->shared)
- got_addr += htab->sgotplt->output_section->vma + sgotplt->output_offset;
+ if (!bfd_link_pic (info))
+ got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
/* Fill in the entry in the procedure linkage table. */
bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
- splt->contents + h->plt.offset);
- if (info->shared)
- bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
- splt->contents + h->plt.offset + 4);
+ splt->contents + h->plt.offset);
+ if (bfd_link_pic (info))
+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
+ splt->contents + h->plt.offset + 4);
else
- bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
- splt->contents + h->plt.offset + 4);
+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
+ splt->contents + h->plt.offset + 4);
bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
- splt->contents + h->plt.offset + 8);
+ splt->contents + h->plt.offset + 8);
bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
- splt->contents + h->plt.offset + 12);
+ splt->contents + h->plt.offset + 12);
/* Any additions to the .got section??? */
/* bfd_put_32 (output_bfd,
/* Fill in the entry in the .rela.plt section. */
rela.r_offset = (sgotplt->output_section->vma
- + sgotplt->output_offset
- + got_offset);
+ + sgotplt->output_offset
+ + got_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
rela.r_addend = 0;
loc = srela->contents;
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
- {
- /* Mark the symbol as undefined, rather than as defined in
- the .plt section. Zero the value. */
- sym->st_shndx = SHN_UNDEF;
- sym->st_value = 0;
- }
+ {
+ /* Mark the symbol as undefined, rather than as defined in
+ the .plt section. Zero the value. */
+ sym->st_shndx = SHN_UNDEF;
+ sym->st_value = 0;
+ }
}
- if (h->got.offset != (bfd_vma) -1)
+ /* h->got.refcount to be checked ? */
+ if (h->got.offset != (bfd_vma) -1 &&
+ ! ((h->got.offset & 1) ||
+ IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
{
asection *sgot;
asection *srela;
- Elf_Internal_Rela rela;
- bfd_byte *loc;
+ bfd_vma offset;
/* This symbol has an entry in the global offset table. Set it
- up. */
+ up. */
- sgot = htab->sgot;
- srela = htab->srelgot;
+ sgot = htab->elf.sgot;
+ srela = htab->elf.srelgot;
BFD_ASSERT (sgot != NULL && srela != NULL);
- rela.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + (h->got.offset &~ (bfd_vma) 1));
+ offset = (sgot->output_section->vma + sgot->output_offset
+ + (h->got.offset &~ (bfd_vma) 1));
/* If this is a -Bsymbolic link, and the symbol is defined
- locally, we just want to emit a RELATIVE reloc. Likewise if
- 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
- && (info->symbolic || h->dynindx == -1)
- && h->def_regular)
- {
- asection *sec = h->root.u.def.section;
- rela.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
- rela.r_addend = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
+ locally, we just want to emit a RELATIVE reloc. Likewise if
+ 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 (bfd_link_pic (info)
+ && ((info->symbolic && h->def_regular)
+ || h->dynindx == -1))
+ {
+ asection *sec = h->root.u.def.section;
+ bfd_vma value;
+
+ value = h->root.u.def.value;
+ if (sec->output_section != NULL)
+ /* PR 21180: If the output section is NULL, then the symbol is no
+ longer needed, and in theory the GOT entry is redundant. But
+ it is too late to change our minds now... */
+ value += sec->output_section->vma + sec->output_offset;
+
+ microblaze_elf_output_dynamic_relocation (output_bfd,
+ srela, srela->reloc_count++,
+ /* symindex= */ 0,
+ R_MICROBLAZE_REL, offset,
+ value);
+ }
else
- {
- rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_GLOB_DAT);
- rela.r_addend = 0;
- }
+ {
+ microblaze_elf_output_dynamic_relocation (output_bfd,
+ srela, srela->reloc_count++,
+ h->dynindx,
+ R_MICROBLAZE_GLOB_DAT,
+ offset, 0);
+ }
bfd_put_32 (output_bfd, (bfd_vma) 0,
- sgot->contents + (h->got.offset &~ (bfd_vma) 1));
- loc = srela->contents;
- loc += srela->reloc_count++ * sizeof (Elf32_External_Rela);
- bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+ sgot->contents + (h->got.offset &~ (bfd_vma) 1));
}
if (h->needs_copy)
BFD_ASSERT (h->dynindx != -1);
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
rela.r_addend = 0;
+ if (h->root.u.def.section == htab->elf.sdynrelro)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
/* Mark some specially defined symbols as absolute. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
- || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
+ if (h == htab->elf.hdynamic
+ || h == htab->elf.hgot
+ || h == htab->elf.hplt)
sym->st_shndx = SHN_ABS;
return TRUE;
dynobj = htab->elf.dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (htab->elf.dynamic_sections_created)
{
asection *splt;
Elf32_External_Dyn *dyncon, *dynconend;
- splt = bfd_get_section_by_name (dynobj, ".plt");
- BFD_ASSERT (splt != NULL && sdyn != NULL);
-
dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
for (; dyncon < dynconend; dyncon++)
- {
- Elf_Internal_Dyn dyn;
- const char *name;
- bfd_boolean size;
-
- bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
-
- switch (dyn.d_tag)
- {
- case DT_PLTGOT: name = ".got.plt"; size = FALSE; break;
- case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
- case DT_JMPREL: name = ".rela.plt"; size = FALSE; break;
- case DT_RELA: name = ".rela.dyn"; size = FALSE; break;
- case DT_RELASZ: name = ".rela.dyn"; size = TRUE; break;
- default: name = NULL; size = FALSE; break;
- }
-
- if (name != NULL)
- {
- asection *s;
-
- s = bfd_get_section_by_name (output_bfd, name);
- if (s == NULL)
- dyn.d_un.d_val = 0;
- else
- {
- if (! size)
- dyn.d_un.d_ptr = s->vma;
- else
- dyn.d_un.d_val = s->size;
- }
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
- }
- }
+ {
+ Elf_Internal_Dyn dyn;
+ asection *s;
+ bfd_boolean size;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ case DT_PLTGOT:
+ s = htab->elf.sgotplt;
+ size = FALSE;
+ break;
+
+ case DT_PLTRELSZ:
+ s = htab->elf.srelplt;
+ size = TRUE;
+ break;
+
+ case DT_JMPREL:
+ s = htab->elf.srelplt;
+ size = FALSE;
+ break;
+
+ default:
+ continue;
+ }
+
+ if (s == NULL)
+ dyn.d_un.d_val = 0;
+ else
+ {
+ if (!size)
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+ else
+ dyn.d_un.d_val = s->size;
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ }
+
+ splt = htab->elf.splt;
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
/* Clear the first entry in the procedure linkage table,
and put a nop in the last four bytes. */
if (splt->size > 0)
- {
- memset (splt->contents, 0, PLT_ENTRY_SIZE);
- bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop. */,
- splt->contents + splt->size - 4);
- }
+ {
+ memset (splt->contents, 0, PLT_ENTRY_SIZE);
+ bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop. */,
+ splt->contents + splt->size - 4);
- elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+ if (splt->output_section != bfd_abs_section_ptr)
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+ }
}
/* Set the first entry in the global offset table to the address of
the dynamic section. */
- sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ sgot = htab->elf.sgotplt;
if (sgot && sgot->size > 0)
{
if (sdyn == NULL)
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
else
- bfd_put_32 (output_bfd,
- sdyn->output_section->vma + sdyn->output_offset,
- sgot->contents);
+ bfd_put_32 (output_bfd,
+ sdyn->output_section->vma + sdyn->output_offset,
+ sgot->contents);
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
}
- if (htab->sgot && htab->sgot->size > 0)
- elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
+ if (htab->elf.sgot && htab->elf.sgot->size > 0)
+ elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
return TRUE;
}
static bfd_boolean
microblaze_elf_add_symbol_hook (bfd *abfd,
- struct bfd_link_info *info,
- Elf_Internal_Sym *sym,
- const char **namep ATTRIBUTE_UNUSED,
- flagword *flagsp ATTRIBUTE_UNUSED,
- asection **secp,
- bfd_vma *valp)
+ struct bfd_link_info *info,
+ Elf_Internal_Sym *sym,
+ const char **namep ATTRIBUTE_UNUSED,
+ flagword *flagsp ATTRIBUTE_UNUSED,
+ asection **secp,
+ bfd_vma *valp)
{
if (sym->st_shndx == SHN_COMMON
- && !info->relocatable
+ && !bfd_link_relocatable (info)
&& sym->st_size <= elf_gp_size (abfd))
{
/* Common symbols less than or equal to -G nn bytes are automatically
put into .sbss. */
- *secp = bfd_make_section_anyway (abfd, ".sbss");
+ *secp = bfd_make_section_old_way (abfd, ".sbss");
if (*secp == NULL
- || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
- return FALSE;
+ || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
+ return FALSE;
*valp = sym->st_size;
}
return TRUE;
}
+#define TARGET_LITTLE_SYM microblaze_elf32_le_vec
+#define TARGET_LITTLE_NAME "elf32-microblazeel"
-#define TARGET_BIG_SYM bfd_elf32_microblaze_vec
+#define TARGET_BIG_SYM microblaze_elf32_vec
#define TARGET_BIG_NAME "elf32-microblaze"
#define ELF_ARCH bfd_arch_microblaze
#define ELF_TARGET_ID MICROBLAZE_ELF_DATA
#define ELF_MACHINE_CODE EM_MICROBLAZE
#define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
-#define ELF_MAXPAGESIZE 0x4 /* 4k, if we ever have 'em. */
+#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto microblaze_elf_info_to_howto
#define elf_info_to_howto_rel NULL
#define bfd_elf32_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
-#define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
+#define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
#define elf_backend_relocate_section microblaze_elf_relocate_section
-#define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
+#define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
+#define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
#define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
#define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook microblaze_elf_gc_sweep_hook
-#define elf_backend_check_relocs microblaze_elf_check_relocs
-#define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
-#define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
+#define elf_backend_check_relocs microblaze_elf_check_relocs
+#define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
+#define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
#define elf_backend_can_gc_sections 1
-#define elf_backend_can_refcount 1
-#define elf_backend_want_got_plt 1
-#define elf_backend_plt_readonly 1
-#define elf_backend_got_header_size 12
-#define elf_backend_rela_normal 1
-
-#define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
-#define elf_backend_create_dynamic_sections microblaze_elf_create_dynamic_sections
-#define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
-#define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
-#define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
+#define elf_backend_can_refcount 1
+#define elf_backend_want_got_plt 1
+#define elf_backend_plt_readonly 1
+#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
+#define elf_backend_rela_normal 1
+#define elf_backend_dtrel_excludes_plt 1
+
+#define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
+#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
+#define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
+#define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
+#define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
#define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
#include "elf32-target.h"