| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // 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;
- }
|