* gas/config/tc-avr.h (TC_VALIDATE_FIX): Define. Disable fixups for PMEM
authorNick Clifton <nickc@redhat.com>
Fri, 5 May 2006 17:46:47 +0000 (17:46 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 5 May 2006 17:46:47 +0000 (17:46 +0000)
    related expressions.
* bfd/elf32-avr.c (elf32_avr_relax_delete_bytes): Iterate over all of the
    bfd's sections for the reloc-addend adjustments.

bfd/ChangeLog
bfd/elf32-avr.c
gas/ChangeLog
gas/config/tc-avr.h

index 1a4f31433b3ba5aaf3aac0fd0afef64b9f689291..29687028dda55c0749cb0388ad7ca582eed951f6 100644 (file)
@@ -1,3 +1,8 @@
+2006-05-05  Bjoern Haase  <bjoern.m.haase@web.de>
+
+       * bfd/elf32-avr.c (elf32_avr_relax_delete_bytes): Iterate over all
+       of the bfd's sections for the reloc-addend adjustments.
+
 2006-05-05  Martin Schwidefsky  <schwidefsky@de.ibm.com>
 
        * elf32-s390.c (invalid_tls_insn): Call bfd_set_error.
index ec42bb335d1a2c7629ec176d160a603b8da9eebc..e5f09c606d850acf5253eed83d038da8cc729a11 100644 (file)
@@ -433,6 +433,7 @@ struct avr_reloc_map
 unsigned int avr_pc_wrap_around = 0x10000000;
 
 /* Calculates the effective distance of a pc relative jump/call.  */
+
 static int
 avr_relative_distance_considering_wrap_around (unsigned int distance)
 {
@@ -455,10 +456,8 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   for (i = 0;
        i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map);
        i++)
-    {
-      if (avr_reloc_map[i].bfd_reloc_val == code)
-       return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
-    }
+    if (avr_reloc_map[i].bfd_reloc_val == code)
+      return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
 
   return NULL;
 }
@@ -1049,9 +1048,9 @@ elf32_avr_object_p (bfd *abfd)
 
 static bfd_boolean
 elf32_avr_relax_delete_bytes (bfd *abfd,
-                             asection *sec,
+                              asection *sec,
                               bfd_vma addr,
-                             int count)
+                              int count)
 {
   Elf_Internal_Shdr *symtab_hdr;
   unsigned int sec_shndx;
@@ -1085,10 +1084,9 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
              (size_t) (toaddr - addr - count));
   sec->size -= count;
 
-  /* Adjust all the relocs.  */
+  /* Adjust all the reloc addresses.  */
   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
     {
-      bfd_vma symval;
       bfd_vma old_reloc_address;
       bfd_vma shrinked_insn_address;
 
@@ -1111,69 +1109,91 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
           irel->r_offset -= count;
         }
 
-      /* The reloc's own addresses are now ok. However, we need to readjust
-         the reloc's addend if two conditions are met:
-         1.) the reloc is relative to a symbol in this section that
-             is located in front of the shrinked instruction
-         2.) symbol plus addend end up behind the shrinked instruction.
-
-         This should happen only for local symbols that are progmem related.  */
-
-      /* Read this BFD's local symbols if we haven't done so already.  */
-      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
-        {
-          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
-          if (isymbuf == NULL)
-            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
-                                            symtab_hdr->sh_info, 0,
-                                            NULL, NULL, NULL);
-          if (isymbuf == NULL)
-             return FALSE;
-         }
-
-      /* Get the value of the symbol referred to by the reloc.  */
-      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
-        {
-          /* A local symbol.  */
-          Elf_Internal_Sym *isym;
-          asection *sym_sec;
+    }
 
