summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2006-05-05 17:46:47 +0000
committerNick Clifton <nickc@redhat.com>2006-05-05 17:46:47 +0000
commit2c6c7d30cef4e8d7c6b351707ac61479bff2b521 (patch)
tree9dd18b97305e3e9159b6b4efbfed81fdb38c8331
parent2aa12fbec81d02258178f259e0685c64d481d925 (diff)
downloadbinutils-redhat-2c6c7d30cef4e8d7c6b351707ac61479bff2b521.tar.gz
* gas/config/tc-avr.h (TC_VALIDATE_FIX): Define. Disable fixups for PMEM
related expressions. * bfd/elf32-avr.c (elf32_avr_relax_delete_bytes): Iterate over all of the bfd's sections for the reloc-addend adjustments.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf32-avr.c154
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-avr.h21
4 files changed, 116 insertions, 69 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1a4f31433b..29687028dd 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 ec42bb335d..e5f09c606d 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 82de3ccf29..ab362dd91a 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 df12045a42..61e76e60df 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; \
+ }
+