* 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:
parent
1f4c5b4746
commit
9b691193ef
2 changed files with 45 additions and 6 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue