Extend the assembler so that it can automatically generate GNU Build attribute notes...
authorNick Clifton <nickc@redhat.com>
Thu, 26 Apr 2018 14:12:42 +0000 (15:12 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 26 Apr 2018 14:12:42 +0000 (15:12 +0100)
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.

15 files changed:
binutils/ChangeLog
binutils/readelf.c
binutils/testsuite/binutils-all/note-5.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-5.s [new file with mode: 0644]
binutils/testsuite/binutils-all/objcopy.exp
gas/ChangeLog
gas/NEWS
gas/as.c
gas/as.h
gas/config.in
gas/configure
gas/configure.ac
gas/doc/as.texinfo
gas/symbols.c
gas/write.c

index 702c0cfbedf479047b7f49d5cad92622ae1d1cbc..3b98be4aaec384865921cf4d0c56309e0fbf7185 100644 (file)
@@ -1,3 +1,11 @@
+2018-04-26  Nick Clifton  <nickc@redhat.com>
+
+       * 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  <christophe.lyon@st.com>
 
        * testsuite/binutils-all/elfedit-2.d: Accept arm*-*-uclinuxfdpiceabi.
index e8e1b9681eb894ab6597000208542f3d9ab01327..eecc05b3fa65246809004ca651e9799ba958ffd3 100644 (file)
@@ -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 (file)
index 0000000..d3bef15
--- /dev/null
@@ -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\$<version>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 (file)
index 0000000..4375b25
--- /dev/null
@@ -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
index 2a2e757a92f12d6ade11fad66a072dc0b89b0633..33812369a43230c0649823d847fd3cafacbb763a 100644 (file)
@@ -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"
index 4801b59ced91d6c85a11a5e066a72c07e5b6d617..d3ce68fbe01f777395f37972c51707384a27645e 100644 (file)
@@ -1,3 +1,23 @@
+2018-04-26  Nick Clifton  <nickc@redhat.com>
+
+       * 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  <jbeulich@suse.com>
 
        * 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.
index 4cb6d738c30892398761b317c69256967355ad1f..ec1ba78a66a268de156cad06d89adcf087bec868 100644 (file)
--- 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
index 6e8ec5678556e8b41f52d9f80a7398fa7d2ca80c..cdf8cfed487a432b75f9d9a766ffd43721a08e7b 100644 (file)
--- 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;
index d75ff425231354951b6fb2a78310714b1c4121e3..52bb5a79a71dd3d5af274a83449d296e9ee79331 100644 (file)
--- 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
index fcadc4ae5c33c3ab91005485cd9bb9dd70cd9ec3..60bfcc93e7eaa6e07d6f6b78a2c627ad39a71829 100644 (file)
 /* 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
index a45e531fec36efb86207e4cc0c76ad9a8467cd67..ea6b3b16a8647c1b7f530b7219cc6c85c83b384a 100755 (executable)
@@ -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
index 4a84f16f519d6ae2aa88ebc1e62a621b44b49071..a639422026ca7444d3c66b0ac923ba746afde0e2 100644 (file)
@@ -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
index e1ff8515ab265fd287f2898ad002e73af10defa7..35616c8b55d37c46728898c3d6d50ed229e805c5 100644 (file)
@@ -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
index 96bf9637c33c12449d40e1ac014417237107c2b2..40888379de82be16663424608c0567647448e243 100644 (file)
@@ -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 (&notes, name, name_length);
   ret = (char *) obstack_finish (&notes);
index 2d0bbe4601d3599339d6fee5c0ebad1cd79a5193..b902bf85659024d9f6124fa817cf42bebc7d9ed9 100644 (file)
@@ -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_("<gnu build note>");
+  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$\ 13a1", 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