Files
linux/scripts/gendwarfksyms/gendwarfksyms.c
Sami Tolvanen fdf302e6be gendwarfksyms: Skip files with no exports
Starting with Rust 1.91.0 (released 2025-10-30), in upstream commit
ab91a63d403b ("Ignore intrinsic calls in cross-crate-inlining cost model")
[1][2], `bindings.o` stops containing DWARF debug information because the
`Default` implementations contained `write_bytes()` calls which are now
ignored in that cost model (note that `CLIPPY=1` does not reproduce it).

This means `gendwarfksyms` complains:

      RUSTC L rust/bindings.o
    error: gendwarfksyms: process_module: dwarf_get_units failed: no debugging information?

There are several alternatives that would work here: conditionally
skipping in the cases needed (but that is subtle and brittle), forcing
DWARF generation with e.g. a dummy `static` (ugly and we may need to
do it in several crates), skipping the call to the tool in the Kbuild
command when there are no exports (fine) or teaching the tool to do so
itself (simple and clean).

Thus do the last one: don't attempt to process files if we have no symbol
versions to calculate.

  [ I used the commit log of my patch linked below since it explained the
    root issue and expanded it a bit more to summarize the alternatives.

      - Miguel ]

Cc: stable@vger.kernel.org # Needed in 6.17.y.
Reported-by: Haiyue Wang <haiyuewa@163.com>
Closes: https://lore.kernel.org/rust-for-linux/b8c1c73d-bf8b-4bf2-beb1-84ffdcd60547@163.com/
Suggested-by: Miguel Ojeda <ojeda@kernel.org>
Link: https://lore.kernel.org/rust-for-linux/CANiq72nKC5r24VHAp9oUPR1HVPqT+=0ab9N0w6GqTF-kJOeiSw@mail.gmail.com/
Link: ab91a63d40 [1]
Link: https://github.com/rust-lang/rust/pull/145910 [2]
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Haiyue Wang <haiyuewa@163.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251110131913.1789896-1-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-11-11 20:37:11 +01:00

189 lines
4.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2024 Google LLC
*/
#include <fcntl.h>
#include <getopt.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include "gendwarfksyms.h"
/*
* Options
*/
/* Print debugging information to stderr */
int debug;
/* Dump DIE contents */
int dump_dies;
/* Print debugging information about die_map changes */
int dump_die_map;
/* Print out type strings (i.e. type_map) */
int dump_types;
/* Print out expanded type strings used for symbol versions */
int dump_versions;
/* Support kABI stability features */
int stable;
/* Write a symtypes file */
int symtypes;
static const char *symtypes_file;
static void usage(void)
{
fputs("Usage: gendwarfksyms [options] elf-object-file ... < symbol-list\n\n"
"Options:\n"
" -d, --debug Print debugging information\n"
" --dump-dies Dump DWARF DIE contents\n"
" --dump-die-map Print debugging information about die_map changes\n"
" --dump-types Dump type strings\n"
" --dump-versions Dump expanded type strings used for symbol versions\n"
" -s, --stable Support kABI stability features\n"
" -T, --symtypes file Write a symtypes file\n"
" -h, --help Print this message\n"
"\n",
stderr);
}
static int process_module(Dwfl_Module *mod, void **userdata, const char *name,
Dwarf_Addr base, void *arg)
{
Dwarf_Addr dwbias;
Dwarf_Die cudie;
Dwarf_CU *cu = NULL;
Dwarf *dbg;
FILE *symfile = arg;
int res;
debug("%s", name);
dbg = dwfl_module_getdwarf(mod, &dwbias);
/*
* Look for exported symbols in each CU, follow the DIE tree, and add
* the entries to die_map.
*/
do {
res = dwarf_get_units(dbg, cu, &cu, NULL, NULL, &cudie, NULL);
if (res < 0)
error("dwarf_get_units failed: no debugging information?");
if (res == 1)
break; /* No more units */
process_cu(&cudie);
} while (cu);
/*
* Use die_map to expand type strings, write them to `symfile`, and
* calculate symbol versions.
*/
generate_symtypes_and_versions(symfile);
die_map_free();
return DWARF_CB_OK;
}
static const Dwfl_Callbacks callbacks = {
.section_address = dwfl_offline_section_address,
.find_debuginfo = dwfl_standard_find_debuginfo,
};
int main(int argc, char **argv)
{
FILE *symfile = NULL;
unsigned int n;
int opt;
static const struct option opts[] = {
{ "debug", 0, NULL, 'd' },
{ "dump-dies", 0, &dump_dies, 1 },
{ "dump-die-map", 0, &dump_die_map, 1 },
{ "dump-types", 0, &dump_types, 1 },
{ "dump-versions", 0, &dump_versions, 1 },
{ "stable", 0, NULL, 's' },
{ "symtypes", 1, NULL, 'T' },
{ "help", 0, NULL, 'h' },
{ 0, 0, NULL, 0 }
};
while ((opt = getopt_long(argc, argv, "dsT:h", opts, NULL)) != EOF) {
switch (opt) {
case 0:
break;
case 'd':
debug = 1;
break;
case 's':
stable = 1;
break;
case 'T':
symtypes = 1;
symtypes_file = optarg;
break;
case 'h':
usage();
return 0;
default:
usage();
return 1;
}
}
if (dump_die_map)
dump_dies = 1;
if (optind >= argc) {
usage();
error("no input files?");
}
if (!symbol_read_exports(stdin))
return 0;
if (symtypes_file) {
symfile = fopen(symtypes_file, "w");
if (!symfile)
error("fopen failed for '%s': %s", symtypes_file,
strerror(errno));
}
for (n = optind; n < argc; n++) {
Dwfl *dwfl;
int fd;
fd = open(argv[n], O_RDONLY);
if (fd == -1)
error("open failed for '%s': %s", argv[n],
strerror(errno));
symbol_read_symtab(fd);
kabi_read_rules(fd);
dwfl = dwfl_begin(&callbacks);
if (!dwfl)
error("dwfl_begin failed for '%s': %s", argv[n],
dwarf_errmsg(-1));
if (!dwfl_report_offline(dwfl, argv[n], argv[n], fd))
error("dwfl_report_offline failed for '%s': %s",
argv[n], dwarf_errmsg(-1));
dwfl_report_end(dwfl, NULL, NULL);
if (dwfl_getmodules(dwfl, &process_module, symfile, 0))
error("dwfl_getmodules failed for '%s'", argv[n]);
dwfl_end(dwfl);
kabi_free();
}
if (symfile)
check(fclose(symfile));
symbol_print_versions();
symbol_free();
return 0;
}