analyze: Add dlopen-metadata verb

systemd-analyze dlopen-metadata will show dlopen metadata
in the ELF binary.
This commit is contained in:
Daan De Meyer
2025-10-30 11:58:23 +01:00
parent da30f59f60
commit 0fe29d0672
6 changed files with 98 additions and 0 deletions
+10
View File
@@ -915,6 +915,16 @@ alias.service:7: Unknown key name 'MysteryKey' in section 'Service', ignoring.
</example>
</refsect2>
<refsect2>
<title><command>systemd-analyze dlopen-metadata <replaceable>FILE</replaceable></command></title>
<para>This command will load the specified file, and if it is an ELF object (executables,
libraries, core files, etc.) it will parse the embedded dlopen metadata, if any, and print
it in a table or json format. See the
<ulink url="https://systemd.io/ELF_DLOPEN_METADATA/">
dlopen() Metadata for ELF Files</ulink> document for more information.</para>
</refsect2>
<refsect2>
<title><command>systemd-analyze fdstore <replaceable>UNIT</replaceable>...</command></title>
+72
View File
@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-json.h"
#include "alloc-util.h"
#include "analyze.h"
#include "analyze-dlopen-metadata.h"
#include "chase.h"
#include "elf-util.h"
#include "fd-util.h"
#include "format-table.h"
#include "json-util.h"
#include "strv.h"
int verb_dlopen_metadata(int argc, char *argv[], void *userdata) {
int r;
_cleanup_free_ char *abspath = NULL;
_cleanup_close_ int fd = -EBADF;
fd = chase_and_open(argv[1], arg_root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC, &abspath);
if (fd < 0)
return log_error_errno(fd, "Could not open \"%s\": %m", argv[1]);
_cleanup_(sd_json_variant_unrefp) sd_json_variant *dlopen_metadata = NULL;
r = parse_elf_object(
fd,
abspath,
arg_root,
/* fork_disable_dump= */ false,
/* ret= */ NULL,
NULL,
&dlopen_metadata);
if (r < 0)
return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath);
if (!dlopen_metadata)
return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "%s does not contain any .note.dlopen sections", argv[1]);
if (sd_json_format_enabled(arg_json_format_flags))
return sd_json_variant_dump(dlopen_metadata, arg_json_format_flags, stdout, NULL);
_cleanup_(table_unrefp) Table *t = NULL;
t = table_new("feature", "description", "soname", "priority");
if (!t)
return log_oom();
table_set_ersatz_string(t, TABLE_ERSATZ_NA);
sd_json_variant *z;
JSON_VARIANT_ARRAY_FOREACH(z, dlopen_metadata) {
_cleanup_strv_free_ char **sonames = NULL;
r = sd_json_variant_strv(sd_json_variant_by_key(z, "soname"), &sonames);
if (r < 0)
return log_error_errno(r, "Failed to extract sonames from dlopen metadata: %m");
r = table_add_many(
t,
TABLE_STRING, sd_json_variant_string(sd_json_variant_by_key(z, "feature")),
TABLE_STRING, sd_json_variant_string(sd_json_variant_by_key(z, "description")),
TABLE_STRV_WRAPPED, sonames,
TABLE_STRING, sd_json_variant_string(sd_json_variant_by_key(z, "priority")));
if (r < 0)
return table_log_add_error(r);
}
r = table_print(t, NULL);
if (r < 0)
return table_log_print_error(r);
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int verb_dlopen_metadata(int argc, char *argv[], void *userdata);
+2
View File
@@ -22,6 +22,7 @@
#include "analyze-compare-versions.h"
#include "analyze-condition.h"
#include "analyze-critical-chain.h"
#include "analyze-dlopen-metadata.h"
#include "analyze-dot.h"
#include "analyze-dump.h"
#include "analyze-exit-status.h"
@@ -798,6 +799,7 @@ static int run(int argc, char *argv[]) {
{ "timespan", 2, VERB_ANY, 0, verb_timespan },
{ "security", VERB_ANY, VERB_ANY, 0, verb_security },
{ "inspect-elf", 2, VERB_ANY, 0, verb_elf_inspection },
{ "dlopen-metadata", 2, 2, 0, verb_dlopen_metadata },
{ "malloc", VERB_ANY, VERB_ANY, 0, verb_malloc },
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
{ "image-policy", 2, 2, 0, verb_image_policy },
+1
View File
@@ -10,6 +10,7 @@ systemd_analyze_sources = files(
'analyze-compare-versions.c',
'analyze-condition.c',
'analyze-critical-chain.c',
'analyze-dlopen-metadata.c',
'analyze-dot.c',
'analyze-dump.c',
'analyze-exit-status.c',
+9
View File
@@ -1006,7 +1006,16 @@ systemd-analyze security --threshold=25 --offline=true \
rm /tmp/img/usr/lib/systemd/system/testfile.service
if systemd-analyze --version | grep -q -F "+ELFUTILS"; then
systemd-analyze inspect-elf /lib/systemd/systemd
systemd-analyze inspect-elf --json=short /lib/systemd/systemd | grep -q -F '"elfType":"executable"'
# For some unknown reason the .note.dlopen sections are removed when building with sanitizers, so only
# run this test if we're not running under sanitizers.
if [[ ! -v ASAN_OPTIONS ]]; then
shared="$(ldd /lib/systemd/systemd | grep shared | cut -d' ' -f3)"
systemd-analyze dlopen-metadata "$shared"
systemd-analyze dlopen-metadata --json=short "$shared"
fi
fi
systemd-analyze --threshold=90 security systemd-journald.service