From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by sourceware.org (Postfix) with ESMTPS id 618423858407 for ; Tue, 26 Jul 2022 19:22:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 618423858407 Received: by mail-wm1-x330.google.com with SMTP id r1-20020a05600c35c100b003a326685e7cso1293154wmq.1 for ; Tue, 26 Jul 2022 12:22:24 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=TdKBS9cmEGJs/zmgjEftDCcwLOY0JcpMObljfkB0CDA=; b=f0w7/+BcAVYKriVIsi5guNX7UVMBOBiaR1YYrPghm4HMSolXgPdm32to5l1PByWf57 ogTExy/VjjLavMAT2/vcrkverukSbOQeAEhQSAkDJ7cw+GR3Q0697P0lFiGmTpEkQxkE NuMWnN5QLV82/QfWAGSLHrELER0/pVWGTHtTqhGxntxkHZcJERp9k/QK5KVV3hmHxfoQ jNGpxd/qJq8awlzpWXYlQiIMAuhbkKRd3/UUlEAtHF+Ct+nR9FHQgR5odoG2JwjkVsRP ZWTdDd8LpQUzDS79hUXkzHw9JiHuBtP3iEmM5DOuDG4Azzn1zX7VbGLPx1XWDzsMfHMn DLcQ== X-Gm-Message-State: AJIora95yrxrF6R73AXXG7M3+AM15BX2b6/dHN380uMMIdHmrhSu5Y4y ti7vbFI7bp3VQ59azU7Amjxa/WLJtGY= X-Google-Smtp-Source: AGRyM1sPCwl+BHl5eaIEcK8ofNWEaaRXU8d6qPcUoImYvjdEX93A77PBSn7GMkIcvkuyGiwgShbzqQ== X-Received: by 2002:a05:600c:4f88:b0:3a3:30b7:4921 with SMTP id n8-20020a05600c4f8800b003a330b74921mr480589wmq.16.1658863342752; Tue, 26 Jul 2022 12:22:22 -0700 (PDT) Received: from localhost ([137.220.125.106]) by smtp.gmail.com with ESMTPSA id r11-20020a5d498b000000b0021e42e7c7dbsm15627407wrq.83.2022.07.26.12.22.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Jul 2022 12:22:22 -0700 (PDT) From: luca.boccassi@gmail.com To: binutils@sourceware.org Subject: [PATCH] gold: add --package-metadata Date: Tue, 26 Jul 2022 20:22:16 +0100 Message-Id: <20220726192216.1751042-1-luca.boccassi@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Jul 2022 19:22:30 -0000 From: Luca Boccassi Following the same format as the implementation in ld: 9e2bb0cb5e74aed4158f08495534922d7108f928 Generate a .note.package FDO package metadata ELF note, following the spec: https://systemd.io/ELF_PACKAGE_METADATA/ If the jansson library is available at build time (and it is explicitly enabled), link ld to it, and use it to validate that the input is correct JSON, to avoid writing garbage to the file. The configure option --enable-jansson has to be used to explicitly enable it (error out when not found). This allows bootstrappers (or others who are not interested) to seamlessly skip it without issues. --- Re-sending after rebase, no changes. The same functionality was added to ld: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=9e2bb0cb5e74aed4158f08495534922d7108f928 elfcpp/elfcpp.h | 4 ++- gold/Makefile.am | 8 ++--- gold/configure.ac | 26 ++++++++++++++ gold/layout.cc | 48 ++++++++++++++++++++++++++ gold/layout.h | 6 ++++ gold/options.h | 4 +++ gold/testsuite/Makefile.am | 15 +++++--- gold/testsuite/package_metadata_main.c | 5 +++ 8 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 gold/testsuite/package_metadata_main.c diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index 4b0aff0da7f..3ca2d614947 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -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 --git a/gold/Makefile.am b/gold/Makefile.am index 2e406716f29..934e3669977 100644 --- a/gold/Makefile.am +++ b/gold/Makefile.am @@ -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-dump.cc 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 --git a/gold/configure.ac b/gold/configure.ac index 4f432809b37..25fae6b998b 100644 --- a/gold/configure.ac +++ b/gold/configure.ac @@ -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 --git a/gold/layout.cc b/gold/layout.cc index 3efe8d98ae9..ece14a07088 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -38,6 +38,9 @@ #include #include #endif +#ifdef HAVE_JANSSON +#include +#endif #include "parameters.h" #include "options.h" @@ -2437,6 +2440,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 @@ -3534,6 +3538,50 @@ 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) + gold_fatal(_("error: --package-metadata=%s does not contain valid " + "JSON: %s\n"), + desc, json_error.text); + else + json_decref (json); +#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 diff --git a/gold/layout.h b/gold/layout.h index 98c03b93f5f..ee4f78c3c78 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -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 --git a/gold/options.h b/gold/options.h index 9509a445e8e..17236eb9cb9 100644 --- a/gold/options.h +++ b/gold/options.h @@ -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 --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 38e54818f48..b15000ee7f3 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -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"}' diff --git a/gold/testsuite/package_metadata_main.c b/gold/testsuite/package_metadata_main.c new file mode 100644 index 00000000000..77bc677e8eb --- /dev/null +++ b/gold/testsuite/package_metadata_main.c @@ -0,0 +1,5 @@ +int +main(void) +{ + return 0; +} -- 2.34.1