]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
coredump: shorten output about package metadata to one line
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 18 Sep 2022 17:26:29 +0000 (19:26 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 28 Sep 2022 08:47:42 +0000 (10:47 +0200)
We would print the whole thing in extenso. Users generally don't care,
and would likely prefer to just get the compact identifier of the package
that they can use in a bug report or package manager commands.

Before:
systemd-coredump[40645]: [🡕] Process 1975 (gnome-shell) of user 1000 dumped core.

                         Module /usr/bin/gnome-shell (deleted) with build-id aafdb7d69a7efca937e490080ad9348541fc57d8
                         Metadata for module /usr/bin/gnome-shell (deleted) owned by FDO found: {
                                 "type" : "rpm",
                                 "name" : "gnome-shell",
                                 "version" : "43~rc-3.fc37",
                                 "architecture" : "x86_64",
                                 "osCpe" : "cpe:/o:fedoraproject:fedora:37"
                         }

                         Module /usr/lib64/gnome-shell/libgvc.so (deleted) with build-id 56cbb9862e1ee84ca1549b94f2b4cda03537613e
                         Metadata for module /usr/lib64/gnome-shell/libgvc.so (deleted) owned by FDO found: {
                                 "type" : "rpm",
                                 "name" : "gnome-shell",
                                 "version" : "43~rc-2.fc37",
                                 "architecture" : "x86_64",
                                 "osCpe" : "cpe:/o:fedoraproject:fedora:37"
                         }

                         Module /usr/lib64/libLLVM-14.so (deleted) with build-id ffa7e43f48eb4c189304c0241b1862710de4c3a4
                         Metadata for module /usr/lib64/libLLVM-14.so (deleted) owned by FDO found: {
                                 "type" : "rpm",
                                 "name" : "gnome-shell",
                                 "version" : "43~rc-2.fc37",
                                 "architecture" : "x86_64",
                                 "osCpe" : "cpe:/o:fedoraproject:fedora:37"
                         }

After:
systemd-coredump[235218]: [🡕] Process 235216 (bash) of user 1000 dumped core.

                          Module libtinfo.so.6 from rpm ncurses-6.3-3.20220501.fc37.x86_64, build-id=71a04d23fd572525eb6efc47026c379725e06d96
                          Module bash from rpm bash-5.1.16-3.fc37.x86_64, build-id=6c936aff95a2ccda04a3fb685a81a84a0a8d10da
                          Stack trace of thread 235216:
                          #0  0x00007fa409ec8d8b kill (libc.so.6 + 0x38d8b)
                          #1  0x0000560d35e366b1 kill_builtin (bash + 0xad6b1)
                          #2  0x0000560d35dd7227 execute_builtin.lto_priv.0 (bash + 0x4e227)
                          #3  0x0000560d35dd0459 execute_simple_command (bash + 0x47459)
                          #4  0x0000560d35dd1de0 execute_command_internal (bash + 0x48de0)
                          #5  0x0000560d35e307aa parse_and_execute (bash + 0xa77aa)
                          #6  0x0000560d35e91b08 run_one_command.isra.0 (bash + 0x108b08)
                          #7  0x0000560d35dba07c main (bash + 0x3107c)
                          #8  0x00007fa409eb3510 __libc_start_call_main (libc.so.6 + 0x23510)
                          #9  0x00007fa409eb35c9 __libc_start_main@@GLIBC_2.34 (libc.so.6 + 0x235c9)
                          #10 0x0000560d35dbad85 _start (bash + 0x31d85)

TODO
src/shared/elf-util.c

diff --git a/TODO b/TODO
index 7a074dd6f874bffbd007b578feac2429ed7f176b..1acd9b4697510afec943b4db05022cce21820593 100644 (file)
--- a/TODO
+++ b/TODO
@@ -2018,8 +2018,7 @@ Features:
 * coredump:
   - save coredump in Windows/Mozilla minidump format
   - when truncating coredumps, also log the full size that the process had, and make a metadata field so we can report truncated coredumps
-  - when using package notes, compact output to one-line-per-module:
-    libfoo.so, build-id DEADF12340, foo-libs-33.4-1.fc12
+  - add examples for other distros in ELF_PACKAGE_METADATA
 
 * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting)
 
index ae4193cacfb28fc51d5cae444c76bf847199205a..c235eac5a0e585877dbe0221bea27d7018494f53 100644 (file)
@@ -266,6 +266,60 @@ static int thread_callback(Dwfl_Thread *thread, void *userdata) {
         return DWARF_CB_OK;
 }
 
