On 8/15/24 19:39, Sami Tolvanen wrote:
> Add a basic DWARF parser, which uses libdw to traverse the debugging
> information in an object file and looks for functions and variables.
> In follow-up patches, this will be expanded to produce symbol versions
> for CONFIG_MODVERSIONS from DWARF.
> 
> Signed-off-by: Sami Tolvanen <samitolva...@google.com>
> ---
>  kernel/module/Kconfig                 |   8 ++
>  scripts/Makefile                      |   1 +
>  scripts/gendwarfksyms/.gitignore      |   2 +
>  scripts/gendwarfksyms/Makefile        |   7 ++
>  scripts/gendwarfksyms/dwarf.c         |  87 +++++++++++++++
>  scripts/gendwarfksyms/gendwarfksyms.c | 146 ++++++++++++++++++++++++++
>  scripts/gendwarfksyms/gendwarfksyms.h |  78 ++++++++++++++
>  7 files changed, 329 insertions(+)
>  create mode 100644 scripts/gendwarfksyms/.gitignore
>  create mode 100644 scripts/gendwarfksyms/Makefile
>  create mode 100644 scripts/gendwarfksyms/dwarf.c
>  create mode 100644 scripts/gendwarfksyms/gendwarfksyms.c
>  create mode 100644 scripts/gendwarfksyms/gendwarfksyms.h
> 
> [...]
> +static int parse_options(int argc, const char **argv)
> +{
> +     for (int i = 1; i < argc; i++) {
> +             bool flag = false;
> +
> +             for (int j = 0; j < ARRAY_SIZE(options); j++) {
> +                     if (strcmp(argv[i], options[j].arg))
> +                             continue;
> +
> +                     *options[j].flag = true;
> +
> +                     if (options[j].param) {
> +                             if (++i >= argc) {
> +                                     error("%s needs an argument",
> +                                           options[j].arg);
> +                                     return -1;
> +                             }
> +
> +                             *options[j].param = argv[i];
> +                     }
> +
> +                     flag = true;
> +                     break;
> +             }
> +
> +             if (!flag)
> +                     object_files[object_count++] = argv[i];

I would rather add a check that this doesn't produce an out-of-bounds
access.

> [...]
> +int main(int argc, const char **argv)
> +{
> +     unsigned int n;
> +
> +     if (parse_options(argc, argv) < 0)
> +             return usage();
> +
> +     for (n = 0; n < object_count; n++) {
> +             Dwfl *dwfl;
> +             int fd;
> +
> +             fd = open(object_files[n], O_RDONLY);
> +             if (fd == -1) {
> +                     error("open failed for '%s': %s", object_files[n],
> +                           strerror(errno));
> +                     return -1;
> +             }
> +
> +             dwfl = dwfl_begin(&callbacks);
> +             if (!dwfl) {
> +                     error("dwfl_begin failed for '%s': %s", object_files[n],
> +                           dwarf_errmsg(-1));
> +                     return -1;
> +             }
> +
> +             if (!dwfl_report_offline(dwfl, object_files[n], object_files[n],
> +                                      fd)) {
> +                     error("dwfl_report_offline failed for '%s': %s",
> +                           object_files[n], dwarf_errmsg(-1));
> +                     return -1;
> +             }
> +
> +             dwfl_report_end(dwfl, NULL, NULL);
> +
> +             if (dwfl_getmodules(dwfl, &process_modules, NULL, 0)) {
> +                     error("dwfl_getmodules failed for '%s'",
> +                           object_files[n]);
> +                     return -1;
> +             }

I see that libdwfl has also directly function dwfl_nextcu(). Would it
make sense to use it to simplify the code?

> +
> +             dwfl_end(dwfl);
> +             close(fd);

Isn't fd consumed by dwfl_report_offline() on success? I'm seeing EBADF
from this close() call.

> +     }
> +
> +     return 0;
> +}

-- 
Thanks,
Petr

Reply via email to