diff options
author | Luca Boccassi <luca.boccassi@microsoft.com> | 2021-04-06 18:02:41 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@microsoft.com> | 2021-04-06 23:12:51 +0100 |
commit | d1b5a0c69108921a1d471e259e48bb89b9664269 (patch) | |
tree | 52af3742bea0ed33d08b9b39023be4904cdffa65 /src/coredump | |
parent | c546154a4448ddf9c22363c3f491313aeadd117e (diff) | |
download | systemd-d1b5a0c69108921a1d471e259e48bb89b9664269.tar.gz |
coredumpctl: parse and print package metadata
Diffstat (limited to 'src/coredump')
-rw-r--r-- | src/coredump/coredumpctl.c | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 0c4ef2e123..3418753a31 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -545,7 +545,8 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { *boot_id = NULL, *machine_id = NULL, *hostname = NULL, *slice = NULL, *cgroup = NULL, *owner_uid = NULL, *message = NULL, *timestamp = NULL, *filename = NULL, - *truncated = NULL, *coredump = NULL; + *truncated = NULL, *coredump = NULL, + *pkgmeta_name = NULL, *pkgmeta_version = NULL, *pkgmeta_json = NULL; const void *d; size_t l; bool normal_coredump; @@ -574,6 +575,9 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { RETRIEVE(d, l, "COREDUMP_FILENAME", filename); RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated); RETRIEVE(d, l, "COREDUMP", coredump); + RETRIEVE(d, l, "COREDUMP_PKGMETA_PACKAGE", pkgmeta_name); + RETRIEVE(d, l, "COREDUMP_PKGMETA_PACKAGEVERSION", pkgmeta_version); + RETRIEVE(d, l, "COREDUMP_PKGMETA_JSON", pkgmeta_json); RETRIEVE(d, l, "_BOOT_ID", boot_id); RETRIEVE(d, l, "_MACHINE_ID", machine_id); RETRIEVE(d, l, "MESSAGE", message); @@ -716,6 +720,68 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { else fprintf(file, " Storage: none\n"); + if (pkgmeta_name && pkgmeta_version) + fprintf(file, " Package: %s/%s\n", pkgmeta_name, pkgmeta_version); + + /* Print out the build-id of the 'main' ELF module, by matching the JSON key + * with the 'exe' field. */ + if (exe && pkgmeta_json) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + r = json_parse(pkgmeta_json, 0, &v, NULL, NULL); + if (r < 0) { + log_warning_errno(r, "json_parse on %s failed, ignoring: %m", pkgmeta_json); + } else { + const char *module_name; + JsonVariant *module_json; + + /* Cannot nest two JSON_VARIANT_OBJECT_FOREACH as they define the same + * iterator variable '_state' */ + for (struct json_variant_foreach_state _state2 = { (v), 0 }; \ + json_variant_is_object(_state2.variant) && \ + _state2.idx < json_variant_elements(_state2.variant) && \ + ({ module_name = json_variant_string(json_variant_by_index(_state2.variant, _state2.idx)); \ + module_json = json_variant_by_index(_state2.variant, _state2.idx + 1); \ + true; }); \ + _state2.idx += 2) { + _cleanup_free_ char *module_basename = NULL, *exe_basename = NULL; + const char *key; + JsonVariant *w; + + /* The module name, most likely parsed from the ELF core file, + * sometimes contains the full path and sometimes does not. */ + r = path_extract_filename(module_name, &module_basename); + if (r < 0) { + log_warning_errno(r, "Failed to parse module basename: %m"); + break; + } + r = path_extract_filename(exe, &exe_basename); + if (r < 0) { + log_warning_errno(r, "Failed to parse executable basename: %m"); + break; + } + + /* We only print the build-id for the 'main' ELF module */ + if (!streq(module_basename, exe_basename)) + continue; + + JSON_VARIANT_OBJECT_FOREACH(key, w, module_json) { + if (!json_variant_is_string(w)) + continue; + + if (!streq(key, "buildid")) + continue; + + fprintf(file, " build-id: %s\n", json_variant_string(w)); + + break; + } + + break; + } + } + } + if (message) { _cleanup_free_ char *m = NULL; |