Support for Toshiba MeP and for complex relocations.
authorDave Brolley <brolley@redhat.com>
Mon, 5 Feb 2007 19:50:12 +0000 (19:50 +0000)
committerDave Brolley <brolley@redhat.com>
Mon, 5 Feb 2007 19:50:12 +0000 (19:50 +0000)
19 files changed:
bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/archures.c
bfd/bfd-in2.h
bfd/config.bfd
bfd/configure
bfd/configure.in
bfd/cpu-mep.c [new file with mode: 0644]
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-mep.c [new file with mode: 0644]
bfd/elfcode.h
bfd/elflink.c
bfd/libbfd.h
bfd/mep-relocs.pl [new file with mode: 0755]
bfd/reloc.c
bfd/syms.c
bfd/targets.c

index 3f418816541c3f03ae8a970b1217718a2d70cc04..032ae91e973f7622ea8cdd2a4c776304732f8eac 100644 (file)
@@ -1,3 +1,374 @@
+2007-02-05  Dave Brolley  <brolley@redhat.com>
+
+       * elflink.c (evaluate_complex_relocation_symbols): Check for
+       STT_SRELC for global symbols.
+       (perform_complex_relocations): Renamed to
+       perform_complex_relocation and now examines only one relocation.
+       (elf_link_input_bfd): Don't call perform_complex_relocations.
+       * elf-bfd.h (bfd_elf_perform_complex_relocation_: New prototype.: 
+       * elf32-mep.c (mep_elf_howto_table): Add R_RELC.
+       (OD,OS,OU): #undefs corrected to N, S and U repectively.
+       (mep_reloc_type_lookup): Handle BFD_RELOC_RELC.
+       (complex_reloc_installation_howto): Removed.
+       (mep_info_to_howto_rela): Remove special case for r_type==0xff.
+       (mep_elf_relocate_section): Call bfd_elf_perform_complex_relocation.
+
+2007-02-05  Dave Brolley  <brolley@redhat.com>
+
+       * Contribute the following changes:
+       2006-12-19  Dave Brolley  <brolley@redhat.com>
+
+       * elf32-mep.c: Fix problems with DEBUG printfs.
+       * elflink.h (elf_link_input_bfd): Always setup finfo->internal_syms.
+
+       2006-10-17  Nick Clifton  <nickc@redhat.com>
+
+       * elf32-mep.c (mep_elf_print_private_bfd_data): Remove redundant
+       check against 0.
+
+       2006-09-25  Dave Brolley  <brolley@redhat.com>
+
+       * elf32-mep.c (mep_elf_print_private_bfd_data): Check that
+       (long)partial_flags is non-negative before using it as an
+       array index.
+
+       2004-06-24  Dave Brolley  <brolley@redhat.com>
+
+       * elf32-mep.c: Regenerated by MeP-Integrator.
+
+       2005-04-22  Richard Sandiford  <rsandifo@redhat.com>
+
+       * elf32-mep.c (mep_elf_merge_private_bfd_data): Allow two objects
+       to be linked together if one of them uses the EF_MEP_LIBRARY flag.
+       Give priority to flag sets in which EF_MEP_LIBRARY is not set.
+
+       2005-04-05  Richard Sandiford  <rsandifo@redhat.com>
+
+       * elf32-mep.c (config_names): Reduce divergence from MeP-Integrator
+       output.
+
+       2004-08-03  Richard Sandiford  <rsandifo@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate): Fix overflow check for
+       R_MEP_PCABS24A2.
+
+       2004-06-24  Dave Brolley  <brolley@redhat.com>
+
+       * archures.c (bfd_mach_mep_h1): #define as 0x6831.
+       * bfd-in2.h: Regenerated.
+
+       2004-06-21  Dave Brolley  <brolley@redhat.com>
+
+       * elf32-mep.c (mep_elf_copy_private_bfd_data): Remove assertion about
+       flags being identical.
+       (mep_elf_merge_private_bfd_data): Handle existence of multiple CGEN
+       MACHs.
+       (mep_elf_print_private_bfd_data): Ditto.
+       (config_names): Give the machine at index 0 the name "basic".
+       (core_names): New table.
+       (elf32_mep_machine): New function.
+       (mep_elf_object_p): Call bfd_default_set_arch_mach.
+       * cpu-mep.c (bfd_h1_arch): Define it and link it into the chain.
+       * archures.c (bfd_mach_mep_h1): Define it.
+       * bfd-in2.h: Regenerated.
+
+       2003-07-19  Nick Clifton  <nickc@redhat.com>
+
+       * elf32-mep.c: Convert to ISO C.
+
+       2002-04-09  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate): Allow impossible
+       relocations to undefined weak functions.
+
+       2002-02-08  Frank Ch. Eigler  <fche@redhat.com>
+
+        * cpu-mep.c (mep_compatible): Remove: only one bfd_mach used now.
+        * elf32-mep.c (elf32_mep_machine): Ditto.
+
+       2001-12-12  Ben Elliston  <bje@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate): Do not adjust the pc
+       prior to applying a pc-relative relocation.
+
+       2001-10-02  Nick Clifton  <nickc@cambridge.redhat.com>
+
+       * elf32-mep.c: Add missing prototypes.
+
+       2001-10-01  Frank Ch. Eigler  <fche@redhat.com>
+
+       * elf32-mep.c (mep_elf_merge_private_bfd_data): Enforce endianness
+       compatibility.
+
+       2001-09-28  Richard Henderson  <rth@redhat.com>
+
+       * elf32-mep.c (mep_elf_section_flags): New.
+       (mep_elf_fake_sections): New.
+       (elf_backend_section_flags): New.
+       (elf_backend_fake_sections): New.
+
+       2001-09-27  Nick Clifton  <nickc@cambridge.redhat.com>
+
+       * elf32-mep.c: Add missing function prototypes.
+       Fix compile time warnings.  Improve formatting.
+       * mep_relocs.pl: Improve formatting in generated code.
+
+       2001-09-21  Nick Clifton  <nickc@cambridge.redhat.com>
+
+       * cpu-mep.c: Add missing function prototype.
+
+       2001-07-25  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate): Adjust calculation of PC
+       to be endian-sensitive.
+
+       2001-07-17  Richard Henderson  <rth@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate) [R_MEP_HI16S]: Correctly
+       compensate for high bit set in R_MEP_LOW16.
+
+       2001-07-12  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate): Don't do overflow
+       checking on VT relocs.
+       (mep_elf_merge_private_bfd_data): Return true if we chose not to
+       merge the data.
+       
+       2001-07-09  DJ Delorie  <dj@redhat.com>
+
+       * cpu-mep.c (mep_compatible): New, base compatibility on
+       conflicting configurations.
+       (bfd_mep_arch): Use a macro and wrap with comments for the config
+       tool.
+       * elf32-mep.c (elf32_mep_machine): Take bfd_mach directly from
+       flags.
+       (mep_elf_merge_private_bfd_data): Merge configurations sanely.
+       (config_names): New.
+       (mep_elf_print_private_bfd_data): Print config name if possible.
+
+       2001-06-25  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_reloc_type_lookup): Add vtable special cases,
+       regenerate others.
+       * reloc.c: Regenerate with new elf/mep.h relocs.
+       * libbfd.h: Likewise.
+       * bfd-in2.h: Likewise.
+       
+       2001-06-25  Ben Elliston  <bje@redhat.com>
+
+       * elf32-mep.c (mep_reloc): Mark unused parameters as such.
+       (mep_final_link_relocate): Remove unused local variables.
+
+       2001-06-06  DJ Delorie  <dj@redhat.com>
+
+       * config.bfd (mep-*-elf): Add bfd_elf32_mep_little_vec.
+       * configure.in: Ditto.
+       * configure: Ditto.
+       * mep-relocs.pl: Support both endians.
+       * elf32-mep.c: Regenerate; add little endian targets.
+
+       2001-05-31  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_elf_relocate_section): Fix error message.
+
+       2001-05-21  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_final_link_relocate): Fix pcrel logic.
+
+       2001-05-10  DJ Delorie  <dj@redhat.com>
+
+       * mep-relocs.pl: Detect no-overflow relocs better.
+       * elf32-mep.c: Regenerate.  HI16U, HI16S have correct shifts and
+       those and LOW16 are no-overflow now.
+
+       2001-05-03  DJ Delorie  <dj@redhat.com>
+
+       * mep-relocs.pl: New, generates reloc-handling code for
+       elf32-mep.c.
+       * elf32-mep.c: Regenerate.
+
+       2001-05-02  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c (mep_elf_howto_table): Fix size fields.
+       (mep_lookup_global, mep_tpoff_base, mep_sdaoff_base): New,
+       support %tpoff() and %sdaoff() relocs.
+       (mep_final_link_reloc): Add support for MeP relocs.
+       (mep_elf_relocate_section): Support %tpoff() and %sdaoff().
+
+       2001-05-01  DJ Delorie  <dj@redhat.com>
+
+       * elf32-mep.c: Use RELA only.
+       (mep_elf_howto_table): Add MeP-specific relocs.
+       (mep_reloc_type_lookup): Map relocs.
+       * reloc.c: Add MeP-specific relocs.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Regenerate.
+
+       2001-04-03  Ben Elliston  <bje@redhat.com>
+
+       * Makefile.am (ALL_MACHINES): Add cpu-mep.lo.
+       (ALL_MACHINES_CFILES): Add cpu-mep.c.
+       (BFD32_BACKENDS): Add elf32-mep.lo.
+       (BFD32_BACKENDS_CFILES): Add elf32-mep.c.
+       (cpu-mep.lo): New target.
+       * Makefile.in: Regenerate.
+       * config.bfd: Handle mep-*-elf.
+       * archures.c (bfd_architecture): Add bfd_{arch,mach}_mep.
+       (bfd_archures_list): Add bfd_mep_arch.
+       * configure.in: Handle bfd_elf32_mep_vec.
+       * configure: Regenerate.
+       * targets.c (bfd_elf32_mep_vec): Declare.
+       (bfd_target_vector): Add bfd_elf32_mep_vec.
+       * elf.c (prep_headers): Set e_machine to EM_CYGNUS_MEP.
+       * cpu-mep.c: New file.
+       * elf32-mep.c: Likewise.
+       * bfd-in2.h: Regenerate.
+       * po/POTFILES.in: Likewise.
+       
+2007-02-05  Dave Brolley  <brolley@redhat.com>
+
+       * Contribute the following changes:
+       2004-07-23  Richard Sandiford  <rsandifo@redhat.com>
+
+       * elflink.c (perform_complex_relocation): Detect relocations against
+       undefined symbols.
+
+       2002-04-02  DJ Delorie  <dj@redhat.com>
+
+       * elflink.h (resolve_symbol): Handle weak symbols.
+
+       2002-03-07  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h (perform_complex_relocations): Minor debug message
+       touchup.
+
+       2002-01-23  Graydon Hoare  <graydon@redhat.com>
+
+       * bfd-in2.h: Add signed RELC (SRELC) symbols.
+       * elf.c (swap_out_syms): Likewise.
+       * elfcode.h (elf_slurp_symbol_table): Likewise.
+       (elf_symbol_flags): Likewise.
+       * syms.c: Likewise.
+       * elflink.h (eval_symbol): Introduce signed RELC evaluation.
+       (evaluate_complex_relocation_symbols): Likewise.
+       (perform_complex_relocations): Remove sign-extension logic,
+       which was broken anyways.
+
+       2002-01-15  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h (decode_complex_addend): Add oplen, signed_p, trunc_p
+       params.
+       (perform_complex_relocations): Call decode with new args,
+       Sign extend leftmost signed fields, delegate overflow check to
+       bfd_check_overflow in reloc.c, enhance overflow error messages.
+
+       2002-01-08  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h (resolve_symbol): Fix symbol -> section relationship.
+       (resolve_symbol): Remove unused parameter.
+       (eval_symbol): Remove unused arg from resolve_symbol call.
+
+       2002-01-01  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h (perform_complex_relocations): Add overflow
+       checking for RELC fragments.
+
+       2001-12-15  Nick Clifton  <nickc@cambridge.redhat.com>
+
+       * elflink.h (evaluate_complex_relocation_symbols): Formatting
+       tidy ups.  Process all symbols, even if an error is
+       encountered.
+
+       2001-12-10  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h (evaluate_complex_relocation_symbols): Resolve
+       global RELC symbols using separate logic from local symbols.
+
+       2001-12-10  Nick Clifton  <nickc@cambridge.redhat.com>
+
+       Various formatting tidy ups and compile time warning removals,
+       plus:
+       
+       * elflink.h (eval_symbol): Set bfd_error for failure returns.
+       (evaluate_complex_relocation_symbols): Only evaluate local
+       symbols.
+
+       2001-11-24  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h.c (resolve_symbol): Skip non-local syms in 
+       local lookup loop; get section offset from section 
+       symbol occurs in (rather than reloc section); handle 
+       common symbols.
+
+       2001-11-24  Graydon Hoare  <graydon@redhat.com>
+
+       * elflink.h.c (resolve_symbol): Use
+       bfd_elf_string_from_elf_section to look up local symbols in
+       current bfd.
+       (eval_symbol): Add input_bfd parameter for resolve_symbol's
+       use.
+       (evaluate_complex_relocation_symbols): Pass parameter.
+       (resolve_section) Fix silly typo.
+
+       2001-10-16  Jeff Holcomb  <jeffh@redhat.com>
+
+       * elflink.h (eval_symbol): Buffer size needs to be an integer for
+       Solaris cc.
+
+       2001-11-15  graydon hoare  <graydon@redhat.com>
+
+       * elf32-mep.c (mep_info_to_howto_rela): Add complex reloc
+       howto.
+       * elflink.h (resolve_section): Add support for pseudo-sections
+       in complex symbols.
+       (evaluate_complex_relocation_symbols): Permit evaluating RELC
+       symbols on non-RELC relocs. They are distinct issues.
+
+       2001-10-15  graydon hoare  <graydon@redhat.com>
+
+       * reloc.c (bfd_reloc_code_type): Define BFD_RELOC_RELC,
+       in the _correct_ place.
+
+       2001-10-11  graydon hoare  <graydon@redhat.com>
+
+       * elflink.h (eval_symbol): Fix strtol calls with undefined
+       behavior.
+
+       2001-10-03  graydon hoare  <graydon@redhat.com>
+
+       * elflink.h (set_symbol_value): New function for relc.
+       (resolve_symbol): Likewise.
+       (resolve_section): Likewise.
+       (undefined_reference): Likewise.
+       (eval_symbol): Likewise.
+       (evaluate_complex_relocation_symbols): Likewise.
+       (put_value): Likewise.
+       (get_value): Likewise.
+       (decode_complex_addend): Likewise.
+       (perform_complex_relocations): Likewise.
+       (elf_link_input_bfd): Insert hook into
+       evaluate_complex_relocation_symbols.
+       (elf_link_input_bfd): Insert hook into
+       perform_complex_relocations.
+
+       * bfd-in2.h: Define BFD_RELOC_RELC, BSF_RELC.
+
+       * elf.c (swap_out_syms): Add BSF_RELC / STT_RELC support.
+
+       * elfcode.h (elf_slurp_symbol_table): Likewise.
+       (elf_symbol_flags): Likewise.
+
+       * libbfd.h: Add "BFD_RELOC_RELC" to bfd_reloc_code_real_names
+       table.
+
+       2001-06-20  Frank Ch. Eigler  <fche@redhat.com>
+
+       * syms.c (BSF_RELC): New symbol flag.
+       * elf.c (swap_out_syms): Map BSF_RELC -> STT_RELC.
+       * elfcode.h (elf_slurp_symbol_table): Map STT_RELC -> BSF_RELC.
+       (elf_symbol_flags): Display BSF_RELC as "relc".
+       * bfd-in2.h: Regenerated.
+
 2007-02-05  Bob Wilson  <bob.wilson@acm.org>
        
        * elf32-xtensa.c (elf_xtensa_make_sym_local): Delete.
