* elf32-m68hc11.c (m68hc11_elf_relax_section): Don't treat relocs

with symbols in other sections if we relaxed something;  the sections
	output offsets must be re-computed before.
This commit is contained in:
Stephane Carrez 2002-10-12 14:00:55 +00:00
parent 1f4c5b4746
commit 9b691193ef
2 changed files with 45 additions and 6 deletions

View File

@ -1,3 +1,9 @@
2002-10-12 Stephane Carrez <stcarrez@nerim.fr>
* elf32-m68hc11.c (m68hc11_elf_relax_section): Don't treat relocs
with symbols in other sections if we relaxed something; the sections
output offsets must be re-computed before.
2002-10-12 Stephane Carrez <stcarrez@nerim.fr>
* elf32-m68hc11.c (m68hc11_elf_relax_section): Update symbols

View File

@ -693,6 +693,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
bfd_vma symval;
bfd_vma value;
Elf_Internal_Sym *isym;
asection *sym_sec;
/* If this isn't something that can be relaxed, then ignore
this reloc. */
@ -791,8 +792,6 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
/* A local symbol. */
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
@ -819,9 +818,11 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
continue;
}
isym = 0;
sym_sec = h->root.u.def.section;
symval = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+ sym_sec->output_section->vma
+ sym_sec->output_offset);
}
if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
@ -838,6 +839,32 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
continue;
}
/* When we relax some bytes, the size of our section changes.
This affects the layout of next input sections that go in our
output section. When the symbol is part of another section that
will go in the same output section as the current one, it's
final address may now be incorrect (too far). We must let the
linker re-compute all section offsets before processing this
reloc. Code example:
Initial Final
.sect .text section size = 6 section size = 4
jmp foo
jmp bar
.sect .text.foo_bar output_offset = 6 output_offset = 4
foo: rts
bar: rts
If we process the reloc now, the jmp bar is replaced by a
relative branch to the initial bar address (output_offset 6). */
if (*again && sym_sec != sec
&& sym_sec->output_section == sec->output_section)
{
prev_insn_group = 0;
prev_insn_branch = 0;
continue;
}
value = symval;
/* Try to turn a far branch to a near branch. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
@ -883,6 +910,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
irel->r_offset - 1, 3);
}
prev_insn_branch = 0;
*again = true;
}
/* Try to turn a 16 bit address into a 8 bit page0 address. */
@ -904,6 +932,8 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
if (prev_insn_group)
{
unsigned long old_sec_size = sec->_cooked_size;
/* Note that we've changed the reldection contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
free_relocs = NULL;
@ -921,6 +951,8 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
prev_insn_group = 0;
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_M68HC11_NONE);
if (sec->_cooked_size != old_sec_size)
*again = true;
continue;
}
@ -956,8 +988,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_M68HC11_8);
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
/* That will change things, so, we should relax again. */
*again = true;
}
else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16)
@ -999,6 +1030,8 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
R_M68HC11_NONE);
m68hc11_elf_relax_delete_bytes (abfd, sec,
irel->r_offset + 1, 1);
/* That will change things, so, we should relax again. */
*again = true;
}
}
}