diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 8ffae997..cbd0465 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -988,3 +988,10 @@ extern void bfd_elf32_ia64_after_parse extern void bfd_elf64_ia64_after_parse (int); + +/* V850 Note manipulation routines. */ +extern bfd_boolean v850_elf_create_sections + (struct bfd_link_info *); + +extern bfd_boolean v850_elf_set_note + (bfd *, unsigned int, unsigned int); diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c index 0155b7d..ae96ec2 100644 --- a/bfd/elf32-v850.c +++ b/bfd/elf32-v850.c @@ -2344,6 +2344,327 @@ v850_elf_gc_mark_hook (asection *sec, return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } +static void +v850_set_note (bfd * abfd, asection * s, enum v850_notes note, unsigned int val) +{ + bfd_byte * data = s->contents + ((note - 1) * SIZEOF_V850_NOTE); + + bfd_put_32 (abfd, 4, data + 0); + bfd_put_32 (abfd, 4, data + 4); + bfd_put_32 (abfd, note, data + 8); + memcpy (data + 12, V850_NOTE_NAME, 4); + bfd_put_32 (abfd, val, data + 16); +} + +/* Create the note section if not already present. This is done early so + that the linker maps the sections to the right place in the output. */ + +static asection * +v850_elf_make_note_section (bfd * abfd) +{ + asection *s; + bfd_byte *data; + flagword flags; + enum v850_notes id; + + /* Make the note section. */ + flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_MERGE; + + s = bfd_make_section_anyway_with_flags (abfd, V850_NOTE_SECNAME, flags); + if (s == NULL) + return NULL; + + if (!bfd_set_section_alignment (abfd, s, 2)) + return NULL; + + /* Allocate space for all known notes. */ + if (!bfd_set_section_size (abfd, s, NUM_V850_NOTES * SIZEOF_V850_NOTE)) + return NULL; + + data = bfd_zalloc (abfd, NUM_V850_NOTES * SIZEOF_V850_NOTE); + if (data == NULL) + return NULL; + + s->contents = data; + + /* Provide default (= uninitilaised) values for all of the notes. */ + for (id = V850_NOTE_ALIGNMENT; id <= NUM_V850_NOTES; id++) + v850_set_note (abfd, s, id, 0); + + return s; +} + +/* Create the note section if not already present. This is done early so + that the linker maps the sections to the right place in the output. */ + +bfd_boolean +v850_elf_create_sections (struct bfd_link_info * info) +{ + bfd * ibfd; + + /* If we already have a note section, do not make another. */ + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) + if (bfd_get_section_by_name (ibfd, V850_NOTE_SECNAME) != NULL) + return TRUE; + + return v850_elf_make_note_section (info->input_bfds) != NULL; +} + +bfd_boolean +v850_elf_set_note (bfd * abfd, enum v850_notes note, unsigned int val) +{ + asection * notes = bfd_get_section_by_name (abfd, V850_NOTE_SECNAME); + + if (val > 2) + /* At the moment, no known note has a value over 2. */ + return FALSE; + + if (notes == NULL) + notes = v850_elf_make_note_section (abfd); + if (notes == NULL) + return FALSE; + + v850_set_note (abfd, notes, note, val); + return TRUE; +} + +/* Copy backend specific data from one object module to another. */ + +static bfd_boolean +v850_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd) +{ + asection * onotes; + asection * inotes; + + /* If the output bfd does not have a note section, then + skip the merge. The normal input to output section + copying will take care of everythng for us. */ + if ((onotes = bfd_get_section_by_name (obfd, V850_NOTE_SECNAME)) == NULL) + return TRUE; + + if ((inotes = bfd_get_section_by_name (ibfd, V850_NOTE_SECNAME)) != NULL) + { + bfd_byte * icont; + bfd_byte * ocont; + + BFD_ASSERT (bfd_section_size (ibfd, inotes) == bfd_section_size (obfd, onotes)); + + if ((icont = elf_section_data (inotes)->this_hdr.contents) == NULL) + BFD_ASSERT (bfd_malloc_and_get_section (ibfd, inotes, & icont)); + + if ((ocont = elf_section_data (onotes)->this_hdr.contents) == NULL) + BFD_ASSERT (bfd_malloc_and_get_section (obfd, onotes, & ocont)); + + /* Copy/overwrite notes from the input to the output. */ + memcpy (ocont, icont, bfd_section_size (obfd, onotes)); + } + + return TRUE; +} +#define bfd_elf32_bfd_copy_private_bfd_data v850_elf_copy_private_bfd_data + +static bfd_boolean +v850_elf_merge_notes (bfd * ibfd, bfd *obfd) +{ + asection * onotes; + asection * inotes; + bfd_boolean result = TRUE; + + /* If the output bfd does not have a note section, then + skip the merge. The normal input to output section + copying will take care of everythng for us. */ + if ((onotes = bfd_get_section_by_name (obfd, V850_NOTE_SECNAME)) == NULL) + return TRUE; + + if ((inotes = bfd_get_section_by_name (ibfd, V850_NOTE_SECNAME)) != NULL) + { + enum v850_notes id; + bfd_byte * icont; + bfd_byte * ocont; + + BFD_ASSERT (bfd_section_size (ibfd, inotes) == bfd_section_size (obfd, onotes)); + + if ((icont = elf_section_data (inotes)->this_hdr.contents) == NULL) + BFD_ASSERT (bfd_malloc_and_get_section (ibfd, inotes, & icont)); + + if ((ocont = elf_section_data (onotes)->this_hdr.contents) == NULL) + BFD_ASSERT (bfd_malloc_and_get_section (obfd, onotes, & ocont)); + + for (id = V850_NOTE_ALIGNMENT; id <= NUM_V850_NOTES; id++) + { + unsigned int ival; + unsigned int oval; + bfd_byte * idata = icont + ((id - 1) * SIZEOF_V850_NOTE) + 16; + bfd_byte * odata = ocont + ((id - 1) * SIZEOF_V850_NOTE) + 16; + + ival = bfd_get_32 (ibfd, idata); + oval = bfd_get_32 (obfd, odata); + + if (ival == 0 || ival == oval) + continue; + + if (oval == 0) + { + bfd_put_32 (obfd, ival, odata); + v850_set_note (obfd, onotes, id, ival); + continue; + } + + /* We have a mismatch. The ABI defines how to handle + this siutation on a per note type basis. */ + switch (id) + { + case V850_NOTE_ALIGNMENT: + if (oval == EF_RH850_DATA_ALIGN4) + { + _bfd_error_handler + (_("error: %B needs 8-byte aligment but %B is set for 4-byte alignment"), + ibfd, obfd); + result = FALSE; + } + else + /* ibfd uses 4-byte alignment, obfd uses 8-byte alignment. + Leave the obfd alignment as it is. */ + BFD_ASSERT (oval == EF_RH850_DATA_ALIGN8); + + break; + + case V850_NOTE_DATA_SIZE: + if (oval == EF_RH850_DOUBLE32) + { + _bfd_error_handler (_("error: %B uses 64-bit doubles but %B uses 32-bit doubles"), + ibfd, obfd); + result = FALSE; + } + else + /* ibfd uses 32-bit doubles, obfd uses 64-bit doubles. + This is acceptable. Honest, that is what the ABI says. */ + BFD_ASSERT (oval == EF_RH850_DOUBLE64); + break; + + case V850_NOTE_FPU_INFO: + if (oval == EF_RH850_FPU20) + { + _bfd_error_handler (_("error: %B uses FPU-3.0 but %B only supports FPU-2.0"), + ibfd, obfd); + result = FALSE; + } + else + /* ibfd uses FPU-2.0, obfd uses FPU-3.0. Leave obfd as it is. */ + BFD_ASSERT (oval == EF_RH850_FPU30); + + break; + + default: + /* None of the other conflicts matter. + Stick with the current output values. */ + break; + } + } + + /* FIXME: We should also check for conflicts between the notes + and the EF flags in the ELF header. */ + } + + return result; +} + +static void +print_v850_note (bfd * abfd, FILE * file, bfd_byte * data, enum v850_notes id) +{ + unsigned int value = bfd_get_32 (abfd, data + ((id - 1) * SIZEOF_V850_NOTE) + 16); + + switch (id) + { + case V850_NOTE_ALIGNMENT: + fprintf (file, _(" alignment of 8-byte entities: ")); + switch (value) + { + case EF_RH850_DATA_ALIGN4: fprintf (file, _("4-byte")); break; + case EF_RH850_DATA_ALIGN8: fprintf (file, _("8-byte")); break; + case 0: fprintf (file, _("not set")); break; + default: fprintf (file, _("unknown: %x"), value); break; + } + fputc ('\n', file); + break; + + case V850_NOTE_DATA_SIZE: + fprintf (file, _(" size of doubles: ")); + switch (value) + { + case EF_RH850_DOUBLE32: fprintf (file, _("4-bytes")); break; + case EF_RH850_DOUBLE64: fprintf (file, _("8-bytes")); break; + case 0: fprintf (file, _("not set")); break; + default: fprintf (file, _("unknown: %x"), value); break; + } + fputc ('\n', file); + break; + + case V850_NOTE_FPU_INFO: + fprintf (file, _(" FPU support required: ")); + switch (value) + { + case EF_RH850_FPU20: fprintf (file, _("FPU-2.0")); break; + case EF_RH850_FPU30: fprintf (file, _("FPU-3.0")); break; + case 0: fprintf (file, _("none")); break; + default: fprintf (file, _("unknown: %x"), value); break; + } + fputc ('\n', file); + break; + + case V850_NOTE_SIMD_INFO: + fprintf (file, _("SIMD use: ")); + switch (value) + { + case EF_RH850_SIMD: fprintf (file, _("yes")); break; + case 0: fprintf (file, _("no")); break; + default: fprintf (file, _("unknown: %x"), value); break; + } + fputc ('\n', file); + break; + + case V850_NOTE_CACHE_INFO: + fprintf (file, _("CACHE use: ")); + switch (value) + { + case EF_RH850_CACHE: fprintf (file, _("yes")); break; + case 0: fprintf (file, _("no")); break; + default: fprintf (file, _("unknown: %x"), value); break; + } + fputc ('\n', file); + break; + + case V850_NOTE_MMU_INFO: + fprintf (file, _("MMU use: ")); + switch (value) + { + case EF_RH850_MMU: fprintf (file, _("yes")); break; + case 0: fprintf (file, _("no")); break; + default: fprintf (file, _("unknown: %x"), value); break; + } + fputc ('\n', file); + break; + + default: + BFD_ASSERT (0); + } +} + +static void +v850_elf_print_notes (bfd * abfd, FILE * file) +{ + asection * notes = bfd_get_section_by_name (abfd, V850_NOTE_SECNAME); + enum v850_notes id; + + if (notes == NULL || notes->contents == NULL) + return; + + BFD_ASSERT (bfd_section_size (abfd, notes) == NUM_V850_NOTES * SIZEOF_V850_NOTE); + + for (id = V850_NOTE_ALIGNMENT; id <= NUM_V850_NOTES; id++) + print_v850_note (abfd, file, notes->contents, id); +} + /* Set the right machine number and architecture. */ static bfd_boolean @@ -2439,11 +2760,14 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { flagword out_flags; flagword in_flags; + bfd_boolean result = TRUE; if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; + result &= v850_elf_merge_notes (ibfd, obfd); + in_flags = elf_elfheader (ibfd)->e_flags; out_flags = elf_elfheader (obfd)->e_flags; @@ -2463,14 +2787,14 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) && bfd_get_arch_info (obfd)->the_default) - return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); + result &= bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); - return TRUE; + return result; } /* Check flag compatibility. */ if (in_flags == out_flags) - return TRUE; + return result; if (bfd_get_arch (obfd) == bfd_arch_v850_rh850) { @@ -2481,14 +2805,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) elf_elfheader (obfd)->e_flags |= EF_V800_850E3; } - if ((in_flags & EF_RH850_DATA_ALIGN8) != (out_flags & EF_RH850_DATA_ALIGN8)) - { - _bfd_error_handler (_("%B: Alignment mismatch with previous modules"), - ibfd); - elf_elfheader (obfd)->e_flags |= EF_RH850_DATA_ALIGN8; - } - - return TRUE; + return result; } if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH) @@ -2499,14 +2816,14 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) which we set to v850e. */ if ( (in_flags & EF_V850_ARCH) == E_V850E1_ARCH && (out_flags & EF_V850_ARCH) == E_V850E_ARCH) - return TRUE; + return result; if ( (in_flags & EF_V850_ARCH) == E_V850_ARCH && (out_flags & EF_V850_ARCH) == E_V850E_ARCH) { elf_elfheader (obfd)->e_flags = ((out_flags & ~ EF_V850_ARCH) | E_V850E_ARCH); - return TRUE; + return result; } if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH @@ -2515,7 +2832,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { elf_elfheader (obfd)->e_flags = ((out_flags & ~ EF_V850_ARCH) | E_V850E2_ARCH); - return TRUE; + return result; } if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH @@ -2525,7 +2842,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { elf_elfheader (obfd)->e_flags = ((out_flags & ~ EF_V850_ARCH) | E_V850E2V3_ARCH); - return TRUE; + return result; } if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH @@ -2536,14 +2853,14 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { elf_elfheader (obfd)->e_flags = ((out_flags & ~ EF_V850_ARCH) | E_V850E3V5_ARCH); - return TRUE; + return result; } _bfd_error_handler (_("%B: Architecture mismatch with previous modules"), ibfd); } - return TRUE; + return result; } /* Display the flags field. */ @@ -2568,9 +2885,6 @@ v850_elf_print_private_bfd_data (bfd *abfd, void * ptr) fprintf (file, _("v850 E3 architecture")); else fprintf (file, _("v850 architecture")); - - if (elf_elfheader (abfd)->e_flags & EF_RH850_DATA_ALIGN8) - fprintf (file, _(", 8-byte data alignment")); } else { @@ -2588,6 +2902,8 @@ v850_elf_print_private_bfd_data (bfd *abfd, void * ptr) fputc ('\n', file); + v850_elf_print_notes (abfd, file); + return TRUE; } @@ -2860,6 +3176,12 @@ v850_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, hdr->sh_type = SHT_V850_TCOMMON; else if (strcmp (name, ".zcommon") == 0) hdr->sh_type = SHT_V850_ZCOMMON; + /* Tweak the section type of .note.renesas. */ + else if (strcmp (name, V850_NOTE_SECNAME) == 0) + { + hdr->sh_type = SHT_RENESAS_INFO; + hdr->sh_entsize = SIZEOF_V850_NOTE; + } return TRUE; } @@ -3801,8 +4123,8 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] = #define elf_backend_gc_mark_hook v850_elf_gc_mark_hook #define elf_backend_special_sections v850_elf_special_sections -#define elf_backend_can_gc_sections 1 -#define elf_backend_rela_normal 1 +#define elf_backend_can_gc_sections 1 +#define elf_backend_rela_normal 1 #define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name #define bfd_elf32_bfd_is_target_special_symbol v850_elf_is_target_special_symbol @@ -3911,7 +4233,6 @@ v800_elf_info_to_howto (bfd * abfd, cache_ptr->howto = v800_elf_howto_table + r_type; } - #undef TARGET_LITTLE_SYM #define TARGET_LITTLE_SYM v800_elf32_vec #undef TARGET_LITTLE_NAME diff --git a/binutils/readelf.c b/binutils/readelf.c index b3f4733..559ab4b 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -2952,12 +2952,8 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) { case EF_RH850_FPU_DOUBLE: strcat (buf, ", double precision FPU"); break; case EF_RH850_FPU_SINGLE: strcat (buf, ", single precision FPU"); break; - case EF_RH850_SIMD: strcat (buf, ", SIMD"); break; - case EF_RH850_CACHE: strcat (buf, ", CACHE"); break; - case EF_RH850_MMU: strcat (buf, ", MMU"); break; case EF_RH850_REGMODE22: strcat (buf, ", regmode:22"); break; case EF_RH850_REGMODE32: strcat (buf, ", regmode:23"); break; - case EF_RH850_DATA_ALIGN8: strcat (buf, ", 8-byte alignment"); break; case EF_RH850_GP_FIX: strcat (buf, ", r4 fixed"); break; case EF_RH850_GP_NOFIX: strcat (buf, ", r4 free"); break; case EF_RH850_EP_FIX: strcat (buf, ", r30 fixed"); break; @@ -3759,6 +3755,20 @@ get_msp430x_section_type_name (unsigned int sh_type) } static const char * +get_v850_section_type_name (unsigned int sh_type) +{ + switch (sh_type) + { + case SHT_V850_SCOMMON: return "V850 Small Common"; + case SHT_V850_TCOMMON: return "V850 Tiny Common"; + case SHT_V850_ZCOMMON: return "V850 Zero Common"; + case SHT_RENESAS_IOP: return "RENESAS IOP"; + case SHT_RENESAS_INFO: return "RENESAS INFO"; + default: return NULL; + } +} + +static const char * get_section_type_name (unsigned int sh_type) { static char buff[32]; @@ -3826,6 +3836,11 @@ get_section_type_name (unsigned int sh_type) case EM_MSP430: result = get_msp430x_section_type_name (sh_type); break; + case EM_V800: + case EM_V850: + case EM_CYGNUS_V850: + result = get_v850_section_type_name (sh_type); + break; default: result = NULL; break; @@ -3856,7 +3871,19 @@ get_section_type_name (unsigned int sh_type) sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS); } else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER)) - sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER); + { + switch (elf_header.e_machine) + { + case EM_V800: + case EM_V850: + case EM_CYGNUS_V850: + return get_v850_section_type_name (sh_type); + default: + break; + } + + sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER); + } else /* This message is probably going to be displayed in a 15 character wide field, so put the hex value first. */ @@ -14808,6 +14835,85 @@ print_gnu_note (Elf_Internal_Note *pnote) } static const char * +get_v850_elf_note_type (enum v850_notes n_type) +{ + static char buff[64]; + + switch (n_type) + { + case V850_NOTE_ALIGNMENT: return _("Alignment of 8-byte objects"); + case V850_NOTE_DATA_SIZE: return _("Sizeof double and long double"); + case V850_NOTE_FPU_INFO: return _("Type of FPU support needed"); + case V850_NOTE_SIMD_INFO: return _("Use of SIMD instructions"); + case V850_NOTE_CACHE_INFO: return _("Use of cache"); + case V850_NOTE_MMU_INFO: return _("Use of MMU"); + default: + snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), n_type); + return buff; + } +} + +static int +print_v850_note (Elf_Internal_Note * pnote) +{ + unsigned int val; + + if (pnote->descsz != 4) + return 0; + val = byte_get ((unsigned char *) pnote->descdata, pnote->descsz); + + if (val == 0) + { + printf (_("not set\n")); + return 1; + } + + switch (pnote->type) + { + case V850_NOTE_ALIGNMENT: + switch (val) + { + case EF_RH850_DATA_ALIGN4: printf (_("4-byte\n")); return 1; + case EF_RH850_DATA_ALIGN8: printf (_("8-byte\n")); return 1; + } + break; + + case V850_NOTE_DATA_SIZE: + switch (val) + { + case EF_RH850_DOUBLE32: printf (_("4-bytes\n")); return 1; + case EF_RH850_DOUBLE64: printf (_("8-bytes\n")); return 1; + } + break; + + case V850_NOTE_FPU_INFO: + switch (val) + { + case EF_RH850_FPU20: printf (_("FPU-2.0\n")); return 1; + case EF_RH850_FPU30: printf (_("FPU-3.0\n")); return 1; + } + break; + + case V850_NOTE_MMU_INFO: + case V850_NOTE_CACHE_INFO: + case V850_NOTE_SIMD_INFO: + if (val == EF_RH850_SIMD) + { + printf (_("yes\n")); + return 1; + } + break; + + default: + /* An 'unknown note type' message will already have been displayed. */ + break; + } + + printf (_("unknown value: %x\n"), val); + return 0; +} + +static const char * get_netbsd_elfcore_note_type (unsigned e_type) { static char buff[64]; @@ -15248,6 +15354,78 @@ process_corefile_note_segments (FILE * file) } static int +process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length) +{ + Elf_External_Note * pnotes; + Elf_External_Note * external; + int res = 1; + + if (length <= 0) + return 0; + + pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length, + _("v850 notes")); + if (pnotes == NULL) + return 0; + + external = pnotes; + + printf (_("\nDisplaying contents of Renesas V850 notes section at offset 0x%lx with length 0x%lx:\n"), + (unsigned long) offset, (unsigned long) length); + + while (external < (Elf_External_Note *) ((char *) pnotes + length)) + { + Elf_External_Note * next; + Elf_Internal_Note inote; + + inote.type = BYTE_GET (external->type); + inote.namesz = BYTE_GET (external->namesz); + inote.namedata = external->name; + inote.descsz = BYTE_GET (external->descsz); + inote.descdata = inote.namedata + align_power (inote.namesz, 2); + inote.descpos = offset + (inote.descdata - (char *) pnotes); + + next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2)); + + if ( ((char *) next > ((char *) pnotes) + length) + || ((char *) next < (char *) pnotes)) + { + warn (_("corrupt descsz found in note at offset 0x%lx\n"), + (unsigned long) ((char *) external - (char *) pnotes)); + warn (_(" type: 0x%lx, namesize: 0x%lx, descsize: 0x%lx\n"), + inote.type, inote.namesz, inote.descsz); + break; + } + + external = next; + + /* Prevent out-of-bounds indexing. */ + if ( inote.namedata + inote.namesz > (char *) pnotes + length + || inote.namedata + inote.namesz < inote.namedata) + { + warn (_("corrupt namesz found in note at offset 0x%lx\n"), + (unsigned long) ((char *) external - (char *) pnotes)); + warn (_(" type: 0x%lx, namesize: 0x%lx, descsize: 0x%lx\n"), + inote.type, inote.namesz, inote.descsz); + break; + } + + printf (" %s: ", get_v850_elf_note_type (inote.type)); + + if (! print_v850_note (& inote)) + { + res = 0; + printf ("\n", + inote.namesz, inote.descsz); + } + } + + free (pnotes); + + return res; +} + +static int process_note_sections (FILE * file) { Elf_Internal_Shdr * section; @@ -15258,13 +15436,26 @@ process_note_sections (FILE * file) for (i = 0, section = section_headers; i < elf_header.e_shnum && section != NULL; i++, section++) - if (section->sh_type == SHT_NOTE) - { - res &= process_corefile_note_segment (file, - (bfd_vma) section->sh_offset, - (bfd_vma) section->sh_size); - n++; - } + { + if (section->sh_type == SHT_NOTE) + { + res &= process_corefile_note_segment (file, + (bfd_vma) section->sh_offset, + (bfd_vma) section->sh_size); + n++; + } + + if (( elf_header.e_machine == EM_V800 + || elf_header.e_machine == EM_V850 + || elf_header.e_machine == EM_CYGNUS_V850) + && section->sh_type == SHT_RENESAS_INFO) + { + res &= process_v850_notes (file, + (bfd_vma) section->sh_offset, + (bfd_vma) section->sh_size); + n++; + } + } if (n == 0) /* Try processing NOTE segments instead. */ diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index f41392d..ae21b22 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -954,9 +954,11 @@ if [is_elf_format] { run_dump_test "strip-8" run_dump_test "strip-9" # Non-EABI ARM targets will set OSABI to ARM + # The V850 sets the OSABI to UNIX - System V if { ![istarget "*-*-hpux*"] && ![istarget "msp*-*-*"] && ![istarget "visium-*-*"] + && ![istarget "v850*-*-*"] && !([istarget "arm*-*-*"] && ![istarget "arm-*-*eabi*"])} { run_dump_test "strip-10" } diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index c48c011..fc55106 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -31,6 +31,9 @@ static bfd_boolean warn_signed_overflows = FALSE; static bfd_boolean warn_unsigned_overflows = FALSE; +/* Non-zero if floating point insns are not being used. */ +static signed int soft_float = -1; + /* Indicates the target BFD machine number. */ static int machine = -1; @@ -1537,6 +1540,8 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); +static bfd_boolean v850_data_8 = FALSE; + void md_show_usage (FILE *stream) { @@ -1560,6 +1565,8 @@ md_show_usage (FILE *stream) fprintf (stream, _(" -mrh850-abi Mark the binary as using the RH850 ABI (default)\n")); fprintf (stream, _(" -m8byte-align Mark the binary as using 64-bit alignment\n")); fprintf (stream, _(" -m4byte-align Mark the binary as using 32-bit alignment (default)\n")); + fprintf (stream, _(" -msoft-float Mark the binary as not using FP insns (default for pre e2v3)\n")); + fprintf (stream, _(" -mhard-float Mark the binary as using FP insns (default for e2v3 and up)\n")); } int @@ -1646,6 +1653,14 @@ md_parse_option (int c, char *arg) v850_target_format = "elf32-v850-rh850"; } else if (strcmp (arg, "8byte-align") == 0) + v850_data_8 = TRUE; + else if (strcmp (arg, "4byte-align") == 0) + v850_data_8 = FALSE; + else if (strcmp (arg, "soft-float") == 0) + soft_float = 1; + else if (strcmp (arg, "hard-float") == 0) + soft_float = 0; + else if (strcmp (arg, "8byte-align") == 0) v850_e_flags |= EF_RH850_DATA_ALIGN8; else if (strcmp (arg, "4byte-align") == 0) v850_e_flags &= ~ EF_RH850_DATA_ALIGN8; @@ -1940,6 +1955,9 @@ md_begin (void) as_bad (_("Unable to determine default target processor from string: %s"), TARGET_CPU); + if (soft_float == -1) + soft_float = machine < bfd_mach_v850e2v3; + v850_hash = hash_new (); /* Insert unique names into hash table. The V850 instruction set @@ -3716,3 +3734,73 @@ v850_force_relocation (struct fix *fixP) return generic_force_reloc (fixP); } + +/* Create a v850 note section. */ +void +v850_md_end (void) +{ + segT note_sec; + segT orig_seg = now_seg; + subsegT orig_subseg = now_subseg; + enum v850_notes id; + + note_sec = subseg_new (V850_NOTE_SECNAME, 0); + bfd_set_section_flags (stdoutput, note_sec, SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE); + bfd_set_section_alignment (stdoutput, note_sec, 2); + + /* Provide default values for all of the notes. */ + for (id = V850_NOTE_ALIGNMENT; id <= NUM_V850_NOTES; id++) + { + int val = 0; + char * p; + + /* Follow the standard note section layout: + First write the length of the name string. */ + p = frag_more (4); + md_number_to_chars (p, 4, 4); + + /* Next comes the length of the "descriptor", i.e., the actual data. */ + p = frag_more (4); + md_number_to_chars (p, 4, 4); + + /* Write the note type. */ + p = frag_more (4); + md_number_to_chars (p, (valueT) id, 4); + + /* Write the name field. */ + p = frag_more (4); + memcpy (p, V850_NOTE_NAME, 4); + + /* Finally, write the descriptor. */ + p = frag_more (4); + switch (id) + { + case V850_NOTE_ALIGNMENT: + val = v850_data_8 ? EF_RH850_DATA_ALIGN8 : EF_RH850_DATA_ALIGN4; + break; + + case V850_NOTE_DATA_SIZE: + /* GCC does not currently support an option + for 32-bit doubles with the V850 backend. */ + val = EF_RH850_DOUBLE64; + break; + + case V850_NOTE_FPU_INFO: + if (! soft_float) + switch (machine) + { + case bfd_mach_v850e3v5: val = EF_RH850_FPU30; break; + case bfd_mach_v850e2v3: val = EF_RH850_FPU20; break; + default: break; + } + break; + + default: + break; + } + md_number_to_chars (p, val, 4); + } + + /* Paranoia - we probably do not need this. */ + subseg_set (orig_seg, orig_subseg); +} diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h index 0808bd8..efce415 100644 --- a/gas/config/tc-v850.h +++ b/gas/config/tc-v850.h @@ -84,3 +84,6 @@ extern long v850_pcrel_from_section (struct fix *, asection *); processed so that the resulting value can be inserted correctly. */ #define TC_FIX_TYPE void * #define TC_INIT_FIX_DATA(fixP) (fixP)->tc_fix_data = NULL + +#define md_end v850_md_end +extern void v850_md_end (void); diff --git a/gas/doc/c-v850.texi b/gas/doc/c-v850.texi index 0e4e05b..2f78f51 100644 --- a/gas/doc/c-v850.texi +++ b/gas/doc/c-v850.texi @@ -100,24 +100,39 @@ attempt to relax them. @cindex @code{-mgcc-abi} command line option, V850 @item -mgcc-abi -Marks the generated objecy file as supporting the old GCC ABI. +Marks the generated object file as supporting the old GCC ABI. @cindex @code{-mrh850-abi} command line option, V850 @item -mrh850-abi -Marks the generated objecy file as supporting the RH850 ABI. This is +Marks the generated object file as supporting the RH850 ABI. This is the default. @cindex @code{-m8byte-align} command line option, V850 @item -m8byte-align -Marks the generated objecy file as supporting a maximum 64-bits of +Marks the generated object file as supporting a maximum 64-bits of alignment for variables defined in the source code. @cindex @code{-m4byte-align} command line option, V850 @item -m4byte-align -Marks the generated objecy file as supporting a maximum 32-bits of +Marks the generated object file as supporting a maximum 32-bits of alignment for variables defined in the source code. This is the default. +@cindex @code{-msoft-float} command line option, V850 +@item -msoft-float +Marks the generated object file as not using any floating point +instructions - and hence can be linked with other V850 binaries +that do or do not use floating point. This is the default for +binaries for architectures earlier than the @code{e2v3}. + +@cindex @code{-mhard-float} command line option, V850 +@item -mhard-float +Marks the generated object file as one that uses floating point +instructions - and hence can only be linked with other V850 binaries +that use the same kind of floating point instructions, or with +binaries that do not use floating point at all. This is the default +for binaries the @code{e2v3} and later architectures. + @end table @node V850 Syntax diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 2398e88..47b5a21 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -76,6 +76,9 @@ if { [is_elf_format] } then { if {[istarget "rx-*-*"]} then { set target_machine -rx } + if {[istarget "v850*-*-*"]} then { + set target_machine -v850 + } if {[istarget "arm*-*-*"]} { set target_machine -arm } diff --git a/include/elf/v850.h b/include/elf/v850.h index 5cc3581..0a2784b 100644 --- a/include/elf/v850.h +++ b/include/elf/v850.h @@ -158,12 +158,8 @@ END_RELOC_NUMBERS (R_V850_max) #define EF_RH850_FPU_DOUBLE 0x00000001 /* sizeof(double) == 8. */ #define EF_RH850_FPU_SINGLE 0x00000002 /* sizeof(double) == 4. */ -#define EF_RH850_SIMD 0x00000004 -#define EF_RH850_CACHE 0x00000008 -#define EF_RH850_MMU 0x00000010 #define EF_RH850_REGMODE22 0x00000020 /* Registers r15-r24 (inclusive) are not used. */ #define EF_RH850_REGMODE32 0x00000040 -#define EF_RH850_DATA_ALIGN8 0x00000080 /* 8-byte alignment supported. */ #define EF_RH850_GP_FIX 0x00000100 /* r4 is fixed. */ #define EF_RH850_GP_NOFIX 0x00000200 /* r4 is callee save. */ #define EF_RH850_EP_FIX 0x00000400 /* r30 is fixed. */ @@ -173,7 +169,7 @@ END_RELOC_NUMBERS (R_V850_max) #define EF_RH850_REG2_RESERVE 0x00004000 /* r2 is fixed. */ #define EF_RH850_REG2_NORESERVE 0x00008000 /* r2 is callee saved. */ -#define SHT_RNESAS_IOP SHT_LOUSER /* Used by Renesas linker. */ +#define SHT_RENESAS_IOP SHT_LOUSER /* Used by Renesas linker. */ #define SHF_RENESAS_ABS 0x80000000 /* Absolute section. */ #define SHF_GHS_ABS 0x00000400 /* Use unknown. */ @@ -280,4 +276,54 @@ START_RELOC_NUMBERS (v800_reloc_type) END_RELOC_NUMBERS (R_V800_max) +/* Type for Renesas note sections. NB/ This is in application space + rather than processor space as it refers to the requirements of the + binary concerned. A given processor may be able to handle multiple + different types of application. */ +#define SHT_RENESAS_INFO 0xa0000000 + +/* Contents of a Renesas note entry: + + namesz +------------------+ + | 4 | "REL\0" + descsz +------------------+ + | 4 | Currently 4byte only + type +------------------+ + | ID | + name +------------------+ + | REL\0 | + desc +------------------+ + | Value | + +------------------+ */ + +#define V850_NOTE_SECNAME ".note.renesas" +#define SIZEOF_V850_NOTE 20 +#define V850_NOTE_NAME "REL" + +enum v850_notes +{ + V850_NOTE_ALIGNMENT = 1, /* Alignment of 8-byte entities. */ +#define EF_RH850_DATA_ALIGN4 0x0001 /* Aligned to 4-byte bounadries. */ +#define EF_RH850_DATA_ALIGN8 0x0002 /* Aligned to 8-byte bounadries. */ + + V850_NOTE_DATA_SIZE = 2, /* Sizeof double and long double. */ +#define EF_RH850_DOUBLE32 0x0001 /* 32-bits in size. */ +#define EF_RH850_DOUBLE64 0x0002 /* 64-bits in size. */ + + V850_NOTE_FPU_INFO = 3, /* Defined if extended floating point insns are used. */ +#define EF_RH850_FPU20 0x0001 /* Set if [N]]M{ADD|SUB}F.S are used. */ +#define EF_RH850_FPU30 0x0002 /* Set if ADSF.D or ADDF.D is used. */ + + V850_NOTE_SIMD_INFO = 4, +#define EF_RH850_SIMD 0x0001 + + V850_NOTE_CACHE_INFO = 5, +#define EF_RH850_CACHE 0x0001 + + V850_NOTE_MMU_INFO = 6 +#define EF_RH850_MMU 0x0001 +}; + +#define NUM_V850_NOTES V850_NOTE_MMU_INFO + #endif /* _ELF_V850_H */ diff --git a/ld/Makefile.am b/ld/Makefile.am index 11de1c4..58daa41 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -1777,10 +1777,10 @@ etic54xcoff.c: $(srcdir)/emulparams/tic54xcoff.sh \ etic80coff.c: $(srcdir)/emulparams/tic80coff.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/tic80coff.sc ${GEN_DEPENDS} -ev850.c: $(srcdir)/emulparams/v850.sh \ +ev850.c: $(srcdir)/emulparams/v850.sh $(srcdir)/emultempl/v850elf.em \ $(ELF_DEPS) $(srcdir)/scripttempl/v850.sc ${GEN_DEPENDS} -ev850_rh850.c: $(srcdir)/emulparams/v850_rh850.sh \ +ev850_rh850.c: $(srcdir)/emulparams/v850_rh850.sh $(srcdir)/emultempl/v850elf.em \ $(ELF_DEPS) $(srcdir)/scripttempl/v850_rh850.sc ${GEN_DEPENDS} evanilla.c: $(srcdir)/emulparams/vanilla.sh \ diff --git a/ld/Makefile.in b/ld/Makefile.in index 9b803d7..83dc7f1 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -3264,10 +3264,10 @@ etic54xcoff.c: $(srcdir)/emulparams/tic54xcoff.sh \ etic80coff.c: $(srcdir)/emulparams/tic80coff.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/tic80coff.sc ${GEN_DEPENDS} -ev850.c: $(srcdir)/emulparams/v850.sh \ +ev850.c: $(srcdir)/emulparams/v850.sh $(srcdir)/emultempl/v850elf.em \ $(ELF_DEPS) $(srcdir)/scripttempl/v850.sc ${GEN_DEPENDS} -ev850_rh850.c: $(srcdir)/emulparams/v850_rh850.sh \ +ev850_rh850.c: $(srcdir)/emulparams/v850_rh850.sh $(srcdir)/emultempl/v850elf.em \ $(ELF_DEPS) $(srcdir)/scripttempl/v850_rh850.sc ${GEN_DEPENDS} evanilla.c: $(srcdir)/emulparams/vanilla.sh \ diff --git a/ld/emulparams/v850.sh b/ld/emulparams/v850.sh index 96cdc68..c2bdda3 100644 --- a/ld/emulparams/v850.sh +++ b/ld/emulparams/v850.sh @@ -1,5 +1,6 @@ MACHINE= SCRIPT_NAME=v850 +EXTRA_EM_FILE=v850elf OUTPUT_FORMAT="elf32-v850" TEXT_START_ADDR=0x100000 ZDATA_START_ADDR=0x160 diff --git a/ld/emulparams/v850_rh850.sh b/ld/emulparams/v850_rh850.sh index 4315d2b..febdad3 100644 --- a/ld/emulparams/v850_rh850.sh +++ b/ld/emulparams/v850_rh850.sh @@ -1,5 +1,6 @@ MACHINE= SCRIPT_NAME=v850_rh850 +EXTRA_EM_FILE=v850elf OUTPUT_FORMAT="elf32-v850-rh850" TEXT_START_ADDR=0x100000 ZDATA_START_ADDR=0x160 diff --git a/ld/scripttempl/v850.sc b/ld/scripttempl/v850.sc index d8a873e..ef6c92e 100644 --- a/ld/scripttempl/v850.sc +++ b/ld/scripttempl/v850.sc @@ -194,6 +194,8 @@ SECTIONS ${RELOCATING+PROVIDE (end = .);} ${RELOCATING+PROVIDE (_heap_start = .);} + .note.renesas 0 : { KEEP(*(.note.renesas)) } + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } diff --git a/ld/scripttempl/v850_rh850.sc b/ld/scripttempl/v850_rh850.sc index 63a3937..0316a36 100644 --- a/ld/scripttempl/v850_rh850.sc +++ b/ld/scripttempl/v850_rh850.sc @@ -214,6 +214,8 @@ SECTIONS ${RELOCATING+PROVIDE (end = .);} ${RELOCATING+PROVIDE (_heap_start = .);} + .note.renesas 0 : { KEEP(*(.note.renesas)) } + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } diff --git a/ld/testsuite/ld-elf/extract-symbol-1sec.d b/ld/testsuite/ld-elf/extract-symbol-1sec.d index 57a5662..35ca898 100644 --- a/ld/testsuite/ld-elf/extract-symbol-1sec.d +++ b/ld/testsuite/ld-elf/extract-symbol-1sec.d @@ -3,8 +3,9 @@ #ld: -Textract-symbol-1.ld #objcopy_linked_file: --extract-symbol #objdump: --headers -#xfail: "hppa*-*-*" "rx-*-*" +#xfail: "hppa*-*-*" "rx-*-*" "v850*-*-*" # FAILS on the RX because the linker has to set LMA == VMA for the Renesas loader. +# FAILS on the V850 because an extra section - .note.renesas - is created. #... Sections: *Idx +Name +Size +VMA +LMA .* *** /dev/null 2015-02-24 07:14:50.765971671 +0000 --- gas/testsuite/gas/elf/section2.e-v850 2015-02-24 15:30:35.004454421 +0000 *************** *** 0 **** --- 1,9 ---- + + Symbol table '.symtab' contains 6 entries: + +Num: +Value +Size +Type +Bind +Vis +Ndx +Name + +0: 0+0 +0 +NOTYPE +LOCAL +DEFAULT +UND + +1: 0+0 +0 +SECTION +LOCAL +DEFAULT +1 + +2: 0+0 +0 +SECTION +LOCAL +DEFAULT +2 + +3: 0+0 +0 +SECTION +LOCAL +DEFAULT +3 + +4: 0+0 +0 +SECTION +LOCAL +DEFAULT +4 + +5: 0+0 +0 +SECTION +LOCAL +DEFAULT +5 *** /dev/null 2015-02-24 07:14:50.765971671 +0000 --- ld/emultempl/v850elf.em 2015-02-24 15:55:20.019307748 +0000 *************** *** 0 **** --- 1,54 ---- + # This shell script emits a C file. -*- C -*- + # Copyright 2013-2015 Free Software Foundation, Inc. + # + # This file is part of the GNU Binutils. + # + # 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 3 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. + # + + # This file is sourced from elf32.em, and defines extra cpu specific + # features. + # + fragment <xvec == & v850_elf32_vec + || link_info.output_bfd->xvec == & v800_elf32_vec; + } + + /* Create our note section. */ + + static void + v850_after_open (void) + { + if (is_v850_target () + && ! link_info.relocatable + && link_info.input_bfds != NULL + && ! v850_elf_create_sections (& link_info)) + einfo ("%X%P: can not create note section: %E\n"); + + gld${EMULATION_NAME}_after_open (); + } + + EOF + + LDEMUL_AFTER_OPEN=v850_after_open