-          isym = isymbuf + ELF32_R_SYM (irel->r_info);
-          sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
-          symval = isym->st_value;
-          /* If the reloc is absolute, it will not have
-             a symbol or section associated with it.  */
-          if (sym_sec)
-            {
-               symval += sym_sec->output_section->vma
-                         + sym_sec->output_offset;
-
-               if (DEBUG_RELAX)
-                printf ("Checking if the relocation's "
-                        "addend needs corrections.\n"
-                        "Address of anchor symbol: 0x%x \n"
-                        "Address of relocation target: 0x%x \n"
-                        "Address of relaxed insn: 0x%x \n",
-                        (unsigned int) symval,
-                        (unsigned int) (symval + irel->r_addend),
-                        (unsigned int) shrinked_insn_address);
-
-               if (symval <= shrinked_insn_address
-                   && (symval + irel->r_addend) > shrinked_insn_address)
-                 {
-                   irel->r_addend -= count;
+   /* The reloc's own addresses are now ok. However, we need to readjust
+      the reloc's addend, i.e. the reloc's value if two conditions are met:
+      1.) the reloc is relative to a symbol in this section that
+          is located in front of the shrinked instruction
+      2.) symbol plus addend end up behind the shrinked instruction.  
+      
+      The most common case where this happens are relocs relative to
+      the section-start symbol.
+         
+      This step needs to be done for all of the sections of the bfd.  */
+
+  {
+    struct bfd_section *isec;
+
+    for (isec = abfd->sections; isec; isec = isec->next)
+     {
+       bfd_vma symval;
+       bfd_vma shrinked_insn_address;
+
+       shrinked_insn_address = (sec->output_section->vma
+                                + sec->output_offset + addr - count);
+
+       irelend = elf_section_data (isec)->relocs + isec->reloc_count;
+       for (irel = elf_section_data (isec)->relocs; 
+            irel < irelend;
+            irel++)
+         {
+           /* Read this BFD's local symbols if we haven't done 
+              so already.  */
+           if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+             {
+               isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+               if (isymbuf == NULL)
+                 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                                 symtab_hdr->sh_info, 0,
+                                                 NULL, NULL, NULL);
+               if (isymbuf == NULL)
+                 return FALSE;
+             }
+
+           /* Get the value of the symbol referred to by the reloc.  */
+           if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+             {
+               /* A local symbol.  */
+               Elf_Internal_Sym *isym;
+               asection *sym_sec;
+
+               isym = isymbuf + ELF32_R_SYM (irel->r_info);
+               sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+               symval = isym->st_value;
+               /* If the reloc is absolute, it will not have
+                  a symbol or section associated with it.  */
+               if (sym_sec == sec)
+                 { 
+                   symval += sym_sec->output_section->vma
+                             + sym_sec->output_offset;
 
                    if (DEBUG_RELAX)
-                     printf ("Anchor symbol and relocation target bracket "
-                             "shrinked insn address.\n"
-                             "Need for new addend : 0x%x\n",
-                             (unsigned int) irel->r_addend);
+                     printf ("Checking if the relocation's "
+                             "addend needs corrections.\n"
+                             "Address of anchor symbol: 0x%x \n"
+                             "Address of relocation target: 0x%x \n"
+                             "Address of relaxed insn: 0x%x \n",
+                             (unsigned int) symval,
+                             (unsigned int) (symval + irel->r_addend),
+                             (unsigned int) shrinked_insn_address);
+
+                   if (symval <= shrinked_insn_address
+                       && (symval + irel->r_addend) > shrinked_insn_address)
+                     {
+                       irel->r_addend -= count;
+
+                       if (DEBUG_RELAX)
+                         printf ("Relocation's addend needed to be fixed \n");
+                     }
                  }
-            }
-         /* else ... Reference symbol is absolute.  No adjustment needed.  */
-        }
-      /* else ... Reference symbol is extern. No need for adjusting the addend.  */
-    }
+              /* else...Reference symbol is absolute.  No adjustment needed.  */
+              }
+          /* else...Reference symbol is extern. No need for adjusting 
+             the addend.  */
+          }
+     }
+  }
 
   /* Adjust the local symbols defined in this section.  */
   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
index 82de3ccf29c2554c3fac9b1fd987f84846fa4f06..ab362dd91aa2bccfd5ff8f64d669a816c6b14e01 100644 (file)
@@ -1,3 +1,8 @@
+2006-05-05  Bjoern Haase  <bjoern.m.haase@web.de>
+
+       * gas/config/tc-avr.h (TC_VALIDATE_FIX): Define.  Disable fixups
+       for PMEM related expressions.
+
 2006-05-05  Nick Clifton  <nickc@redhat.com>
 
        PR gas/2582
index df12045a42583208ec93041e954eff47830b332b..61e76e60dff5e339fa14d7e50116575e4dcbec55 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is tc-avr.h
-   Copyright 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
 
    Contributed by Denis Chertykov <denisc@overta.ru>
 
@@ -109,7 +109,7 @@ extern long md_pcrel_from_section (struct fix *, segT);
    would print `12 34 56 78'.  The default value is 4.  */
 #define LISTING_WORD_SIZE 2
 
-/* AVR port uses `$' as a logical line separator */
+/* AVR port uses `$' as a logical line separator */
 #define LEX_DOLLAR 0
 
 /* An `.lcomm' directive with no explicit alignment parameter will
@@ -120,3 +120,20 @@ extern long md_pcrel_from_section (struct fix *, segT);
    also affected by this macro.  The default definition will set
    P2VAR to the truncated power of two of sizes up to eight bytes.  */
 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) (P2VAR) = 0
+
+/* We don't want gas to fixup the following program memory related relocations.
+   We will need them in case that we want to do linker relaxation.
+   We could in principle keep these fixups in gas when not relaxing.
+   However, there is no serious performance penilty when making the linker
+   make the fixup work.  */
+#define TC_VALIDATE_FIX(FIXP,SEG,SKIP)                      \
+  if ( FIXP->fx_r_type == BFD_RELOC_AVR_7_PCREL             \
+    || FIXP->fx_r_type == BFD_RELOC_AVR_13_PCREL            \
+    || FIXP->fx_r_type == BFD_RELOC_AVR_LO8_LDI_PM          \
+    || FIXP->fx_r_type == BFD_RELOC_AVR_HI8_LDI_PM          \
+    || FIXP->fx_r_type == BFD_RELOC_AVR_HH8_LDI_PM          \
+    || FIXP->fx_r_type == BFD_RELOC_AVR_16_PM)              \
+    {                                                       \
+      goto SKIP;                                            \
+    }
+