index 6b4aebfb2f89a988123ec0d40c602cdee0cc1482..2e6915b40f3ece767a958392affcf43d75bdee7a 100644 (file)
@@ -91,6 +91,7 @@ ALL_MACHINES = \
        cpu-m10300.lo \
        cpu-maxq.lo \
        cpu-mcore.lo \
+       cpu-mep.lo \
        cpu-mips.lo \
        cpu-mmix.lo \
        cpu-mt.lo \
@@ -155,6 +156,7 @@ ALL_MACHINES_CFILES = \
        cpu-m10300.c \
        cpu-maxq.c \
        cpu-mcore.c \
+       cpu-mep.c \
        cpu-mips.c \
        cpu-mmix.c \
        cpu-mt.c \
@@ -266,6 +268,7 @@ BFD32_BACKENDS = \
        elf-m10200.lo \
        elf-m10300.lo \
        elf32-mcore.lo \
+       elf32-mep.lo \
        elfxx-mips.lo \
        elf32-mips.lo \
        elf32-mt.lo \
@@ -442,6 +445,7 @@ BFD32_BACKENDS_CFILES = \
        elf-m10200.c \
        elf-m10300.c \
        elf32-mcore.c \
+       elf32-mep.c \
        elfxx-mips.c \
        elf32-mips.c \
        elf32-mt.c \
@@ -1066,6 +1070,7 @@ cpu-m10200.lo: cpu-m10200.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-maxq.lo: cpu-maxq.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+cpu-mep.lo: cpu-mep.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mt.lo: cpu-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
@@ -1408,6 +1413,10 @@ elf32-mcore.lo: elf32-mcore.c $(INCDIR)/filenames.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/mcore.h \
   $(INCDIR)/elf/reloc-macros.h elf32-target.h
+elf32-mep.lo: elf32-mep.c elf-bfd.h $(INCDIR)/elf/common.h \
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+  $(INCDIR)/elf/mep.h $(INCDIR)/elf/reloc-macros.h \
+  elf32-target.h
 elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/libiberty.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
index c9a8c323386b3943edfe07444f8c53b08dba9791..1fbbc0e2f0415dc7511d186668abf97c1f9506c4 100644 (file)
@@ -323,6 +323,7 @@ ALL_MACHINES = \
        cpu-m10300.lo \
        cpu-maxq.lo \
        cpu-mcore.lo \
+       cpu-mep.lo \
        cpu-mips.lo \
        cpu-mmix.lo \
        cpu-mt.lo \
@@ -387,6 +388,7 @@ ALL_MACHINES_CFILES = \
        cpu-m10300.c \
        cpu-maxq.c \
        cpu-mcore.c \
+       cpu-mep.c \
        cpu-mips.c \
        cpu-mmix.c \
        cpu-mt.c \
@@ -499,6 +501,7 @@ BFD32_BACKENDS = \
        elf-m10200.lo \
        elf-m10300.lo \
        elf32-mcore.lo \
+       elf32-mep.lo \
        elfxx-mips.lo \
        elf32-mips.lo \
        elf32-mt.lo \
@@ -675,6 +678,7 @@ BFD32_BACKENDS_CFILES = \
        elf-m10200.c \
        elf-m10300.c \
        elf32-mcore.c \
+       elf32-mep.c \
        elfxx-mips.c \
        elf32-mips.c \
        elf32-mt.c \
@@ -1629,6 +1633,7 @@ cpu-m10200.lo: cpu-m10200.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-maxq.lo: cpu-maxq.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+cpu-mep.lo: cpu-mep.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
 cpu-mt.lo: cpu-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
@@ -1971,6 +1976,10 @@ elf32-mcore.lo: elf32-mcore.c $(INCDIR)/filenames.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/mcore.h \
   $(INCDIR)/elf/reloc-macros.h elf32-target.h
+elf32-mep.lo: elf32-mep.c elf-bfd.h $(INCDIR)/elf/common.h \
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+  $(INCDIR)/elf/mep.h $(INCDIR)/elf/reloc-macros.h \
+  elf32-target.h
 elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/libiberty.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
index a9fca3bffd350bbda1c52a9fbd412aa34ad3424c..f43e2e6be2677d9ec71bc201bb1b99a8235fe9d6 100644 (file)
@@ -318,6 +318,9 @@ DESCRIPTION
 .#define bfd_mach_fr500                500
 .#define bfd_mach_fr550                550
 .  bfd_arch_mcore,
+.  bfd_arch_mep,
+.#define bfd_mach_mep          1
+.#define bfd_mach_mep_h1       0x6831
 .  bfd_arch_ia64,      {* HP/Intel ia64 *}
 .#define bfd_mach_ia64_elf64   64
 .#define bfd_mach_ia64_elf32   32
@@ -456,6 +459,7 @@ extern const bfd_arch_info_type bfd_m68k_arch;
 extern const bfd_arch_info_type bfd_m88k_arch;
 extern const bfd_arch_info_type bfd_maxq_arch;
 extern const bfd_arch_info_type bfd_mcore_arch;
+extern const bfd_arch_info_type bfd_mep_arch;
 extern const bfd_arch_info_type bfd_mips_arch;
 extern const bfd_arch_info_type bfd_mmix_arch;
 extern const bfd_arch_info_type bfd_mn10200_arch;
@@ -525,6 +529,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
     &bfd_m88k_arch,
     &bfd_maxq_arch,
     &bfd_mcore_arch,
+    &bfd_mep_arch,
     &bfd_mips_arch,
     &bfd_mmix_arch,
     &bfd_mn10200_arch,
index e641e838c759c00a814a6f6e0070915b27ca3258..66a7dd21fea946fd9268d43d66705c986e5c39f8 100644 (file)
@@ -1974,6 +1974,9 @@ enum bfd_architecture
 #define bfd_mach_fr500         500
 #define bfd_mach_fr550         550
   bfd_arch_mcore,
+  bfd_arch_mep,
+#define bfd_mach_mep           1
+#define bfd_mach_mep_h1        0x6831
   bfd_arch_ia64,      /* HP/Intel ia64 */
 #define bfd_mach_ia64_elf64    64
 #define bfd_mach_ia64_elf32    32
@@ -3560,6 +3563,29 @@ short offset into 11 bits.  */
   BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
   BFD_RELOC_MCORE_RVA,
 
+/* Toshiba Media Processor Relocations.  */
+  BFD_RELOC_MEP_8,
+  BFD_RELOC_MEP_16,
+  BFD_RELOC_MEP_32,
+  BFD_RELOC_MEP_PCREL8A2,
+  BFD_RELOC_MEP_PCREL12A2,
+  BFD_RELOC_MEP_PCREL17A2,
+  BFD_RELOC_MEP_PCREL24A2,
+  BFD_RELOC_MEP_PCABS24A2,
+  BFD_RELOC_MEP_LOW16,
+  BFD_RELOC_MEP_HI16U,
+  BFD_RELOC_MEP_HI16S,
+  BFD_RELOC_MEP_GPREL,
+  BFD_RELOC_MEP_TPREL,
+  BFD_RELOC_MEP_TPREL7,
+  BFD_RELOC_MEP_TPREL7A2,
+  BFD_RELOC_MEP_TPREL7A4,
+  BFD_RELOC_MEP_UIMM24,
+  BFD_RELOC_MEP_ADDR24A4,
+  BFD_RELOC_MEP_GNU_VTINHERIT,
+  BFD_RELOC_MEP_GNU_VTENTRY,
+
+
 /* These are relocations for the GETA instruction.  */
   BFD_RELOC_MMIX_GETA,
   BFD_RELOC_MMIX_GETA_1,
@@ -4177,6 +4203,10 @@ This is the 5 bits of a value.  */
   BFD_RELOC_XSTORMY16_24,
   BFD_RELOC_XSTORMY16_FPTR16,
 
+/* Self-describing complex relocations.  */
+  BFD_RELOC_RELC,
+
+
 /* Infineon Relocations.  */
   BFD_RELOC_XC16X_PAG,
   BFD_RELOC_XC16X_POF,
@@ -4426,6 +4456,14 @@ typedef struct bfd_symbol
   /* This symbol is thread local.  Used in ELF.  */
 #define BSF_THREAD_LOCAL  0x40000
 
+  /* This symbol represents a complex relocation expression,
+     with the expression tree serialized in the symbol name.  */
+#define BSF_RELC 0x80000
+
+  /* This symbol represents a signed complex relocation expression,
+     with the expression tree serialized in the symbol name.  */
+#define BSF_SRELC 0x100000
+
   flagword flags;
 
   /* A pointer to the section to which this symbol is
@@ -5161,6 +5199,7 @@ typedef struct bfd_target
   reloc_howto_type *
               (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type);
 
+
   /* Routines used when writing an object file.  */
 #define BFD_JUMP_TABLE_WRITE(NAME) \
   NAME##_set_arch_mach, \
index 70d2c703b075065f26966a1db74ec4653384a7e3..871fb4380f0e1fbd726a7e4569a72b9be33f3dfa 100644 (file)
@@ -840,6 +840,11 @@ case "${targ}" in
     targ_selvecs="mcore_pe_big_vec mcore_pe_little_vec mcore_pei_big_vec mcore_pei_little_vec"
     ;;
 
+  mep-*-elf)
+    targ_defvec=bfd_elf32_mep_vec
+    targ_selvecs=bfd_elf32_mep_little_vec
+    ;;
+
   mips*-big-*)
     targ_defvec=ecoff_big_vec
     targ_selvecs=ecoff_little_vec
index bb52f50be9c2b1ab9857ed3ab74c10b589b59962..5295a2608feecf9544110ff46f44644e345da2f1 100755 (executable)
@@ -10869,6 +10869,8 @@ do
     bfd_elf32_m88k_vec)                tb="$tb elf32-m88k.lo elf32.lo $elf" ;;
     bfd_elf32_mcore_big_vec)   tb="$tb elf32-mcore.lo elf32.lo $elf" ;;
     bfd_elf32_mcore_little_vec)        tb="$tb elf32-mcore.lo elf32.lo $elf" ;;
+    bfd_elf32_mep_vec)         tb="$tb elf32-mep.lo elf32.lo $elf" ;;
+    bfd_elf32_mep_little_vec)  tb="$tb elf32-mep.lo elf32.lo $elf" ;;
     bfd_elf32_mn10200_vec)     tb="$tb elf-m10200.lo elf32.lo $elf" ;;
     bfd_elf32_mn10300_vec)     tb="$tb elf-m10300.lo elf32.lo $elf" ;;
     bfd_elf32_mt_vec)           tb="$tb elf32-mt.lo elf32.lo $elf" ;;
index 5dcb91c26c7e0b780687bff2c27ddc4354eb3f82..662d93abcf049f93da1de3b4bd980a4f36b845ec 100644 (file)
@@ -650,6 +650,8 @@ do
     bfd_elf32_m88k_vec)                tb="$tb elf32-m88k.lo elf32.lo $elf" ;;
     bfd_elf32_mcore_big_vec)   tb="$tb elf32-mcore.lo elf32.lo $elf" ;;
     bfd_elf32_mcore_little_vec)        tb="$tb elf32-mcore.lo elf32.lo $elf" ;;
+    bfd_elf32_mep_vec)         tb="$tb elf32-mep.lo elf32.lo $elf" ;;
+    bfd_elf32_mep_little_vec)  tb="$tb elf32-mep.lo elf32.lo $elf" ;;
     bfd_elf32_mn10200_vec)     tb="$tb elf-m10200.lo elf32.lo $elf" ;;
     bfd_elf32_mn10300_vec)     tb="$tb elf-m10300.lo elf32.lo $elf" ;;
     bfd_elf32_mt_vec)           tb="$tb elf32-mt.lo elf32.lo $elf" ;;
diff --git a/bfd/cpu-mep.c b/bfd/cpu-mep.c
new file mode 100644 (file)
index 0000000..66db750
--- /dev/null
@@ -0,0 +1,28 @@
+/* BFD support for the Toshiba Media Engine Processor.
+   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define MA(x, n, def, y) { 32, 32, 8, bfd_arch_mep, x, "mep", n, \
+       2, def, bfd_default_compatible, bfd_default_scan, y }
+
+static const bfd_arch_info_type bfd_h1_arch = MA (bfd_mach_mep_h1, "h1", FALSE, NULL);
+const bfd_arch_info_type bfd_mep_arch = MA (bfd_mach_mep, "mep", TRUE, & bfd_h1_arch);
index a9d51a3598560f1ae14caa1cadc0db81e8c78eef..151c5d0605336cdd12877e31673d3fa53dfc2757 100644 (file)
@@ -1735,6 +1735,16 @@ extern bfd_boolean _bfd_elf_symbol_refs_local_p
 extern bfd_boolean bfd_elf_match_symbols_in_sections
   (asection *, asection *, struct bfd_link_info *);
 
+extern void bfd_elf_perform_complex_relocation
+  (bfd *                   output_bfd ATTRIBUTE_UNUSED,
+   struct bfd_link_info *  info,
+   bfd *                   input_bfd,
+   asection *              input_section,
+   bfd_byte *              contents,
+   Elf_Internal_Rela *     rel,
+   Elf_Internal_Sym *      local_syms,
+   asection **             local_sections);
+
 extern bfd_boolean _bfd_elf_setup_sections
   (bfd *);
 
index 7efca9ca1457074b8c54e711b6cbf1f764dd1cb2..460502c2e49bd2659c306332294474c4d7531968 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6378,6 +6378,10 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
        type = STT_FUNC;
       else if ((flags & BSF_OBJECT) != 0)
        type = STT_OBJECT;
+      else if ((flags & BSF_RELC) != 0)
+       type = STT_RELC;
+      else if ((flags & BSF_SRELC) != 0)
+       type = STT_SRELC;
       else
        type = STT_NOTYPE;
 
diff --git a/bfd/elf32-mep.c b/bfd/elf32-mep.c
new file mode 100644 (file)
index 0000000..4036d1e
--- /dev/null
@@ -0,0 +1,940 @@
+/* MeP-specific support for 32-bit ELF.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/mep.h"
+#include "libiberty.h"
+
+/* Forward declarations.  */
+
+/* Private relocation functions.  */
+\f
+#define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
+  {(unsigned)type, right, size, bits, pcrel, left, overflow, mep_reloc, #type, FALSE, 0, mask, 0 }
+
+#define N complain_overflow_dont
+#define S complain_overflow_signed
+#define U complain_overflow_unsigned
+
+static bfd_reloc_status_type mep_reloc (bfd *, arelent *, struct bfd_symbol *,
+                                       void *, asection *, bfd *, char **);
+
+static reloc_howto_type mep_elf_howto_table [] =
+{
+  /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
+  MEPREL (R_MEP_NONE,     0,  0, 0, 0, 0, N, 0),
+  MEPREL (R_RELC,         0,  0, 0, 0, 0, N, 0),
+  /* MEPRELOC:HOWTO */
+    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
+  MEPREL (R_MEP_8,        0,  8, 0, 0, 0, U, 0xff),
+  MEPREL (R_MEP_16,       1, 16, 0, 0, 0, U, 0xffff),
+  MEPREL (R_MEP_32,       2, 32, 0, 0, 0, U, 0xffffffff),
+  MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
+  MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
+  MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
+  MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
+  MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
+  MEPREL (R_MEP_LOW16,    2, 16, 0, 0, 0, N, 0x0000ffff),
+  MEPREL (R_MEP_HI16U,    2, 32, 0,16, 0, N, 0x0000ffff),
+  MEPREL (R_MEP_HI16S,    2, 32, 0,16, 0, N, 0x0000ffff),
+  MEPREL (R_MEP_GPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
+  MEPREL (R_MEP_TPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
+  MEPREL (R_MEP_TPREL7,   1,  7, 0, 0, 0, U, 0x007f),
+  MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
+  MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
+  MEPREL (R_MEP_UIMM24,   2, 24, 0, 0, 0, U, 0x00ffffff),
+  MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
+  MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
+  MEPREL (R_MEP_GNU_VTENTRY,1,  0,16,32, 0, N, 0x0000),
+  /* MEPRELOC:END */
+};
+
+#define VALID_MEP_RELOC(N) ((N) >= 0 \
+  && (N) < ARRAY_SIZE (mep_elf_howto_table)
+
+#undef N
+#undef S
+#undef U
+
+static bfd_reloc_status_type
+mep_reloc
+    (bfd *               abfd ATTRIBUTE_UNUSED,
+     arelent *           reloc_entry ATTRIBUTE_UNUSED,
+     struct bfd_symbol * symbol ATTRIBUTE_UNUSED,
+     void *              data ATTRIBUTE_UNUSED,
+     asection *          input_section ATTRIBUTE_UNUSED,
+     bfd *               output_bfd ATTRIBUTE_UNUSED,
+     char **             error_message ATTRIBUTE_UNUSED)
+{
+  return bfd_reloc_ok;
+}
+
+\f
+
+#define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
+#else
+#define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
+#endif
+
+static reloc_howto_type *
+mep_reloc_type_lookup
+    (bfd * abfd ATTRIBUTE_UNUSED,
+     bfd_reloc_code_real_type code)
+{
+  unsigned int type = 0;
+
+  switch (code)
+    {
+    MAP(NONE);
+    case BFD_RELOC_8:
+      type = R_MEP_8;
+      break;
+    case BFD_RELOC_16:
+      type = R_MEP_16;
+      break;
+    case BFD_RELOC_32:
+      type = R_MEP_32;
+      break;
+    case BFD_RELOC_VTABLE_ENTRY:
+      type = R_MEP_GNU_VTENTRY;
+      break;
+    case BFD_RELOC_VTABLE_INHERIT:
+      type = R_MEP_GNU_VTINHERIT;
+      break;
+    case BFD_RELOC_RELC:
+      type = R_RELC;
+      break;
+
+    /* MEPRELOC:MAP */
+    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
+    MAP(8);
+    MAP(16);
+    MAP(32);
+    MAP(PCREL8A2);
+    MAP(PCREL12A2);
+    MAP(PCREL17A2);
+    MAP(PCREL24A2);
+    MAP(PCABS24A2);
+    MAP(LOW16);
+    MAP(HI16U);
+    MAP(HI16S);
+    MAP(GPREL);
+    MAP(TPREL);
+    MAP(TPREL7);
+    MAP(TPREL7A2);
+    MAP(TPREL7A4);
+    MAP(UIMM24);
+    MAP(ADDR24A4);
+    MAP(GNU_VTINHERIT);
+    MAP(GNU_VTENTRY);
+    /* MEPRELOC:END */
+
+    default:
+      /* Pacify gcc -Wall.  */
+      fprintf (stderr, "mep: no reloc for code %d\n", code);
+      return NULL;
+    }
+
+  if (mep_elf_howto_table[type].type != type)
+    {
+      fprintf (stderr, "MeP: howto %d has type %d\n", type, mep_elf_howto_table[type].type);
+      abort ();
+    }
+
+  return mep_elf_howto_table + type;
+}
+
+#undef MAP
+
+\f
+/* Perform a single relocation.  */
+
+static struct bfd_link_info *mep_info;
+static int warn_tp = 0, warn_sda = 0;
+
+static bfd_vma
+mep_lookup_global
+    (char *    name,
+     bfd_vma   ofs,
+     bfd_vma * cache,
+     int *     warn)
+{
+  struct bfd_link_hash_entry *h;
+
+  if (*cache || *warn)
+    return *cache;
+
+  h = bfd_link_hash_lookup (mep_info->hash, name, FALSE, FALSE, TRUE);
+  if (h == 0 || h->type != bfd_link_hash_defined)
+    {
+      *warn = ofs + 1;
+      return 0;
+    }
+  *cache = (h->u.def.value
+         + h->u.def.section->output_section->vma
+         + h->u.def.section->output_offset);
+  return *cache;
+}
+
+static bfd_vma
+mep_tpoff_base (bfd_vma ofs)
+{
+  static bfd_vma cache = 0;
+  return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
+}
+
+static bfd_vma
+mep_sdaoff_base (bfd_vma ofs)
+{
+  static bfd_vma cache = 0;
+  return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
+}
+
+static bfd_reloc_status_type
+mep_final_link_relocate
+    (reloc_howto_type *  howto,
+     bfd *               input_bfd,
+     asection *          input_section,
+     bfd_byte *          contents,
+     Elf_Internal_Rela * rel,
+     bfd_vma             relocation)
+{
+  unsigned long u;
+  long s;
+  unsigned char *byte;
+  bfd_vma pc;
+  bfd_reloc_status_type r = bfd_reloc_ok;
+  int e2, e4;
+
+  if (bfd_big_endian (input_bfd))
+    {
+      e2 = 0;
+      e4 = 0;
+    }
+  else
+    {
+      e2 = 1;
+      e4 = 3;
+    }
+
+  pc = (input_section->output_section->vma
+       + input_section->output_offset
+       + rel->r_offset);
+
+  s = relocation + rel->r_addend;
+
+  byte = (unsigned char *)contents + rel->r_offset;
+
+  if (howto->type == R_MEP_PCREL24A2
+      && s == 0
+      && pc >= 0x800000)
+    {
+      /* This is an unreachable branch to an undefined weak function.
+        Silently ignore it, since the opcode can't do that but should
+        never be executed anyway.  */
+      return bfd_reloc_ok;
+    }
+
+  if (howto->pc_relative)
+    s -= pc;
+
+  u = (unsigned long) s;
+
+  switch (howto->type)
+    {
+    /* MEPRELOC:APPLY */
+    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
+    case R_MEP_8: /* 76543210 */
+      if (u > 255) r = bfd_reloc_overflow;
+      byte[0] = (u & 0xff);
+      break;
+    case R_MEP_16: /* fedcba9876543210 */
+      if (u > 65535) r = bfd_reloc_overflow;
+      byte[0^e2] = ((u >> 8) & 0xff);
+      byte[1^e2] = (u & 0xff);
+      break;
+    case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
+      byte[0^e4] = ((u >> 24) & 0xff);
+      byte[1^e4] = ((u >> 16) & 0xff);
+      byte[2^e4] = ((u >> 8) & 0xff);
+      byte[3^e4] = (u & 0xff);
+      break;
+    case R_MEP_PCREL8A2: /* --------7654321- */
+      if (-128 > s || s > 127) r = bfd_reloc_overflow;
+      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
+      break;
+    case R_MEP_PCREL12A2: /* ----ba987654321- */
+      if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
+      byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
+      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
+      break;
+    case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
+      if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
+      byte[2^e2] = ((s >> 9) & 0xff);
+      byte[3^e2] = ((s >> 1) & 0xff);
+      break;
+    case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
+      if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
+      byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
+      byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
+      byte[2^e2] = ((s >> 16) & 0xff);
+      byte[3^e2] = ((s >> 8) & 0xff);
+      break;
+    case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
+      if (u > 16777215) r = bfd_reloc_overflow;
+      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
+      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
+      byte[2^e2] = ((u >> 16) & 0xff);
+      byte[3^e2] = ((u >> 8) & 0xff);
+      break;
+    case R_MEP_LOW16: /* ----------------fedcba9876543210 */
+      byte[2^e2] = ((u >> 8) & 0xff);
+      byte[3^e2] = (u & 0xff);
+      break;
+    case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
+      byte[2^e2] = ((u >> 24) & 0xff);
+      byte[3^e2] = ((u >> 16) & 0xff);
+      break;
+    case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
+      byte[2^e2] = ((s >> 24) & 0xff);
+      byte[3^e2] = ((s >> 16) & 0xff);
+      break;
+    case R_MEP_GPREL: /* ----------------fedcba9876543210 */
+      s -= mep_sdaoff_base(rel->r_offset);
+      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
+      byte[2^e2] = ((s >> 8) & 0xff);
+      byte[3^e2] = (s & 0xff);
+      break;
+    case R_MEP_TPREL: /* ----------------fedcba9876543210 */
+      s -= mep_tpoff_base(rel->r_offset);
+      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
+      byte[2^e2] = ((s >> 8) & 0xff);
+      byte[3^e2] = (s & 0xff);
+      break;
+    case R_MEP_TPREL7: /* ---------6543210 */
+      u -= mep_tpoff_base(rel->r_offset);
+      if (u > 127) r = bfd_reloc_overflow;
+      byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
+      break;
+    case R_MEP_TPREL7A2: /* ---------654321- */
+      u -= mep_tpoff_base(rel->r_offset);
+      if (u > 127) r = bfd_reloc_overflow;
+      byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
+      break;
+    case R_MEP_TPREL7A4: /* ---------65432-- */
+      u -= mep_tpoff_base(rel->r_offset);
+      if (u > 127) r = bfd_reloc_overflow;
+      byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
+      break;
+    case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
+      if (u > 16777215) r = bfd_reloc_overflow;
+      byte[1^e2] = (u & 0xff);
+      byte[2^e2] = ((u >> 16) & 0xff);
+      byte[3^e2] = ((u >> 8) & 0xff);
+      break;
+    case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
+      if (u > 16777215) r = bfd_reloc_overflow;
+      byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
+      byte[2^e2] = ((u >> 16) & 0xff);
+      byte[3^e2] = ((u >> 8) & 0xff);
+      break;
+    case R_MEP_GNU_VTINHERIT: /* ---------------- */
+      break;
+    case R_MEP_GNU_VTENTRY: /* ---------------- */
+      break;
+    /* MEPRELOC:END */
+    default:
+      abort ();
+    }
+
+  return r;
+}
+\f
+/* Set the howto pointer for a MEP ELF reloc.  */
+
+static void
+mep_info_to_howto_rela
+    (bfd *               abfd ATTRIBUTE_UNUSED,
+     arelent *           cache_ptr,
+     Elf_Internal_Rela * dst)
+{
+  unsigned int r_type;
+
+  r_type = ELF32_R_TYPE (dst->r_info);
+  cache_ptr->howto = & mep_elf_howto_table [r_type];
+}
+
+/* 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
+mep_elf_check_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->relocatable)
+    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];
+    }
+  return TRUE;
+}
+
+\f
+/* Relocate a MEP ELF section.
+   There is some attempt to make this function usable for many architectures,
+   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
+   if only to serve as a learning tool.
+
+   The RELOCATE_SECTION function is called by the new ELF backend linker
+   to handle the relocations for a section.
+
+   The relocs are always passed as Rela structures; if the section
+   actually uses Rel structures, the r_addend field will always be
+   zero.
+
+   This function is responsible for adjusting the section contents as
+   necessary, and (if using Rela relocs and generating a relocatable
+   output file) adjusting the reloc addend as necessary.
+
+   This function does not have to worry about setting the reloc
+   address or the reloc symbol index.
+
+   LOCAL_SYMS is a pointer to the swapped in local symbols.
+
+   LOCAL_SECTIONS is an array giving the section in the input file
+   corresponding to the st_shndx field of each local symbol.
+
+   The global hash table entry for the global symbols can be found
+   via elf_sym_hashes (input_bfd).
+
+   When generating relocatable output, this function must handle
+   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
+   going to be the section symbol corresponding to the output
+   section, which means that the addend must be adjusted
+   accordingly.  */
+
+static bfd_boolean
+mep_elf_relocate_section
+    (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;
+  Elf_Internal_Rela *           relend;
+
+  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+  relend     = relocs + input_section->reloc_count;
+
+  mep_info = info;
+
+  for (rel = relocs; rel < relend; rel ++)
+    {
+      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;
+      const char *                 name = NULL;
+      int                          r_type;
+
+      r_type = ELF32_R_TYPE (rel->r_info);
+
+      r_symndx = ELF32_R_SYM (rel->r_info);
+
+      if (info->relocatable)
+       {
+         /* This is a relocatable 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;
+       }
+
+      /* Is this a complex relocation?  */
+      if (ELF32_R_TYPE (rel->r_info) == R_RELC)
+       {
+         bfd_elf_perform_complex_relocation (output_bfd, info,
+                                             input_bfd, input_section, contents,
+                                             rel, local_syms, local_sections);
+         continue;
+       }
+
+      /* This is a final link.  */
+      howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
+      h      = NULL;
+      sym    = NULL;
+      sec    = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections [r_symndx];
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+
+         name = bfd_elf_string_from_elf_section
+           (input_bfd, symtab_hdr->sh_link, sym->st_name);
+         name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
+#if 0
+         fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
+                  sec->name, name, sym->st_name,
+                  sec->output_section->vma, sec->output_offset,
+                  sym->st_value, rel->r_addend);
+#endif
+       }
+      else
+       {
+         h = sym_hashes [r_symndx];
+
+         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;
+
+         name = h->root.root.string;
+
+         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);
+#if 0
+             fprintf (stderr,
+                      "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
+                      sec->name, name, h->root.u.def.value,
+                      sec->output_section->vma, sec->output_offset, relocation);
+#endif
+           }
+         else if (h->root.type == bfd_link_hash_undefweak)
+           {
+#if 0
+             fprintf (stderr, "undefined: sec: %s, name: %s\n",
+                      sec->name, name);
+#endif
+             relocation = 0;
+           }
+         else
+           {
+             if (! ((*info->callbacks->undefined_symbol)
+                    (info, h->root.root.string, input_bfd,
+                     input_section, rel->r_offset,
+                     (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR))))
+               return FALSE;
+#if 0
+             fprintf (stderr, "unknown: name: %s\n", name);
+#endif
+             relocation = 0;
+           }
+       }
+
+      switch (r_type)
+       {
+       default:
+         r = mep_final_link_relocate (howto, input_bfd, input_section,
+                                        contents, rel, relocation);
+         break;
+       }
+
+      if (r != bfd_reloc_ok)
+       {
+         const char * msg = (const char *) NULL;
+
+         switch (r)
+           {
+           case bfd_reloc_overflow:
+             r = info->callbacks->reloc_overflow
+               (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
+                input_bfd, input_section, rel->r_offset);
+             break;
+
+           case bfd_reloc_undefined:
+             r = info->callbacks->undefined_symbol
+               (info, name, input_bfd, input_section, rel->r_offset, TRUE);
+             break;
+
+           case bfd_reloc_outofrange:
+             msg = _("internal error: out of range error");
+             break;
+
+           case bfd_reloc_notsupported:
+             msg = _("internal error: unsupported relocation error");
+             break;
+
+           case bfd_reloc_dangerous:
+             msg = _("internal error: dangerous relocation");
+             break;
+
+           default:
+             msg = _("internal error: unknown error");
+             break;
+           }
+
+         if (msg)
+           r = info->callbacks->warning
+             (info, msg, name, input_bfd, input_section, rel->r_offset);
+
+         if (! r)
+           return FALSE;
+       }
+    }
+
+  if (warn_tp)
+    info->callbacks->undefined_symbol
+      (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
+  if (warn_sda)
+    info->callbacks->undefined_symbol
+      (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
+  if (warn_sda || warn_tp)
+    return FALSE;
+
+  return TRUE;
+}
+\f
+
+/* Update the got entry reference counts for the section being
+   removed.  */
+
+static bfd_boolean
+mep_elf_gc_sweep_hook
+    (bfd *                     abfd ATTRIBUTE_UNUSED,
+     struct bfd_link_info *    info ATTRIBUTE_UNUSED,
+     asection *                sec ATTRIBUTE_UNUSED,
+     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+/* Return the section that should be marked against GC for a given
+   relocation.  */
+
+static asection *
+mep_elf_gc_mark_hook
+    (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
+    {
+      if (!(elf_bad_symtab (sec->owner)
+           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+               && sym->st_shndx != SHN_COMMON))
+       return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+    }
+
+  return NULL;
+}
+
+\f
+/* Function to set the ELF flag bits.  */
+
+static bfd_boolean
+mep_elf_set_private_flags (bfd *    abfd,
+                          flagword flags)
+{
+  elf_elfheader (abfd)->e_flags = flags;
+  elf_flags_init (abfd) = TRUE;
+  return TRUE;
+}
+
+static bfd_boolean
+mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
+{
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return TRUE;
+
+  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+  elf_flags_init (obfd) = TRUE;
+  return TRUE;
+}
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
+{
+  static bfd *last_ibfd = 0;
+  flagword old_flags, new_flags;
+  flagword old_partial, new_partial;
+
+  /* Check if we have the same endianess.  */
+  if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
+    return FALSE;
+
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  old_flags = elf_elfheader (obfd)->e_flags;
+
+#ifdef DEBUG
+  _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
+                     ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
+#endif
+
+    /* First call, no flags set.  */
+    if (!elf_flags_init (obfd))
+    {
+      elf_flags_init (obfd) = TRUE;
+      old_flags = new_flags;
+    }
+  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
+    {
+      /* Non-library flags trump library flags.  The choice doesn't really
+        matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
+      if (old_flags & EF_MEP_LIBRARY)
+       old_flags = new_flags;
+    }
+  else
+    {
+      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
+        mach.  */
+      new_partial = (new_flags & EF_MEP_CPU_MASK);
+      old_partial = (old_flags & EF_MEP_CPU_MASK);
+      if (new_partial == old_partial)
+       ;
+      else if (new_partial == EF_MEP_CPU_MEP)
+       ;
+      else if (old_partial == EF_MEP_CPU_MEP)
+       old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
+      else
+       {
+         _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
+         bfd_set_error (bfd_error_invalid_target);
+         return FALSE;
+       }
+
+      /* Make sure they're for the same me_module.  Allow basic config to
+        mix with any other.  */
+      new_partial = (new_flags & EF_MEP_INDEX_MASK);
+      old_partial = (old_flags & EF_MEP_INDEX_MASK);
+      if (new_partial == old_partial)
+       ;
+      else if (new_partial == 0)
+       ;
+      else if (old_partial == 0)
+       old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
+      else
+       {
+         _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
+         bfd_set_error (bfd_error_invalid_target);
+         return FALSE;
+       }
+    }
+
+  elf_elfheader (obfd)->e_flags = old_flags;
+  last_ibfd = ibfd;
+  return TRUE;
+}
+
+/* This will be edited by the MeP configration tool.  */
+static const char * config_names[] =
+{
+  "basic"
+  /* start-mepcfgtool */
+  ,"simple"
+  ,"fmax"
+  /* end-mepcfgtool */
+};
+
+static const char * core_names[] =
+{
+  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
+};
+
+static bfd_boolean
+mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
+{
+  FILE *   file = (FILE *) ptr;
+  flagword flags, partial_flags;
+
+  BFD_ASSERT (abfd != NULL && ptr != NULL);
+
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+  flags = elf_elfheader (abfd)->e_flags;
+  fprintf (file, _("private flags = 0x%lx"), (long)flags);
+
+  partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
+  if (partial_flags < ARRAY_SIZE (core_names))
+    fprintf (file, "  core: %s", core_names[(long)partial_flags]);
+
+  partial_flags = flags & EF_MEP_INDEX_MASK;
+  if (partial_flags < ARRAY_SIZE (config_names))
+    fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
+
+  fputc ('\n', file);
+
+  return TRUE;
+}
+
+/* Return the machine subcode from the ELF e_flags header.  */
+
+static int
+elf32_mep_machine (bfd * abfd)
+{
+  switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
+    {
+    default: break;
+    case EF_MEP_CPU_C2: return bfd_mach_mep;
+    case EF_MEP_CPU_C3: return bfd_mach_mep;
+    case EF_MEP_CPU_C4: return bfd_mach_mep;
+    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
+    }
+
+  return bfd_mach_mep;
+}
+
+static bfd_boolean
+mep_elf_object_p (bfd * abfd)
+{
+  /* Irix 5 and 6 is broken.  Object file symbol tables are not always
+     sorted correctly such that local symbols preceed global symbols,
+     and the sh_info field in the symbol table is not always right.  */
+  /* This is needed for the RELC support code.  */
+  elf_bad_symtab (abfd) = TRUE;
+  bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
+  return TRUE;
+}
+
+static bfd_boolean
+mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
+{
+  if (hdr->sh_flags & SHF_MEP_VLIW)
+    * flags |= SEC_MEP_VLIW;
+  return TRUE;
+}
+
+static bfd_boolean
+mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
+                      Elf_Internal_Shdr * hdr,
+                      asection *          sec)
+{
+  if (sec->flags & SEC_MEP_VLIW)
+    hdr->sh_flags |= SHF_MEP_VLIW;
+  return TRUE;
+}
+
+\f
+#define ELF_ARCH               bfd_arch_mep
+#define ELF_MACHINE_CODE       EM_CYGNUS_MEP
+#define ELF_MAXPAGESIZE                0x1000
+
+#define TARGET_BIG_SYM         bfd_elf32_mep_vec
+#define TARGET_BIG_NAME                "elf32-mep"
+
+#define TARGET_LITTLE_SYM      bfd_elf32_mep_little_vec
+#define TARGET_LITTLE_NAME     "elf32-mep-little"
+
+#define elf_info_to_howto_rel                  NULL
+#define elf_info_to_howto                      mep_info_to_howto_rela
+#define elf_backend_relocate_section           mep_elf_relocate_section
+#define elf_backend_gc_mark_hook               mep_elf_gc_mark_hook
+#define elf_backend_gc_sweep_hook              mep_elf_gc_sweep_hook
+#define elf_backend_check_relocs                mep_elf_check_relocs
+#define elf_backend_object_p                   mep_elf_object_p
+#define elf_backend_section_flags              mep_elf_section_flags
+#define elf_backend_fake_sections              mep_elf_fake_sections
+
+#define elf_backend_can_gc_sections            1
+
+#define bfd_elf32_bfd_reloc_type_lookup                mep_reloc_type_lookup
+#define bfd_elf32_bfd_set_private_flags                mep_elf_set_private_flags
+#define bfd_elf32_bfd_copy_private_bfd_data    mep_elf_copy_private_bfd_data
+#define bfd_elf32_bfd_merge_private_bfd_data   mep_elf_merge_private_bfd_data
+#define bfd_elf32_bfd_print_private_bfd_data   mep_elf_print_private_bfd_data
+
+/* We use only the RELA entries.  */
+#define USE_RELA
+
+#include "elf32-target.h"
index d58cf344718304d834ec0d3744d70f38f83f7b63..04c2d914b019923b6feb23bb28069d55f07bedf4 100644 (file)
@@ -1237,6 +1237,12 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
            case STT_TLS:
              sym->symbol.flags |= BSF_THREAD_LOCAL;
              break;
+           case STT_RELC:
+             sym->symbol.flags |= BSF_RELC;
+             break;
+           case STT_SRELC:
+             sym->symbol.flags |= BSF_SRELC;
+             break;
            }
 
          if (dynamic)
index 77aae5e49322c9f0ddcd36e9b9dccef5d83dd8a1..4da5d792b73caa6e550286d89ce94f08e4cf36f0 100644 (file)
@@ -6348,6 +6348,716 @@ struct elf_outext_info
   struct elf_final_link_info *finfo;
 };
 
