From: Nick Clifton Date: Thu, 26 Apr 2018 14:12:42 +0000 (+0100) Subject: Extend the assembler so that it can automatically generate GNU Build attribute notes... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0df8ad28f0f727fab3a696d6c98b9a8a77ee1024;p=binutils-gdb.git Extend the assembler so that it can automatically generate GNU Build attribute notes if none are present in the input files. gas * as.c (flag_generate_build_notes): New variable. (show_usage): Add entry for --generate-missing-build-notes. (parse_args): Parse --generate-missing-build-notes. * as.h: Export flag_generate_build_notes. * symbols.c (save_symbol_name): Ensure that the name parameter is not NULL. * write.c (create_obj_attrs_section): Reformat. (create_note_reloc): New function - creates a relocation for a field in a GNU Build attribute note. (maybe_generate_build_notes): New function - created GNU Build attribute notes if none are present in the output file. (write_object_file): Call maybe_generate_build_notes. * configure.ac (--enable-generate-build-notes): New option. * NEWS: Announce the new feature. * doc/as.textinfo: Document the new option. * config.in: Regenerate. * configure: Regenerate. binutils* readelf.c (is_32bit_abs_reloc): Support R_PARISC_DIR32 as a 32-bit absolute reloc for the HPPA target. * testsuite/binutils-all/note-5.d: New test. * testsuite/binutils-all/note-5.s: Source file for new test. * testsuite/binutils-all/objcopy.exp: Run new test. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 702c0cfbedf..3b98be4aaec 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,11 @@ +2018-04-26 Nick Clifton + + * readelf.c (is_32bit_abs_reloc): Support R_PARISC_DIR32 as a + 32-bit absolute reloc for the HPPA target. + * testsuite/binutils-all/note-5.d: New test. + * testsuite/binutils-all/note-5.s: Source file for new test. + * testsuite/binutils-all/objcopy.exp: Run new test. + 2018-04-25 Christophe Lyon * testsuite/binutils-all/elfedit-2.d: Accept arm*-*-uclinuxfdpiceabi. diff --git a/binutils/readelf.c b/binutils/readelf.c index e8e1b9681eb..eecc05b3fa6 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -12305,7 +12305,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) case EM_OR1K: return reloc_type == 1; /* R_OR1K_32. */ case EM_PARISC: - return (reloc_type == 1 /* R_PARISC_DIR32. */ + return (reloc_type == 1 /* R_PARISC_DIR32. */ + || reloc_type == 2 /* R_PARISC_DIR21L. */ || reloc_type == 41); /* R_PARISC_SECREL32. */ case EM_PJ: case EM_PJ_OLD: diff --git a/binutils/testsuite/binutils-all/note-5.d b/binutils/testsuite/binutils-all/note-5.d new file mode 100644 index 00000000000..d3bef15d508 --- /dev/null +++ b/binutils/testsuite/binutils-all/note-5.d @@ -0,0 +1,11 @@ +#PROG: objcopy +#as: --generate-missing-build-notes=yes +#readelf: --notes --wide +#name: assembler generated build notes +#source: note-5.s + +#... +Displaying notes found in: .gnu.build.attributes +[ ]+Owner[ ]+Data size[ ]+Description +[ ]+GA\$3a1[ ]+0x000000(08|10)[ ]+OPEN[ ]+Applies to region from 0 to 0x.. \(note_5.s\) +#... diff --git a/binutils/testsuite/binutils-all/note-5.s b/binutils/testsuite/binutils-all/note-5.s new file mode 100644 index 00000000000..4375b253fb7 --- /dev/null +++ b/binutils/testsuite/binutils-all/note-5.s @@ -0,0 +1,14 @@ + .text + .global note_5.s +note_5.s: + .dc.l 2 + .dc.l 4 + .dc.l 6 + .dc.l 8 + .dc.l 8 + .dc.l 8 + .dc.l 8 + .dc.l 8 + .dc.l 8 + .dc.l 8 + \ No newline at end of file diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index 2a2e757a92f..33812369a43 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -1058,6 +1058,7 @@ if [is_elf_format] { run_dump_test "note-3-32" run_dump_test "note-4-32" } + run_dump_test "note-5" } run_dump_test "copy-2" diff --git a/gas/ChangeLog b/gas/ChangeLog index 4801b59ced9..d3ce68fbe01 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,23 @@ +2018-04-26 Nick Clifton + + * as.c (flag_generate_build_notes): New variable. + (show_usage): Add entry for --generate-missing-build-notes. + (parse_args): Parse --generate-missing-build-notes. + * as.h: Export flag_generate_build_notes. + * symbols.c (save_symbol_name): Ensure that the name parameter is + not NULL. + * write.c (create_obj_attrs_section): Reformat. + (create_note_reloc): New function - creates a relocation for a + field in a GNU Build attribute note. + (maybe_generate_build_notes): New function - created GNU Build + attribute notes if none are present in the output file. + (write_object_file): Call maybe_generate_build_notes. + * configure.ac (--enable-generate-build-notes): New option. + * NEWS: Announce the new feature. + * doc/as.textinfo: Document the new option. + * config.in: Regenerate. + * configure: Regenerate. + 2018-04-26 Jan Beulich * config/tc-i386.c (check_VecOperands): Add AVX512VL check. Set @@ -22,7 +42,7 @@ recording EVEX encoding. Don't check previously specified encoding. * testsuite/gas/i386/xmmhi32.s: Add {x,y,z}mm{16,24} cases. - * testsuite/gas/i386/xmmhi32.d: Adjust expectations. + * testsuite/gas/i386/xmmhi32.d: Adjust expectations. * testsuite/gas/i386/xmmhi64.s, testsuite/gas/i386/xmmhi64.d: New. * testsuite/gas/i386/i386.exp: Run new test. diff --git a/gas/NEWS b/gas/NEWS index 4cb6d738c30..ec1ba78a66a 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,11 @@ -*- text -*- +* Add --generate-missing-build-notes=[yes|no] option to create (or not) GNU + Build Attribute notes if none are present in the input sources. Add a + --enable-generate-build-notes=[yes|no] configure time option to set the + default behaviour. Set the default if the configure option is not used + to "no". + * Remove -mold-gcc command-line option for x86 targets. * Add -O[2|s] command-line options to x86 assembler to enable alternate diff --git a/gas/as.c b/gas/as.c index 6e8ec567855..cdf8cfed487 100644 --- a/gas/as.c +++ b/gas/as.c @@ -97,6 +97,7 @@ int verbose = 0; #if defined OBJ_ELF || defined OBJ_MAYBE_ELF int flag_use_elf_stt_common = DEFAULT_GENERATE_ELF_STT_COMMON; +bfd_boolean flag_generate_build_notes = DEFAULT_GENERATE_BUILD_NOTES; #endif /* Keep the output file. */ @@ -304,7 +305,18 @@ Options:\n\ generate ELF common symbols with STT_COMMON type\n")); fprintf (stream, _("\ --sectname-subst enable section name substitution sequences\n")); + + fprintf (stream, _("\ + --generate-missing-build-notes=[no|yes] ")); +#if DEFAULT_GENERATE_BUILD_NOTES + fprintf (stream, _("(default: yes)\n")); +#else + fprintf (stream, _("(default: no)\n")); #endif + fprintf (stream, _("\ + generate GNU Build notes if none are present in the input\n")); +#endif /* OBJ_ELF */ + fprintf (stream, _("\ -f skip whitespace and comment preprocessing\n")); fprintf (stream, _("\ @@ -470,6 +482,7 @@ parse_args (int * pargc, char *** pargv) OPTION_NOEXECSTACK, OPTION_SIZE_CHECK, OPTION_ELF_STT_COMMON, + OPTION_ELF_BUILD_NOTES, OPTION_SECTNAME_SUBST, OPTION_ALTERNATE, OPTION_AL, @@ -508,6 +521,7 @@ parse_args (int * pargc, char *** pargv) ,{"size-check", required_argument, NULL, OPTION_SIZE_CHECK} ,{"elf-stt-common", required_argument, NULL, OPTION_ELF_STT_COMMON} ,{"sectname-subst", no_argument, NULL, OPTION_SECTNAME_SUBST} + ,{"generate-missing-build-notes", required_argument, NULL, OPTION_ELF_BUILD_NOTES} #endif ,{"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL} ,{"gdwarf-2", no_argument, NULL, OPTION_GDWARF2} @@ -900,7 +914,19 @@ This program has absolutely no warranty.\n")); case OPTION_SECTNAME_SUBST: flag_sectname_subst = 1; break; -#endif + + case OPTION_ELF_BUILD_NOTES: + if (strcasecmp (optarg, "no") == 0) + flag_generate_build_notes = FALSE; + else if (strcasecmp (optarg, "yes") == 0) + flag_generate_build_notes = TRUE; + else + as_fatal (_("Invalid --generate-missing-build-notes option: `%s'"), + optarg); + break; + +#endif /* OBJ_ELF */ + case 'Z': flag_always_generate_output = 1; break; diff --git a/gas/as.h b/gas/as.h index d75ff425231..52bb5a79a71 100644 --- a/gas/as.h +++ b/gas/as.h @@ -595,6 +595,10 @@ COMMON int flag_allow_nonconst_size; /* If we should generate ELF common symbols with the STT_COMMON type. */ extern int flag_use_elf_stt_common; +/* TRUE iff GNU Build attribute notes should + be generated if none are in the input files. */ +extern bfd_boolean flag_generate_build_notes; + /* If section name substitution sequences should be honored */ COMMON int flag_sectname_subst; #endif diff --git a/gas/config.in b/gas/config.in index fcadc4ae5c3..60bfcc93e7e 100644 --- a/gas/config.in +++ b/gas/config.in @@ -39,6 +39,10 @@ /* Define if you want compressed debug sections by default. */ #undef DEFAULT_FLAG_COMPRESS_DEBUG +/* Define to 1 if you want to generate GNU Build attribute notes by default, + if none are contained in the input. */ +#undef DEFAULT_GENERATE_BUILD_NOTES + /* Define to 1 if you want to generate ELF common symbols with the STT_COMMON type by default. */ #undef DEFAULT_GENERATE_ELF_STT_COMMON diff --git a/gas/configure b/gas/configure index a45e531fec3..ea6b3b16a86 100755 --- a/gas/configure +++ b/gas/configure @@ -771,6 +771,7 @@ enable_checking enable_compressed_debug_sections enable_x86_relax_relocations enable_elf_stt_common +enable_generate_build_notes enable_werror enable_build_warnings with_cpu @@ -1426,6 +1427,9 @@ Optional Features: generate x86 relax relocations by default --enable-elf-stt-common generate ELF common symbols with STT_COMMON type by default + --enable-generate-build-notes + generate GNU Build notes if none are provided by the + input --enable-werror treat compile warnings as errors --enable-build-warnings enable build-time compiler warnings --disable-nls do not use Native Language Support @@ -10987,7 +10991,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10990 "configure" +#line 10994 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11093,7 +11097,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11096 "configure" +#line 11100 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11747,6 +11751,20 @@ if test "${enable_elf_stt_common+set}" = set; then : esac fi + +# Decide if the ELF assembler should default to generating +# GNU Build notes if none are provided by the input. +ac_default_generate_build_notes=0 +# Provide a configuration option to override the default. +# Check whether --enable-generate_build_notes was given. +if test "${enable_generate_build_notes+set}" = set; then : + enableval=$enable_generate_build_notes; case "${enableval}" in + yes) ac_default_generate_build_notes=1 ;; + no) ac_default_generate_build_notes=0 ;; +esac +fi + + using_cgen=no @@ -12670,6 +12688,12 @@ cat >>confdefs.h <<_ACEOF _ACEOF + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_GENERATE_BUILD_NOTES $ac_default_generate_build_notes +_ACEOF + + if test x$ac_default_compressed_debug_sections = xyes ; then $as_echo "#define DEFAULT_FLAG_COMPRESS_DEBUG 1" >>confdefs.h diff --git a/gas/configure.ac b/gas/configure.ac index 4a84f16f519..a639422026c 100644 --- a/gas/configure.ac +++ b/gas/configure.ac @@ -100,6 +100,20 @@ AC_ARG_ENABLE(elf_stt_common, yes) ac_default_elf_stt_common=1 ;; esac])dnl + +# Decide if the ELF assembler should default to generating +# GNU Build notes if none are provided by the input. +ac_default_generate_build_notes=0 +# Provide a configuration option to override the default. +AC_ARG_ENABLE(generate_build_notes, + AS_HELP_STRING([--enable-generate-build-notes], + [generate GNU Build notes if none are provided by the input]), +[case "${enableval}" in + yes) ac_default_generate_build_notes=1 ;; + no) ac_default_generate_build_notes=0 ;; +esac])dnl + + using_cgen=no AM_BINUTILS_WARNINGS @@ -596,6 +610,11 @@ AC_DEFINE_UNQUOTED(DEFAULT_GENERATE_ELF_STT_COMMON, [Define to 1 if you want to generate ELF common symbols with the STT_COMMON type by default.]) +AC_DEFINE_UNQUOTED(DEFAULT_GENERATE_BUILD_NOTES, + $ac_default_generate_build_notes, + [Define to 1 if you want to generate GNU Build attribute notes + by default, if none are contained in the input.]) + if test x$ac_default_compressed_debug_sections = xyes ; then AC_DEFINE(DEFAULT_FLAG_COMPRESS_DEBUG, 1, [Define if you want compressed debug sections by default.]) fi diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index e1ff8515ab2..35616c8b55d 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -241,6 +241,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. [@b{-Z}] [@b{@@@var{FILE}}] [@b{--sectname-subst}] [@b{--size-check=[error|warning]}] [@b{--elf-stt-common=[no|yes]}] + [@b{--generate-missing-build-notes=[no|yes]}] [@b{--target-help}] [@var{target-options}] [@b{--}|@var{files} @dots{}] @c @@ -743,6 +744,14 @@ Issue an error or warning for invalid ELF .size directive. These options control whether the ELF assembler should generate common symbols with the @code{STT_COMMON} type. The default can be controlled by a configure option @option{--enable-elf-stt-common}. + +@item --generate-missing-build-notes=yes +@itemx --generate-missing-build-notes=no +These options control whether the ELF assembler should generate GNU Build +attribute notes if none are present in the input sources. +The default can be controlled by the @option{--enable-generate-build-notes} +configure option. + @end ifset @item --help diff --git a/gas/symbols.c b/gas/symbols.c index 96bf9637c33..40888379de8 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -108,6 +108,7 @@ save_symbol_name (const char *name) size_t name_length; char *ret; + gas_assert (name != NULL); name_length = strlen (name) + 1; /* +1 for \0. */ obstack_grow (¬es, name, name_length); ret = (char *) obstack_finish (¬es); diff --git a/gas/write.c b/gas/write.c index 2d0bbe4601d..b902bf85659 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1867,25 +1867,200 @@ create_obj_attrs_section (void) const char *name; size = bfd_elf_obj_attr_size (stdoutput); - if (size) + if (size == 0) + return; + + name = get_elf_backend_data (stdoutput)->obj_attrs_section; + if (!name) + name = ".gnu.attributes"; + s = subseg_new (name, 0); + elf_section_type (s) + = get_elf_backend_data (stdoutput)->obj_attrs_section_type; + bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA); + frag_now_fix (); + p = frag_more (size); + bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size); + + subsegs_finish_section (s); + relax_segment (seg_info (s)->frchainP->frch_root, s, 0); + size_seg (stdoutput, s, NULL); +} + +#include "struc-symbol.h" + +/* Create a relocation against an entry in a GNU Build attribute section. */ + +static void +create_note_reloc (segT sec, + symbolS * sym, + bfd_size_type offset, + int reloc_type, + bfd_vma addend, + char * note) +{ + struct reloc_list * reloc; + + reloc = XNEW (struct reloc_list); + + /* We create a .b type reloc as resolve_reloc_expr_symbols() has already been called. */ + reloc->u.b.sec = sec; + reloc->u.b.s = sym->bsym; + reloc->u.b.r.sym_ptr_ptr = & reloc->u.b.s; + reloc->u.b.r.address = offset; + reloc->u.b.r.addend = addend; + reloc->u.b.r.howto = bfd_reloc_type_lookup (stdoutput, reloc_type); + + if (reloc->u.b.r.howto == NULL) { - name = get_elf_backend_data (stdoutput)->obj_attrs_section; - if (!name) - name = ".gnu.attributes"; - s = subseg_new (name, 0); - elf_section_type (s) - = get_elf_backend_data (stdoutput)->obj_attrs_section_type; - bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA); - frag_now_fix (); - p = frag_more (size); - bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size); - - subsegs_finish_section (s); - relax_segment (seg_info (s)->frchainP->frch_root, s, 0); - size_seg (stdoutput, s, NULL); + as_bad (_("unable to create reloc for build note")); + return; + } + + reloc->file = N_(""); + reloc->line = 0; + + reloc->next = reloc_list; + reloc_list = reloc; + + /* For REL relocs, store the addend in the section. */ + if (! sec->use_rela_p + /* The SH target is a special case that uses RELA relocs + but still stores the addend in the word being relocated. */ + || strstr (bfd_get_target (stdoutput), "-sh") != NULL) + { + if (target_big_endian) + { + if (bfd_arch_bits_per_address (stdoutput) <= 32) + note[offset + 3] = addend; + else + note[offset + 7] = addend; + } + else + note[offset] = addend; } } -#endif + +static void +maybe_generate_build_notes (void) +{ + segT sec; + char * note; + offsetT note_size; + offsetT desc_size; + offsetT desc2_offset; + int desc_reloc; + symbolS * sym; + + if (! flag_generate_build_notes + || bfd_get_section_by_name (stdoutput, + GNU_BUILD_ATTRS_SECTION_NAME) != NULL) + return; + + /* Create a GNU Build Attribute section. */ + sec = subseg_new (GNU_BUILD_ATTRS_SECTION_NAME, FALSE); + elf_section_type (sec) = SHT_NOTE; + bfd_set_section_flags (stdoutput, sec, + SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA); + bfd_set_section_alignment (stdoutput, sec, 2); + + /* Create a version note. */ + if (bfd_arch_bits_per_address (stdoutput) <= 32) + { + note_size = 28; + desc_size = 8; /* Two 4-byte offsets. */ + desc2_offset = 24; + + /* FIXME: The BFD backend for the CRX target does not support the + BFD_RELOC_32, even though it really should. Likewise for the + CR16 target. So we have special case code here... */ + if (strstr (bfd_get_target (stdoutput), "-crx") != NULL) + desc_reloc = BFD_RELOC_CRX_NUM32; + else if (strstr (bfd_get_target (stdoutput), "-cr16") != NULL) + desc_reloc = BFD_RELOC_CR16_NUM32; + else + desc_reloc = BFD_RELOC_32; + } + else + { + note_size = 36; + desc_size = 16; /* Two 8-byte offsets. */ + desc2_offset = 28; + /* FIXME: The BFD backend for the IA64 target does not support the + BFD_RELOC_64, even though it really should. The HPPA backend + has a similar issue, although it does not support BFD_RELOCs at + all! So we have special case code to handle these targets. */ + if (strstr (bfd_get_target (stdoutput), "-ia64") != NULL) + desc_reloc = target_big_endian ? BFD_RELOC_IA64_DIR32MSB : BFD_RELOC_IA64_DIR32LSB; + else if (strstr (bfd_get_target (stdoutput), "-hppa") != NULL) + desc_reloc = 80; /* R_PARISC_DIR64. */ + else + desc_reloc = BFD_RELOC_64; + } + + frag_now_fix (); + note = frag_more (note_size); + memset (note, 0, note_size); + + if (target_big_endian) + { + note[3] = 8; /* strlen (name) + 1. */ + note[7] = desc_size; /* Two 8-byte offsets. */ + note[10] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8; + note[11] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff; + } + else + { + note[0] = 8; /* strlen (name) + 1. */ + note[4] = desc_size; /* Two 8-byte offsets. */ + note[8] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff; + note[9] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8; + } + + /* The a1 version number indicates that this note was + generated by the assembler and not the gcc annobin plugin. */ + memcpy (note + 12, "GA$3a1", 8); + + /* Find the first code section symbol. */ + for (sym = symbol_rootP; sym != NULL; sym = sym->sy_next) + if (sym->bsym != NULL + && sym->bsym->flags & BSF_SECTION_SYM + && sym->bsym->section != NULL + && sym->bsym->section->flags & SEC_CODE) + { + /* Found one - now create a relocation against this symbol. */ + create_note_reloc (sec, sym, 20, desc_reloc, 0, note); + break; + } + + /* Find the last code section symbol. */ + if (sym) + { + for (sym = symbol_lastP; sym != NULL; sym = sym->sy_previous) + if (sym->bsym != NULL + && sym->bsym->flags & BSF_SECTION_SYM + && sym->bsym->section != NULL + && sym->bsym->section->flags & SEC_CODE) + { + /* Create a relocation against the end of this symbol. */ + create_note_reloc (sec, sym, desc2_offset, desc_reloc, + bfd_get_section_size (sym->bsym->section), + note); + break; + } + } + /* else - if we were unable to find any code section symbols then + probably there is no code in the output. So leaving the start + and end values as zero in the note is OK. */ + + /* FIXME: Maybe add a note recording the assembler command line and version ? */ + + /* Install the note(s) into the section. */ + bfd_set_section_contents (stdoutput, sec, (bfd_byte *) note, 0, note_size); + subsegs_finish_section (sec); + relax_segment (seg_info (sec)->frchainP->frch_root, sec, 0); + size_seg (stdoutput, sec, NULL); +} +#endif /* OBJ_ELF */ /* Write the object file. */ @@ -2097,6 +2272,11 @@ write_object_file (void) resolve_local_symbol_values (); resolve_reloc_expr_symbols (); +#ifdef OBJ_ELF + if (IS_ELF) + maybe_generate_build_notes (); +#endif + PROGRESS (1); #ifdef tc_frob_file_before_adjust @@ -2273,6 +2453,7 @@ write_object_file (void) #ifdef obj_coff_generate_pdata obj_coff_generate_pdata (); #endif + bfd_map_over_sections (stdoutput, write_relocs, (char *) 0); #ifdef tc_frob_file_after_relocs