* elf32-m68hc11.c (m68hc11_elf_relax_delete_bytes): Also adjust

symbols that mark the end of the section.
	(m68hc11_elf_relax_section): Use R_M68HC11_PCREL_8 relocs when
	converting to a relative branch so that the offset is computed after
	the relaxation; also relocate a jsr into a bsr if possible but don't
	relax them if they are to a far symbol as we need to call the
	trampoline code.
	(elf_m68hc11_howto_table): Set pcrel_offset to true.
This commit is contained in:
Stephane Carrez
2003-04-04 21:17:06 +00:00
parent 11889732f8
commit 196486bed9
2 changed files with 38 additions and 19 deletions

View File

@ -1,3 +1,14 @@
2003-04-04 Stephane Carrez <stcarrez@nerim.fr>
* elf32-m68hc11.c (m68hc11_elf_relax_delete_bytes): Also adjust
symbols that mark the end of the section.
(m68hc11_elf_relax_section): Use R_M68HC11_PCREL_8 relocs when
converting to a relative branch so that the offset is computed after
the relaxation; also relocate a jsr into a bsr if possible but don't
relax them if they are to a far symbol as we need to call the
trampoline code.
(elf_m68hc11_howto_table): Set pcrel_offset to true.
2003-04-04 Svein E. Seldal <Svein.Seldal@solidas.com> 2003-04-04 Svein E. Seldal <Svein.Seldal@solidas.com>
* archures.c: Namespace cleanup. Rename bfd_mach_c3x to * archures.c: Namespace cleanup. Rename bfd_mach_c3x to

View File

