1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "analyze-inspect-elf.h"
6 #include "errno-util.h"
8 #include "format-table.h"
9 #include "format-util.h"
11 #include "path-util.h"
14 static int analyze_elf(char **filenames
, JsonFormatFlags json_flags
) {
17 STRV_FOREACH(filename
, filenames
) {
18 _cleanup_(json_variant_unrefp
) JsonVariant
*package_metadata
= NULL
;
19 _cleanup_(table_unrefp
) Table
*t
= NULL
;
20 _cleanup_free_
char *abspath
= NULL
;
21 _cleanup_close_
int fd
= -EBADF
;
23 r
= path_make_absolute_cwd(*filename
, &abspath
);
25 return log_error_errno(r
, "Could not make an absolute path out of \"%s\": %m", *filename
);
27 path_simplify(abspath
);
29 fd
= RET_NERRNO(open(abspath
, O_RDONLY
|O_CLOEXEC
));
31 return log_error_errno(fd
, "Could not open \"%s\": %m", abspath
);
33 r
= parse_elf_object(fd
, abspath
, /* fork_disable_dump= */false, NULL
, &package_metadata
);
35 return log_error_errno(r
, "Parsing \"%s\" as ELF object failed: %m", abspath
);
37 t
= table_new_vertical();
44 TABLE_STRING
, abspath
);
46 return table_log_add_error(r
);
48 if (package_metadata
) {
49 JsonVariant
*module_json
;
50 const char *module_name
;
52 JSON_VARIANT_OBJECT_FOREACH(module_name
, module_json
, package_metadata
) {
53 const char *field_name
;
56 /* The ELF type and architecture are added as top-level objects,
57 * since they are only parsed for the file itself, but the packaging
58 * metadata is parsed recursively in core files, so there might be
59 * multiple modules. */
60 if (STR_IN_SET(module_name
, "elfType", "elfArchitecture")) {
63 TABLE_FIELD
, module_name
,
64 TABLE_STRING
, json_variant_string(module_json
));
66 return table_log_add_error(r
);
71 /* path/elfType/elfArchitecture come first just once per file,
72 * then we might have multiple modules, so add a separator between
73 * them to make the output more readable. */
74 r
= table_add_many(t
, TABLE_EMPTY
, TABLE_EMPTY
);
76 return table_log_add_error(r
);
78 /* In case of core files the module name will be the executable,
79 * but for binaries/libraries it's just the path, so don't print it
81 if (!streq(abspath
, module_name
)) {
84 TABLE_FIELD
, "module name",
85 TABLE_STRING
, module_name
);
87 return table_log_add_error(r
);
90 JSON_VARIANT_OBJECT_FOREACH(field_name
, field
, module_json
)
91 if (json_variant_is_string(field
)) {
94 TABLE_FIELD
, field_name
,
95 TABLE_STRING
, json_variant_string(field
));
97 return table_log_add_error(r
);
101 if (json_flags
& JSON_FORMAT_OFF
) {
102 r
= table_print(t
, NULL
);
104 return table_log_print_error(r
);
106 json_variant_dump(package_metadata
, json_flags
, stdout
, NULL
);
112 int verb_elf_inspection(int argc
, char *argv
[], void *userdata
) {
113 pager_open(arg_pager_flags
);
115 return analyze_elf(strv_skip(argv
, 1), arg_json_format_flags
);