+static char* build_package_reference(
+                const char *type,
+                const char *name,
+                const char *version,
+                const char *arch) {
+
+        /* Construct an identifier for a specific version of the package. The syntax is most suitable for
+         * rpm: the resulting string can be used directly in queries and rpm/dnf/yum commands. For dpkg and
+         * other systems, it might not be usable directly, but users should still be able to figure out the
+         * meaning.
+         */
+
+        return strjoin(type ?: "package",
+                       " ",
+                       name,
+
+                       version ? "-" : "",
+                       strempty(version),
+
+                       /* arch is meaningful even without version, so always print it */
+                       arch ? "." : "",
+                       strempty(arch));
+}
+
+static void report_module_metadata(StackContext *c, const char *name, JsonVariant *metadata) {
+        assert(c);
+        assert(name);
+        assert(metadata);
+
+        if (!c->f)
+                return;
+
+        const char
+                *build_id = json_variant_string(json_variant_by_key(metadata, "buildId")),
+                *type = json_variant_string(json_variant_by_key(metadata, "type")),
+                *package = json_variant_string(json_variant_by_key(metadata, "name")),
+                *version = json_variant_string(json_variant_by_key(metadata, "version")),
+                *arch = json_variant_string(json_variant_by_key(metadata, "architecture"));
+
+        fprintf(c->f, "Module %s", name);
+
+        if (package) {
+                /* Version/architecture is only meaningful with a package name.
+                 * Skip the detailed fields if package is unknown. */
+                _cleanup_free_ char *id = build_package_reference(type, package, version, arch);
+                fprintf(c->f, " from %s", strnull(id));
+        }
+
+        if (build_id)
+                fprintf(c->f, ", build-id=%s", build_id);
+
+        fputs("\n", c->f);
+}
+
 static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *elf, bool *ret_interpreter_found, StackContext *c) {
         bool interpreter_found = false;
         size_t n_program_headers;
@@ -315,7 +369,6 @@ static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *e
                      (note_offset = sym_gelf_getnote(data, note_offset, &note_header, &name_offset, &desc_offset)) > 0;) {
 
                         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
-                        const char *note_name = (const char *)data->d_buf + name_offset;
                         const char *payload = (const char *)data->d_buf + desc_offset;
 
                         if (note_header.n_namesz == 0 || note_header.n_descsz == 0)
@@ -343,23 +396,18 @@ static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *e
                         if (r < 0)
                                 return log_error_errno(r, "json_parse on %s failed: %m", payload);
 
-                        /* First pretty-print to the buffer, so that the metadata goes as
-                         * plaintext in the journal. */
-                        if (c->f) {
-                                fprintf(c->f, "Metadata for module %s owned by %s found: ",
-                                        name, note_name);
-                                json_variant_dump(v, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, c->f, NULL);
-                                fputc('\n', c->f);
-                        }
-
-                        /* Secondly, if we have a build-id, merge it in the same JSON object
-                         * so that it appears all nicely together in the logs/metadata. */
+                        /* If we have a build-id, merge it in the same JSON object so that it appears all
+                         * nicely together in the logs/metadata. */
                         if (id_json) {
                                 r = json_variant_merge(&v, id_json);
                                 if (r < 0)
-                                        return log_error_errno(r, "json_variant_merge of package meta with buildid failed: %m");
+                                        return log_error_errno(r, "json_variant_merge of package meta with buildId failed: %m");
                         }
 
+                        /* Pretty-print to the buffer, so that the metadata goes as plaintext in the
+                         * journal. */
+                        report_module_metadata(c, name, v);
+
                         /* Then we build a new object using the module name as the key, and merge it
                          * with the previous parses, so that in the end it all fits together in a single
                          * JSON blob. */
@@ -369,7 +417,7 @@ static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *e
 
                         r = json_variant_merge(c->package_metadata, w);
                         if (r < 0)
-                                return log_error_errno(r, "json_variant_merge of package meta with buildid failed: %m");
+                                return log_error_errno(r, "json_variant_merge of package meta with buildId failed: %m");
 
                         /* Finally stash the name, so we avoid double visits. */
                         r = set_put_strdup(c->modules, name);
@@ -418,13 +466,7 @@ static int parse_buildid(Dwfl_Module *mod, Elf *elf, const char *name, StackCont
                 * will then be added as metadata to the journal message with the stack trace. */
                 r = json_build(&id_json, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("buildId", JSON_BUILD_HEX(id, id_len))));
                 if (r < 0)
-                        return log_error_errno(r, "json_build on build-id failed: %m");
-
-                if (c->f) {
-                        JsonVariant *build_id = json_variant_by_key(id_json, "buildId");
-                        assert(build_id);
-                        fprintf(c->f, "Module %s with build-id %s\n", name, json_variant_string(build_id));
-                }
+                        return log_error_errno(r, "json_build on buildId failed: %m");
         }
 
         if (ret_id_json)
@@ -478,6 +520,8 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
         if (r < 0) {
                 log_warning("Could not parse number of program headers from core file: %s",
                             sym_elf_errmsg(-1)); /* -1 retrieves the most recent error */
+                report_module_metadata(c, name, id_json);
+
                 return DWARF_CB_OK;
         }