/* AVR-specific support for 32-bit ELF
- Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2020 Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru>
This file is part of BFD, the Binary File Descriptor library.
#include "elf-bfd.h"
#include "elf/avr.h"
#include "elf32-avr.h"
-#include "bfd_stdint.h"
/* Enable debugging printout at stdout with this variable. */
static bfd_boolean debug_relax = FALSE;
{ BFD_RELOC_32_PCREL, R_AVR_32_PCREL}
};
+static const struct bfd_elf_special_section elf_avr_special_sections[] =
+{
+ { STRING_COMMA_LEN (".noinit"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { NULL, 0, 0, 0, 0 }
+};
+
/* Meant to be filled one day with the wrap around address for the
specific device. I.e. should get the value 0x4000 for 16k devices,
0x8000 for 32k devices and so on.
unsigned int wrap_around_mask = avr_pc_wrap_around - 1;
int dist_with_wrap_around = distance & wrap_around_mask;
- if (dist_with_wrap_around > ((int) (avr_pc_wrap_around >> 1)))
+ if (dist_with_wrap_around >= ((int) (avr_pc_wrap_around >> 1)))
dist_with_wrap_around -= avr_pc_wrap_around;
return dist_with_wrap_around;
/* Set the howto pointer for an AVR ELF reloc. */
-static void
-avr_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
+static bfd_boolean
+avr_info_to_howto_rela (bfd *abfd,
arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
if (r_type >= (unsigned int) R_AVR_max)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%pB: invalid AVR reloc number: %d"), abfd, r_type);
- r_type = 0;
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
cache_ptr->howto = &elf_avr_howto_table[r_type];
+ return TRUE;
}
static bfd_boolean
name = bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name);
- name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
+ name = name == NULL ? bfd_section_name (sec) : name;
}
else
{
file. This gets the AVR architecture right based on the machine
number. */
-static void
-bfd_elf_avr_final_write_processing (bfd *abfd,
- bfd_boolean linker ATTRIBUTE_UNUSED)
+static bfd_boolean
+bfd_elf_avr_final_write_processing (bfd *abfd)
{
unsigned long val;
elf_elfheader (abfd)->e_machine = EM_AVR;
elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
elf_elfheader (abfd)->e_flags |= val;
+ return _bfd_elf_final_write_processing (abfd);
}
/* Set the right machine number. */
return (a->offset - b->offset);
if (a->section != b->section)
- return (bfd_get_section_vma (a->section->owner, a->section)
- - bfd_get_section_vma (b->section->owner, b->section));
+ return bfd_section_vma (a->section) - bfd_section_vma (b->section);
return (a->type - b->type);
}
/* Compute the distance from this insn to the branch target. */
gap = value - dot;
+ /* The ISA manual states that addressable range is PC - 2k + 1 to
+ PC + 2k. In bytes, that would be -4094 <= PC <= 4096. The range
+ is shifted one word to the right, because pc-relative instructions
+ implicitly add one word i.e. rjmp 0 jumps to next insn, not the
+ current one.
+ Therefore, for the !shrinkable case, the range is as above.
+ If shrinkable, then the current code only deletes bytes 3 and
+ 4 of the absolute call/jmp, so the forward jump range increases
+ by 2 bytes, but the backward (negative) jump range remains
+ the same. */
+
+
/* Check if the gap falls in the range that can be accommodated
in 13bits signed (It is 12bits when encoded, as we deal with
word addressing). */
- if (!shrinkable && ((int) gap >= -4096 && (int) gap <= 4095))
+ if (!shrinkable && ((int) gap >= -4094 && (int) gap <= 4096))
distance_short_enough = 1;
/* If shrinkable, then we can check for a range of distance which
- is two bytes farther on both the directions because the call
+ is two bytes farther on the positive direction because the call
or jump target will be closer by two bytes after the
relaxation. */
- else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4097))
+ else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4098))
distance_short_enough = 1;
/* Here we handle the wrap-around case. E.g. for a 16k device
len = 8 + 1 + 8 + 1 + 1;
stub_name = bfd_malloc (len);
-
- sprintf (stub_name, "%08x+%08x",
- symbol_section->id & 0xffffffff,
- (unsigned int) ((rela->r_addend & 0xffffffff) + symbol_offset));
+ if (stub_name != NULL)
+ sprintf (stub_name, "%08x+%08x",
+ symbol_section->id & 0xffffffff,
+ (unsigned int) ((rela->r_addend & 0xffffffff) + symbol_offset));
return stub_name;
}
/* Return true if ADDRESS is within the vma range of SECTION from ABFD. */
static bfd_boolean
-avr_is_section_for_address (bfd *abfd, asection *section, bfd_vma address)
+avr_is_section_for_address (asection *section, bfd_vma address)
{
bfd_vma vma;
bfd_size_type size;
- vma = bfd_get_section_vma (abfd, section);
+ vma = bfd_section_vma (section);
if (address < vma)
return FALSE;
perform any checks, and just returns. */
static void
-avr_find_section_for_address (bfd *abfd,
+avr_find_section_for_address (bfd *abfd ATTRIBUTE_UNUSED,
asection *section, void *data)
{
struct avr_find_section_data *fs_data
return;
/* If this section isn't part of the addressable code content, skip it. */
- if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0
- && (bfd_get_section_flags (abfd, section) & SEC_CODE) == 0)
+ if ((bfd_section_flags (section) & SEC_ALLOC) == 0
+ && (bfd_section_flags (section) & SEC_CODE) == 0)
return;
- if (avr_is_section_for_address (abfd, section, fs_data->address))
+ if (avr_is_section_for_address (section, fs_data->address))
fs_data->section = section;
}
fs_data.section = NULL;
- size = bfd_get_section_size (sec);
+ size = bfd_section_size (sec);
contents = bfd_malloc (size);
bfd_get_section_contents (abfd, sec, contents, 0, size);
ptr = contents;
{
/* Try to find section and offset from address. */
if (fs_data.section != NULL
- && !avr_is_section_for_address (abfd, fs_data.section,
- address))
+ && !avr_is_section_for_address (fs_data.section, address))
fs_data.section = NULL;
if (fs_data.section == NULL)
r_list->records [i].section = fs_data.section;
r_list->records [i].offset
- = address - bfd_get_section_vma (abfd, fs_data.section);
+ = address - bfd_section_vma (fs_data.section);
}
r_list->records [i].type = *((bfd_byte *) ptr);
#define bfd_elf32_bfd_get_relocated_section_contents \
elf32_avr_get_relocated_section_contents
#define bfd_elf32_new_section_hook elf_avr_new_section_hook
+#define elf_backend_special_sections elf_avr_special_sections
#include "elf32-target.h"