diff options
-rw-r--r-- | bfd/ChangeLog | 5 | ||||
-rw-r--r-- | bfd/elf32-avr.c | 154 | ||||
-rw-r--r-- | gas/ChangeLog | 5 | ||||
-rw-r--r-- | gas/config/tc-avr.h | 21 |
4 files changed, 116 insertions, 69 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1a4f314..2968702 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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. diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index ec42bb3..e5f09c6 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -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; diff --git a/gas/ChangeLog b/gas/ChangeLog index 82de3cc..ab362dd 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-avr.h b/gas/config/tc-avr.h index df12045..61e76e6 100644 --- a/gas/config/tc-avr.h +++ b/gas/config/tc-avr.h @@ -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; \ + } + |