/* AVR-specific support for 32-bit ELF
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
+ 2010, 2011 Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru>
This file is part of BFD, the Binary File Descriptor library.
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A low 8 bit absolute relocation of 24 bit program memory address.
- For LDI command. Will be changed when linker stubs are needed. */
+ For LDI command. Will be changed when linker stubs are needed. */
HOWTO (R_AVR_LO8_LDI_GS, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A low 8 bit absolute relocation of 24 bit program memory address.
- For LDI command. Will be changed when linker stubs are needed. */
+ For LDI command. Will be changed when linker stubs are needed. */
HOWTO (R_AVR_HI8_LDI_GS, /* type */
9, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
FALSE, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
- FALSE) /* pcrel_offset */
+ FALSE), /* pcrel_offset */
+ /* 8 bit offset. */
+ HOWTO (R_AVR_8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_AVR_8", /* name */
+ FALSE, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* Map BFD reloc types to AVR ELF reloc types. */
{ BFD_RELOC_AVR_CALL, R_AVR_CALL },
{ BFD_RELOC_AVR_LDI, R_AVR_LDI },
{ BFD_RELOC_AVR_6, R_AVR_6 },
- { BFD_RELOC_AVR_6_ADIW, R_AVR_6_ADIW }
+ { BFD_RELOC_AVR_6_ADIW, R_AVR_6_ADIW },
+ { BFD_RELOC_8, R_AVR_8 }
};
/* Meant to be filled one day with the wrap around address for the
cache_ptr->howto = &elf_avr_howto_table[r_type];
}
-/* Look through the relocs for a section during the first phase.
- Since we don't do .gots or .plts, we just need to consider the
- virtual table relocs for gc. */
-
-static bfd_boolean
-elf32_avr_check_relocs (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
-
- if (info->relocatable)
- return TRUE;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
-
- rel_end = relocs + sec->reloc_count;
- for (rel = relocs; rel < rel_end; rel++)
- {
- struct elf_link_hash_entry *h;
- unsigned long r_symndx;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
- else
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- 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;
- }
- }
-
- return TRUE;
-}
-
static bfd_boolean
avr_stub_is_required_for_16_bit_reloc (bfd_vma relocation)
{
r_type = ELF32_R_TYPE (rel->r_info);
r_symndx = ELF32_R_SYM (rel->r_info);
- howto = elf_avr_howto_table + ELF32_R_TYPE (rel->r_info);
+ howto = elf_avr_howto_table + r_type;
h = NULL;
sym = NULL;
sec = NULL;
}
if (sec != NULL && elf_discarded_section (sec))
- {
- /* For relocs against symbols from removed linkonce sections,
- or sections discarded by a linker script, we just want the
- section contents zeroed. Avoid any special processing. */
- _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
- rel->r_info = 0;
- rel->r_addend = 0;
- continue;
- }
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, relend, howto, contents);
if (info->relocatable)
continue;
case bfd_mach_avr6:
val = E_AVR_MACH_AVR6;
break;
+
+ case bfd_mach_avrxmega1:
+ val = E_AVR_MACH_XMEGA1;
+ break;
+
+ case bfd_mach_avrxmega2:
+ val = E_AVR_MACH_XMEGA2;
+ break;
+
+ case bfd_mach_avrxmega3:
+ val = E_AVR_MACH_XMEGA3;
+ break;
+
+ case bfd_mach_avrxmega4:
+ val = E_AVR_MACH_XMEGA4;
+ break;
+
+ case bfd_mach_avrxmega5:
+ val = E_AVR_MACH_XMEGA5;
+ break;
+
+ case bfd_mach_avrxmega6:
+ val = E_AVR_MACH_XMEGA6;
+ break;
+
+ case bfd_mach_avrxmega7:
+ val = E_AVR_MACH_XMEGA7;
+ break;
}
elf_elfheader (abfd)->e_machine = EM_AVR;
case E_AVR_MACH_AVR6:
e_set = bfd_mach_avr6;
break;
+
+ case E_AVR_MACH_XMEGA1:
+ e_set = bfd_mach_avrxmega1;
+ break;
+
+ case E_AVR_MACH_XMEGA2:
+ e_set = bfd_mach_avrxmega2;
+ break;
+
+ case E_AVR_MACH_XMEGA3:
+ e_set = bfd_mach_avrxmega3;
+ break;
+
+ case E_AVR_MACH_XMEGA4:
+ e_set = bfd_mach_avrxmega4;
+ break;
+
+ case E_AVR_MACH_XMEGA5:
+ e_set = bfd_mach_avrxmega5;
+ break;
+
+ case E_AVR_MACH_XMEGA6:
+ e_set = bfd_mach_avrxmega6;
+ break;
+
+ case E_AVR_MACH_XMEGA7:
+ e_set = bfd_mach_avrxmega7;
+ break;
}
}
return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
unsigned int sec_shndx;
bfd_byte *contents;
Elf_Internal_Rela *irel, *irelend;
- Elf_Internal_Rela *irelalign;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymbuf = NULL;
bfd_vma toaddr;
sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
contents = elf_section_data (sec)->this_hdr.contents;
- /* The deletion must stop at the next ALIGN reloc for an aligment
- power larger than the number of bytes we are deleting. */
-
- irelalign = NULL;
toaddr = sec->size;
irel = elf_section_data (sec)->relocs;
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
{
bfd_vma old_reloc_address;
- bfd_vma shrinked_insn_address;
old_reloc_address = (sec->output_section->vma
+ sec->output_offset + irel->r_offset);
- shrinked_insn_address = (sec->output_section->vma
- + sec->output_offset + addr - count);
/* Get the new reloc address. */
if ((irel->r_offset > addr
Elf_Internal_Rela *irel, *irelend;
bfd_byte *contents = NULL;
Elf_Internal_Sym *isymbuf = NULL;
- static asection *last_input_section = NULL;
- static Elf_Internal_Rela *last_reloc = NULL;
struct elf32_avr_link_hash_table *htab;
if (link_info->relocatable)
if (internal_relocs == NULL)
goto error_return;
- if (sec != last_input_section)
- last_reloc = NULL;
-
- last_input_section = sec;
-
/* Walk through the relocs looking for relaxing opportunities. */
irelend = internal_relocs + sec->reloc_count;
for (irel = internal_relocs; irel < irelend; irel++)
if ((0x95 == next_insn_msb) && (0x08 == next_insn_lsb))
{
/* The next insn is a ret. We possibly could delete
- this ret. First we need to check for preceeding
+ this ret. First we need to check for preceding
sbis/sbic/sbrs or cpse "skip" instructions. */
- int there_is_preceeding_non_skip_insn = 1;
+ int there_is_preceding_non_skip_insn = 1;
bfd_vma address_of_ret;
address_of_ret = dot + insn_size;
printf ("found jmp / ret sequence at address 0x%x\n",
(int) dot);
- /* We have to make sure that there is a preceeding insn. */
+ /* We have to make sure that there is a preceding insn. */
if (irel->r_offset >= 2)
{
- unsigned char preceeding_msb;
- unsigned char preceeding_lsb;
- preceeding_msb =
+ unsigned char preceding_msb;
+ unsigned char preceding_lsb;
+
+ preceding_msb =
bfd_get_8 (abfd, contents + irel->r_offset - 1);
- preceeding_lsb =
+ preceding_lsb =
bfd_get_8 (abfd, contents + irel->r_offset - 2);
/* sbic. */
- if (0x99 == preceeding_msb)
- there_is_preceeding_non_skip_insn = 0;
+ if (0x99 == preceding_msb)
+ there_is_preceding_non_skip_insn = 0;
/* sbis. */
- if (0x9b == preceeding_msb)
- there_is_preceeding_non_skip_insn = 0;
+ if (0x9b == preceding_msb)
+ there_is_preceding_non_skip_insn = 0;
/* sbrc */
- if ((0xfc == (preceeding_msb & 0xfe)
- && (0x00 == (preceeding_lsb & 0x08))))
- there_is_preceeding_non_skip_insn = 0;
+ if ((0xfc == (preceding_msb & 0xfe)
+ && (0x00 == (preceding_lsb & 0x08))))
+ there_is_preceding_non_skip_insn = 0;
/* sbrs */
- if ((0xfe == (preceeding_msb & 0xfe)
- && (0x00 == (preceeding_lsb & 0x08))))
- there_is_preceeding_non_skip_insn = 0;
+ if ((0xfe == (preceding_msb & 0xfe)
+ && (0x00 == (preceding_lsb & 0x08))))
+ there_is_preceding_non_skip_insn = 0;
/* cpse */
- if (0x10 == (preceeding_msb & 0xfc))
- there_is_preceeding_non_skip_insn = 0;
+ if (0x10 == (preceding_msb & 0xfc))
+ there_is_preceding_non_skip_insn = 0;
- if (there_is_preceeding_non_skip_insn == 0)
+ if (there_is_preceding_non_skip_insn == 0)
if (debug_relax)
- printf ("preceeding skip insn prevents deletion of"
- " ret insn at addr 0x%x in section %s\n",
+ printf ("preceding skip insn prevents deletion of"
+ " ret insn at Addy 0x%x in section %s\n",
(int) dot + 2, sec->name);
}
else
{
/* There is no previous instruction. */
- there_is_preceeding_non_skip_insn = 0;
+ there_is_preceding_non_skip_insn = 0;
}
- if (there_is_preceeding_non_skip_insn)
+ if (there_is_preceding_non_skip_insn)
{
/* We now only have to make sure that there is no
local label defined at the address of the ret
static bfd_boolean
avr_mark_stub_not_to_be_necessary (struct bfd_hash_entry *bh,
- void *in_arg)
+ void *in_arg ATTRIBUTE_UNUSED)
{
struct elf32_avr_stub_hash_entry *hsh;
- struct elf32_avr_link_hash_table *htab;
- htab = in_arg;
hsh = avr_stub_hash_entry (bh);
hsh->is_actually_needed = FALSE;
}
#define ELF_ARCH bfd_arch_avr
+#define ELF_TARGET_ID AVR_ELF_DATA
#define ELF_MACHINE_CODE EM_AVR
#define ELF_MACHINE_ALT1 EM_AVR_OLD
#define ELF_MAXPAGESIZE 1
#define elf_info_to_howto avr_info_to_howto_rela
#define elf_info_to_howto_rel NULL
#define elf_backend_relocate_section elf32_avr_relocate_section
-#define elf_backend_check_relocs elf32_avr_check_relocs
#define elf_backend_can_gc_sections 1
#define elf_backend_rela_normal 1
#define elf_backend_final_write_processing \