* 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.
This commit is contained in:
Nick Clifton 2006-05-05 17:46:47 +00:00
parent 605a56cbd3
commit 731608473a
4 changed files with 111 additions and 64 deletions

View 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.

View 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. */
/* 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. */
/* 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;
}
{
struct bfd_section *isec;
/* 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;
for (isec = abfd->sections; isec; isec = isec->next)
{
bfd_vma symval;
bfd_vma shrinked_insn_address;
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;
shrinked_insn_address = (sec->output_section->vma
+ sec->output_offset + addr - count);
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);
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;
}
if (symval <= shrinked_insn_address
&& (symval + irel->r_addend) > shrinked_insn_address)
{
irel->r_addend -= count;
/* 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;

View 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

View 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; \
}