summaryrefslogtreecommitdiff
path: root/src/coredump
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@microsoft.com>2021-04-06 18:02:41 +0100
committerLuca Boccassi <luca.boccassi@microsoft.com>2021-04-06 23:12:51 +0100
commitd1b5a0c69108921a1d471e259e48bb89b9664269 (patch)
tree52af3742bea0ed33d08b9b39023be4904cdffa65 /src/coredump
parentc546154a4448ddf9c22363c3f491313aeadd117e (diff)
downloadsystemd-d1b5a0c69108921a1d471e259e48bb89b9664269.tar.gz
coredumpctl: parse and print package metadata
Diffstat (limited to 'src/coredump')
-rw-r--r--src/coredump/coredumpctl.c68
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;