diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:35:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:35:18 +0000 |
commit | b750101eb236130cf056c675997decbac904cc49 (patch) | |
tree | a5df1a06754bdd014cb975c051c83b01c9a97532 /src/analyze/analyze-inspect-elf.c | |
parent | Initial commit. (diff) | |
download | systemd-b750101eb236130cf056c675997decbac904cc49.tar.xz systemd-b750101eb236130cf056c675997decbac904cc49.zip |
Adding upstream version 252.22.upstream/252.22
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/analyze/analyze-inspect-elf.c')
-rw-r--r-- | src/analyze/analyze-inspect-elf.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/analyze/analyze-inspect-elf.c b/src/analyze/analyze-inspect-elf.c new file mode 100644 index 0000000..155c611 --- /dev/null +++ b/src/analyze/analyze-inspect-elf.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "analyze.h" +#include "analyze-inspect-elf.h" +#include "elf-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "format-table.h" +#include "format-util.h" +#include "json.h" +#include "path-util.h" +#include "strv.h" + +static int analyze_elf(char **filenames, JsonFormatFlags json_flags) { + int r; + + STRV_FOREACH(filename, filenames) { + _cleanup_(json_variant_unrefp) JsonVariant *package_metadata = NULL; + _cleanup_(table_unrefp) Table *t = NULL; + _cleanup_free_ char *abspath = NULL; + _cleanup_close_ int fd = -1; + + r = path_make_absolute_cwd(*filename, &abspath); + if (r < 0) + return log_error_errno(r, "Could not make an absolute path out of \"%s\": %m", *filename); + + path_simplify(abspath); + + fd = RET_NERRNO(open(abspath, O_RDONLY|O_CLOEXEC)); + if (fd < 0) + return log_error_errno(fd, "Could not open \"%s\": %m", abspath); + + r = parse_elf_object(fd, abspath, /* fork_disable_dump= */false, NULL, &package_metadata); + if (r < 0) + return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath); + + t = table_new("", ""); + if (!t) + return log_oom(); + + r = table_set_align_percent(t, TABLE_HEADER_CELL(0), 100); + if (r < 0) + return table_log_add_error(r); + + r = table_add_many( + t, + TABLE_STRING, "path:", + TABLE_STRING, abspath); + if (r < 0) + return table_log_add_error(r); + + if (package_metadata) { + JsonVariant *module_json; + const char *module_name; + + JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, package_metadata) { + const char *field_name; + JsonVariant *field; + + /* The ELF type and architecture are added as top-level objects, + * since they are only parsed for the file itself, but the packaging + * metadata is parsed recursively in core files, so there might be + * multiple modules. */ + if (STR_IN_SET(module_name, "elfType", "elfArchitecture")) { + _cleanup_free_ char *suffixed = NULL; + + suffixed = strjoin(module_name, ":"); + if (!suffixed) + return log_oom(); + + r = table_add_many( + t, + TABLE_STRING, suffixed, + TABLE_STRING, json_variant_string(module_json)); + if (r < 0) + return table_log_add_error(r); + + continue; + } + + /* path/elfType/elfArchitecture come first just once per file, + * then we might have multiple modules, so add a separator between + * them to make the output more readable. */ + r = table_add_many(t, TABLE_EMPTY, TABLE_EMPTY); + if (r < 0) + return table_log_add_error(r); + + /* In case of core files the module name will be the executable, + * but for binaries/libraries it's just the path, so don't print it + * twice. */ + if (!streq(abspath, module_name)) { + r = table_add_many( + t, + TABLE_STRING, "module name:", + TABLE_STRING, module_name); + if (r < 0) + return table_log_add_error(r); + } + + JSON_VARIANT_OBJECT_FOREACH(field_name, field, module_json) + if (json_variant_is_string(field)) { + _cleanup_free_ char *suffixed = NULL; + + suffixed = strjoin(field_name, ":"); + if (!suffixed) + return log_oom(); + + r = table_add_many( + t, + TABLE_STRING, suffixed, + TABLE_STRING, json_variant_string(field)); + if (r < 0) + return table_log_add_error(r); + } + } + } + if (json_flags & JSON_FORMAT_OFF) { + (void) table_set_header(t, true); + + r = table_print(t, NULL); + if (r < 0) + return table_log_print_error(r); + } else + json_variant_dump(package_metadata, json_flags, stdout, NULL); + } + + return 0; +} + +int verb_elf_inspection(int argc, char *argv[], void *userdata) { + pager_open(arg_pager_flags); + + return analyze_elf(strv_skip(argv, 1), arg_json_format_flags); +} |