From: Luca Boccassi Date: Thu, 18 Nov 2021 00:51:41 +0000 (+0000) Subject: elf-util: split out helper to parse build-id X-Git-Tag: v250-rc1~108^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5564c6d802e8fc8fd4d47bb0d781f7514e097f39;p=thirdparty%2Fsystemd.git elf-util: split out helper to parse build-id --- diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c index 12b42bf90fb..9eb8495c351 100644 --- a/src/shared/elf-util.c +++ b/src/shared/elf-util.c @@ -245,51 +245,71 @@ static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *e return 0; } -static int module_callback(Dwfl_Module *mod, void **userdata, const char *name, Dwarf_Addr start, void *arg) { +/* Get the build-id out of an ELF object or a dwarf core module. */ +static int parse_buildid(Dwfl_Module *mod, Elf *elf, const char *name, StackContext *c, JsonVariant **ret_id_json) { _cleanup_(json_variant_unrefp) JsonVariant *id_json = NULL; - StackContext *c = arg; - size_t n_program_headers; - GElf_Addr id_vaddr, bias; const unsigned char *id; - int id_len, r; - Elf *elf; + GElf_Addr id_vaddr; + ssize_t id_len; + int r; - assert(mod); + assert(mod || elf); assert(c); - if (!name) - name = "(unnamed)"; /* For logging purposes */ - - /* We are iterating on each "module", which is what dwfl calls ELF objects contained in the - * core file, and extracting the build-id first and then the package metadata. - * We proceed in a best-effort fashion - not all ELF objects might contain both or either. - * The build-id is easy, as libdwfl parses it during the dwfl_core_file_report() call and - * stores it separately in an internal library struct. */ - id_len = dwfl_module_build_id(mod, &id, &id_vaddr); + if (mod) + id_len = dwfl_module_build_id(mod, &id, &id_vaddr); + else + id_len = dwelf_elf_gnu_build_id(elf, (const void **)&id); if (id_len <= 0) { /* If we don't find a build-id, note it in the journal message, and try * anyway to find the package metadata. It's unlikely to have the latter * without the former, but there's no hard rule. */ if (c->f) - fprintf(c->f, "Found module %s without build-id.\n", name); + fprintf(c->f, "Module %s without build-id.\n", name); } else { - JsonVariant *build_id; - /* We will later parse package metadata json and pass it to our caller. Prepare the * build-id in json format too, so that it can be appended and parsed cleanly. It * 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) { - log_error_errno(r, "json_build on build-id failed: %m"); - return DWARF_CB_ABORT; - } + if (r < 0) + return log_error_errno(r, "json_build on build-id failed: %m"); - build_id = json_variant_by_key(id_json, "buildId"); - assert_se(build_id); - if (c->f) - fprintf(c->f, "Found module %s with build-id: %s\n", name, json_variant_string(build_id)); + 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)); + } } + if (ret_id_json) + *ret_id_json = TAKE_PTR(id_json); + + return 0; +} + +static int module_callback(Dwfl_Module *mod, void **userdata, const char *name, Dwarf_Addr start, void *arg) { + _cleanup_(json_variant_unrefp) JsonVariant *id_json = NULL; + StackContext *c = arg; + size_t n_program_headers; + GElf_Addr bias; + int r; + Elf *elf; + + assert(mod); + assert(c); + + if (!name) + name = "(unnamed)"; /* For logging purposes */ + + /* We are iterating on each "module", which is what dwfl calls ELF objects contained in the + * core file, and extracting the build-id first and then the package metadata. + * We proceed in a best-effort fashion - not all ELF objects might contain both or either. + * The build-id is easy, as libdwfl parses it during the dwfl_core_file_report() call and + * stores it separately in an internal library struct. */ + r = parse_buildid(mod, NULL, name, c, &id_json); + if (r < 0) + return DWARF_CB_ABORT; + /* The .note.package metadata is more difficult. From the module, we need to get a reference * to the ELF object first. We might be lucky and just get it from elfutils. */ elf = dwfl_module_getelf(mod, &bias);