diff -rup binutils.orig/bfd/elf-bfd.h binutils-2.38/bfd/elf-bfd.h --- binutils.orig/bfd/elf-bfd.h 2022-08-04 11:11:01.755495353 +0100 +++ binutils-2.38/bfd/elf-bfd.h 2022-08-04 11:11:09.149453165 +0100 @@ -1917,6 +1917,14 @@ struct output_elf_obj_tdata asection *sec; } build_id; + /* FDO_PACKAGING_METADATA note type info. */ + struct + { + bool (*after_write_object_contents) (bfd *); + const char *json; + asection *sec; + } package_metadata; + /* Records the result of `get_program_header_size'. */ bfd_size_type program_header_size; Only in binutils-2.38/bfd: elf-bfd.h.orig diff -rup binutils.orig/bfd/elf.c binutils-2.38/bfd/elf.c --- binutils.orig/bfd/elf.c 2022-08-04 11:11:01.771495262 +0100 +++ binutils-2.38/bfd/elf.c 2022-08-04 11:11:09.150453159 +0100 @@ -6762,8 +6762,12 @@ _bfd_elf_write_object_contents (bfd *abf return false; /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0]. */ - if (t->o->build_id.after_write_object_contents != NULL) - return (*t->o->build_id.after_write_object_contents) (abfd); + if (t->o->build_id.after_write_object_contents != NULL + && !(*t->o->build_id.after_write_object_contents) (abfd)) + return false; + if (t->o->package_metadata.after_write_object_contents != NULL + && !(*t->o->package_metadata.after_write_object_contents) (abfd)) + return false; return true; } Only in binutils-2.38/bfd: elf.c.orig diff -rup binutils.orig/elfcpp/elfcpp.h binutils-2.38/elfcpp/elfcpp.h --- binutils.orig/elfcpp/elfcpp.h 2022-08-04 11:11:00.940500003 +0100 +++ binutils-2.38/elfcpp/elfcpp.h 2022-08-04 11:12:26.124013955 +0100 @@ -999,7 +999,9 @@ enum // string. NT_GNU_GOLD_VERSION = 4, // Program property note, as described in "Linux Extensions to the gABI". - NT_GNU_PROPERTY_TYPE_0 = 5 + NT_GNU_PROPERTY_TYPE_0 = 5, + // FDO .note.package notes as defined on https://systemd.io/ELF_PACKAGE_METADATA/ + FDO_PACKAGING_METADATA = 0xcafe1a7e }; // The OS values which may appear in word 0 of a NT_GNU_ABI_TAG note. diff -rup binutils.orig/gold/Makefile.am binutils-2.38/gold/Makefile.am --- binutils.orig/gold/Makefile.am 2022-08-04 11:11:01.788495165 +0100 +++ binutils-2.38/gold/Makefile.am 2022-08-04 11:12:26.124013955 +0100 @@ -35,7 +35,7 @@ THREADFLAGS = @PTHREAD_CFLAGS@ THREADLIBS = @PTHREAD_LIBS@ AM_CFLAGS = $(WARN_CFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) $(ZLIBINC) $(THREADFLAGS) -AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) $(ZLIBINC) $(THREADFLAGS) +AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) $(ZLIBINC) $(THREADFLAGS) $(JANSSON_CFLAGS) AM_LDFLAGS = $(THREADFLAGS) AM_CPPFLAGS = \ @@ -187,7 +187,7 @@ libgold_a_LIBADD = $(LIBOBJS) sources_var = main.cc deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP) ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(GOLD_LDADD) $(LIBINTL) \ - $(THREADLIBS) $(LIBDL) $(ZLIB) + $(THREADLIBS) $(LIBDL) $(ZLIB) $(JANSSON_LIBS) ldflags_var = $(GOLD_LDFLAGS) ld_new_SOURCES = $(sources_var) @@ -201,12 +201,12 @@ incremental_dump_SOURCES = incremental-d incremental_dump_DEPENDENCIES = $(TARGETOBJS) libgold.a $(LIBIBERTY) \ $(LIBINTL_DEP) incremental_dump_LDADD = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \ - $(THREADLIBS) $(LIBDL) $(ZLIB) + $(THREADLIBS) $(LIBDL) $(ZLIB) $(JANSSON_LIBS) dwp_SOURCES = dwp.cc dwp_DEPENDENCIES = libgold.a $(LIBIBERTY) $(LIBINTL_DEP) dwp_LDADD = libgold.a $(LIBIBERTY) $(GOLD_LDADD) $(LIBINTL) $(THREADLIBS) \ - $(LIBDL) $(ZLIB) + $(LIBDL) $(ZLIB) $(JANSSON_LIBS) dwp_LDFLAGS = $(GOLD_LDFLAGS) CONFIG_STATUS_DEPENDENCIES = $(srcdir)/../bfd/development.sh diff -rup binutils.orig/gold/configure.ac binutils-2.38/gold/configure.ac --- binutils.orig/gold/configure.ac 2022-08-04 11:11:01.783495194 +0100 +++ binutils-2.38/gold/configure.ac 2022-08-04 11:12:26.124013955 +0100 @@ -591,6 +591,32 @@ if test "$threads" = "yes"; then fi AM_CONDITIONAL(THREADS, test "$threads" = "yes") +# Used to validate --package-metadata= input. Disabled by default. +AC_ARG_ENABLE([jansson], + [AS_HELP_STRING([--enable-jansson], + [enable jansson [default=no]])], + [enable_jansson=$enableval], + [enable_jansson="no"]) + +if test "x$enable_jansson" != "xno"; then + PKG_PROG_PKG_CONFIG + AS_IF([test -n "$PKG_CONFIG"], + [ + PKG_CHECK_MODULES(JANSSON, [jansson], + [ + AC_DEFINE(HAVE_JANSSON, 1, [The jansson library is to be used]) + AC_SUBST([JANSSON_CFLAGS]) + AC_SUBST([JANSSON_LIBS]) + ], + [ + AC_MSG_ERROR([Cannot find jansson library]) + ]) + ], + [ + AC_MSG_ERROR([Cannot find pkg-config]) + ]) +fi + dnl We have to check these in C, not C++, because autoconf generates dnl tests which have no type information, and current glibc provides dnl multiple declarations of functions like basename when compiling diff -rup binutils.orig/gold/layout.cc binutils-2.38/gold/layout.cc --- binutils.orig/gold/layout.cc 2022-08-04 11:11:01.783495194 +0100 +++ binutils-2.38/gold/layout.cc 2022-08-04 11:12:26.125013949 +0100 @@ -38,6 +38,9 @@ #include #include #endif +#ifdef HAVE_JANSSON +#include +#endif #include "parameters.h" #include "options.h" @@ -2439,6 +2442,7 @@ Layout::create_notes() this->create_gold_note(); this->create_stack_segment(); this->create_build_id(); + this->create_package_metadata(); } // Create the dynamic sections which are needed before we read the @@ -3536,6 +3540,52 @@ Layout::create_build_id() } } +// If --package-metadata was used, set up the package metadata note. +// https://systemd.io/ELF_PACKAGE_METADATA/ + +void +Layout::create_package_metadata() +{ + if (!parameters->options().user_set_package_metadata()) + return; + + const char* desc = parameters->options().package_metadata(); + if (strcmp(desc, "") == 0) + return; + +#ifdef HAVE_JANSSON + json_error_t json_error; + json_t *json = json_loads(desc, 0, &json_error); + if (json) + json_decref(json); + else + { + gold_fatal(_("error: --package-metadata=%s does not contain valid " + "JSON: %s\n"), + desc, json_error.text); + } +#endif + + // Create the note. + size_t trailing_padding; + // Ensure the trailing NULL byte is always included, as per specification. + size_t descsz = strlen(desc) + 1; + Output_section* os = this->create_note("FDO", elfcpp::FDO_PACKAGING_METADATA, + ".note.package", descsz, true, + &trailing_padding); + if (os == NULL) + return; + + Output_section_data* posd = new Output_data_const(desc, descsz, 4); + os->add_output_section_data(posd); + + if (trailing_padding != 0) + { + posd = new Output_data_zero_fill(trailing_padding, 0); + os->add_output_section_data(posd); + } +} + // If we have both .stabXX and .stabXXstr sections, then the sh_link // field of the former should point to the latter. I'm not sure who // started this, but the GNU linker does it, and some tools depend Only in binutils-2.38/gold: layout.cc.orig diff -rup binutils.orig/gold/layout.h binutils-2.38/gold/layout.h --- binutils.orig/gold/layout.h 2022-08-04 11:11:01.788495165 +0100 +++ binutils-2.38/gold/layout.h 2022-08-04 11:12:26.125013949 +0100 @@ -1107,6 +1107,10 @@ class Layout void create_build_id(); + // Create a package metadata note if needed. + void + create_package_metadata(); + // Link .stab and .stabstr sections. void link_stabs_sections(); @@ -1453,6 +1457,8 @@ class Layout Gdb_index* gdb_index_data_; // The space for the build ID checksum if there is one. Output_section_data* build_id_note_; + // The space for the package metadata JSON if there is one. + Output_section_data* package_metadata_note_; // The output section containing dwarf abbreviations Output_reduced_debug_abbrev_section* debug_abbrev_; // The output section containing the dwarf debug info tree diff -rup binutils.orig/gold/options.h binutils-2.38/gold/options.h --- binutils.orig/gold/options.h 2022-08-04 11:11:01.785495182 +0100 +++ binutils-2.38/gold/options.h 2022-08-04 11:12:26.125013949 +0100 @@ -1102,6 +1102,10 @@ class General_options DEFINE_bool(p, options::ONE_DASH, 'p', false, N_("Ignored for ARM compatibility"), NULL); + DEFINE_optional_string(package_metadata, options::TWO_DASHES, '\0', NULL, + N_("Generate package metadata note"), + N_("[=JSON]")); + DEFINE_bool(pie, options::ONE_DASH, '\0', false, N_("Create a position independent executable"), N_("Do not create a position independent executable")); diff -rup binutils.orig/gold/testsuite/Makefile.am binutils-2.38/gold/testsuite/Makefile.am --- binutils.orig/gold/testsuite/Makefile.am 2022-08-04 11:11:01.802495085 +0100 +++ binutils-2.38/gold/testsuite/Makefile.am 2022-08-04 11:12:26.126013943 +0100 @@ -149,25 +149,25 @@ check_PROGRAMS += object_unittest object_unittest_SOURCES = object_unittest.cc object_unittest_LDFLAGS = $(THREADFLAGS) object_unittest_LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ - $(THREADLIBS) $(LIBDL) $(ZLIB) + $(THREADLIBS) $(LIBDL) $(ZLIB) $(JANSSON_LIBS) check_PROGRAMS += binary_unittest binary_unittest_SOURCES = binary_unittest.cc binary_unittest_LDFLAGS = $(THREADFLAGS) binary_unittest_LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ - $(THREADLIBS) $(LIBDL) $(ZLIB) + $(THREADLIBS) $(LIBDL) $(ZLIB) $(JANSSON_LIBS) check_PROGRAMS += leb128_unittest leb128_unittest_SOURCES = leb128_unittest.cc leb128_unittest_LDFLAGS = $(THREADFLAGS) leb128_unittest_LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ - $(THREADLIBS) $(LIBDL) $(ZLIB) + $(THREADLIBS) $(LIBDL) $(ZLIB) $(JANSSON_LIBS) check_PROGRAMS += overflow_unittest overflow_unittest_SOURCES = overflow_unittest.cc overflow_unittest_LDFLAGS = $(THREADFLAGS) overflow_unittest_LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ - $(THREADLIBS) $(LIBDL) $(ZLIB) + $(THREADLIBS) $(LIBDL) $(ZLIB) $(JANSSON_LIBS) overflow_unittest.o: overflow_unittest.cc $(CXXCOMPILE) -O3 -c -o $@ $< @@ -4435,3 +4435,10 @@ retain_2.o: retain_2.s $(TEST_AS) -o $@ $< endif DEFAULT_TARGET_X86_64 + +check_PROGRAMS += package_metadata_test +package_metadata_test.o: package_metadata_main.c + $(COMPILE) -c -o $@ $< +package_metadata_test$(EXEEXT): package_metadata_test.o gcctestdir/ld + $(CXXLINK) package_metadata_test.o -Wl,--package-metadata='{"foo":"bar"}' + $(TEST_READELF) --notes $@ | grep -q '{"foo":"bar"}' Only in binutils-2.38/gold/testsuite: package_metadata_main.c diff -rup binutils.orig/ld/Makefile.am binutils-2.38/ld/Makefile.am --- binutils.orig/ld/Makefile.am 2022-08-04 11:11:01.311497887 +0100 +++ binutils-2.38/ld/Makefile.am 2022-08-04 11:11:09.150453159 +0100 @@ -46,7 +46,7 @@ ELF_CLFAGS=-DELF_LIST_OPTIONS=@elf_list_ -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@ WARN_CFLAGS = @WARN_CFLAGS@ NO_WERROR = @NO_WERROR@ -AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) +AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS) # We put the scripts in the directory $(scriptdir)/ldscripts. # We can't put the scripts in $(datadir) because the SEARCH_DIR @@ -973,8 +973,8 @@ ld_new_SOURCES = ldgram.y ldlex-wrapper. ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c plugin.c \ ldbuildid.c ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) \ - $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP) -ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB) + $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP) $(JANSSON_LIBS) +ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB) $(JANSSON_LIBS) # Dependency tracking for the generated emulation files. EXTRA_ld_new_SOURCES += $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES) Only in binutils-2.38/ld: Makefile.am.orig diff -rup binutils.orig/ld/Makefile.in binutils-2.38/ld/Makefile.in --- binutils.orig/ld/Makefile.in 2022-08-04 11:11:01.310497892 +0100 +++ binutils-2.38/ld/Makefile.in 2022-08-04 11:11:09.150453159 +0100 @@ -122,6 +122,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../b $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/nls.m4 \ $(top_srcdir)/../config/override.m4 \ + $(top_srcdir)/../config/pkg.m4 \ $(top_srcdir)/../config/plugins.m4 \ $(top_srcdir)/../config/po.m4 \ $(top_srcdir)/../config/progtest.m4 \ @@ -405,6 +406,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ LARGEFILE_CPPFLAGS = @LARGEFILE_CPPFLAGS@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -450,6 +453,9 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSUB = @POSUB@ RANLIB = @RANLIB@ SED = @SED@ @@ -558,7 +564,7 @@ ELF_CLFAGS = -DELF_LIST_OPTIONS=@elf_lis -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \ -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@ -AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) +AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS) # We put the scripts in the directory $(scriptdir)/ldscripts. # We can't put the scripts in $(datadir) because the SEARCH_DIR @@ -1010,9 +1016,9 @@ ld_new_SOURCES = ldgram.y ldlex-wrapper. ldbuildid.c ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) \ - $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP) + $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP) $(JANSSON_LIBS) -ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB) +ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB) $(JANSSON_LIBS) # # # Build a dummy plugin using libtool. Only in binutils-2.38/ld: Makefile.in.orig diff -rup binutils.orig/ld/NEWS binutils-2.38/ld/NEWS --- binutils.orig/ld/NEWS 2022-08-04 11:11:01.323497818 +0100 +++ binutils-2.38/ld/NEWS 2022-08-04 11:11:09.150453159 +0100 @@ -3,6 +3,12 @@ * TYPE= is now supported in an output section description to set the section type value. +* The ELF linker now supports a new --package-metadata option that allows + embedding a JSON payload in accordance to the Package Metadata specification. + If support for libjansson is enabled at build time, the linker will use it to + validate the input. This can be enabled with --enable-jansson. + For more details, see: https://systemd.io/ELF_PACKAGE_METADATA/ + Changes in 2.38: * Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF Only in binutils-2.38/ld: NEWS.orig diff -rup binutils.orig/ld/aclocal.m4 binutils-2.38/ld/aclocal.m4 --- binutils.orig/ld/aclocal.m4 2022-08-04 11:11:01.024499524 +0100 +++ binutils-2.38/ld/aclocal.m4 2022-08-04 11:11:09.150453159 +0100 @@ -1198,6 +1198,7 @@ m4_include([../config/lcmessage.m4]) m4_include([../config/lead-dot.m4]) m4_include([../config/nls.m4]) m4_include([../config/override.m4]) +m4_include([../config/pkg.m4]) m4_include([../config/plugins.m4]) m4_include([../config/po.m4]) m4_include([../config/progtest.m4]) diff -rup binutils.orig/ld/config.in binutils-2.38/ld/config.in --- binutils.orig/ld/config.in 2022-08-04 11:11:01.023499530 +0100 +++ binutils-2.38/ld/config.in 2022-08-04 11:11:09.151453154 +0100 @@ -88,6 +88,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* The jansson library is to be used */ +#undef HAVE_JANSSON + /* Define if your file defines LC_MESSAGES. */ #undef HAVE_LC_MESSAGES Only in binutils-2.38/ld: config.in.orig diff -rup binutils.orig/ld/configure binutils-2.38/ld/configure --- binutils.orig/ld/configure 2022-08-04 11:11:01.023499530 +0100 +++ binutils-2.38/ld/configure 2022-08-04 11:11:09.153453142 +0100 @@ -677,6 +677,11 @@ WARN_WRITE_STRINGS NO_WERROR WARN_CFLAGS_FOR_BUILD WARN_CFLAGS +JANSSON_LIBS +JANSSON_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG enable_libctf ENABLE_LIBCTF_FALSE ENABLE_LIBCTF_TRUE @@ -842,6 +847,7 @@ enable_error_handling_script enable_default_hash_style enable_initfini_array enable_libctf +enable_jansson enable_werror enable_build_warnings enable_nls @@ -860,6 +866,11 @@ CXXFLAGS CCC CPP CXXCPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +JANSSON_CFLAGS +JANSSON_LIBS YACC YFLAGS' @@ -1517,6 +1528,7 @@ Optional Features: use this default hash style --disable-initfini-array do not use .init_array/.fini_array sections --enable-libctf Handle .ctf type-info sections [default=yes] + --enable-jansson enable jansson [default=no] --enable-werror treat compile warnings as errors --enable-build-warnings enable build-time compiler warnings --disable-nls do not use Native Language Support @@ -1543,6 +1555,15 @@ Some influential environment variables: CXXFLAGS C++ compiler flags CPP C preprocessor CXXCPP C++ preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + JANSSON_CFLAGS + C compiler flags for JANSSON, overriding pkg-config + JANSSON_LIBS + linker flags for JANSSON, overriding pkg-config YACC The `Yet Another Compiler Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. @@ -15529,6 +15550,251 @@ fi +# Used to validate --package-metadata= input. Disabled by default. +# Check whether --enable-jansson was given. +if test "${enable_jansson+set}" = set; then : + enableval=$enable_jansson; enable_jansson=$enableval +else + enable_jansson="no" +fi + + +if test "x$enable_jansson" != "xno"; then + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + if test -n "$PKG_CONFIG"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for jansson" >&5 +$as_echo_n "checking for jansson... " >&6; } + +if test -n "$JANSSON_CFLAGS"; then + pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson\""; } >&5 + ($PKG_CONFIG --exists --print-errors "jansson") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_JANSSON_CFLAGS=`$PKG_CONFIG --cflags "jansson" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$JANSSON_LIBS"; then + pkg_cv_JANSSON_LIBS="$JANSSON_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson\""; } >&5 + ($PKG_CONFIG --exists --print-errors "jansson") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_JANSSON_LIBS=`$PKG_CONFIG --libs "jansson" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + +if test $pkg_failed = no; then + pkg_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $pkg_cv_JANSSON_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + pkg_failed=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$pkg_save_LDFLAGS +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + JANSSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "jansson" 2>&1` + else + JANSSON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "jansson" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$JANSSON_PKG_ERRORS" >&5 + + + as_fn_error $? "Cannot find jansson library" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + as_fn_error $? "Cannot find jansson library" "$LINENO" 5 + +else + JANSSON_CFLAGS=$pkg_cv_JANSSON_CFLAGS + JANSSON_LIBS=$pkg_cv_JANSSON_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_JANSSON 1" >>confdefs.h + + + + +fi + +else + + as_fn_error $? "Cannot find pkg-config" "$LINENO" 5 + +fi +fi + # Set the 'development' global. . $srcdir/../bfd/development.sh diff -rup binutils.orig/ld/configure.ac binutils-2.38/ld/configure.ac --- binutils.orig/ld/configure.ac 2022-08-04 11:11:01.323497818 +0100 +++ binutils-2.38/ld/configure.ac 2022-08-04 11:11:09.153453142 +0100 @@ -258,6 +258,32 @@ fi AM_CONDITIONAL(ENABLE_LIBCTF, test "${enable_libctf}" = yes) AC_SUBST(enable_libctf) +# Used to validate --package-metadata= input. Disabled by default. +AC_ARG_ENABLE([jansson], + [AS_HELP_STRING([--enable-jansson], + [enable jansson [default=no]])], + [enable_jansson=$enableval], + [enable_jansson="no"]) + +if test "x$enable_jansson" != "xno"; then + PKG_PROG_PKG_CONFIG + AS_IF([test -n "$PKG_CONFIG"], + [ + PKG_CHECK_MODULES(JANSSON, [jansson], + [ + AC_DEFINE(HAVE_JANSSON, 1, [The jansson library is to be used]) + AC_SUBST([JANSSON_CFLAGS]) + AC_SUBST([JANSSON_LIBS]) + ], + [ + AC_MSG_ERROR([Cannot find jansson library]) + ]) + ], + [ + AC_MSG_ERROR([Cannot find pkg-config]) + ]) +fi + AM_BINUTILS_WARNINGS AM_LC_MESSAGES Only in binutils-2.38/ld: configure.ac.orig Only in binutils-2.38/ld: configure.orig Only in binutils-2.38/ld: configure.rej diff -rup binutils.orig/ld/emultempl/elf.em binutils-2.38/ld/emultempl/elf.em --- binutils.orig/ld/emultempl/elf.em 2022-08-04 11:11:01.027499507 +0100 +++ binutils-2.38/ld/emultempl/elf.em 2022-08-04 11:11:09.153453142 +0100 @@ -556,6 +556,7 @@ enum elf_options OPTION_EXCLUDE_LIBS, OPTION_HASH_STYLE, OPTION_BUILD_ID, + OPTION_PACKAGE_METADATA, OPTION_AUDIT, OPTION_COMPRESS_DEBUG }; @@ -586,6 +587,7 @@ EOF fi fragment < 0) + ldelf_emit_note_fdo_package_metadata = xstrdup (optarg); + break; + case OPTION_COMPRESS_DEBUG: if (strcasecmp (optarg, "none") == 0) link_info.compress_debug = COMPRESS_DEBUG_NONE; Only in binutils-2.38/ld/emultempl: elf.em.orig diff -rup binutils.orig/ld/ld.texi binutils-2.38/ld/ld.texi --- binutils.orig/ld/ld.texi 2022-08-04 11:11:01.311497887 +0100 +++ binutils-2.38/ld/ld.texi 2022-08-04 11:11:09.154453136 +0100 @@ -2892,6 +2892,18 @@ string identifying the original linked f Passing @code{none} for @var{style} disables the setting from any @code{--build-id} options earlier on the command line. + +@kindex --package-metadata=@var{JSON} +@item --package-metadata=@var{JSON} +Request the creation of a @code{.note.package} ELF note section. The +contents of the note are in JSON format, as per the package metadata +specification. For more information see: +https://systemd.io/ELF_PACKAGE_METADATA/ +If the JSON argument is missing/empty then this will disable the +creation of the metadata note, if one had been enabled by an earlier +occurrence of the --package-metdata option. +If the linker has been built with libjansson, then the JSON string +will be validated. @end table @c man end Only in binutils-2.38/ld: ld.texi.orig diff -rup binutils.orig/ld/ldelf.c binutils-2.38/ld/ldelf.c --- binutils.orig/ld/ldelf.c 2022-08-04 11:11:01.311497887 +0100 +++ binutils-2.38/ld/ldelf.c 2022-08-04 11:11:09.154453136 +0100 @@ -39,6 +39,9 @@ #include #endif #include "ldelf.h" +#ifdef HAVE_JANSSON +#include +#endif struct dt_needed { @@ -49,6 +52,9 @@ struct dt_needed /* Style of .note.gnu.build-id section. */ const char *ldelf_emit_note_gnu_build_id; +/* Content of .note.package section. */ +const char *ldelf_emit_note_fdo_package_metadata; + /* These variables are required to pass information back and forth between after_open and check_needed and stat_needed and vercheck. */ @@ -1037,7 +1043,8 @@ ldelf_after_open (int use_libpath, int n } } - if (ldelf_emit_note_gnu_build_id != NULL) + if (ldelf_emit_note_gnu_build_id != NULL + || ldelf_emit_note_fdo_package_metadata != NULL) { /* Find an ELF input. */ for (abfd = link_info.input_bfds; @@ -1050,11 +1057,20 @@ ldelf_after_open (int use_libpath, int n /* PR 10555: If there are no ELF input files do not try to create a .note.gnu-build-id section. */ if (abfd == NULL - || !ldelf_setup_build_id (abfd)) + || (ldelf_emit_note_gnu_build_id != NULL + && !ldelf_setup_build_id (abfd))) { free ((char *) ldelf_emit_note_gnu_build_id); ldelf_emit_note_gnu_build_id = NULL; } + + if (abfd == NULL + || (ldelf_emit_note_fdo_package_metadata != NULL + && !ldelf_setup_package_metadata (abfd))) + { + free ((char *) ldelf_emit_note_fdo_package_metadata); + ldelf_emit_note_fdo_package_metadata = NULL; + } } get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info); @@ -1466,6 +1482,121 @@ ldelf_setup_build_id (bfd *ibfd) return false; } +static bool +write_package_metadata (bfd *abfd) +{ + struct elf_obj_tdata *t = elf_tdata (abfd); + const char *json; + asection *asec; + Elf_Internal_Shdr *i_shdr; + unsigned char *contents, *json_bits; + bfd_size_type size; + file_ptr position; + Elf_External_Note *e_note; + + json = t->o->package_metadata.json; + asec = t->o->package_metadata.sec; + if (bfd_is_abs_section (asec->output_section)) + { + einfo (_("%P: warning: .note.package section discarded," + " --package-metadata ignored\n")); + return true; + } + i_shdr = &elf_section_data (asec->output_section)->this_hdr; + + if (i_shdr->contents == NULL) + { + if (asec->contents == NULL) + asec->contents = (unsigned char *) xmalloc (asec->size); + contents = asec->contents; + } + else + contents = i_shdr->contents + asec->output_offset; + + e_note = (Elf_External_Note *) contents; + size = offsetof (Elf_External_Note, name[sizeof "FDO"]); + size = (size + 3) & -(bfd_size_type) 4; + json_bits = contents + size; + size = asec->size - size; + + /* Clear the package metadata field. */ + memset (json_bits, 0, size); + + bfd_h_put_32 (abfd, sizeof "FDO", &e_note->namesz); + bfd_h_put_32 (abfd, size, &e_note->descsz); + bfd_h_put_32 (abfd, FDO_PACKAGING_METADATA, &e_note->type); + memcpy (e_note->name, "FDO", sizeof "FDO"); + memcpy (json_bits, json, strlen(json)); + + position = i_shdr->sh_offset + asec->output_offset; + size = asec->size; + return (bfd_seek (abfd, position, SEEK_SET) == 0 + && bfd_bwrite (contents, size, abfd) == size); +} + +/* Make .note.package section. + https://systemd.io/ELF_PACKAGE_METADATA/ */ + +bool +ldelf_setup_package_metadata (bfd *ibfd) +{ + asection *s; + bfd_size_type size; + size_t json_length; + flagword flags; + + /* If the option wasn't specified, silently return. */ + if (!ldelf_emit_note_fdo_package_metadata) + return false; + + /* The option was specified, but it's empty, log and return. */ + json_length = strlen (ldelf_emit_note_fdo_package_metadata); + if (json_length == 0) + { + einfo (_("%P: warning: --package-metadata is empty, ignoring\n")); + return false; + } + +#ifdef HAVE_JANSSON + json_error_t json_error; + json_t *json = json_loads (ldelf_emit_note_fdo_package_metadata, + 0, &json_error); + if (!json) + { + einfo (_("%P: warning: --package-metadata=%s does not contain valid " + "JSON, ignoring: %s\n"), + ldelf_emit_note_fdo_package_metadata, json_error.text); + return false; + } + else + json_decref (json); +#endif + + size = offsetof (Elf_External_Note, name[sizeof "FDO"]); + size += json_length + 1; + size = (size + 3) & -(bfd_size_type) 4; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY + | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA); + s = bfd_make_section_anyway_with_flags (ibfd, ".note.package", + flags); + if (s != NULL && bfd_set_section_alignment (s, 2)) + { + struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd); + t->o->package_metadata.after_write_object_contents + = &write_package_metadata; + t->o->package_metadata.json = ldelf_emit_note_fdo_package_metadata; + t->o->package_metadata.sec = s; + elf_section_type (s) = SHT_NOTE; + s->size = size; + return true; + } + + einfo (_("%P: warning: cannot create .note.package section," + " --package-metadata ignored\n")); + return false; +} + /* Look through an expression for an assignment statement. */ static void Only in binutils-2.38/ld: ldelf.c.orig diff -rup binutils.orig/ld/ldelf.h binutils-2.38/ld/ldelf.h --- binutils.orig/ld/ldelf.h 2022-08-04 11:11:01.026499513 +0100 +++ binutils-2.38/ld/ldelf.h 2022-08-04 11:11:09.154453136 +0100 @@ -19,11 +19,13 @@ MA 02110-1301, USA. */ extern const char *ldelf_emit_note_gnu_build_id; +extern const char *ldelf_emit_note_fdo_package_metadata; extern void ldelf_after_parse (void); extern bool ldelf_load_symbols (lang_input_statement_type *); extern void ldelf_after_open (int, int, int, int, int, const char *); extern bool ldelf_setup_build_id (bfd *); +extern bool ldelf_setup_package_metadata (bfd *); extern void ldelf_append_to_separated_string (char **, char *); extern void ldelf_before_allocation (char *, char *, const char *); extern bool ldelf_open_dynamic_archive Only in binutils-2.38/ld: ldelf.h.orig diff -rup binutils.orig/ld/lexsup.c binutils-2.38/ld/lexsup.c --- binutils.orig/ld/lexsup.c 2022-08-04 11:11:01.024499524 +0100 +++ binutils-2.38/ld/lexsup.c 2022-08-04 11:11:09.154453136 +0100 @@ -2124,6 +2124,8 @@ elf_static_list_options (FILE *file) fprintf (file, _("\ --build-id[=STYLE] Generate build ID note\n")); fprintf (file, _("\ + --package-metadata[=JSON] Generate package metadata note\n")); + fprintf (file, _("\ --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi]\n\ Compress DWARF debug sections using zlib\n")); #ifdef DEFAULT_FLAG_COMPRESS_DEBUG Only in binutils-2.38/ld: lexsup.c.orig diff -rup binutils.orig/ld/testsuite/ld-bootstrap/bootstrap.exp binutils-2.38/ld/testsuite/ld-bootstrap/bootstrap.exp --- binutils.orig/ld/testsuite/ld-bootstrap/bootstrap.exp 2022-08-04 11:11:01.063499301 +0100 +++ binutils-2.38/ld/testsuite/ld-bootstrap/bootstrap.exp 2022-08-04 11:11:09.154453136 +0100 @@ -155,6 +155,12 @@ foreach flags $test_flags { set extralibs "$extralibs -lz" } + # Check if the system's jansson library is used. If so, the object files will + # be using symbols from it, so link to it. + if { [lindex [remote_exec build grep "-q \"HAVE_JANSSON 1\" config.h" ] 0] == 0 } then { + set extralibs "$extralibs -ljansson" + } + # Plugin support requires linking with libdl. if { $plugins == "yes" } { if { ![istarget "*-*-freebsd*"]} { Only in binutils-2.38/ld/testsuite/ld-elf: package-note.exp Only in binutils-2.38/ld/testsuite/ld-elf: package-note.rd