Memory leaks and ineffective bounds checking in wasm_scan
[deliverable/binutils-gdb.git] / bfd / elf32-avr.c
index 3917d0e820868905516001dc879fbd0ba9832389..e2d4de621147574f08889a7037dbc00144343de3 100644 (file)
@@ -1,5 +1,5 @@
 /* AVR-specific support for 32-bit ELF
-   Copyright (C) 1999-2017 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.
@@ -25,7 +25,6 @@
 #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;
@@ -708,6 +707,12 @@ static const struct avr_reloc_map avr_reloc_map[] =
   { 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.
@@ -905,7 +910,7 @@ avr_relative_distance_considering_wrap_around (unsigned int distance)
   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;
@@ -945,8 +950,8 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
 /* 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)
 {
@@ -956,10 +961,13 @@ avr_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   if (r_type >= (unsigned int) R_AVR_max)
     {
       /* xgettext:c-format */
-      _bfd_error_handler (_("%B: 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
@@ -1457,7 +1465,7 @@ elf32_avr_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
 
          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
        {
@@ -1528,9 +1536,8 @@ elf32_avr_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
    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;
 
@@ -1613,6 +1620,7 @@ bfd_elf_avr_final_write_processing (bfd *abfd,
   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.  */
@@ -2346,8 +2354,7 @@ avr_property_record_compare (const void *ap, const void *bp)
     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);
 }
@@ -2635,16 +2642,28 @@ elf32_avr_relax_section (bfd *abfd,
            /* 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
@@ -3292,10 +3311,10 @@ avr_stub_name (const asection *symbol_section,
 
   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;
 }
@@ -3928,12 +3947,12 @@ internal_reloc_compare (const void *ap, const void *bp)
 /* 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;
 
@@ -3965,7 +3984,7 @@ struct avr_find_section_data
    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
@@ -3976,11 +3995,11 @@ avr_find_section_for_address (bfd *abfd,
     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;
 }
 
@@ -4003,7 +4022,7 @@ avr_elf32_load_records_from_section (bfd *abfd, asection *sec)
 
   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;
@@ -4106,8 +4125,7 @@ avr_elf32_load_records_from_section (bfd *abfd, asection *sec)
        {
          /* 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)
@@ -4125,7 +4143,7 @@ avr_elf32_load_records_from_section (bfd *abfd, asection *sec)
 
          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);
@@ -4253,5 +4271,6 @@ avr_elf32_property_record_name (struct avr_property_record *rec)
 #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"
This page took 0.029066 seconds and 4 git commands to generate.