+
+/* Support for evaluating a complex relocation.
+
+   Complex relocations are generalized, self-describing relocations.  The
+   implementation of them consists of two parts: complex symbols, and the
+   relocations themselves. 
+
+   The relocations are use a reserved elf-wide relocation type code (R_RELC
+   external / BFD_RELOC_RELC internal) and an encoding of relocation field
+   information (start bit, end bit, word width, etc) into the addend.  This
+   information is extracted from CGEN-generated operand tables within gas.
+
+   Complex symbols are mangled symbols (BSF_RELC external / STT_RELC
+   internal) representing prefix-notation expressions, including but not
+   limited to those sorts of expressions normally encoded as addends in the
+   addend field.  The symbol mangling format is:
+
+   <node> := <literal>
+          |  <unary-operator> ':' <node>
+          |  <binary-operator> ':' <node> ':' <node>
+         ;
+
+   <literal> := 's' <digits=N> ':' <N character symbol name>
+             |  'S' <digits=N> ':' <N character section name>
+            |  '#' <hexdigits>
+            ;
+
+   <binary-operator> := as in C
+   <unary-operator> := as in C, plus "0-" for unambiguous negation.  */
+
+static void
+set_symbol_value (bfd *                         bfd_with_globals,
+                 struct elf_final_link_info *  finfo,    
+                 int                           symidx,
+                 bfd_vma                       val)
+{
+  bfd_boolean                    is_local;
+  Elf_Internal_Sym *             sym;
+  struct elf_link_hash_entry **  sym_hashes;
+  struct elf_link_hash_entry *   h;
+
+  sym_hashes = elf_sym_hashes (bfd_with_globals);
+  sym = finfo->internal_syms + symidx;  
+  is_local = ELF_ST_BIND(sym->st_info) == STB_LOCAL;
+  
+  if (is_local)
+    {
+      /* It is a local symbol: move it to the
+        "absolute" section and give it a value.  */
+      sym->st_shndx = SHN_ABS;
+      sym->st_value = val;
+    }
+  else 
+    {
+      /* It is a global symbol: set its link type
+        to "defined" and give it a value.  */
+      h = sym_hashes [symidx];   
+      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;
+      h->root.type = bfd_link_hash_defined;
+      h->root.u.def.value = val;
+      h->root.u.def.section = bfd_abs_section_ptr;
+    }
+}
+
+static bfd_boolean 
+resolve_symbol (const char *                  name,
+               bfd *                         input_bfd,
+               struct elf_final_link_info *  finfo,
+               bfd_vma *                     result,
+               size_t                        locsymcount)
+{
+  Elf_Internal_Sym *            sym;
+  struct bfd_link_hash_entry *  global_entry;
+  const char *                  candidate = NULL;
+  Elf_Internal_Shdr *           symtab_hdr;
+  asection *                    sec = NULL;
+  size_t                        i;
+  
+  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+
+  for (i = 0; i < locsymcount; ++ i)
+    {
+      sym = finfo->internal_syms + i;
+      sec = finfo->sections [i];
+
+      if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+       continue;
+
+      candidate = bfd_elf_string_from_elf_section (input_bfd,
+                                                  symtab_hdr->sh_link,
+                                                  sym->st_name);
+#ifdef DEBUG
+      printf ("Comparing string: '%s' vs. '%s' = 0x%x\n", 
+             name, candidate, (unsigned int)sym->st_value);
+#endif
+      if (candidate && strcmp (candidate, name) == 0)
+       {
+         * result = sym->st_value;
+
+         if (sym->st_shndx > SHN_UNDEF && 
+             sym->st_shndx < SHN_LORESERVE)
+           {
+#ifdef DEBUG
+             printf ("adjusting for sec '%s' @ 0x%x + 0x%x\n",
+                     sec->output_section->name, 
+                     (unsigned int)sec->output_section->vma, 
+                     (unsigned int)sec->output_offset);
+#endif
+             * result += sec->output_offset + sec->output_section->vma;
+           }
+#ifdef DEBUG
+         printf ("Found symbol with effective value %8.8x\n", (unsigned int)* result);
+#endif
+         return TRUE;
+       }
+    }
+
+  /* Hmm, haven't found it yet. perhaps it is a global.  */
+  global_entry = bfd_link_hash_lookup (finfo->info->hash, name, FALSE, FALSE, TRUE);
+  if (!global_entry)
+    return FALSE;
+  
+  if (global_entry->type == bfd_link_hash_defined
+      || global_entry->type == bfd_link_hash_defweak)
+    {
+      * result = global_entry->u.def.value 
+       + global_entry->u.def.section->output_section->vma 
+       + global_entry->u.def.section->output_offset;
+#ifdef DEBUG
+      printf ("Found GLOBAL symbol '%s' with value %8.8x\n",
+             global_entry->root.string, (unsigned int)*result);
+#endif
+      return TRUE;
+    } 
+
+  if (global_entry->type == bfd_link_hash_common)
+    {
+      *result = global_entry->u.def.value +
+       bfd_com_section_ptr->output_section->vma +
+       bfd_com_section_ptr->output_offset;
+#ifdef DEBUG
+      printf ("Found COMMON symbol '%s' with value %8.8x\n",
+             global_entry->root.string, (unsigned int)*result);
+#endif
+      return TRUE;
+    }
+  
+  return FALSE;
+}
+
+static bfd_boolean
+resolve_section (const char *  name,
+                asection *    sections,
+                bfd_vma *     result)
+{
+  asection *    curr;
+  unsigned int  len;
+
+  for (curr = sections; curr; curr = curr->next)    
+    if (strcmp (curr->name, name) == 0)
+      {
+       *result = curr->vma;
+       return TRUE;
+      }
+
+  /* Hmm. still haven't found it. try pseudo-section names.  */
+  for (curr = sections; curr; curr = curr->next)    
+    {
+      len = strlen (curr->name);
+      if (len > strlen (name)) 
+       continue;
+
+      if (strncmp (curr->name, name, len) == 0)
+       {
+         if (strncmp (".end", name + len, 4) == 0)
+           {
+             *result = curr->vma + curr->size;
+             return TRUE;
+           }
+
+         /* Insert more pseudo-section names here, if you like.  */
+       }
+    }
+  
+  return FALSE;
+}
+
+static void
+undefined_reference (const char *  reftype,
+                    const char *  name)
+{
+  _bfd_error_handler (_("undefined %s reference in complex symbol: %s"), reftype, name);
+}
+
+static bfd_boolean
+eval_symbol (bfd_vma *                     result,
+            char *                        sym,
+            char **                       advanced,
+            bfd *                         input_bfd,
+            struct elf_final_link_info *  finfo,
+            bfd_vma                       addr,
+            bfd_vma                       section_offset,
+            size_t                        locsymcount,
+            int                           signed_p)
+{
+  int           len;
+  int           symlen;
+  bfd_vma       a;
+  bfd_vma       b;
+  const int     bufsz = 4096;
+  char          symbuf [bufsz];
+  const char *  symend;
+  bfd_boolean   symbol_is_section = FALSE;
+
+  len = strlen (sym);
+  symend = sym + len;
+
+  if (len < 1 || len > bufsz)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return FALSE;
+    }
+  
+  switch (* sym)
+    {
+    case '.':
+      * result = addr + section_offset;
+      * advanced = sym + 1;
+      return TRUE;
+
+    case '#':
+      ++ sym;
+      * result = strtoul (sym, advanced, 16);
+      return TRUE;
+
+    case 'S':
+      symbol_is_section = TRUE;
+    case 's':      
+      ++ sym;
+      symlen = strtol (sym, &sym, 10);
+      ++ sym; /* Skip the trailing ':'.  */
+
+      if ((symend < sym) || ((symlen + 1) > bufsz))
+       {
+         bfd_set_error (bfd_error_invalid_operation);
+         return FALSE;
+       }
+
+      memcpy (symbuf, sym, symlen);
+      symbuf [symlen] = '\0';
+      * advanced = sym + symlen;
+      
+      /* Is it always possible, with complex symbols, that gas "mis-guessed" 
+        the symbol as a section, or vice-versa. so we're pretty liberal in our
+        interpretation here; section means "try section first", not "must be a
+        section", and likewise with symbol.  */
+
+      if (symbol_is_section) 
+       {
+         if ((resolve_section (symbuf, finfo->output_bfd->sections, result) != TRUE)
+             && (resolve_symbol (symbuf, input_bfd, finfo, result, locsymcount) != TRUE))
+           {
+             undefined_reference ("section", symbuf);
+             return FALSE;
+           }
+       } 
+      else 
+       {
+         if ((resolve_symbol (symbuf, input_bfd, finfo, result, locsymcount) != TRUE)
+             && (resolve_section (symbuf, finfo->output_bfd->sections,
+                                  result) != TRUE))
+           {
+             undefined_reference ("symbol", symbuf);
+             return FALSE;
+           }
+       }
+
+      return TRUE;
+      
+      /* All that remains are operators.  */
+
+#define UNARY_OP(op)                                           \
+  if (strncmp (sym, #op, strlen (#op)) == 0)                   \
+    {                                                          \
+      sym += strlen (#op);                                     \
+      if (* sym == ':')                                                \
+        ++ sym;                                                        \
+      if (eval_symbol (& a, sym, & sym, input_bfd, finfo, addr, \
+                       section_offset, locsymcount, signed_p)   \
+                                                    != TRUE)   \
+        return FALSE;                                          \
+      if (signed_p)                                             \
+        * result = op ((signed)a);                             \
+      else                                                      \
+        * result = op a;                                        \
+      * advanced = sym;                                        \
+      return TRUE;                                             \
+    }
+
+#define BINARY_OP(op)                                          \
+  if (strncmp (sym, #op, strlen (#op)) == 0)                   \
+    {                                                          \
+      sym += strlen (#op);                                     \
+      if (* sym == ':')                                                \
+        ++ sym;                                                        \
+      if (eval_symbol (& a, sym, & sym, input_bfd, finfo, addr, \
+                       section_offset, locsymcount, signed_p)   \
+                                                     != TRUE)  \
+        return FALSE;                                          \
+      ++ sym;                                                  \
+      if (eval_symbol (& b, sym, & sym, input_bfd, finfo, addr, \
+                       section_offset, locsymcount, signed_p)   \
+                                                     != TRUE)  \
+        return FALSE;                                          \
+      if (signed_p)                                             \
+        * result = ((signed) a) op ((signed) b);               \
+      else                                                      \
+        * result = a op b;                                      \
+      * advanced = sym;                                                \
+      return TRUE;                                             \
+    }
+
+    default:
+      UNARY_OP  (0-);
+      BINARY_OP (<<);
+      BINARY_OP (>>);
+      BINARY_OP (==);
+      BINARY_OP (!=);
+      BINARY_OP (<=);
+      BINARY_OP (>=);
+      BINARY_OP (&&);
+      BINARY_OP (||);
+      UNARY_OP  (~);
+      UNARY_OP  (!);
+      BINARY_OP (*);
+      BINARY_OP (/);
+      BINARY_OP (%);
+      BINARY_OP (^);
+      BINARY_OP (|);
+      BINARY_OP (&);
+      BINARY_OP (+);
+      BINARY_OP (-);
+      BINARY_OP (<);
+      BINARY_OP (>);
+#undef UNARY_OP
+#undef BINARY_OP
+      _bfd_error_handler (_("unknown operator '%c' in complex symbol"), * sym);
+      bfd_set_error (bfd_error_invalid_operation);
+      return FALSE;
+    }
+}
+
+/* Entry point to evaluator, called from elf_link_input_bfd.  */
+
+static bfd_boolean
+evaluate_complex_relocation_symbols (bfd * input_bfd,
+                                    struct elf_final_link_info * finfo,
+                                    size_t locsymcount)
+{
+  const struct elf_backend_data * bed;
+  Elf_Internal_Shdr *             symtab_hdr;
+  struct elf_link_hash_entry **   sym_hashes;
+  asection *                      reloc_sec;
+  bfd_boolean                     result = TRUE;
+
+  /* For each section, we're going to check and see if it has any
+     complex relocations, and we're going to evaluate any of them
+     we can.  */
+
+  if (finfo->info->relocatable)
+    return TRUE;
+
+  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+  bed = get_elf_backend_data (input_bfd);
+
+  for (reloc_sec = input_bfd->sections; reloc_sec; reloc_sec = reloc_sec->next)
+    {
+      Elf_Internal_Rela * internal_relocs;
+      unsigned long i;
+
+      /* This section was omitted from the link.  */
+      if (! reloc_sec->linker_mark)
+       continue;
+
+      /* Only process sections containing relocs.  */
+      if ((reloc_sec->flags & SEC_RELOC) == 0)
+       continue;
+
+      if (reloc_sec->reloc_count == 0)
+       continue;
+
+      /* Read in the relocs for this section.  */
+      internal_relocs
+       = _bfd_elf_link_read_relocs (input_bfd, reloc_sec, NULL,
+                                    (Elf_Internal_Rela *) NULL,
+                                    FALSE);
+      if (internal_relocs == NULL)
+       continue;
+
+      for (i = reloc_sec->reloc_count; i--;)
+       {
+         Elf_Internal_Rela * rel;
+         char * sym_name;
+         unsigned long index;
+         Elf_Internal_Sym * sym;
+         bfd_vma result;
+         bfd_vma section_offset;
+         bfd_vma addr;
+         int signed_p = 0;
+
+         rel = internal_relocs + i;
+         section_offset = reloc_sec->output_section->vma
+           + reloc_sec->output_offset;
+         addr = rel->r_offset;
+
+         index = ELF32_R_SYM (rel->r_info);
+         if (bed->s->arch_size == 64)
+           index >>= 24;
+         if (index < locsymcount)
+           {
+             /* The symbol is local.  */
+             sym = finfo->internal_syms + index;
+
+             /* We're only processing STT_RELC or STT_SRELC type symbols.  */
+             if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
+                 (ELF_ST_TYPE (sym->st_info) != STT_SRELC))
+               continue;
+
+             sym_name = bfd_elf_string_from_elf_section
+               (input_bfd, symtab_hdr->sh_link, sym->st_name);
+
+             signed_p = (ELF_ST_TYPE (sym->st_info) == STT_SRELC);
+           }
+         else
+           {
+             /* The symbol is global.  */
+             struct elf_link_hash_entry * h;
+
+             if (elf_bad_symtab (input_bfd))
+               continue;
+
+             h = sym_hashes [index - locsymcount];
+             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->type != STT_RELC && h->type != STT_SRELC)
+               continue;
+
+             signed_p = (h->type == STT_SRELC);
+             sym_name = (char *) h->root.root.string;
+           }
+#ifdef DEBUG
+         printf ("Encountered a complex symbol!");
+         printf (" (input_bfd %s, section %s, reloc %ld\n",
+                 input_bfd->filename, reloc_sec->name, i);
+         printf (" symbol: idx  %8.8lx, name %s\n",
+                 index, sym_name);
+         printf (" reloc : info %8.8lx, addr %8.8lx\n",
+                 rel->r_info, addr);
+         printf (" Evaluating '%s' ...\n ", sym_name);
+#endif
+         if (eval_symbol (& result, sym_name, & sym_name, input_bfd, 
+                          finfo, addr, section_offset, locsymcount,
+                          signed_p))
+           /* Symbol evaluated OK.  Update to absolute value.  */
+           set_symbol_value (input_bfd, finfo, index, result);
+
+         else
+           result = FALSE;
+       }
+
+      if (internal_relocs != elf_section_data (reloc_sec)->relocs)
+       free (internal_relocs);
+    }
+
+  /* If nothing went wrong, then we adjusted 
+     everything we wanted to adjust.  */
+  return result;
+}
+
+static void
+put_value (bfd_vma        size,
+          unsigned long  chunksz,
+          bfd *          input_bfd,
+          bfd_vma        x,
+          bfd_byte *     location)
+{
+  location += (size - chunksz);
+
+  for (; size; size -= chunksz, location -= chunksz, x >>= (chunksz * 8)) 
+    {
+      switch (chunksz)
+       {
+       default:
+       case 0:
+         abort ();
+       case 1:
+         bfd_put_8 (input_bfd, x, location);
+         break;
+       case 2:
+         bfd_put_16 (input_bfd, x, location);
+         break;
+       case 4:
+         bfd_put_32 (input_bfd, x, location);
+         break;
+       case 8:
+#ifdef BFD64
+         bfd_put_64 (input_bfd, x, location);
+#else
+         abort ();
+#endif
+         break;
+       }
+    }
+}
+
+static bfd_vma 
+get_value (bfd_vma        size,
+          unsigned long  chunksz,
+          bfd *          input_bfd,
+          bfd_byte *     location)
+{
+  bfd_vma x = 0;
+
+  for (; size; size -= chunksz, location += chunksz) 
+    {
+      switch (chunksz)
+       {
+       default:
+       case 0:
+         abort ();
+       case 1:
+         x = (x << (8 * chunksz)) | bfd_get_8 (input_bfd, location);
+         break;
+       case 2:
+         x = (x << (8 * chunksz)) | bfd_get_16 (input_bfd, location);
+         break;
+       case 4:
+         x = (x << (8 * chunksz)) | bfd_get_32 (input_bfd, location);
+         break;
+       case 8:
+#ifdef BFD64
+         x = (x << (8 * chunksz)) | bfd_get_64 (input_bfd, location);
+#else
+         abort ();
+#endif
+         break;
+       }
+    }
+  return x;
+}
+
+static void 
+decode_complex_addend
+    (unsigned long * start,   /* in bits */
+     unsigned long * oplen,   /* in bits */
+     unsigned long * len,     /* in bits */
+     unsigned long * wordsz,  /* in bytes */
+     unsigned long * chunksz,  /* in bytes */
+     unsigned long * lsb0_p,
+     unsigned long * signed_p,
+     unsigned long * trunc_p,
+     unsigned long encoded)
+{
+  * start     =  encoded        & 0x3F;
+  * len       = (encoded >>  6) & 0x3F;
+  * oplen     = (encoded >> 12) & 0x3F;
+  * wordsz    = (encoded >> 18) & 0xF;
+  * chunksz   = (encoded >> 22) & 0xF;
+  * lsb0_p    = (encoded >> 27) & 1;
+  * signed_p  = (encoded >> 28) & 1;
+  * trunc_p   = (encoded >> 29) & 1;
+}
+
+void
+bfd_elf_perform_complex_relocation
+    (bfd *                   output_bfd ATTRIBUTE_UNUSED,
+     struct bfd_link_info *  info,
+     bfd *                   input_bfd,
+     asection *              input_section,
+     bfd_byte *              contents,
+     Elf_Internal_Rela *     rel,
+     Elf_Internal_Sym *      local_syms,
+     asection **             local_sections)
+{
+  const struct elf_backend_data * bed;
+  Elf_Internal_Shdr * symtab_hdr;
+  asection * sec;
+  bfd_vma relocation = 0, shift, x;
+  unsigned long r_symndx;
+  bfd_vma mask;
+  unsigned long start, oplen, len, wordsz, 
+    chunksz, lsb0_p, signed_p, trunc_p;
+
+  /*  Perform this reloc, since it is complex.
+      (this is not to say that it necessarily refers to a complex
+      symbol; merely that it is a self-describing CGEN based reloc.
+      i.e. the addend has the complete reloc information (bit start, end,
+      word size, etc) encoded within it.).  */ 
+  r_symndx = ELF32_R_SYM (rel->r_info);
+  bed = get_elf_backend_data (input_bfd);
+  if (bed->s->arch_size == 64)
+    r_symndx >>= 24;
+
+#ifdef DEBUG
+  printf ("Performing complex relocation %ld...\n", r_symndx);
+#endif
+
+  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+  if (r_symndx < symtab_hdr->sh_info)
+    {
+      /* The symbol is local.  */
+      Elf_Internal_Sym * sym;
+
+      sym = local_syms + r_symndx;
+      sec = local_sections [r_symndx];
+      relocation = sym->st_value;
+      if (sym->st_shndx > SHN_UNDEF && 
+         sym->st_shndx < SHN_LORESERVE)
+       relocation += (sec->output_offset +
+                      sec->output_section->vma);
+    }
+  else
+    {
+      /* The symbol is global.  */
+      struct elf_link_hash_entry **sym_hashes;
+      struct elf_link_hash_entry * h;
+
+      sym_hashes = elf_sym_hashes (input_bfd);
+      h = sym_hashes [r_symndx];
+
+      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;
+
+         if (! bfd_is_abs_section (sec))
+           relocation += (sec->output_section->vma 
+                          + sec->output_offset); 
+       }
+      if (h->root.type == bfd_link_hash_undefined
+         && !((*info->callbacks->undefined_symbol)
+              (info, h->root.root.string, input_bfd,
+               input_section, rel->r_offset,
+               info->unresolved_syms_in_objects == RM_GENERATE_ERROR
+               || ELF_ST_VISIBILITY (h->other))))
+       return;
+    }
+
+  decode_complex_addend (& start, & oplen, & len, & wordsz, 
+                        & chunksz, & lsb0_p, & signed_p, 
+                        & trunc_p, rel->r_addend);
+
+  mask = (((1L << (len - 1)) - 1) << 1) | 1;
+
+  if (lsb0_p)
+    shift = (start + 1) - len;
+  else
+    shift = (8 * wordsz) - (start + len);
+
+  x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);          
+
+#ifdef DEBUG
+  printf ("Doing complex reloc: "
+         "lsb0? %ld, signed? %ld, trunc? %ld, wordsz %ld, "
+         "chunksz %ld, start %ld, len %ld, oplen %ld\n"
+         "    dest: %8.8lx, mask: %8.8lx, reloc: %8.8lx\n",
+         lsb0_p, signed_p, trunc_p, wordsz, chunksz, start, len,
+         oplen, x, mask,  relocation);
+#endif
+
+  if (! trunc_p)
+    {
+      /* Now do an overflow check.  */
+      if (bfd_check_overflow ((signed_p ? 
+                              complain_overflow_signed : 
+                              complain_overflow_unsigned),
+                             len, 0, (8 * wordsz), 
+                             relocation) == bfd_reloc_overflow)
+       (*_bfd_error_handler) 
+         ("%s (%s + 0x%lx): relocation overflow: 0x%lx %sdoes not fit "
+          "within 0x%lx", 
+          input_bfd->filename, input_section->name, rel->r_offset,
+          relocation, (signed_p ? "(signed) " : ""), mask);
+    }
+         
+  /* Do the deed.  */
+  x = (x & ~(mask << shift)) | ((relocation & mask) << shift);
+
+#ifdef DEBUG
+  printf ("           relocation: %8.8lx\n"
+         "         shifted mask: %8.8lx\n"
+         " shifted/masked reloc: %8.8lx\n"
+         "               result: %8.8lx\n",
+         relocation, (mask << shift), 
+         ((relocation & mask) << shift), x);
+#endif
+  put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
+}
+
 /* When performing a relocatable link, the input relocations are
    preserved.  But, if they reference global symbols, the indices
    referenced must be updated.  Update all the relocations in
@@ -7509,6 +8219,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
        return FALSE;
     }
 
+  if (! evaluate_complex_relocation_symbols (input_bfd, finfo, locsymcount))
+    return FALSE;
+
   /* Relocate the contents of each section.  */
   sym_hashes = elf_sym_hashes (input_bfd);
   for (o = input_bfd->sections; o != NULL; o = o->next)
index 8c552643fb089a6517a52ed2bfb63e92114726f3..c564e30431a9792731c2010ab736d32b9ab53e52 100644 (file)
@@ -1529,6 +1529,27 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_MCORE_PCREL_32",
   "BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2",
   "BFD_RELOC_MCORE_RVA",
+  "BFD_RELOC_MEP_8",
+  "BFD_RELOC_MEP_16",
+  "BFD_RELOC_MEP_32",
+  "BFD_RELOC_MEP_PCREL8A2",
+  "BFD_RELOC_MEP_PCREL12A2",
+  "BFD_RELOC_MEP_PCREL17A2",
+  "BFD_RELOC_MEP_PCREL24A2",
+  "BFD_RELOC_MEP_PCABS24A2",
+  "BFD_RELOC_MEP_LOW16",
+  "BFD_RELOC_MEP_HI16U",
+  "BFD_RELOC_MEP_HI16S",
+  "BFD_RELOC_MEP_GPREL",
+  "BFD_RELOC_MEP_TPREL",
+  "BFD_RELOC_MEP_TPREL7",
+  "BFD_RELOC_MEP_TPREL7A2",
+  "BFD_RELOC_MEP_TPREL7A4",
+  "BFD_RELOC_MEP_UIMM24",
+  "BFD_RELOC_MEP_ADDR24A4",
+  "BFD_RELOC_MEP_GNU_VTINHERIT",
+  "BFD_RELOC_MEP_GNU_VTENTRY",
+
   "BFD_RELOC_MMIX_GETA",
   "BFD_RELOC_MMIX_GETA_1",
   "BFD_RELOC_MMIX_GETA_2",
@@ -1865,6 +1886,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_XSTORMY16_12",
   "BFD_RELOC_XSTORMY16_24",
   "BFD_RELOC_XSTORMY16_FPTR16",
+  "BFD_RELOC_RELC",
+
   "BFD_RELOC_XC16X_PAG",
   "BFD_RELOC_XC16X_POF",
   "BFD_RELOC_XC16X_SEG",
diff --git a/bfd/mep-relocs.pl b/bfd/mep-relocs.pl
new file mode 100755 (executable)
index 0000000..d227b82
--- /dev/null
@@ -0,0 +1,274 @@
+#!/usr/bin/perl
+# -*- perl -*-
+#
+# Toshiba MeP Media Engine Relocation Generator
+# Copyright (C) 2001, 2007 Free Software Foundation, Inc.
+# This file is part of BFD.
+# Originally written by DJ Delorie <dj@redhat.com>
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+
+# Usage: Run this anywhere inside your source tree.  It will read
+# include/elf/mep.h and scan the comments therein.  It will renumber
+# the relocs to be sequential (this is needed so that bfd/elf32-mep.h
+# works) if needed.  It will then update the reloc list in bfd/reloc.c
+# and the howto, mapping, and apply routines in bfd/elf32-mep.c.  You
+# can then regenerate bfd-in2.h and check everything in.
+
+# FIXME: After the relocation list is finalized, change this to
+# *verify* the reloc list, rather than resequence it.
+
+while (! -f "include/elf/mep.h" && ! -f "bfd/reloc.c") {
+    chdir "..";
+    $pwd = `pwd`;
+    if ($pwd !~ m@/.*/@) {
+       print STDERR "Cannot find include/elf/mep.h or bfd/reloc.h\n";
+       exit 1;
+    }
+}
+$pwd = `pwd`;
+print "srctop is $pwd";
+
+printf "Reading include/elf/mep.h ...\n";
+open(MEPH, "include/elf/mep.h");
+open(MEPHO, "> include/elf/mep.h.new") || die("mep.h.new create: $!");
+$val = 0;
+while (<MEPH>) {
+    if (($pre,$rel,$rest) = /(.*RELOC_NUMBER \()([^,]+), *\d+(.*)/) {
+       $rest =~ s/[\r\n]+$//;
+       print (MEPHO "$pre$rel, $val$rest\n") || die("mep.h.new write: $!");
+       $val ++;
+       $rel =~ s/R_MEP_//;
+       push(@relocs, $rel);
+
+       $rest =~ s@.*/\* @@;
+       ($pattern, $sign, $attrs) = $rest =~ m@(.*) ([US]) (.*)\*/@;
+       $pattern =~ s/ //g;
+       push(@pattern, $pattern);
+       push(@sign, $sign);
+       push(@attrs, $attrs);
+
+       printf "%4d $rel p=`$pattern' s=`$sign' a=`$attrs'\n", $#pattern;
+
+    } else {
+       print(MEPHO) || die("mep.h.new write: $!");
+    }
+}
+close(MEPH);
+close(MEPHO) || die("mep.h.new close: $!");
+
+&swapfile("include/elf/mep.h");
+
+redo_file ("bfd/reloc.c",
+          "",
+          "ENUMDOC\n  Toshiba Media Processor Relocations.\n\nCOMMENT\n",
+          "ENUM\n  BFD_RELOC_MEP_%s\n",
+          "");
+
+$autogen = "    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */\n";
+
+redo_file ("bfd/elf32-mep.c",
+          "MEPRELOC:HOWTO",
+          $autogen,
+          "MEPRELOC:END",
+          "",
+          "&emit_howto();",
+          "MEPRELOC:MAP",
+          $autogen,
+          "MEPRELOC:END",
+          "",
+          "    MAP(%s);\n",
+          "MEPRELOC:APPLY",
+          $autogen,
+          "MEPRELOC:END",
+          "",
+          "&emit_apply();",
+          );
+
+sub mask2shifts {
+    my ($mask) = @_;
+    my ($bits, $left, $right, $ci, $c, $cv);
+    $bits = 0;
+    $left = 0;
+    $right = 32;
+    for ($ci=0; $ci<length($mask); $ci++) {
+       $c = substr($mask, $ci, 1);
+       $left++;
+       next if $c eq '-';
+       $left = 0;
+       $cv = ord($c) - ord('0');
+       $cv -= ord('a') - ord('9') - 1 if $cv > 9;
+       $right = $cv unless $right < $cv;
+       $bits = $cv+1 unless $bits > $cv+1;
+    }
+    $mask =~ tr/-/1/c;
+    $mask =~ tr/-/0/;
+    ($rmask = $mask) =~ tr/01/10/;
+    $mask = unpack("H*", pack("B*", $mask));
+    $rmask = unpack("H*", pack("B*", $rmask));
+    return ($bits, $left, $right, $mask, $rmask);
+}
+
+sub emit_howto {
+    for ($i=2; $i<=$#relocs; $i++) {
+       $mask = $pattern[$i];
+
+       if (length($mask) == 8)     { $bytesize = 0; }
+       elsif (length($mask) == 16) { $bytesize = 1; }
+       elsif (length($mask) == 32) { $bytesize = 2; }
+
+       ($bits, $left, $right, $mask) = mask2shifts ($mask);
+       $bits[$i] = $bits;
+       $pcrel = 0;
+       $pcrel = 1 if $attrs[$i] =~ /pc-rel/i;
+       $overflow = $sign[$i];
+       $overflow = 'N' if $attrs[$i] =~ /no-overflow/;
+
+       $c = "$relocs[$i],";
+       printf(NEW "  MEPREL (R_MEP_%-10s%d,%3d,%2d,%2d,%2d,%2s, 0x%s),\n",
+              $c, $bytesize, $bits, $left, $right, $pcrel, $overflow, $mask);
+    }
+}
+
+sub emit_apply {
+    for ($i=2; $i<=$#relocs; $i++) {
+       $v = "u";
+       $v = "s" if $sign[$i] =~ /S/;
+       if (length($pattern[$i]) == 8) {
+           $e = ''; # no endian swap for bytes
+       } elsif ($pattern[$i] =~ /-/ || length($pattern[$i]) == 16) {
+           $e = '^e2'; # endian swap - 2byte words only
+       } else {
+           $e = '^e4' # endian swap for data
+       }
+       print NEW "    case R_MEP_$relocs[$i]: /* $pattern[$i] */\n";
+       if ($attrs[$i] =~ /tp-rel/i) {
+           print NEW "      $v -= mep_tpoff_base(rel->r_offset);\n";
+       }
+       if ($attrs[$i] =~ /gp-rel/i) {
+           print NEW "      $v -= mep_sdaoff_base(rel->r_offset);\n";
+       }
+       if ($attrs[$i] !~ /no-overflow/ && $bits[$i] < 32) {
+           if ($v eq "u") {
+               $max = (1 << $bits[$i]) - 1;
+               print NEW "      if (u > $max) r = bfd_reloc_overflow;\n";
+           } else {
+               $min = -(1 << ($bits[$i]-1));
+               $max = (1 << ($bits[$i]-1)) - 1;
+               print NEW "      if ($min > s || s > $max) r = bfd_reloc_overflow;\n";
+           }
+       }
+       for ($b=0; $b<length($pattern[$i]); $b += 8) {
+           $mask = substr($pattern[$i], $b, 8);
+           ($bits, $left, $right, $mask, $rmask) = mask2shifts ($mask);
+           if ($left > $right) { $left -= $right; $right = 0; }
+           else { $right -= $left; $left = 0; }
+
+           if ($mask ne "00") {
+               $bb = $b / 8;
+               print NEW "      byte[$bb$e] = ";
+               print NEW "(byte[$bb$e] & 0x$rmask) | " if $rmask ne "00";
+               if ($left) {
+                   print NEW "(($v << $left) & 0x$mask)";
+               } elsif ($right) {
+                   print NEW "(($v >> $right) & 0x$mask)";
+               } else {
+                   print NEW "($v & 0x$mask)";
+               }
+               print NEW ";\n";
+           }
+       }
+       print NEW "      break;\n";
+    }
+}
+
+
+#-----------------------------------------------------------------------------
+
+sub redo_file {
+    my ($file, @control) = @_;
+    open(OLD, $file);
+    open(NEW, "> $file.new") || die("$file.new create: $!");
+
+    print "Scanning file $file ...\n";
+
+    while (1) {
+       $start = shift @control;
+       $prefix = shift @control;
+       $end = shift @control;
+       $suffix = shift @control;
+       $pattern = shift @control;
+
+       if (!$start) {
+           print NEW while <OLD>;
+           last;
+       }
+
+       print "  looking for $start\n";
+       while (<OLD>) {
+           print NEW;
+           last if /\Q$start\E/;
+       }
+       print "can't find $start\n" unless $_;
+       last unless $_;
+
+       print NEW $prefix;
+       if ($pattern =~ /^\&/) {
+           eval $pattern;
+           die("$pattern: $@") if $@;
+       } else {
+           for $i (2..$#relocs) {
+               printf (NEW "$pattern", $relocs[$i]) || die("$file.new write: $!");
+               $pattern =~ s/^ENUM\n/ENUMX\n/;
+           }
+       }
+       print NEW $suffix;
+       while (<OLD>) {
+           last if /\Q$end\E/;
+       }
+       print NEW;
+    }
+
+    close(OLD);
+    close(NEW) || die("$file.new close: $!");
+    &swapfile($file);
+}
+
+#-----------------------------------------------------------------------------
+
+sub swapfile {
+    my ($f) = @_;
+    if ( ! -f "$f.save") {
+       system "cp $f $f.save";
+    }
+    open(ORIG, $f);
+    open(NEW, "$f.new");
+    while (<ORIG>) {
+       $n = <NEW>;
+       if ($n ne $_) {
+           close(ORIG);
+           close(NEW);
+           print "  Updating $f\n";
+           rename "$f", "$f.old";
+           rename "$f.new", "$f";
+           return;
+       }
+    }
+    close(ORIG);
+    close(NEW);
+    print "  No change to $f\n";
+    unlink "$f.new";
+}
index 1b8c8d75e762bfc6927e207c44cc757fc806e4eb..f81a3bffe52a15b15a2c4c8fcf57b32b6b1cfa96 100644 (file)
@@ -3700,6 +3700,50 @@ ENUMX
 ENUMDOC
   Motorola Mcore relocations.
 
+ENUM
+  BFD_RELOC_MEP_8
+ENUMX
+  BFD_RELOC_MEP_16
+ENUMX
+  BFD_RELOC_MEP_32
+ENUMX
+  BFD_RELOC_MEP_PCREL8A2
+ENUMX
+  BFD_RELOC_MEP_PCREL12A2
+ENUMX
+  BFD_RELOC_MEP_PCREL17A2
+ENUMX
+  BFD_RELOC_MEP_PCREL24A2
+ENUMX
+  BFD_RELOC_MEP_PCABS24A2
+ENUMX
+  BFD_RELOC_MEP_LOW16
+ENUMX
+  BFD_RELOC_MEP_HI16U
+ENUMX
+  BFD_RELOC_MEP_HI16S
+ENUMX
+  BFD_RELOC_MEP_GPREL
+ENUMX
+  BFD_RELOC_MEP_TPREL
+ENUMX
+  BFD_RELOC_MEP_TPREL7
+ENUMX
+  BFD_RELOC_MEP_TPREL7A2
+ENUMX
+  BFD_RELOC_MEP_TPREL7A4
+ENUMX
+  BFD_RELOC_MEP_UIMM24
+ENUMX
+  BFD_RELOC_MEP_ADDR24A4
+ENUMX
+  BFD_RELOC_MEP_GNU_VTINHERIT
+ENUMX
+  BFD_RELOC_MEP_GNU_VTENTRY
+ENUMDOC
+  Toshiba Media Processor Relocations.
+COMMENT
+
 ENUM
   BFD_RELOC_MMIX_GETA
 ENUMX
@@ -4670,6 +4714,12 @@ ENUMX
 ENUMDOC
   Sony Xstormy16 Relocations.
 
+ENUM
+  BFD_RELOC_RELC
+ENUMDOC
+  Self-describing complex relocations.
+COMMENT
+
 ENUM
   BFD_RELOC_XC16X_PAG
 ENUMX
index 0ff94164ed5e28dfb78a7049980d30e9c55ca096..17c4ce80400e51f48d2d28473af35113c3023ae3 100644 (file)
@@ -288,6 +288,14 @@ CODE_FRAGMENT
 .  {* This symbol is thread local.  Used in ELF.  *}
 .#define BSF_THREAD_LOCAL  0x40000
 .
+.  {* This symbol represents a complex relocation expression,
+.     with the expression tree serialized in the symbol name.  *}
+.#define BSF_RELC 0x80000
+.
+.  {* This symbol represents a signed complex relocation expression,
+.     with the expression tree serialized in the symbol name.  *}
+.#define BSF_SRELC 0x100000
+.
 .  flagword flags;
 .
 .  {* A pointer to the section to which this symbol is
index 71e3337f4a28a7cde72e3f9df0adfc40535c2c9f..ae4d4bf45163799f23d2ef81954acc6f93a91f5f 100644 (file)
@@ -411,6 +411,7 @@ BFD_JUMP_TABLE macros.
 .  reloc_howto_type *
 .              (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type);
 .
+.
 .  {* Routines used when writing an object file.  *}
 .#define BFD_JUMP_TABLE_WRITE(NAME) \
 .  NAME##_set_arch_mach, \
@@ -609,6 +610,8 @@ extern const bfd_target bfd_elf32_m68k_vec;
 extern const bfd_target bfd_elf32_m88k_vec;
 extern const bfd_target bfd_elf32_mcore_big_vec;
 extern const bfd_target bfd_elf32_mcore_little_vec;
+extern const bfd_target bfd_elf32_mep_vec;
+extern const bfd_target bfd_elf32_mep_little_vec;
 extern const bfd_target bfd_elf32_mn10200_vec;
 extern const bfd_target bfd_elf32_mn10300_vec;
 extern const bfd_target bfd_elf32_mt_vec;
@@ -934,6 +937,7 @@ static const bfd_target * const _bfd_target_vector[] =
        &bfd_elf32_m88k_vec,
        &bfd_elf32_mcore_big_vec,
        &bfd_elf32_mcore_little_vec,
+       &bfd_elf32_mep_vec,
        &bfd_elf32_mn10200_vec,
        &bfd_elf32_mn10300_vec,
        &bfd_elf32_mt_vec,