diff options
-rw-r--r-- | bfd/ChangeLog | 51 | ||||
-rw-r--r-- | bfd/archures.c | 3 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 8 | ||||
-rw-r--r-- | bfd/config.bfd | 3 | ||||
-rw-r--r-- | bfd/cpu-cris.c | 66 | ||||
-rw-r--r-- | bfd/elf32-cris.c | 454 | ||||
-rw-r--r-- | bfd/libbfd.h | 5 | ||||
-rw-r--r-- | bfd/reloc.c | 10 |
8 files changed, 531 insertions, 69 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e2e79d0..444f905 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,54 @@ +2004-11-04 Hans-Peter Nilsson <hp@axis.com> + + * config.bfd: Support crisv32-*-* like cris-*-*. + * archures.c (bfd_mach_cris_v0_v10, bfd_mach_cris_v32) + (bfd_mach_cris_v10_v32): New macros. + * cpu-cris.c: Tweak formatting. + (get_compatible): New function. + (N): New macro. + (bfd_cris_arch_compat_v10_v32, bfd_cris_arch_v32): New + bfd_arch_info_type:s. + (bfd_cris_arch): Use bfd_mach_cris_v0_v10 for member mach, + get_compatible for member compatible and link bfd_cris_arch_v32 as + next. + * elf32-cris.c (cris_elf_pcrel_reloc) + (cris_elf_set_mach_from_flags): New functions. + (cris_elf_howto_table) <R_CRIS_8_PCREL, R_CRIS_16_PCREL> + <R_CRIS_32_PCREL>: Use cris_elf_pcrel_reloc. + (cris_elf_grok_prstatus, cris_elf_grok_psinfo): Give correct + numbers for bfd_mach_cris_v32. + (PLT_ENTRY_SIZE_V32): New macro. + (elf_cris_plt0_entry): Drop last comma in initializer. + (elf_cris_plt0_entry_v32, elf_cris_plt_entry_v32) + (elf_cris_pic_plt0_entry_v32, elf_cris_pic_plt_entry_v32): New + PLT initializers. + (cris_elf_relocate_section): Change all "%B(%A)" messages to + "%B, section %A". + (elf_cris_finish_dynamic_symbol): Do V32-specific PLT entries. + (elf_cris_finish_dynamic_sections): Similar. + (elf_cris_adjust_dynamic_symbol): Similar. + (cris_elf_check_relocs): Change all "%B(%A)" messages to "%B, + section %A". + <switch with PIC relocs>: Emit error and return FALSE for + bfd_mach_cris_v10_v32. + <case R_CRIS_8_PCREL, case R_CRIS_16_PCREL, case R_CRIS_32_PCREL>: + Emit warning when generating textrel reloc. + (cris_elf_object_p): Call cris_elf_set_mach_from_flags. + (cris_elf_final_write_processing): Set flags according to mach. + (cris_elf_print_private_bfd_data): Display + EF_CRIS_VARIANT_COMMON_V10_V32 and EF_CRIS_VARIANT_V32. + (cris_elf_merge_private_bfd_data): Drop variables old_flags, + new_flags. Don't call cris_elf_final_write_processing. Don't + look at the actual elf header flags at all; use + bfd_get_symbol_leading_char to check ibfd, obfd. Trap difference + in bfd_get_mach for ibfd and obfd and handle merging of compatible + objects. + (bfd_elf32_bfd_copy_private_bfd_data): Define. + * reloc.c (BFD_RELOC_CRIS_SIGNED_8, BFD_RELOC_CRIS_UNSIGNED_8) + (BFD_RELOC_CRIS_SIGNED_16, BFD_RELOC_CRIS_UNSIGNED_16) + (BFD_RELOC_CRIS_LAPCQ_OFFSET): New relocs. + * bfd-in2.h, libbfd.h: Regenerate. + 2004-11-04 Alan Modra <amodra@bigpond.net.au> * elf64-ppc.h (ppc64_elf_edit_toc): Declare. diff --git a/bfd/archures.c b/bfd/archures.c index 4904b62..c8375bb 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -323,6 +323,9 @@ DESCRIPTION . bfd_arch_crx, {* National Semiconductor CRX. *} .#define bfd_mach_crx 1 . bfd_arch_cris, {* Axis CRIS *} +.#define bfd_mach_cris_v0_v10 255 +.#define bfd_mach_cris_v32 32 +.#define bfd_mach_cris_v10_v32 1032 . bfd_arch_s390, {* IBM s390 *} .#define bfd_mach_s390_31 31 .#define bfd_mach_s390_64 64 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index a25bef3..0ee36a7 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1774,6 +1774,9 @@ enum bfd_architecture bfd_arch_crx, /* National Semiconductor CRX. */ #define bfd_mach_crx 1 bfd_arch_cris, /* Axis CRIS */ +#define bfd_mach_cris_v0_v10 255 +#define bfd_mach_cris_v32 32 +#define bfd_mach_cris_v10_v32 1032 bfd_arch_s390, /* IBM s390 */ #define bfd_mach_s390_31 31 #define bfd_mach_s390_64 64 @@ -3508,6 +3511,11 @@ This is the 5 bits of a value. */ BFD_RELOC_CRIS_UNSIGNED_5, BFD_RELOC_CRIS_SIGNED_6, BFD_RELOC_CRIS_UNSIGNED_6, + BFD_RELOC_CRIS_SIGNED_8, + BFD_RELOC_CRIS_UNSIGNED_8, + BFD_RELOC_CRIS_SIGNED_16, + BFD_RELOC_CRIS_UNSIGNED_16, + BFD_RELOC_CRIS_LAPCQ_OFFSET, BFD_RELOC_CRIS_UNSIGNED_4, /* Relocs used in ELF shared libraries for CRIS. */ diff --git a/bfd/config.bfd b/bfd/config.bfd index 2e137b2..fe668c3 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -54,6 +54,7 @@ arm*) targ_archs=bfd_arm_arch ;; c30*) targ_archs=bfd_tic30_arch ;; c4x*) targ_archs=bfd_tic4x_arch ;; c54x*) targ_archs=bfd_tic54x_arch ;; +crisv32) targ_archs=bfd_cris_arch ;; crx*) targ_archs=bfd_crx_arch ;; dlx*) targ_archs=bfd_dlx_arch ;; hppa*) targ_archs=bfd_hppa_arch ;; @@ -326,7 +327,7 @@ case "${targ}" in targ_underscore=yes ;; - cris-*-*) + cris-*-* | crisv32-*-*) targ_defvec=cris_aout_vec targ_selvecs="bfd_elf32_us_cris_vec bfd_elf32_cris_vec ieee_vec" targ_underscore=yes # Note: not true for bfd_elf32_cris_vec. diff --git a/bfd/cpu-cris.c b/bfd/cpu-cris.c index 9e60ff0..d15a275 100644 --- a/bfd/cpu-cris.c +++ b/bfd/cpu-cris.c @@ -23,8 +23,58 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sysdep.h" #include "libbfd.h" -const bfd_arch_info_type -bfd_cris_arch = +/* This routine is provided two arch_infos and returns the lowest common + denominator. CRIS v0..v10 vs. v32 are not compatible in general, but + there's a compatible subset for which we provide an arch_info. */ + +static const bfd_arch_info_type * get_compatible + PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *)); + +static const bfd_arch_info_type * +get_compatible (a,b) + const bfd_arch_info_type *a; + const bfd_arch_info_type *b; +{ + /* Arches must match. */ + if (a->arch != b->arch) + return NULL; + + /* If either is the compatible mach, return the other. */ + if (a->mach == bfd_mach_cris_v10_v32) + return b; + if (b->mach == bfd_mach_cris_v10_v32) + return a; + +#if 0 + /* See ldlang.c:lang_check. Quite illogically, incompatible arches + (as signalled by this function) are only *warned* about, while with + this function signalling compatible ones, we can have the + cris_elf_merge_private_bfd_data function return an error. This is + undoubtedly a FIXME: in general. Also, the + command_line.warn_mismatch flag and the --no-warn-mismatch option + are misnamed for the multitude of ports that signal compatibility: + it is there an error, not a warning. We work around it by + pretending matching machs here. */ + + /* Except for the compatible mach, machs must match. */ + if (a->mach != b->mach) + return NULL; +#endif + + return a; +} + +#define N(NUMBER, PRINT, NEXT) \ + { 32, 32, 8, bfd_arch_cris, NUMBER, "cris", PRINT, 1, FALSE, \ + get_compatible, bfd_default_scan, NEXT } + +static const bfd_arch_info_type bfd_cris_arch_compat_v10_v32 = + N (bfd_mach_cris_v10_v32, "cris:common_v10_v32", NULL); + +static const bfd_arch_info_type bfd_cris_arch_v32 = + N (bfd_mach_cris_v32, "crisv32", &bfd_cris_arch_compat_v10_v32); + +const bfd_arch_info_type bfd_cris_arch = { 32, /* There's 32 bits_per_word. */ 32, /* There's 32 bits_per_address. */ @@ -32,20 +82,20 @@ bfd_cris_arch = bfd_arch_cris, /* One of enum bfd_architecture, defined in archures.c and provided in generated header files. */ - 0xff, /* Only 1 machine, but #255 for - historical reasons. */ + bfd_mach_cris_v0_v10, /* Random BFD-internal number for this + machine, similarly listed in + archures.c. Not emitted in output. */ "cris", /* The arch_name. */ "cris", /* The printable name is the same. */ 1, /* Section alignment power; each section is aligned to (only) 2^1 bytes. */ - TRUE, /* This is the default "machine", since - there's only one. */ - bfd_default_compatible, /* A default function for testing + TRUE, /* This is the default "machine". */ + get_compatible, /* A function for testing "machine" compatibility of two bfd_arch_info_type. */ bfd_default_scan, /* Check if a bfd_arch_info_type is a match. */ - NULL /* Pointer to next bfd_arch_info_type in + &bfd_cris_arch_v32 /* Pointer to next bfd_arch_info_type in the same family. */ }; diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c index ad93071..d043111 100644 --- a/bfd/elf32-cris.c +++ b/bfd/elf32-cris.c @@ -33,6 +33,9 @@ static reloc_howto_type * cris_reloc_type_lookup static void cris_info_to_howto_rela PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); +static bfd_reloc_status_type cris_elf_pcrel_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); + static bfd_boolean cris_elf_grok_prstatus PARAMS ((bfd *abfd, Elf_Internal_Note *note)); @@ -59,9 +62,13 @@ static bfd_boolean cris_elf_object_p PARAMS ((bfd *)); static void cris_elf_final_write_processing PARAMS ((bfd *, bfd_boolean)); +static bfd_boolean cris_elf_set_mach_from_flags + PARAMS ((bfd *, unsigned long int)); + static bfd_boolean cris_elf_print_private_bfd_data PARAMS ((bfd *, PTR)); static bfd_boolean cris_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); +static bfd_boolean cris_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); struct elf_cris_link_hash_entry; static bfd_boolean elf_cris_discard_excess_dso_dynamics @@ -164,7 +171,7 @@ static reloc_howto_type cris_elf_howto_table [] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + cris_elf_pcrel_reloc, /* special_function */ "R_CRIS_8_PCREL", /* name */ FALSE, /* partial_inplace */ 0x0000, /* src_mask */ @@ -179,7 +186,7 @@ static reloc_howto_type cris_elf_howto_table [] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + cris_elf_pcrel_reloc, /* special_function */ "R_CRIS_16_PCREL", /* name */ FALSE, /* partial_inplace */ 0x00000000, /* src_mask */ @@ -194,7 +201,7 @@ static reloc_howto_type cris_elf_howto_table [] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + cris_elf_pcrel_reloc, /* special_function */ "R_CRIS_32_PCREL", /* name */ FALSE, /* partial_inplace */ 0x00000000, /* src_mask */ @@ -398,7 +405,7 @@ static reloc_howto_type cris_elf_howto_table [] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + cris_elf_pcrel_reloc, /* special_function */ "R_CRIS_32_PLT_PCREL", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -466,8 +473,39 @@ cris_info_to_howto_rela (abfd, cache_ptr, dst) BFD_ASSERT (r_type < (unsigned int) R_CRIS_max); cache_ptr->howto = & cris_elf_howto_table [r_type]; } + +bfd_reloc_status_type +cris_elf_pcrel_reloc (abfd, reloc_entry, symbol, data, input_section, + output_bfd, error_message) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *reloc_entry; + asymbol *symbol; + PTR data ATTRIBUTE_UNUSED; + asection *input_section; + bfd *output_bfd; + char **error_message ATTRIBUTE_UNUSED; +{ + /* By default (using only bfd_elf_generic_reloc when linking to + non-ELF formats) PC-relative relocs are relative to the beginning + of the reloc. CRIS PC-relative relocs are relative to the position + *after* the reloc because that's what pre-CRISv32 PC points to + after reading an insn field with that reloc. (For CRISv32, PC is + actually relative to the start of the insn, but we keep the old + definition.) Still, we use as much generic machinery as we can. + + Only adjust when doing a final link. */ + if (output_bfd == (bfd *) NULL) + reloc_entry->addend -= 1 << reloc_entry->howto->size; + + return + bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); +} -/* Support for core dump NOTE sections. */ +/* Support for core dump NOTE sections. + The slightly unintuitive code layout is an attempt to keep at least + some similarities with other ports, hoping to simplify general + changes, while still keeping Linux/CRIS and Linux/CRISv32 code apart. */ static bfd_boolean cris_elf_grok_prstatus (abfd, note) @@ -477,8 +515,28 @@ cris_elf_grok_prstatus (abfd, note) int offset; size_t size; - switch (note->descsz) - { + if (bfd_get_mach (abfd) == bfd_mach_cris_v32) + switch (note->descsz) + { + default: + return FALSE; + + case 202: /* Linux/CRISv32 */ + /* pr_cursig */ + elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); + + /* pr_pid */ + elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 22); + + /* pr_reg */ + offset = 70; + size = 128; + + break; + } + else + switch (note->descsz) + { default: return FALSE; @@ -494,7 +552,7 @@ cris_elf_grok_prstatus (abfd, note) size = 140; break; - } + } /* Make a ".reg/999" section. */ return _bfd_elfcore_make_pseudosection (abfd, ".reg", @@ -506,17 +564,30 @@ cris_elf_grok_psinfo (abfd, note) bfd *abfd; Elf_Internal_Note *note; { - switch (note->descsz) - { + if (bfd_get_mach (abfd) == bfd_mach_cris_v32) + switch (note->descsz) + { + default: + return FALSE; + + case 124: /* Linux/CRISv32 elf_prpsinfo */ + elf_tdata (abfd)->core_program + = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); + elf_tdata (abfd)->core_command + = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); + } + else + switch (note->descsz) + { default: return FALSE; case 124: /* Linux/CRIS elf_prpsinfo */ elf_tdata (abfd)->core_program - = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); + = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); elf_tdata (abfd)->core_command - = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); - } + = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); + } /* Note that for some reason, a spurious space is tacked onto the end of the args in some (at least one anyway) @@ -541,6 +612,7 @@ cris_elf_grok_psinfo (abfd, note) /* The size in bytes of an entry in the procedure linkage table. */ #define PLT_ENTRY_SIZE 20 +#define PLT_ENTRY_SIZE_V32 26 /* The first entry in an absolute procedure linkage table looks like this. */ @@ -553,7 +625,21 @@ static const bfd_byte elf_cris_plt0_entry[PLT_ENTRY_SIZE] = 0x30, 0x7a, /* move [...],mof */ 0x7f, 0x0d, /* (dip [pc+]) */ 0, 0, 0, 0, /* Replaced with address of .got + 8. */ - 0x30, 0x09, /* jump [...] */ + 0x30, 0x09 /* jump [...] */ +}; + +static const bfd_byte elf_cris_plt0_entry_v32[PLT_ENTRY_SIZE_V32] = +{ + 0x84, 0xe2, /* subq 4,$sp */ + 0x6f, 0xfe, /* move.d 0,$acr */ + 0, 0, 0, 0, /* Replaced by address of .got + 4. */ + 0x7e, 0x7a, /* move $mof,[$sp] */ + 0x3f, 0x7a, /* move [$acr],$mof */ + 0x04, 0xf2, /* addq 4,acr */ + 0x6f, 0xfa, /* move.d [$acr],$acr */ + 0xbf, 0x09, /* jump $acr */ + 0xb0, 0x05, /* nop */ + 0, 0 /* Pad out to 26 bytes. */ }; /* Subsequent entries in an absolute procedure linkage table look like @@ -571,6 +657,20 @@ static const bfd_byte elf_cris_plt_entry[PLT_ENTRY_SIZE] = 0xff, 0xff /* Replaced with offset to start of .plt. */ }; +static const bfd_byte elf_cris_plt_entry_v32[PLT_ENTRY_SIZE_V32] = +{ + 0x6f, 0xfe, /* move.d 0,$acr */ + 0, 0, 0, 0, /* Replaced with address of this symbol in .got. */ + 0x6f, 0xfa, /* move.d [$acr],$acr */ + 0xbf, 0x09, /* jump $acr */ + 0xb0, 0x05, /* nop */ + 0x3f, 0x7e, /* move 0,mof */ + 0, 0, 0, 0, /* Replaced with offset into relocation table. */ + 0xbf, 0x0e, /* ba start_of_plt0_entry */ + 0, 0, 0, 0, /* Replaced with offset to plt0 entry. */ + 0xb0, 0x05 /* nop */ +}; + /* The first entry in a PIC procedure linkage table looks like this. */ static const bfd_byte elf_cris_pic_plt0_entry[PLT_ENTRY_SIZE] = @@ -581,6 +681,21 @@ static const bfd_byte elf_cris_pic_plt0_entry[PLT_ENTRY_SIZE] = 0, 0, 0, 0, 0, 0, 0, 0, /* Pad out to 20 bytes. */ }; +static const bfd_byte elf_cris_pic_plt0_entry_v32[PLT_ENTRY_SIZE_V32] = +{ + 0x84, 0xe2, /* subq 4,$sp */ + 0x04, 0x01, /* addoq 4,$r0,$acr */ + 0x7e, 0x7a, /* move $mof,[$sp] */ + 0x3f, 0x7a, /* move [$acr],$mof */ + 0x04, 0xf2, /* addq 4,$acr */ + 0x6f, 0xfa, /* move.d [$acr],$acr */ + 0xbf, 0x09, /* jump $acr */ + 0xb0, 0x05, /* nop */ + 0, 0, /* Pad out to 26 bytes. */ + 0, 0, 0, 0, + 0, 0, 0, 0 +}; + /* Subsequent entries in a PIC procedure linkage table look like this. */ static const bfd_byte elf_cris_pic_plt_entry[PLT_ENTRY_SIZE] = @@ -594,6 +709,20 @@ static const bfd_byte elf_cris_pic_plt_entry[PLT_ENTRY_SIZE] = 0xec, 0xff, /* Replaced with offset to start of .plt. */ 0xff, 0xff }; + +static const bfd_byte elf_cris_pic_plt_entry_v32[PLT_ENTRY_SIZE_V32] = +{ + 0x6f, 0x0d, /* addo.d 0,$r0,$acr */ + 0, 0, 0, 0, /* Replaced with offset of this symbol in .got. */ + 0x6f, 0xfa, /* move.d [$acr],$acr */ + 0xbf, 0x09, /* jump $acr */ + 0xb0, 0x05, /* nop */ + 0x3f, 0x7e, /* move relocoffs,$mof */ + 0, 0, 0, 0, /* Replaced with offset into relocation table. */ + 0xbf, 0x0e, /* ba start_of_plt */ + 0, 0, 0, 0, /* Replaced with offset to start of .plt. */ + 0xb0, 0x05 /* nop */ +}; /* We copy elf32-m68k.c and elf32-i386.c for the basic linker hash bits (and most other PIC/shlib stuff). Check that we don't drift away @@ -917,7 +1046,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, else if (unresolved_reloc) { _bfd_error_handler - (_("%B(%A): unresolvable relocation %s against symbol `%s'"), + (_("%B, section %A: unresolvable relocation %s against symbol `%s'"), input_bfd, input_section, cris_elf_howto_table[r_type].name, @@ -972,9 +1101,9 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, { (*_bfd_error_handler) ((h->got.offset == (bfd_vma) -1) - ? _("%B(%A): No PLT nor GOT for relocation %s" + ? _("%B, section %A: No PLT nor GOT for relocation %s" " against symbol `%s'") - : _("%B(%A): No PLT for relocation %s" + : _("%B, section %A: No PLT for relocation %s" " against symbol `%s'"), input_bfd, input_section, @@ -1098,7 +1227,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, allowed to pass us these kinds of things. */ if (h == NULL) (*_bfd_error_handler) - (_("%B(%A): relocation %s with non-zero addend %d" + (_("%B, section %A: relocation %s with non-zero addend %d" " against local symbol"), input_bfd, input_section, @@ -1106,7 +1235,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, rel->r_addend); else (*_bfd_error_handler) - (_("%B(%A): relocation %s with non-zero addend %d" + (_("%B, section %A: relocation %s with non-zero addend %d" " against symbol `%s'"), input_bfd, input_section, @@ -1132,7 +1261,8 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, && h->root.type == bfd_link_hash_undefweak)))) { (*_bfd_error_handler) - (_("%B(%A): relocation %s is not allowed for global symbol: `%s'"), + (_("%B, section %A: relocation %s is" + " not allowed for global symbol: `%s'"), input_bfd, input_section, cris_elf_howto_table[r_type].name, @@ -1147,7 +1277,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (sgot == NULL) { (*_bfd_error_handler) - (_("%B: relocation %s in section %A with no GOT created"), + (_("%B, section %A: relocation %s with no GOT created"), input_bfd, input_section, cris_elf_howto_table[r_type].name); @@ -1407,8 +1537,33 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) Elf_Internal_Sym *sym; { bfd *dynobj; + + /* Where in the plt entry to put values. */ int plt_off1 = 2, plt_off2 = 10, plt_off3 = 16; + /* What offset to add to the distance to the first PLT entry for the + value at plt_off3. */ + int plt_off3_value_bias = 4; + + /* Where in the PLT entry the call-dynlink-stub is (happens to be same + for PIC and non-PIC for v32 and pre-v32). */ + int plt_stub_offset = 8; + int plt_entry_size = PLT_ENTRY_SIZE; + const bfd_byte *plt_entry = elf_cris_plt_entry; + const bfd_byte *plt_pic_entry = elf_cris_pic_plt_entry; + + /* Adjust the various PLT entry offsets. */ + if (bfd_get_mach (output_bfd) == bfd_mach_cris_v32) + { + plt_off2 = 14; + plt_off3 = 20; + plt_off3_value_bias = -2; + plt_stub_offset = 12; + plt_entry_size = PLT_ENTRY_SIZE_V32; + plt_entry = elf_cris_plt_entry_v32; + plt_pic_entry = elf_cris_pic_plt_entry_v32; + } + dynobj = elf_hash_table (info)->dynobj; if (h->plt.offset != (bfd_vma) -1) @@ -1460,8 +1615,8 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) /* Fill in the entry in the procedure linkage table. */ if (! info->shared) { - memcpy (splt->contents + h->plt.offset, elf_cris_plt_entry, - PLT_ENTRY_SIZE); + memcpy (splt->contents + h->plt.offset, plt_entry, + plt_entry_size); /* We need to enter the absolute address of the GOT entry here. */ bfd_put_32 (output_bfd, got_base + got_offset, @@ -1469,8 +1624,8 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) } else { - memcpy (splt->contents + h->plt.offset, elf_cris_pic_plt_entry, - PLT_ENTRY_SIZE); + memcpy (splt->contents + h->plt.offset, plt_pic_entry, + plt_entry_size); bfd_put_32 (output_bfd, got_offset, splt->contents + h->plt.offset + plt_off1); } @@ -1479,13 +1634,14 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) PLT entry. */ if (has_gotplt) { - /* Fill in the offset into the reloc table. */ + /* Fill in the offset to the reloc table. */ bfd_put_32 (output_bfd, gotplt_index * sizeof (Elf32_External_Rela), splt->contents + h->plt.offset + plt_off2); /* Fill in the offset to the first PLT entry, where to "jump". */ - bfd_put_32 (output_bfd, - (h->plt.offset + plt_off3 + 4), + bfd_put_32 (output_bfd, + - (h->plt.offset + plt_off3 + plt_off3_value_bias), splt->contents + h->plt.offset + plt_off3); /* Fill in the entry in the global offset table with the address of @@ -1494,7 +1650,7 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) (splt->output_section->vma + splt->output_offset + h->plt.offset - + 8), + + plt_stub_offset), sgotplt->contents + got_offset); /* Fill in the entry in the .rela.plt section. */ @@ -1695,20 +1851,45 @@ elf_cris_finish_dynamic_sections (output_bfd, info) /* Fill in the first entry in the procedure linkage table. */ if (splt->size > 0) { - if (info->shared) - memcpy (splt->contents, elf_cris_pic_plt0_entry, PLT_ENTRY_SIZE); + if (bfd_get_mach (output_bfd) == bfd_mach_cris_v32) + { + if (info->shared) + memcpy (splt->contents, elf_cris_pic_plt0_entry_v32, + PLT_ENTRY_SIZE_V32); + else + { + memcpy (splt->contents, elf_cris_plt0_entry_v32, + PLT_ENTRY_SIZE_V32); + bfd_put_32 (output_bfd, + sgot->output_section->vma + + sgot->output_offset + 4, + splt->contents + 4); + + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = PLT_ENTRY_SIZE_V32; + } + } else - { - memcpy (splt->contents, elf_cris_plt0_entry, PLT_ENTRY_SIZE); - bfd_put_32 (output_bfd, - sgot->output_section->vma + sgot->output_offset + 4, - splt->contents + 6); - bfd_put_32 (output_bfd, - sgot->output_section->vma + sgot->output_offset + 8, - splt->contents + 14); - - elf_section_data (splt->output_section)->this_hdr.sh_entsize - = PLT_ENTRY_SIZE; + { + if (info->shared) + memcpy (splt->contents, elf_cris_pic_plt0_entry, + PLT_ENTRY_SIZE); + else + { + memcpy (splt->contents, elf_cris_plt0_entry, + PLT_ENTRY_SIZE); + bfd_put_32 (output_bfd, + sgot->output_section->vma + + sgot->output_offset + 4, + splt->contents + 6); + bfd_put_32 (output_bfd, + sgot->output_section->vma + + sgot->output_offset + 8, + splt->contents + 14); + + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = PLT_ENTRY_SIZE; + } } } } @@ -2018,6 +2199,7 @@ elf_cris_adjust_dynamic_symbol (info, h) bfd *dynobj; asection *s; unsigned int power_of_two; + bfd_size_type plt_entry_size; dynobj = elf_hash_table (info)->dynobj; @@ -2029,6 +2211,10 @@ elf_cris_adjust_dynamic_symbol (info, h) && h->ref_regular && !h->def_regular))); + plt_entry_size + = (bfd_get_mach (dynobj) == bfd_mach_cris_v32 + ? PLT_ENTRY_SIZE_V32 : PLT_ENTRY_SIZE); + /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later, when we know the address of the .got section. */ @@ -2089,7 +2275,7 @@ elf_cris_adjust_dynamic_symbol (info, h) /* If this is the first .plt entry, make room for the special first entry. */ if (s->size == 0) - s->size += PLT_ENTRY_SIZE; + s->size += plt_entry_size; /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this @@ -2113,8 +2299,8 @@ elf_cris_adjust_dynamic_symbol (info, h) /* Mark the PLT offset to use the GOT entry by setting the low bit in the plt offset; it is always a multiple of - pointer-size. */ - BFD_ASSERT ((s->size & 3) == 0); + plt_entry_size (which is at least a multiple of 2). */ + BFD_ASSERT ((s->size % plt_entry_size) == 0); /* Change the PLT refcount to an offset. */ h->plt.offset = s->size; @@ -2125,7 +2311,7 @@ elf_cris_adjust_dynamic_symbol (info, h) h)->gotplt_offset == 0); /* Make room for this entry. */ - s->size += PLT_ENTRY_SIZE; + s->size += plt_entry_size; return TRUE; } @@ -2134,7 +2320,7 @@ elf_cris_adjust_dynamic_symbol (info, h) h->plt.offset = s->size; /* Make room for this entry. */ - s->size += PLT_ENTRY_SIZE; + s->size += plt_entry_size; /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ @@ -2305,6 +2491,18 @@ cris_elf_check_relocs (abfd, info, sec, relocs) { elf_hash_table (info)->dynobj = dynobj = abfd; + /* We could handle this if we can get a handle on the + output bfd in elf_cris_adjust_dynamic_symbol. Failing + that, we must insist on dynobj being a specific mach. */ + if (bfd_get_mach (dynobj) == bfd_mach_cris_v10_v32) + { + (*_bfd_error_handler) + (_("%B, section %A:\n v10/v32 compatible object %s" + " must not contain a PIC relocation"), + abfd, sec); + return FALSE; + } + /* Create the .got section, so we can assume it's always present whenever there's a dynobj. */ if (!_bfd_elf_create_got_section (dynobj, info)) @@ -2486,7 +2684,8 @@ cris_elf_check_relocs (abfd, info, sec, relocs) { /* FIXME: How do we make this optionally a warning only? */ (*_bfd_error_handler) - (_("%B, section %A:\n relocation %s should not be used in a shared object; recompile with -fPIC"), + (_("%B, section %A:\n relocation %s should not" + " be used in a shared object; recompile with -fPIC"), abfd, sec, cris_elf_howto_table[r_type].name); @@ -2548,6 +2747,17 @@ cris_elf_check_relocs (abfd, info, sec, relocs) && h->root.type != bfd_link_hash_defweak && h->def_regular) break; + + if ((sec->flags & SEC_READONLY) != 0) + { + /* FIXME: How do we make this optionally a warning only? */ + (*_bfd_error_handler) + (_("%B, section %A:\n relocation %s should not be used" + " in a shared object; recompile with -fPIC"), + abfd, + sec, + cris_elf_howto_table[r_type].name); + } } /* We create a reloc section in dynobj and make room for this @@ -2932,23 +3142,81 @@ static bfd_boolean cris_elf_object_p (abfd) bfd *abfd; { + if (! cris_elf_set_mach_from_flags (abfd, elf_elfheader (abfd)->e_flags)) + return FALSE; + if ((elf_elfheader (abfd)->e_flags & EF_CRIS_UNDERSCORE)) return (bfd_get_symbol_leading_char (abfd) == '_'); else return (bfd_get_symbol_leading_char (abfd) == 0); } -/* Mark presence or absence of leading underscore. */ +/* Mark presence or absence of leading underscore. Set machine type + flags from mach type. */ static void cris_elf_final_write_processing (abfd, linker) bfd *abfd; bfd_boolean linker ATTRIBUTE_UNUSED; { + unsigned long e_flags = elf_elfheader (abfd)->e_flags; + + e_flags &= ~EF_CRIS_UNDERSCORE; if (bfd_get_symbol_leading_char (abfd) == '_') - elf_elfheader (abfd)->e_flags |= EF_CRIS_UNDERSCORE; - else - elf_elfheader (abfd)->e_flags &= ~EF_CRIS_UNDERSCORE; + e_flags |= EF_CRIS_UNDERSCORE; + + switch (bfd_get_mach (abfd)) + { + case bfd_mach_cris_v0_v10: + e_flags |= EF_CRIS_VARIANT_ANY_V0_V10; + break; + + case bfd_mach_cris_v10_v32: + e_flags |= EF_CRIS_VARIANT_COMMON_V10_V32; + break; + + case bfd_mach_cris_v32: + e_flags |= EF_CRIS_VARIANT_V32; + break; + + default: + _bfd_abort (__FILE__, __LINE__, + _("Unexpected machine number")); + } + + elf_elfheader (abfd)->e_flags = e_flags; +} + +/* Set the mach type from e_flags value. */ + +static bfd_boolean +cris_elf_set_mach_from_flags (abfd, flags) + bfd *abfd; + unsigned long flags; +{ + switch (flags & EF_CRIS_VARIANT_MASK) + { + case EF_CRIS_VARIANT_ANY_V0_V10: + bfd_default_set_arch_mach (abfd, bfd_arch_cris, bfd_mach_cris_v0_v10); + break; + + case EF_CRIS_VARIANT_V32: + bfd_default_set_arch_mach (abfd, bfd_arch_cris, bfd_mach_cris_v32); + break; + + case EF_CRIS_VARIANT_COMMON_V10_V32: + bfd_default_set_arch_mach (abfd, bfd_arch_cris, bfd_mach_cris_v10_v32); + break; + + default: + /* Since we don't recognize them, we obviously can't support them + with this code; we'd have to require that all future handling + would be optional. */ + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } + + return TRUE; } /* Display the flags field. */ @@ -2968,6 +3236,12 @@ cris_elf_print_private_bfd_data (abfd, ptr) if (elf_elfheader (abfd)->e_flags & EF_CRIS_UNDERSCORE) fprintf (file, _(" [symbols have a _ prefix]")); + if ((elf_elfheader (abfd)->e_flags & EF_CRIS_VARIANT_MASK) + == EF_CRIS_VARIANT_COMMON_V10_V32) + fprintf (file, _(" [v10 and v32]")); + if ((elf_elfheader (abfd)->e_flags & EF_CRIS_VARIANT_MASK) + == EF_CRIS_VARIANT_V32) + fprintf (file, _(" [v32]")); fputc ('\n', file); return TRUE; @@ -2980,7 +3254,7 @@ cris_elf_merge_private_bfd_data (ibfd, obfd) bfd *ibfd; bfd *obfd; { - flagword old_flags, new_flags; + int imach, omach; if (! _bfd_generic_verify_endian_match (ibfd, obfd)) return FALSE; @@ -2989,23 +3263,29 @@ cris_elf_merge_private_bfd_data (ibfd, obfd) || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; + imach = bfd_get_mach (ibfd); + if (! elf_flags_init (obfd)) { /* This happens when ld starts out with a 'blank' output file. */ elf_flags_init (obfd) = TRUE; - /* Set flags according to current bfd_target. */ - cris_elf_final_write_processing (obfd, FALSE); + /* We ignore the linker-set mach, and instead set it according to + the first input file. This would also happen if we could + somehow filter out the OUTPUT_ARCH () setting from elf.sc. + This allows us to keep the same linker config across + cris(v0..v10) and crisv32. The drawback is that we can't force + the output type, which might be a sane thing to do for a + v10+v32 compatibility object. */ + if (! bfd_set_arch_mach (obfd, bfd_arch_cris, imach)) + return FALSE; } - old_flags = elf_elfheader (obfd)->e_flags; - new_flags = elf_elfheader (ibfd)->e_flags; - - /* Is this good or bad? We'll follow with other excluding flags. */ - if ((old_flags & EF_CRIS_UNDERSCORE) != (new_flags & EF_CRIS_UNDERSCORE)) + if (bfd_get_symbol_leading_char (ibfd) + != bfd_get_symbol_leading_char (obfd)) { (*_bfd_error_handler) - ((new_flags & EF_CRIS_UNDERSCORE) + (bfd_get_symbol_leading_char (ibfd) == '_' ? _("%B: uses _-prefixed symbols, but writing file with non-prefixed symbols") : _("%B: uses non-prefixed symbols, but writing file with _-prefixed symbols"), ibfd); @@ -3013,9 +3293,61 @@ cris_elf_merge_private_bfd_data (ibfd, obfd) return FALSE; } + omach = bfd_get_mach (obfd); + + if (imach != omach) + { + /* We can get an incompatible combination only if either is + bfd_mach_cris_v32, and the other one isn't compatible. */ + if ((imach == bfd_mach_cris_v32 + && omach != bfd_mach_cris_v10_v32) + || (omach == bfd_mach_cris_v32 + && imach != bfd_mach_cris_v10_v32)) + { + (*_bfd_error_handler) + ((imach == bfd_mach_cris_v32) + ? _("%B contains CRIS v32 code, incompatible" + " with previous objects") + : _("%B contains non-CRIS-v32 code, incompatible" + " with previous objects"), + ibfd); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* We don't have to check the case where the input is compatible + with v10 and v32, because the output is already known to be set + to the other (compatible) mach. */ + if (omach == bfd_mach_cris_v10_v32 + && ! bfd_set_arch_mach (obfd, bfd_arch_cris, imach)) + return FALSE; + } + return TRUE; } +/* Do side-effects of e_flags copying to obfd. */ + +static bfd_boolean +cris_elf_copy_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + /* Call the base function. */ + if (!_bfd_elf_copy_private_bfd_data (ibfd, obfd)) + return FALSE; + + /* If output is big-endian for some obscure reason, stop here. */ + if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE) + return FALSE; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return TRUE; + + /* Do what we really came here for. */ + return bfd_set_arch_mach (obfd, bfd_arch_cris, bfd_get_mach (ibfd)); +} static enum elf_reloc_type_class elf_cris_reloc_type_class (rela) @@ -3061,6 +3393,8 @@ elf_cris_reloc_type_class (rela) cris_elf_print_private_bfd_data #define bfd_elf32_bfd_merge_private_bfd_data \ cris_elf_merge_private_bfd_data +#define bfd_elf32_bfd_copy_private_bfd_data \ + cris_elf_copy_private_bfd_data #define bfd_elf32_bfd_reloc_type_lookup cris_reloc_type_lookup diff --git a/bfd/libbfd.h b/bfd/libbfd.h index c308d88..20372dd 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1579,6 +1579,11 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_CRIS_UNSIGNED_5", "BFD_RELOC_CRIS_SIGNED_6", "BFD_RELOC_CRIS_UNSIGNED_6", + "BFD_RELOC_CRIS_SIGNED_8", + "BFD_RELOC_CRIS_UNSIGNED_8", + "BFD_RELOC_CRIS_SIGNED_16", + "BFD_RELOC_CRIS_UNSIGNED_16", + "BFD_RELOC_CRIS_LAPCQ_OFFSET", "BFD_RELOC_CRIS_UNSIGNED_4", "BFD_RELOC_CRIS_COPY", "BFD_RELOC_CRIS_GLOB_DAT", diff --git a/bfd/reloc.c b/bfd/reloc.c index 78d19d2..e4fdbe3 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -3947,6 +3947,16 @@ ENUMX ENUMX BFD_RELOC_CRIS_UNSIGNED_6 ENUMX + BFD_RELOC_CRIS_SIGNED_8 +ENUMX + BFD_RELOC_CRIS_UNSIGNED_8 +ENUMX + BFD_RELOC_CRIS_SIGNED_16 +ENUMX + BFD_RELOC_CRIS_UNSIGNED_16 +ENUMX + BFD_RELOC_CRIS_LAPCQ_OFFSET +ENUMX BFD_RELOC_CRIS_UNSIGNED_4 ENUMDOC These relocs are only used within the CRIS assembler. They are not |