@ -1,5 +1,5 @@
/* Motorola 68HC11-specific support for 32-bit ELF /* Motorola 68HC11-specific support for 32-bit ELF
Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr) Contributed by Stephane Carrez (stcarrez@nerim.fr)
(Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com)) (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
@ -143,7 +143,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0x00ff, /* src_mask */ 0x00ff, /* src_mask */
0x00ff, /* dst_mask */ 0x00ff, /* dst_mask */
FALSE), /* pcrel_offset */ TRUE), /* pcrel_offset */
/* A 16 bit absolute relocation */ /* A 16 bit absolute relocation */
HOWTO (R_M68HC11_16, /* type */ HOWTO (R_M68HC11_16, /* type */
@ -204,7 +204,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0xffff, /* src_mask */ 0xffff, /* src_mask */
0xffff, /* dst_mask */ 0xffff, /* dst_mask */
FALSE), /* pcrel_offset */ TRUE), /* pcrel_offset */
/* GNU extension to record C++ vtable hierarchy */ /* GNU extension to record C++ vtable hierarchy */
HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */ HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
@ -247,8 +247,8 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
bfd_elf_generic_reloc, /* special_function */ bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_24", /* name */ "R_M68HC11_24", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0xffff, /* src_mask */ 0xffffff, /* src_mask */
0xffff, /* dst_mask */ 0xffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* A 16-bit low relocation */ /* A 16-bit low relocation */
@ -445,6 +445,9 @@ elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
return TRUE; return TRUE;
} }
/* 68HC11 Linker Relaxation. */
struct m68hc11_direct_relax struct m68hc11_direct_relax
{ {
const char *name; const char *name;
@ -694,6 +697,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
bfd_vma value; bfd_vma value;
Elf_Internal_Sym *isym; Elf_Internal_Sym *isym;
asection *sym_sec; asection *sym_sec;
int is_far = 0;
/* 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. */
@ -747,7 +751,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
prev_insn_group = 0; prev_insn_group = 0;
/* Do nothing if this reloc is the last byte in the section. */ /* Do nothing if this reloc is the last byte in the section. */
if (irel->r_offset == sec->_cooked_size) if (irel->r_offset + 2 >= sec->_cooked_size)
continue; continue;
/* See if the next instruction is an unconditional pc-relative /* See if the next instruction is an unconditional pc-relative
@ -793,6 +797,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
{ {
/* A local symbol. */ /* A local symbol. */
isym = isymbuf + ELF32_R_SYM (irel->r_info); isym = isymbuf + ELF32_R_SYM (irel->r_info);
is_far = isym->st_other & STO_M68HC12_FAR;
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
+ sym_sec->output_section->vma + sym_sec->output_section->vma
@ -818,6 +823,7 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
continue; continue;
} }
is_far = h->other & STO_M68HC12_FAR;
isym = 0; isym = 0;
sym_sec = h->root.u.def.section; sym_sec = h->root.u.def.section;
symval = (h->root.u.def.value symval = (h->root.u.def.value
@ -891,23 +897,25 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
{ {
code = 0x20; code = 0x20;
bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset); bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
bfd_put_8 (abfd, offset, bfd_put_8 (abfd, 0xff,
contents + prev_insn_branch->r_offset + 1); contents + prev_insn_branch->r_offset + 1);
irel->r_offset = prev_insn_branch->r_offset + 1;
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_PCREL_8);
m68hc11_elf_relax_delete_bytes (abfd, sec, m68hc11_elf_relax_delete_bytes (abfd, sec,
irel->r_offset, 1); irel->r_offset + 1, 1);
} }
else else
{ {
code ^= 0x1; code ^= 0x1;
bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset); bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
bfd_put_8 (abfd, offset, bfd_put_8 (abfd, 0xff,
contents + prev_insn_branch->r_offset + 1); contents + prev_insn_branch->r_offset + 1);
irel->r_offset = prev_insn_branch->r_offset + 1;
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_PCREL_8);
m68hc11_elf_relax_delete_bytes (abfd, sec, m68hc11_elf_relax_delete_bytes (abfd, sec,
irel->r_offset - 1, 3); irel->r_offset + 1, 3);
} }
prev_insn_branch = 0; prev_insn_branch = 0;
*again = TRUE; *again = TRUE;
@ -991,14 +999,14 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
/* That will change things, so, we should relax again. */ /* That will change things, so, we should relax again. */
*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 && !is_far)
{ {
unsigned char code; unsigned char code;
bfd_vma offset; bfd_vma offset;
prev_insn_branch = 0; prev_insn_branch = 0;
code = bfd_get_8 (abfd, contents + irel->r_offset - 1); code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
if (code == 0x7e) if (code == 0x7e || code == 0xbd)
{ {
offset = value - (irel->r_offset offset = value - (irel->r_offset
+ sec->output_section->vma + sec->output_section->vma
@ -1021,13 +1029,13 @@ m68hc11_elf_relax_section (abfd, sec, link_info, again)
free_extsyms = NULL; free_extsyms = NULL;
/* Shrink the branch. */ /* Shrink the branch. */
code = 0x20; code = (code == 0x7e) ? 0x20 : 0x8d;
bfd_put_8 (abfd, code, bfd_put_8 (abfd, code,
contents + irel->r_offset - 1); contents + irel->r_offset - 1);
bfd_put_8 (abfd, offset, bfd_put_8 (abfd, 0xff,
contents + irel->r_offset); contents + irel->r_offset);
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_PCREL_8);
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. */ /* That will change things, so, we should relax again. */
@ -1220,7 +1228,7 @@ m68hc11_elf_relax_delete_bytes (abfd, sec, addr, count)
{ {
if (isym->st_shndx == sec_shndx if (isym->st_shndx == sec_shndx
&& isym->st_value > addr && isym->st_value > addr
&& isym->st_value < toaddr) && isym->st_value <= toaddr)
isym->st_value -= count; isym->st_value -= count;
} }
@ -1236,7 +1244,7 @@ m68hc11_elf_relax_delete_bytes (abfd, sec, addr, count)
|| sym_hash->root.type == bfd_link_hash_defweak) || sym_hash->root.type == bfd_link_hash_defweak)
&& sym_hash->root.u.def.section == sec && sym_hash->root.u.def.section == sec
&& sym_hash->root.u.def.value > addr && sym_hash->root.u.def.value > addr
&& sym_hash->root.u.def.value < toaddr) && sym_hash->root.u.def.value <= toaddr)
{ {
sym_hash->root.u.def.value -= count; sym_hash->root.u.def.value -= count;
} }