* elf32-m68hc1x.c: New file (from elf32-m68hc11.c and elf32-m68hc12.c)

(m68hc11_elf_hash_table_create): New function.
	(elf32_m68hc11_link_hash_table_free): New function.
	(stub_hash_newfunc): New function.
	(m68hc11_add_stub): New function.
	(elf32_m68hc11_add_symbol_hook): New function.
	(elf32_m68hc11_setup_section_lists): New function.
	(elf32_m68hc11_next_input_section): New function.
	(elf32_m68hc11_size_stubs): New function.
	(elf32_m68hc11_build_stubs): New function.
	(m68hc11_get_relocation_value): New function.
	(elf32_m68hc11_relocate_section): Call the above to redirect
	some relocations to the trampoline code.
	(m68hc11_elf_export_one_stub): New function.
	(m68hc11_elf_set_symbol): New function.
	(elf32_m68hc11_build_stubs): Call it via bfd_hash_traverse.
	(m68hc11_elf_get_bank_parameters): Get parameters only when the info
	is not yet initialized.

	* elf32-m68hc1x.h: New file (from elf32-m68hc11.c and elf32-m68hc12.c)
	(elf32_m68hc11_stub_hash_entry): New struct.
	(m68hc11_page_info): Add trampoline handler address.
	(m68hc11_elf_link_hash_table): Add stubs generation members.
	(elf32_m68hc11_add_symbol_hook): Declare.
	(elf32_m68hc11_setup_section_lists): Declare.
	(elf32_m68hc11_size_stubs): Declare.
	(elf32_m68hc11_build_stubs): Declare.

	* elf32-m68hc11.c (m68hc11_elf_ignore_reloc): Move to elf32-m68hc1x.c.
	(elf32_m68hc11_gc_mark_hook, elf32_m68hc11_gc_sweep_hook): Likewise.
	(elf32_m68hc11_check_relocs, elf32_m68hc11_relocate_section): Ditto.
	(_bfd_m68hc11_elf_set_private_flags): Ditto.
	(_bfd_m68hc11_elf_merge_private_bfd_data): Ditto.
	(_bfd_m68hc11_elf_print_private_bfd_data): Ditto.
	(bfd_elf32_bfd_link_hash_table_create): Define.
	(elf_backend_add_symbol_hook): Define.
	(m68hc11_elf_bfd_link_hash_table_create): New function.
	(m68hc11_elf_build_one_stub): New function.
	(m68hc11_elf_size_one_stub): New function.
	(m68hc11_elf_bfd_link_hash_table_create): Install the above.
	(bfd_elf32_bfd_link_hash_table_create): Define.

	* elf32-m68hc12.c (m68hc11_elf_ignore_reloc): Remove.
	(m68hc12_addr_is_banked): Remove, use m68hc11_addr_is_banked.
	(m68hc12_phys_addr): Ditto.
	(m68hc12_phys_page): Ditto.
	(m68hc12_elf_special_reloc): Move to elf32-m68hc1x.c.
	(elf32_m68hc11_gc_mark_hook): Likewise.
	(elf32_m68hc11_gc_sweep_hook): Likewise.
	(elf32_m68hc11_check_relocs): Likewise.
	(elf32_m68hc11_relocate_section): Likewise.
	(_bfd_m68hc12_elf_set_private_flags): Likewise.
	(_bfd_m68hc12_elf_merge_private_bfd_data): Likewise.
	(_bfd_m68hc12_elf_print_private_bfd_data): Likewise.
	(m68hc12_elf_build_one_stub): New function.
	(m68hc12_elf_size_one_stub): New function.
	(m68hc12_elf_bfd_link_hash_table_create): New function, use the above.
	(elf_backend_add_symbol_hook): Define.
	(elf_m68hc11_howto_table): Use TRUE for pcrel relocs; fix masks.
This commit is contained in:
Stephane Carrez 2003-04-21 13:22:14 +00:00
parent 81eca1a78a
commit 3a65329d1f
5 changed files with 2003 additions and 808 deletions

View File

@ -1,3 +1,65 @@
2003-04-21 Stephane Carrez <stcarrez@nerim.fr>
* elf32-m68hc1x.c: New file (from elf32-m68hc11.c and elf32-m68hc12.c)
(m68hc11_elf_hash_table_create): New function.
(elf32_m68hc11_link_hash_table_free): New function.
(stub_hash_newfunc): New function.
(m68hc11_add_stub): New function.
(elf32_m68hc11_add_symbol_hook): New function.
(elf32_m68hc11_setup_section_lists): New function.
(elf32_m68hc11_next_input_section): New function.
(elf32_m68hc11_size_stubs): New function.
(elf32_m68hc11_build_stubs): New function.
(m68hc11_get_relocation_value): New function.
(elf32_m68hc11_relocate_section): Call the above to redirect
some relocations to the trampoline code.
(m68hc11_elf_export_one_stub): New function.
(m68hc11_elf_set_symbol): New function.
(elf32_m68hc11_build_stubs): Call it via bfd_hash_traverse.
(m68hc11_elf_get_bank_parameters): Get parameters only when the info
is not yet initialized.
* elf32-m68hc1x.h: New file (from elf32-m68hc11.c and elf32-m68hc12.c)
(elf32_m68hc11_stub_hash_entry): New struct.
(m68hc11_page_info): Add trampoline handler address.
(m68hc11_elf_link_hash_table): Add stubs generation members.
(elf32_m68hc11_add_symbol_hook): Declare.
(elf32_m68hc11_setup_section_lists): Declare.
(elf32_m68hc11_size_stubs): Declare.
(elf32_m68hc11_build_stubs): Declare.
* elf32-m68hc11.c (m68hc11_elf_ignore_reloc): Move to elf32-m68hc1x.c.
(elf32_m68hc11_gc_mark_hook, elf32_m68hc11_gc_sweep_hook): Likewise.
(elf32_m68hc11_check_relocs, elf32_m68hc11_relocate_section): Ditto.
(_bfd_m68hc11_elf_set_private_flags): Ditto.
(_bfd_m68hc11_elf_merge_private_bfd_data): Ditto.
(_bfd_m68hc11_elf_print_private_bfd_data): Ditto.
(bfd_elf32_bfd_link_hash_table_create): Define.
(elf_backend_add_symbol_hook): Define.
(m68hc11_elf_bfd_link_hash_table_create): New function.
(m68hc11_elf_build_one_stub): New function.
(m68hc11_elf_size_one_stub): New function.
(m68hc11_elf_bfd_link_hash_table_create): Install the above.
(bfd_elf32_bfd_link_hash_table_create): Define.
* elf32-m68hc12.c (m68hc11_elf_ignore_reloc): Remove.
(m68hc12_addr_is_banked): Remove, use m68hc11_addr_is_banked.
(m68hc12_phys_addr): Ditto.
(m68hc12_phys_page): Ditto.
(m68hc12_elf_special_reloc): Move to elf32-m68hc1x.c.
(elf32_m68hc11_gc_mark_hook): Likewise.
(elf32_m68hc11_gc_sweep_hook): Likewise.
(elf32_m68hc11_check_relocs): Likewise.
(elf32_m68hc11_relocate_section): Likewise.
(_bfd_m68hc12_elf_set_private_flags): Likewise.
(_bfd_m68hc12_elf_merge_private_bfd_data): Likewise.
(_bfd_m68hc12_elf_print_private_bfd_data): Likewise.
(m68hc12_elf_build_one_stub): New function.
(m68hc12_elf_size_one_stub): New function.
(m68hc12_elf_bfd_link_hash_table_create): New function, use the above.
(elf_backend_add_symbol_hook): Define.
(elf_m68hc11_howto_table): Use TRUE for pcrel relocs; fix masks.
2003-04-18 Nick Clifton <nickc@redhat.com>
* format.c (bfd_check_format_matches): Only check associated

View File

@ -24,29 +24,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf32-m68hc1x.h"
#include "elf/m68hc11.h"
#include "opcode/m68hc11.h"
/* Relocation functions. */
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static void m68hc11_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
static bfd_reloc_status_type m68hc11_elf_ignore_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
/* Trampoline generation. */
static bfd_boolean m68hc11_elf_size_one_stub
PARAMS((struct bfd_hash_entry *gen_entry, PTR in_arg));
static bfd_boolean m68hc11_elf_build_one_stub
PARAMS((struct bfd_hash_entry *gen_entry, PTR in_arg));
static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
PARAMS ((bfd* abfd));
/* GC mark and sweep. */
static asection *elf32_m68hc11_gc_mark_hook
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static bfd_boolean elf32_m68hc11_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static bfd_boolean elf32_m68hc11_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static bfd_boolean elf32_m68hc11_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
/* Linker relaxation. */
static bfd_boolean m68hc11_elf_relax_section
PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
static void m68hc11_elf_relax_delete_bytes
@ -56,18 +52,14 @@ static void m68hc11_relax_group
unsigned long, unsigned long));
static int compare_reloc PARAMS ((const void *, const void *));
bfd_boolean _bfd_m68hc11_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
bfd_boolean _bfd_m68hc11_elf_set_private_flags PARAMS ((bfd *, flagword));
bfd_boolean _bfd_m68hc11_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
/* Use REL instead of RELA to save space */
#define USE_REL 1
/* The Motorola 68HC11 microcontroler only addresses 64Kb.
/* The Motorola 68HC11 microcontroller only addresses 64Kb but we also
support a memory bank switching mechanism similar to 68HC12.
We must handle 8 and 16-bit relocations. The 32-bit relocation
is defined but not used except by gas when -gstabs is used (which
is wrong).
are used for debugging sections (DWARF2) to represent a virtual
address.
The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
static reloc_howto_type elf_m68hc11_howto_table[] = {
/* This reloc does nothing. */
@ -367,25 +359,6 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
return NULL;
}
/* This function is used for relocs which are only used for relaxing,
which the linker should otherwise ignore. */
static bfd_reloc_status_type
m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd ATTRIBUTE_UNUSED;
arelent *reloc_entry;
asymbol *symbol ATTRIBUTE_UNUSED;
PTR data ATTRIBUTE_UNUSED;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
if (output_bfd != NULL)
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
/* Set the howto pointer for an M68HC11 ELF reloc. */
static void
@ -401,50 +374,106 @@ m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
}
static asection *
elf32_m68hc11_gc_mark_hook (sec, info, rel, h, sym)
asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
/* Far trampoline generation. */
/* Build a 68HC11 trampoline stub. */
static bfd_boolean
m68hc11_elf_build_one_stub (gen_entry, in_arg)
struct bfd_hash_entry *gen_entry;
PTR in_arg;
{
if (h != NULL)
{
switch (ELF32_R_TYPE (rel->r_info))
{
default:
switch (h->root.type)
{
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
return h->root.u.def.section;
struct elf32_m68hc11_stub_hash_entry *stub_entry;
struct bfd_link_info *info;
struct m68hc11_elf_link_hash_table *htab;
asection *stub_sec;
bfd *stub_bfd;
bfd_byte *loc;
bfd_vma sym_value, phys_page, phys_addr;
case bfd_link_hash_common:
return h->root.u.c.p->section;
/* Massage our args to the form they really have. */
stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
info = (struct bfd_link_info *) in_arg;
default:
break;
}
}
}
else
return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
htab = m68hc11_elf_hash_table (info);
return NULL;
stub_sec = stub_entry->stub_sec;
/* Make a note of the offset within the stubs for this entry. */
stub_entry->stub_offset = stub_sec->_raw_size;
stub_sec->_raw_size += 10;
loc = stub_sec->contents + stub_entry->stub_offset;
stub_bfd = stub_sec->owner;
/* Create the trampoline call stub:
pshb
ldab #%page(symbol)
ldy #%addr(symbol)
jmp __trampoline
*/
sym_value = (stub_entry->target_value
+ stub_entry->target_section->output_offset
+ stub_entry->target_section->output_section->vma);
phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
/* pshb; ldab #%page(sym) */
bfd_put_8 (stub_bfd, 0x37, loc);
bfd_put_8 (stub_bfd, 0xC6, loc + 1);
bfd_put_8 (stub_bfd, phys_page, loc + 2);
loc += 3;
/* ldy #%addr(sym) */
bfd_put_8 (stub_bfd, 0x18, loc);
bfd_put_8 (stub_bfd, 0xCE, loc + 1);
bfd_put_16 (stub_bfd, phys_addr, loc + 2);
loc += 4;
/* jmp __trampoline */
bfd_put_8 (stub_bfd, 0x7E, loc);
bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
return TRUE;
}
/* As above, but don't actually build the stub. Just bump offset so
we know stub section sizes. */
static bfd_boolean
elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
asection *sec ATTRIBUTE_UNUSED;
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
m68hc11_elf_size_one_stub (gen_entry, in_arg)
struct bfd_hash_entry *gen_entry;
PTR in_arg ATTRIBUTE_UNUSED;
{
/* We don't use got and plt entries for 68hc11/68hc12. */
struct elf32_m68hc11_stub_hash_entry *stub_entry;
/* Massage our args to the form they really have. */
stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
stub_entry->stub_sec->_raw_size += 10;
return TRUE;
}
/* Create a 68HC11 ELF linker hash table. */
static struct bfd_link_hash_table *
m68hc11_elf_bfd_link_hash_table_create (abfd)
bfd *abfd;
{
struct m68hc11_elf_link_hash_table *ret;
ret = m68hc11_elf_hash_table_create (abfd);
if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
return NULL;
ret->size_one_stub = m68hc11_elf_size_one_stub;
ret->build_one_stub = m68hc11_elf_build_one_stub;
return &ret->root.root;
}
/* 68HC11 Linker Relaxation. */
@ -1251,365 +1280,7 @@ m68hc11_elf_relax_delete_bytes (abfd, sec, addr, count)
}
}
/* Look through the relocs for a section during the first phase.
Since we don't do .gots or .plts, we just need to consider the
virtual table relocs for gc. */
static bfd_boolean
elf32_m68hc11_check_relocs (abfd, info, sec, relocs)
bfd * abfd;
struct bfd_link_info * info;
asection * sec;
const Elf_Internal_Rela * relocs;
{
Elf_Internal_Shdr * symtab_hdr;
struct elf_link_hash_entry ** sym_hashes;
struct elf_link_hash_entry ** sym_hashes_end;
const Elf_Internal_Rela * rel;
const Elf_Internal_Rela * rel_end;
if (info->relocateable)
return TRUE;
symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
if (!elf_bad_symtab (abfd))
sym_hashes_end -= symtab_hdr->sh_info;
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
struct elf_link_hash_entry * h;
unsigned long r_symndx;
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
h = sym_hashes [r_symndx - symtab_hdr->sh_info];
switch (ELF32_R_TYPE (rel->r_info))
{
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_M68HC11_GNU_VTINHERIT:
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_M68HC11_GNU_VTENTRY:
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
}
return TRUE;
}
/* Relocate a 68hc11/68hc12 ELF section. */
static bfd_boolean
elf32_m68hc11_relocate_section (output_bfd, info, input_bfd, input_section,
contents, relocs, local_syms, local_sections)
bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
bfd *input_bfd;
asection *input_section;
bfd_byte *contents;
Elf_Internal_Rela *relocs;
Elf_Internal_Sym *local_syms;
asection **local_sections;
{
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel, *relend;
const char *name;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
{
int r_type;
reloc_howto_type *howto;
unsigned long r_symndx;
Elf_Internal_Sym *sym;
asection *sec;
struct elf_link_hash_entry *h;
bfd_vma relocation;
bfd_reloc_status_type r;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == R_M68HC11_GNU_VTENTRY
|| r_type == R_M68HC11_GNU_VTINHERIT )
continue;
howto = elf_m68hc11_howto_table + r_type;
if (info->relocateable)
{
/* This is a relocateable link. We don't have to change
anything, unless the reloc is against a section symbol,
in which case we have to adjust according to where the
section symbol winds up in the output section. */
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
{
sec = local_sections[r_symndx];
rel->r_addend += sec->output_offset + sym->st_value;
}
}
continue;
}
/* This is a final link. */
h = NULL;
sym = NULL;
sec = NULL;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
relocation = (sec->output_section->vma
+ sec->output_offset
+ sym->st_value);
}
else
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
relocation = (h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
else
{
if (!((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd,
input_section, rel->r_offset, TRUE)))
return FALSE;
relocation = 0;
}
}
if (h != NULL)
name = h->root.root.string;
else
{
name = (bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name));
if (name == NULL || *name == '\0')
name = bfd_section_name (input_bfd, sec);
}
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
relocation, rel->r_addend);
if (r != bfd_reloc_ok)
{
const char * msg = (const char *) 0;
switch (r)
{
case bfd_reloc_overflow:
if (!((*info->callbacks->reloc_overflow)
(info, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
return FALSE;
break;
case bfd_reloc_undefined:
if (!((*info->callbacks->undefined_symbol)
(info, name, input_bfd, input_section,
rel->r_offset, TRUE)))
return FALSE;
break;
case bfd_reloc_outofrange:
msg = _ ("internal error: out of range error");
goto common_error;
case bfd_reloc_notsupported:
msg = _ ("internal error: unsupported relocation error");
goto common_error;
case bfd_reloc_dangerous:
msg = _ ("internal error: dangerous error");
goto common_error;
default:
msg = _ ("internal error: unknown error");
/* fall through */
common_error:
if (!((*info->callbacks->warning)
(info, msg, name, input_bfd, input_section,
rel->r_offset)))
return FALSE;
break;
}
}
}
return TRUE;
}
/* Set and control ELF flags in ELF header. */
bfd_boolean
_bfd_m68hc11_elf_set_private_flags (abfd, flags)
bfd *abfd;
flagword flags;
{
BFD_ASSERT (!elf_flags_init (abfd)
|| elf_elfheader (abfd)->e_flags == flags);
elf_elfheader (abfd)->e_flags = flags;
elf_flags_init (abfd) = TRUE;
return TRUE;
}
/* Merge backend specific data from an object file to the output
object file when linking. */
bfd_boolean
_bfd_m68hc11_elf_merge_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
flagword old_flags;
flagword new_flags;
bfd_boolean ok = TRUE;
/* Check if we have the same endianess */
if (!_bfd_generic_verify_endian_match (ibfd, obfd))
return FALSE;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
new_flags = elf_elfheader (ibfd)->e_flags;
elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
old_flags = elf_elfheader (obfd)->e_flags;
if (! elf_flags_init (obfd))
{
elf_flags_init (obfd) = TRUE;
elf_elfheader (obfd)->e_flags = new_flags;
elf_elfheader (obfd)->e_ident[EI_CLASS]
= elf_elfheader (ibfd)->e_ident[EI_CLASS];
if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
&& bfd_get_arch_info (obfd)->the_default)
{
if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
bfd_get_mach (ibfd)))
return FALSE;
}
return TRUE;
}
/* Check ABI compatibility. */
if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
{
(*_bfd_error_handler)
(_("%s: linking files compiled for 16-bit integers (-mshort) "
"and others for 32-bit integers"),
bfd_archive_filename (ibfd));
ok = FALSE;
}
if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
{
(*_bfd_error_handler)
(_("%s: linking files compiled for 32-bit double (-fshort-double) "
"and others for 64-bit double"),
bfd_archive_filename (ibfd));
ok = FALSE;
}
new_flags &= ~EF_M68HC11_ABI;
old_flags &= ~EF_M68HC11_ABI;
/* Warn about any other mismatches */
if (new_flags != old_flags)
{
(*_bfd_error_handler)
(_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
bfd_archive_filename (ibfd), (unsigned long) new_flags,
(unsigned long) old_flags);
ok = FALSE;
}
if (! ok)
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
return TRUE;
}
bfd_boolean
_bfd_m68hc11_elf_print_private_bfd_data (abfd, ptr)
bfd *abfd;
PTR ptr;
{
FILE *file = (FILE *) ptr;
BFD_ASSERT (abfd != NULL && ptr != NULL);
/* Print normal ELF private data. */
_bfd_elf_print_private_bfd_data (abfd, ptr);
/* xgettext:c-format */
fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
fprintf (file, _("[abi=32-bit int,"));
else
fprintf (file, _("[abi=16-bit int,"));
if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
fprintf (file, _(" 64-bit double]"));
else
fprintf (file, _(" 32-bit double]"));
if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
fprintf (file, _(" [memory=bank-model]"));
else
fprintf (file, _(" [memory=flat]"));
fputc ('\n', file);
return TRUE;
}
/* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
The Motorola spec says to use a different Elf machine code. */
#define ELF_ARCH bfd_arch_m68hc11
#define ELF_MACHINE_CODE EM_68HC11
#define ELF_MAXPAGESIZE 0x1000
@ -1624,9 +1295,15 @@ _bfd_m68hc11_elf_print_private_bfd_data (abfd, ptr)
#define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
#define elf_backend_check_relocs elf32_m68hc11_check_relocs
#define elf_backend_relocate_section elf32_m68hc11_relocate_section
#define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
#define elf_backend_object_p 0
#define elf_backend_final_write_processing 0
#define elf_backend_can_gc_sections 1
#define bfd_elf32_bfd_link_hash_table_create \
m68hc11_elf_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_free \
m68hc11_elf_bfd_link_hash_table_free
#define bfd_elf32_bfd_merge_private_bfd_data \
_bfd_m68hc11_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags

View File

@ -1,5 +1,5 @@
/* Motorola 68HC12-specific support for 32-bit ELF
Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
Copyright 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
(Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
@ -21,49 +21,33 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf32-m68hc1x.h"
#include "elf/m68hc11.h"
#include "opcode/m68hc11.h"
/* Relocation functions. */
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static void m68hc11_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
static bfd_reloc_status_type m68hc11_elf_ignore_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type m68hc12_elf_special_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static int m68hc12_addr_is_banked PARAMS ((bfd_vma));
static bfd_vma m68hc12_phys_addr PARAMS ((bfd_vma));
static bfd_vma m68hc12_phys_page PARAMS ((bfd_vma));
/* GC mark and sweep. */
static asection *elf32_m68hc11_gc_mark_hook
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static bfd_boolean elf32_m68hc11_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
/* Trampoline generation. */
static bfd_boolean m68hc12_elf_size_one_stub
PARAMS((struct bfd_hash_entry *gen_entry, PTR in_arg));
static bfd_boolean m68hc12_elf_build_one_stub
PARAMS((struct bfd_hash_entry *gen_entry, PTR in_arg));
static struct bfd_link_hash_table* m68hc12_elf_bfd_link_hash_table_create
PARAMS((bfd*));
static bfd_boolean m68hc12_elf_set_mach_from_flags PARAMS ((bfd *));
bfd_boolean _bfd_m68hc12_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
bfd_boolean _bfd_m68hc12_elf_set_private_flags PARAMS ((bfd *, flagword));
bfd_boolean _bfd_m68hc12_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
/* Use REL instead of RELA to save space */
#define USE_REL 1
/* The Motorola 68HC11 microcontroler only addresses 64Kb.
We must handle 8 and 16-bit relocations. The 32-bit relocation
is defined but not used except by gas when -gstabs is used (which
is wrong).
The 68HC12 microcontroler has a memory bank switching system
/* The 68HC12 microcontroler has a memory bank switching system
with a 16Kb window in the 64Kb address space. The extended memory
is mapped in the 16Kb window (at 0x8000). The page register controls
which 16Kb bank is mapped. The call/rtc instructions take care of
@ -199,7 +183,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* partial_inplace */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
FALSE), /* pcrel_offset */
TRUE), /* pcrel_offset */
/* A 16 bit absolute relocation */
HOWTO (R_M68HC11_16, /* type */
@ -209,7 +193,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
m68hc12_elf_special_reloc, /* special_function */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC12_16", /* name */
FALSE, /* partial_inplace */
0xffff, /* src_mask */
@ -260,7 +244,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
TRUE), /* pcrel_offset */
/* GNU extension to record C++ vtable hierarchy */
HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
@ -295,16 +279,16 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
/* A 24 bit relocation */
HOWTO (R_M68HC11_24, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc12_elf_special_reloc, /* special_function */
m68hc11_elf_special_reloc, /* special_function */
"R_M68HC12_24", /* name */
FALSE, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
0xffffff, /* src_mask */
0xffffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A 16-bit low relocation */
@ -315,7 +299,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc12_elf_special_reloc,/* special_function */
m68hc11_elf_special_reloc,/* special_function */
"R_M68HC12_LO16", /* name */
FALSE, /* partial_inplace */
0xffff, /* src_mask */
@ -330,7 +314,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc12_elf_special_reloc,/* special_function */
m68hc11_elf_special_reloc,/* special_function */
"R_M68HC12_PAGE", /* name */
FALSE, /* partial_inplace */
0x00ff, /* src_mask */
@ -423,158 +407,6 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
return NULL;
}
/* This function is used for relocs which are only used for relaxing,
which the linker should otherwise ignore. */
static bfd_reloc_status_type
m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd ATTRIBUTE_UNUSED;
arelent *reloc_entry;
asymbol *symbol ATTRIBUTE_UNUSED;
PTR data ATTRIBUTE_UNUSED;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
if (output_bfd != NULL)
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
static int
m68hc12_addr_is_banked (addr)
bfd_vma addr;
{
return (addr >= M68HC12_BANK_VIRT) ? 1 : 0;
}
/* Return the physical address seen by the processor, taking
into account banked memory. */
static bfd_vma
m68hc12_phys_addr (addr)
bfd_vma addr;
{
if (addr < M68HC12_BANK_VIRT)
return addr;
/* Map the address to the memory bank. */
addr -= M68HC12_BANK_VIRT;
addr &= M68HC12_BANK_MASK;
addr += M68HC12_BANK_BASE;
return addr;
}
/* Return the page number corresponding to an address in banked memory. */
static bfd_vma
m68hc12_phys_page (addr)
bfd_vma addr;
{
if (addr < M68HC12_BANK_VIRT)
return 0;
/* Map the address to the memory bank. */
addr -= M68HC12_BANK_VIRT;
addr >>= M68HC12_BANK_SHIFT;
addr &= M68HC12_BANK_PAGE_MASK;
return addr;
}
static bfd_reloc_status_type
m68hc12_elf_special_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
reloc_howto_type *howto;
bfd_vma relocation;
bfd_vma phys_addr;
bfd_vma phys_page;
bfd_vma insn_page;
bfd_vma insn_addr;
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
if (output_bfd != NULL)
return bfd_reloc_continue;
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
/* Compute relocation. */
relocation = (symbol->value
+ symbol->section->output_section->vma
+ symbol->section->output_offset);
relocation += reloc_entry->addend;
relocation += bfd_get_16 (abfd, (bfd_byte*) data + reloc_entry->address);
/* Do the memory bank mapping. */
phys_addr = m68hc12_phys_addr (relocation);
phys_page = m68hc12_phys_page (relocation);
howto = reloc_entry->howto;
if (howto->complain_on_overflow != complain_overflow_dont
&& (phys_addr & (((bfd_vma) -1) << 16)))
return bfd_reloc_overflow;
switch (howto->type)
{
case R_M68HC11_16:
/* Get virtual address of instruction having the relocation. */
insn_addr = input_section->output_section->vma
+ input_section->output_offset
+ reloc_entry->address;
insn_page = m68hc12_phys_page (insn_addr);
if (m68hc12_addr_is_banked (relocation)
&& m68hc12_addr_is_banked (insn_addr)
&& phys_page != insn_page)
{
*error_message = _("address is not in the same bank");
return bfd_reloc_dangerous;
}
if (m68hc12_addr_is_banked (relocation)
&& !m68hc12_addr_is_banked (insn_addr))
{
*error_message = _("reference to a banked address in "
"the normal address space");
return bfd_reloc_dangerous;
}
case R_M68HC11_LO16:
bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
break;
case R_M68HC11_24:
bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address + 2);
break;
case R_M68HC11_PAGE:
bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address);
break;
default:
abort ();
break;
}
return bfd_reloc_ok;
}
/* Set the howto pointer for an M68HC11 ELF reloc. */
static void
@ -590,50 +422,97 @@ m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
}
static asection *
elf32_m68hc11_gc_mark_hook (sec, info, rel, h, sym)
asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
{
if (h != NULL)
{
switch (ELF32_R_TYPE (rel->r_info))
{
default:
switch (h->root.type)
{
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
return h->root.u.def.section;
case bfd_link_hash_common:
return h->root.u.c.p->section;
default:
break;
}
}
}
else
return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
/* Far trampoline generation. */
/* Build a 68HC12 trampoline stub. */
static bfd_boolean
elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
asection *sec ATTRIBUTE_UNUSED;
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
m68hc12_elf_build_one_stub (gen_entry, in_arg)
struct bfd_hash_entry *gen_entry;
PTR in_arg;
{
/* We don't use got and plt entries for 68hc11/68hc12. */
struct elf32_m68hc11_stub_hash_entry *stub_entry;
struct bfd_link_info *info;
struct m68hc11_elf_link_hash_table *htab;
asection *stub_sec;
bfd *stub_bfd;
bfd_byte *loc;
bfd_vma sym_value, phys_page, phys_addr;
/* Massage our args to the form they really have. */
stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
info = (struct bfd_link_info *) in_arg;
htab = m68hc11_elf_hash_table (info);
stub_sec = stub_entry->stub_sec;
/* Make a note of the offset within the stubs for this entry. */
stub_entry->stub_offset = stub_sec->_raw_size;
stub_sec->_raw_size += 7;
loc = stub_sec->contents + stub_entry->stub_offset;
stub_bfd = stub_sec->owner;
/* Create the trampoline call stub:
ldy #%addr(symbol)
call %page(symbol), __trampoline
*/
sym_value = (stub_entry->target_value
+ stub_entry->target_section->output_offset
+ stub_entry->target_section->output_section->vma);
phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
/* ldy #%page(sym) */
bfd_put_8 (stub_bfd, 0xCD, loc);
bfd_put_16 (stub_bfd, phys_addr, loc + 1);
loc += 3;
/* call %page(sym), __trampoline */
bfd_put_8 (stub_bfd, 0x4a, loc);
bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
bfd_put_8 (stub_bfd, phys_page, loc + 3);
return TRUE;
}
/* As above, but don't actually build the stub. Just bump offset so
we know stub section sizes. */
static bfd_boolean
m68hc12_elf_size_one_stub (gen_entry, in_arg)
struct bfd_hash_entry *gen_entry;
PTR in_arg ATTRIBUTE_UNUSED;
{
struct elf32_m68hc11_stub_hash_entry *stub_entry;
/* Massage our args to the form they really have. */
stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
stub_entry->stub_sec->_raw_size += 7;
return TRUE;
}
/* Create a 68HC12 ELF linker hash table. */
static struct bfd_link_hash_table *
m68hc12_elf_bfd_link_hash_table_create (abfd)
bfd *abfd;
{
struct m68hc11_elf_link_hash_table *ret;
ret = m68hc11_elf_hash_table_create (abfd);
if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
return NULL;
ret->size_one_stub = m68hc12_elf_size_one_stub;
ret->build_one_stub = m68hc12_elf_build_one_stub;
return &ret->root.root;
}
static bfd_boolean
m68hc12_elf_set_mach_from_flags (abfd)
@ -659,149 +538,6 @@ m68hc12_elf_set_mach_from_flags (abfd)
return TRUE;
}
/* Set and control ELF flags in ELF header. */
bfd_boolean
_bfd_m68hc12_elf_set_private_flags (abfd, flags)
bfd *abfd;
flagword flags;
{
BFD_ASSERT (!elf_flags_init (abfd)
|| elf_elfheader (abfd)->e_flags == flags);
elf_elfheader (abfd)->e_flags = flags;
elf_flags_init (abfd) = TRUE;
return m68hc12_elf_set_mach_from_flags (abfd);
}
/* Merge backend specific data from an object file to the output
object file when linking. */
bfd_boolean
_bfd_m68hc12_elf_merge_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
flagword old_flags;
flagword new_flags;
bfd_boolean ok = TRUE;
/* Check if we have the same endianess */
if (!_bfd_generic_verify_endian_match (ibfd, obfd))
return FALSE;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
new_flags = elf_elfheader (ibfd)->e_flags;
old_flags = elf_elfheader (obfd)->e_flags;
if (! elf_flags_init (obfd))
{
elf_flags_init (obfd) = TRUE;
elf_elfheader (obfd)->e_flags = new_flags;
elf_elfheader (obfd)->e_ident[EI_CLASS]
= elf_elfheader (ibfd)->e_ident[EI_CLASS];
if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
&& bfd_get_arch_info (obfd)->the_default)
{
if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
bfd_get_mach (ibfd)))
return FALSE;
}
return TRUE;
}
/* Check ABI compatibility. */
if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
{
(*_bfd_error_handler)
(_("%s: linking files compiled for 16-bit integers (-mshort) "
"and others for 32-bit integers"),
bfd_archive_filename (ibfd));
ok = FALSE;
}
if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
{
(*_bfd_error_handler)
(_("%s: linking files compiled for 32-bit double (-fshort-double) "
"and others for 64-bit double"),
bfd_archive_filename (ibfd));
ok = FALSE;
}
/* Processor compatibility. */
if (!EF_M68HC11_CAN_MERGE_MACH (new_flags, old_flags))
{
(*_bfd_error_handler)
(_("%s: linking files compiled for HCS12 with "
"others compiled for HC12"),
bfd_archive_filename (ibfd));
ok = FALSE;
}
new_flags = ((new_flags & ~EF_M68HC11_MACH_MASK)
| (EF_M68HC11_MERGE_MACH (new_flags, old_flags)));
elf_elfheader (obfd)->e_flags = new_flags;
/* Warn about any other mismatches */
new_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
old_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
if (new_flags != old_flags)
{
(*_bfd_error_handler)
(_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
bfd_archive_filename (ibfd), (unsigned long) new_flags,
(unsigned long) old_flags);
ok = FALSE;
}
if (! ok)
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
return TRUE;
}
bfd_boolean
_bfd_m68hc12_elf_print_private_bfd_data (abfd, ptr)
bfd *abfd;
PTR ptr;
{
FILE *file = (FILE *) ptr;
BFD_ASSERT (abfd != NULL && ptr != NULL);
/* Print normal ELF private data. */
_bfd_elf_print_private_bfd_data (abfd, ptr);
/* xgettext:c-format */
fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
fprintf (file, _("[abi=32-bit int,"));
else
fprintf (file, _("[abi=16-bit int,"));
if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
fprintf (file, _(" 64-bit double,"));
else
fprintf (file, _(" 32-bit double,"));
if (elf_elfheader (abfd)->e_flags & EF_M68HCS12_MACH)
fprintf (file, _(" cpu=HCS12]"));
else
fprintf (file, _(" cpu=HC12]"));
fputc ('\n', file);
return TRUE;
}
#define ELF_ARCH bfd_arch_m68hc12
#define ELF_MACHINE_CODE EM_68HC12
#define ELF_MAXPAGESIZE 0x1000
@ -813,15 +549,22 @@ _bfd_m68hc12_elf_print_private_bfd_data (abfd, ptr)
#define elf_info_to_howto_rel m68hc11_info_to_howto_rel
#define elf_backend_gc_mark_hook elf32_m68hc11_gc_mark_hook
#define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
#define elf_backend_check_relocs elf32_m68hc11_check_relocs
#define elf_backend_relocate_section elf32_m68hc11_relocate_section
#define elf_backend_object_p m68hc12_elf_set_mach_from_flags
#define elf_backend_final_write_processing 0
/* Disabled as this backend uses the generic linker. */
#define elf_backend_can_gc_sections 0
#define elf_backend_can_gc_sections 1
#define elf_backend_post_process_headers elf32_m68hc11_post_process_headers
#define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
#define bfd_elf32_bfd_link_hash_table_create \
m68hc12_elf_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_free \
m68hc11_elf_bfd_link_hash_table_free
#define bfd_elf32_bfd_merge_private_bfd_data \
_bfd_m68hc12_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags _bfd_m68hc12_elf_set_private_flags
_bfd_m68hc11_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data \
_bfd_m68hc12_elf_print_private_bfd_data
_bfd_m68hc11_elf_print_private_bfd_data
#include "elf32-target.h"

1508
bfd/elf32-m68hc1x.c Normal file

File diff suppressed because it is too large Load Diff

205
bfd/elf32-m68hc1x.h Normal file
View File

@ -0,0 +1,205 @@
/* Motorola 68HC11/68HC12-specific support for 32-bit ELF
Copyright 2003 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _ELF32_M68HC1X_H
#define _ELF32_M68HC1X_H
#include "elf-bfd.h"
#include "bfdlink.h"
#include "elf/m68hc11.h"
/* Name of symbols exported by HC11/HC12 linker when there is a memory
bank window. */
#define BFD_M68HC11_BANK_START_NAME "__bank_start"
#define BFD_M68HC11_BANK_SIZE_NAME "__bank_size"
#define BFD_M68HC11_BANK_VIRTUAL_NAME "__bank_virtual"
/* Set and control ELF flags in ELF header. */
extern bfd_boolean _bfd_m68hc11_elf_merge_private_bfd_data PARAMS ((bfd*,bfd*));
extern bfd_boolean _bfd_m68hc11_elf_set_private_flags PARAMS ((bfd*,flagword));
extern bfd_boolean _bfd_m68hc11_elf_print_private_bfd_data PARAMS ((bfd*,PTR));
/* This hash entry is used to record a trampoline that must be generated
to call a far function using a normal calling convention ('jsr').
The trampoline is used when a pointer to a far function is used.
It takes care of installing the proper memory bank as well as creating
the 'call/rtc' calling convention. */
struct elf32_m68hc11_stub_hash_entry {
/* Base hash table entry structure. */
struct bfd_hash_entry root;
/* The stub section. */
asection *stub_sec;
/* Offset within stub_sec of the beginning of this stub. */
bfd_vma stub_offset;
/* Given the symbol's value and its section we can determine its final
value when building the stubs (so the stub knows where to jump. */
bfd_vma target_value;
asection *target_section;
};
/* Placeholder for the parameters to compute memory page and physical address.
The following formulas are used:
sym > bank_virtual =>
%addr(sym) = (((sym - bank_virtual) & bank_mask) + bank_physical
%page(sym) = (((sym - bank_virtual) >> bank_shift) % 256
sym < bank_virtual =>
%addr(sym) = sym
%page(sym) = 0
These parameters are obtained from the symbol table by looking
at the following:
__bank_start Symbol marking the start of memory bank window
(bank_physical)
__bank_virtual Logical address of symbols for which the transformation
must be computed
__bank_page_size Size in bytes of page size (this is *NOT* the memory
bank window size and the window size is always
less or equal to the page size)
For 68HC12, the window is at 0x8000 and the page size is 16K (full window).
For 68HC11 this is board specific (implemented by external hardware).
*/
struct m68hc11_page_info
{
bfd_vma bank_virtual;
bfd_vma bank_physical;
bfd_vma bank_physical_end;
bfd_vma bank_mask;
bfd_vma bank_size;
int bank_shift;
int bank_param_initialized;
bfd_vma trampoline_addr;
};
struct m68hc11_elf_link_hash_table
{
struct elf_link_hash_table root;
struct m68hc11_page_info pinfo;
/* The stub hash table. */
struct bfd_hash_table* stub_hash_table;
/* Linker stub bfd. */
bfd *stub_bfd;
asection* stub_section;
asection* tramp_section;
/* Linker call-backs. */
asection * (*add_stub_section) PARAMS ((const char *, asection *));
/* Assorted information used by elf32_hppa_size_stubs. */
unsigned int bfd_count;
int top_index;
asection **input_list;
Elf_Internal_Sym **all_local_syms;
/* Small local sym to section mapping cache. */
struct sym_sec_cache sym_sec;
bfd_boolean (* size_one_stub) PARAMS((struct bfd_hash_entry*, PTR));
bfd_boolean (* build_one_stub) PARAMS((struct bfd_hash_entry*, PTR));
};
/* Get the Sparc64 ELF linker hash table from a link_info structure. */
#define m68hc11_elf_hash_table(p) \
((struct m68hc11_elf_link_hash_table *) ((p)->hash))
/* Create a 68HC11/68HC12 ELF linker hash table. */
extern struct m68hc11_elf_link_hash_table* m68hc11_elf_hash_table_create
PARAMS ((bfd*));
extern void m68hc11_elf_bfd_link_hash_table_free
PARAMS ((struct bfd_link_hash_table*));
extern void m68hc11_elf_get_bank_parameters
PARAMS ((struct bfd_link_info*));
/* Return 1 if the address is in banked memory.
This can be applied to a virtual address and to a physical address. */
extern int m68hc11_addr_is_banked
PARAMS ((struct m68hc11_page_info*, bfd_vma));
/* Return the physical address seen by the processor, taking
into account banked memory. */
extern bfd_vma m68hc11_phys_addr
PARAMS ((struct m68hc11_page_info*, bfd_vma));
/* Return the page number corresponding to an address in banked memory. */
extern bfd_vma m68hc11_phys_page
PARAMS ((struct m68hc11_page_info*, bfd_vma));
bfd_reloc_status_type m68hc11_elf_ignore_reloc
PARAMS ((bfd *abfd, arelent *reloc_entry,
asymbol *symbol, PTR data, asection *input_section,
bfd *output_bfd, char **error_message));
bfd_reloc_status_type m68hc11_elf_special_reloc
PARAMS ((bfd *abfd, arelent *reloc_entry,
asymbol *symbol, PTR data, asection *input_section,
bfd *output_bfd, char **error_message));
/* GC mark and sweep. */
asection *elf32_m68hc11_gc_mark_hook
PARAMS ((asection *sec, struct bfd_link_info *info,
Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym));
bfd_boolean elf32_m68hc11_gc_sweep_hook
PARAMS ((bfd *abfd, struct bfd_link_info *info,
asection *sec, const Elf_Internal_Rela *relocs));
bfd_boolean elf32_m68hc11_check_relocs
PARAMS ((bfd * abfd, struct bfd_link_info * info,
asection * sec, const Elf_Internal_Rela * relocs));
bfd_boolean elf32_m68hc11_relocate_section
PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
bfd *input_bfd, asection *input_section,
bfd_byte *contents, Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms, asection **local_sections));
bfd_boolean elf32_m68hc11_add_symbol_hook
PARAMS ((bfd *abfd, struct bfd_link_info *info,
const Elf_Internal_Sym *sym, const char **namep,
flagword *flagsp, asection **secp,
bfd_vma *valp));
/* Tweak the OSABI field of the elf header. */
extern void elf32_m68hc11_post_process_headers
PARAMS ((bfd*, struct bfd_link_info*));
int elf32_m68hc11_setup_section_lists
PARAMS ((bfd *, struct bfd_link_info *));
bfd_boolean elf32_m68hc11_size_stubs
PARAMS ((bfd *, bfd *, struct bfd_link_info *,
asection * (*) PARAMS ((const char *, asection *))));
bfd_boolean elf32_m68hc11_build_stubs
PARAMS ((bfd* abfd, struct bfd_link_info *));
#endif