Index: bfd/elf32-m68hc1x.c |
diff --git a/bfd/elf32-m68hc1x.c b/bfd/elf32-m68hc1x.c |
index 961dce482e63f1c47b2f3867aaa79424763f49f7..d862c9fbe326d0dc895d7ea629342c947d6e3092 100644 |
--- a/bfd/elf32-m68hc1x.c |
+++ b/bfd/elf32-m68hc1x.c |
@@ -1,6 +1,6 @@ |
/* Motorola 68HC11/HC12-specific support for 32-bit ELF |
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
- 2009, 2010, 2011 Free Software Foundation, Inc. |
+ 2009, 2010, 2011, 2012 Free Software Foundation, Inc. |
Contributed by Stephane Carrez (stcarrez@nerim.fr) |
This file is part of BFD, the Binary File Descriptor library. |
@@ -20,8 +20,8 @@ |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
-#include "alloca-conf.h" |
#include "sysdep.h" |
+#include "alloca-conf.h" |
#include "bfd.h" |
#include "bfdlink.h" |
#include "libbfd.h" |
@@ -50,7 +50,7 @@ static void m68hc11_elf_set_symbol (bfd* abfd, struct bfd_link_info *info, |
static bfd_boolean m68hc11_elf_export_one_stub |
(struct bfd_hash_entry *gen_entry, void *in_arg); |
-static void scan_sections_for_abi (bfd*, asection*, PTR); |
+static void scan_sections_for_abi (bfd*, asection*, void *); |
struct m68hc11_scan_param |
{ |
@@ -214,6 +214,20 @@ elf32_m68hc11_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, |
return TRUE; |
} |
+/* Merge non-visibility st_other attributes, STO_M68HC12_FAR and |
+ STO_M68HC12_INTERRUPT. */ |
+ |
+void |
+elf32_m68hc11_merge_symbol_attribute (struct elf_link_hash_entry *h, |
+ const Elf_Internal_Sym *isym, |
+ bfd_boolean definition, |
+ bfd_boolean dynamic ATTRIBUTE_UNUSED) |
+{ |
+ if (definition) |
+ h->other = ((isym->st_other & ~ELF_ST_VISIBILITY (-1)) |
+ | ELF_ST_VISIBILITY (h->other)); |
+} |
+ |
/* External entry points for sizing and building linker stubs. */ |
/* Set up various things so that we can make a list of input sections |
@@ -935,6 +949,7 @@ elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, |
bfd_vma insn_page; |
bfd_boolean is_far = FALSE; |
struct elf_link_hash_entry *h; |
+ bfd_vma val; |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
@@ -970,9 +985,9 @@ elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, |
is_far = (h && (h->other & STO_M68HC12_FAR)); |
} |
- if (sec != NULL && elf_discarded_section (sec)) |
+ if (sec != NULL && discarded_section (sec)) |
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, |
- rel, relend, howto, contents); |
+ rel, 1, relend, howto, 0, contents); |
if (info->relocatable) |
{ |
@@ -1015,6 +1030,50 @@ elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, |
phys_page = m68hc11_phys_page (pinfo, relocation + rel->r_addend); |
switch (r_type) |
{ |
+ case R_M68HC12_LO8XG: |
+ /* This relocation is specific to XGATE IMM16 calls and will precede |
+ a HI8. tc-m68hc11 only generates them in pairs. |
+ Leave the relocation to the HI8XG step. */ |
+ r = bfd_reloc_ok; |
+ r_type = R_M68HC11_NONE; |
+ break; |
+ |
+ case R_M68HC12_HI8XG: |
+ /* This relocation is specific to XGATE IMM16 calls and must follow |
+ a LO8XG. Does not actually check that it was a LO8XG. |
+ Adjusts high and low bytes. */ |
+ relocation = phys_addr; |
+ if ((elf_elfheader (input_bfd)->e_flags & E_M68HC11_XGATE_RAMOFFSET) |
+ && (relocation >= 0x2000)) |
+ relocation += 0xc000; /* HARDCODED RAM offset for XGATE. */ |
+ |
+ /* Fetch 16 bit value including low byte in previous insn. */ |
+ val = (bfd_get_8 (input_bfd, (bfd_byte*) contents + rel->r_offset) << 8) |
+ | bfd_get_8 (input_bfd, (bfd_byte*) contents + rel->r_offset - 2); |
+ |
+ /* Add on value to preserve carry, then write zero to high byte. */ |
+ relocation += val; |
+ |
+ /* Write out top byte. */ |
+ bfd_put_8 (input_bfd, (relocation >> 8) & 0xff, |
+ (bfd_byte*) contents + rel->r_offset); |
+ |
+ /* Write out low byte to previous instruction. */ |
+ bfd_put_8 (input_bfd, relocation & 0xff, |
+ (bfd_byte*) contents + rel->r_offset - 2); |
+ |
+ /* Mark as relocation completed. */ |
+ r = bfd_reloc_ok; |
+ r_type = R_M68HC11_NONE; |
+ break; |
+ |
+ /* The HI8 and LO8 relocs are generated by %hi(expr) %lo(expr) |
+ assembler directives. %hi does not support carry. */ |
+ case R_M68HC11_HI8: |
+ case R_M68HC11_LO8: |
+ relocation = phys_addr; |
+ break; |
+ |
case R_M68HC11_24: |
/* Reloc used by 68HC12 call instruction. */ |
bfd_put_16 (input_bfd, phys_addr, |
@@ -1109,10 +1168,18 @@ elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, |
relocation = phys_addr; |
break; |
} |
+ |
if (r_type != R_M68HC11_NONE) |
- r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
+ { |
+ if ((r_type == R_M68HC12_PCREL_9) || (r_type == R_M68HC12_PCREL_10)) |
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
contents, rel->r_offset, |
- relocation, rel->r_addend); |
+ relocation - 2, rel->r_addend); |
+ else |
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
+ contents, rel->r_offset, |
+ relocation, rel->r_addend); |
+ } |
if (r != bfd_reloc_ok) |
{ |
@@ -1303,6 +1370,9 @@ _bfd_m68hc11_elf_print_private_bfd_data (bfd *abfd, void *ptr) |
else |
fprintf (file, _(" [memory=flat]")); |
+ if (elf_elfheader (abfd)->e_flags & E_M68HC11_XGATE_RAMOFFSET) |
+ fprintf (file, _(" [XGATE RAM offsetting]")); |
+ |
fputc ('\n', file); |
return TRUE; |