* 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>
|
2002-10-12 Stephane Carrez <stcarrez@nerim.fr>
|
||||||
|
|
||||||
* elf32-m68hc11.c (m68hc11_elf_relax_section): Update symbols
|
* 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 symval;
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
Elf_Internal_Sym *isym;
|
Elf_Internal_Sym *isym;
|
||||||
|
asection *sym_sec;
|
||||||
|
|
||||||
/* If this isn't something that can be relaxed, then ignore
|
/* If this isn't something that can be relaxed, then ignore
|
||||||
this reloc. */
|
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)
|
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
||||||
{
|
{
|
||||||
/* A local symbol. */
|
/* A local symbol. */
|
||||||
asection *sym_sec;
|
|
||||||
|
|
||||||
isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
||||||
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
|
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
|
||||||
symval = (isym->st_value
|
symval = (isym->st_value
|
||||||
|
@ -819,9 +818,11 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isym = 0;
|
||||||
|
sym_sec = h->root.u.def.section;
|
||||||
symval = (h->root.u.def.value
|
symval = (h->root.u.def.value
|
||||||
+ h->root.u.def.section->output_section->vma
|
+ sym_sec->output_section->vma
|
||||||
+ h->root.u.def.section->output_offset);
|
+ sym_sec->output_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
|
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;
|
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;
|
value = symval;
|
||||||
/* Try to turn a far branch to a near branch. */
|
/* Try to turn a far branch to a near branch. */
|
||||||
if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
|
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);
|
irel->r_offset - 1, 3);
|
||||||
}
|
}
|
||||||
prev_insn_branch = 0;
|
prev_insn_branch = 0;
|
||||||
|
*again = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to turn a 16 bit address into a 8 bit page0 address. */
|
/* 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)
|
if (prev_insn_group)
|
||||||
{
|
{
|
||||||
|
unsigned long old_sec_size = sec->_cooked_size;
|
||||||
|
|
||||||
/* Note that we've changed the reldection contents, etc. */
|
/* Note that we've changed the reldection contents, etc. */
|
||||||
elf_section_data (sec)->relocs = internal_relocs;
|
elf_section_data (sec)->relocs = internal_relocs;
|
||||||
free_relocs = NULL;
|
free_relocs = NULL;
|
||||||
|
@ -921,6 +951,8 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
|
||||||
prev_insn_group = 0;
|
prev_insn_group = 0;
|
||||||
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
||||||
R_M68HC11_NONE);
|
R_M68HC11_NONE);
|
||||||
|
if (sec->_cooked_size != old_sec_size)
|
||||||
|
*again = true;
|
||||||
continue;
|
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),
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
||||||
R_M68HC11_8);
|
R_M68HC11_8);
|
||||||
|
|
||||||
/* That will change things, so, we should relax again.
|
/* That will change things, so, we should relax again. */
|
||||||
Note that this is not required, and it may be slow. */
|
|
||||||
*again = true;
|
*again = true;
|
||||||
}
|
}
|
||||||
else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16)
|
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);
|
R_M68HC11_NONE);
|
||||||
m68hc11_elf_relax_delete_bytes (abfd, sec,
|
m68hc11_elf_relax_delete_bytes (abfd, sec,
|
||||||
irel->r_offset + 1, 1);
|
irel->r_offset + 1, 1);
|
||||||
|
/* That will change things, so, we should relax again. */
|
||||||
|
*again = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue