Re: kldinfo: utility to display module objects deps and version info

From: Mario Lobo <lobo_at_bsd.com.br>
Date: Fri, 25 Sep 2026 17:49:07 UTC
Oh, Man! This is REALLY cool!

Thank you both!

On Fri, Sep 25, 2026 at 8:59 AM vermaden <vermaden@interia.pl> wrote:

> Hi,
> On 9/25/26 3:13 AM, Ruslan Zalata wrote:
>
> Hello All!
>
> Playing with FreeBSD kernels, hacking driver code and debugging issues on
> laptops sometimes require knowledge of what KObjs are stored in kernel
> module file, their dependencies and, what's more important, for what
> version of kernel a particular module is built! Remember recent vboxdrv.ko
> version mismatch issue ?
>
> Getting FreeBSD kernel module version info is a bit hacky. One of the ways
> involves using "nm" or "readelf" to get a list of special symbols, namely
> "_depend_on_" and "_version", then using "objdump" to get to .data section,
> then using "hexdump" to extract and fine-print version info. One also needs
> to write a script to glue these tools together, otherwise it's too easy
> make a mistake and get wrong data. After some time of struggling with this
> issue, I wrote mine in C, called "kldinfo". :-)
>
> This as simple as a nail "kldinfo" utility behaves like "kldload", but
> instead of loading module it dumps list of objects it finds in module file
> along with their corresponding version and dependency info.
>
> I propose to include "kldinfo" in FreeBSD base along with the other "kld*"
> utils. Note, a similar utility called "modinfo" has been present in most
> Linux distros for decades. I think we should have it in FreeBSD too. ;-) If
> that is ok, I will upload source code for review to Phabricator.
>
> Repo: https://github.com/pointcheck/kldinfo.git
>
> PS:
>
> The code is fully written by hand, no LLMs have been involved.
>
>
> This is very nice tool - thank You for writing it :)
>
> I have played with it a little and introduced different formatting -
> proposal for new look below - along with the patch.
>
> Regards,
>
> vermaden
>
>
>
>
> #./kldinfo /boot/kernel/kernel | head -30
> MODULE: xpt                          DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: xpt                          DEPENDS: cam
> VERSION:       1       1       1
> MODULE: cam                          DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: aprobe                       DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: aprobe                       DEPENDS: cam
> VERSION:       1       1       1
> MODULE: pmp                          DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: pmp                          DEPENDS: cam
> VERSION:       1       1       1
> MODULE: nda                          DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: nda                          DEPENDS: cam
> VERSION:       1       1       1
> MODULE: nvme_probe                   DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: nvme_probe                   DEPENDS: cam
> VERSION:       1       1       1
> MODULE: probe                        DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: probe                        DEPENDS: cam
> VERSION:       1       1       1
> MODULE: cd                           DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: cd                           DEPENDS: cam
> VERSION:       1       1       1
> MODULE: ch                           DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: ch                           DEPENDS: cam
> VERSION:       1       1       1
> MODULE: ada                          DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: ada                          DEPENDS: cam
> VERSION:       1       1       1
> MODULE: da                           DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: da                           DEPENDS: cam
> VERSION:       1       1       1
> MODULE: pass                         DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: pass                         DEPENDS: cam
> VERSION:       1       1       1
> MODULE: sa                           DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: sa                           DEPENDS: cam
> VERSION:       1       1       1
> MODULE: enc                          DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: enc                          DEPENDS: cam
> VERSION:       1       1       1
> MODULE: xz                           DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: aacp_aac                     DEPENDS: kernel
>  VERSION: 1404000 1404000 1499999
> MODULE: aacp                         DEPENDS: cam
> VERSION:       1       1       1
>
>
>
> # ./kldinfo -v /boot/kernel/acpi_ibm.ko
> Section names are in section #19
> Elf Section: name = .text, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x12288, type = 1
> Elf Section: name = .rodata, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x4096, type = 1
> Elf Section: name = .rela.text, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x9120, type = 13
> Elf Section: name = .rela.rodata, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x2496, type = 13
> Elf Section: name = .data, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x440, type = 1
> Elf Section: name = .rela.data, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x672, type = 13
> Elf Section: name = set_sysinit_set, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x16, type = 1
> Elf Section: name = .relaset_sysinit_set, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x48, type = 13
> Elf Section: name = set_sysuninit_set, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x8, type = 1
> Elf Section: name = .relaset_sysuninit_set, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x24, type = 13
> Elf Section: name = set_modmetadata_set, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x32, type = 1
> Elf Section: name = .relaset_modmetadata_set, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x96, type = 13
> Elf Section: name = .bss, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x32, type = 1
> Elf Section: name = .comment, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x104, type = 1
> Elf Section: name = .llvm_addrsig, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x57, type = 1
> Elf Section: name = .note.gnu.build-id, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x36, type = 9
> Elf Section: name = .note.GNU-stack, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x0, type = 1
> Elf Section: name = .gnu_debuglink, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x24, type = 1
> Elf Section: name = .shstrtab, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x294, type = 1
> Elf Section: name = .SUNW_ctf, addr = 0x0, stab = #21
>   Elf Data: off = 0x0, size = 0x3883, type = 1
> Elf Section: name = .symtab, addr = 0x0, stab = #22
>   Elf Data: off = 0x0, size = 0x3288, type = 18
>   Symbol = ibm_ids, info = 0x01, sect = #5, size = 32, addr = 0x180
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = acpi_ibm_sysctls, info = 0x01, sect = #2, size = 480, addr =
> 0x270
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x1 (1)
>   Symbol = ibm_sxlock, info = 0x01, sect = #13, size = 32, addr = 0x0
>     No data buf for sec #13
>   Symbol = ibm_sxlock_sx_sysinit_sys_init, info = 0x01, sect = #5, size =
> 32, addr = 0x18
>     ver1 = 0x1b00000 (28311552), ver2 = 0x1000000 (16777216), ver3 = 0x0
> (0)
>   Symbol = ibm_sxlock_args, info = 0x01, sect = #5, size = 24, addr = 0xd8
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = __set_sysinit_set_sym_ibm_sxlock_sx_sysinit_sys_init, info =
> 0x01, sect = #7, size = 8, addr = 0x0
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = ibm_sxlock_sx_sysuninit_sys_uninit, info = 0x01, sect = #5,
> size = 32, addr = 0x38
>     ver1 = 0x1b00000 (28311552), ver2 = 0x1000000 (16777216), ver3 = 0x0
> (0)
>   Symbol = __set_sysuninit_set_sym_ibm_sxlock_sx_sysuninit_sys_uninit,
> info = 0x01, sect = #9, size = 8, addr = 0x0
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = _mod_metadata_md_acpi_ibm_acpi_on_kernel, info = 0x01, sect =
> #5, size = 24, addr = 0x58
>     ver1 = 0x1 (1), ver2 = 0x1 (1), ver3 = 0x0 (0)
>   Symbol = _acpi_ibm_acpi_depend_on_kernel, info = 0x01, sect = #5, size =
> 12, addr = 0xf0
>     ver1 = 0x156c60 (1404000), ver2 = 0x156c60 (1404000), ver3 = 0x156c60
> (1404000)
>
> MODULE: acpi_ibm_acpi                DEPENDS: kernel
>  VERSION: 1404000 1404000 1404000
>   Symbol =
> __set_modmetadata_set_sym__mod_metadata_md_acpi_ibm_acpi_on_kernel, info =
> 0x01, sect = #11, size = 8, addr = 0x0
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = _mod_metadata_md_acpi_ibm_acpi, info = 0x01, sect = #5, size =
> 24, addr = 0x70
>     ver1 = 0x1 (1), ver2 = 0x2 (2), ver3 = 0x0 (0)
>   Symbol = acpi_ibm_acpi_mod, info = 0x01, sect = #5, size = 24, addr =
> 0x100
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = __set_modmetadata_set_sym__mod_metadata_md_acpi_ibm_acpi, info
> = 0x01, sect = #11, size = 8, addr = 0x8
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = acpi_ibm_acpimodule_sys_init, info = 0x01, sect = #5, size =
> 32, addr = 0x88
>     ver1 = 0x3100000 (51380224), ver2 = 0x1000000 (16777216), ver3 = 0x0
> (0)
>   Symbol = __set_sysinit_set_sym_acpi_ibm_acpimodule_sys_init, info =
> 0x01, sect = #7, size = 8, addr = 0x8
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = _mod_metadata_md_acpi_ibm_on_acpi, info = 0x01, sect = #5, size
> = 24, addr = 0xa8
>     ver1 = 0x1 (1), ver2 = 0x1 (1), ver3 = 0x0 (0)
>   Symbol = _acpi_ibm_depend_on_acpi, info = 0x01, sect = #5, size = 12,
> addr = 0x1a0
>     ver1 = 0x1 (1), ver2 = 0x1 (1), ver3 = 0x1 (1)
>
> MODULE: acpi_ibm                     DEPENDS: acpi
>  VERSION:       1       1       1
>   Symbol = __set_modmetadata_set_sym__mod_metadata_md_acpi_ibm_on_acpi,
> info = 0x01, sect = #11, size = 8, addr = 0x10
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = _mod_metadata_md_acpi_ibm_on_evdev, info = 0x01, sect = #5,
> size = 24, addr = 0xc0
>     ver1 = 0x1 (1), ver2 = 0x1 (1), ver3 = 0x0 (0)
>   Symbol = _acpi_ibm_depend_on_evdev, info = 0x01, sect = #5, size = 12,
> addr = 0x1ac
>     ver1 = 0x1 (1), ver2 = 0x1 (1), ver3 = 0x1 (1)
>
> MODULE: acpi_ibm                     DEPENDS: evdev
> VERSION:       1       1       1
>   Symbol = __set_modmetadata_set_sym__mod_metadata_md_acpi_ibm_on_evdev,
> info = 0x01, sect = #11, size = 8, addr = 0x18
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x69706361 (1768973153)
>   Symbol = acpi_ibm_acpi_driver_mod, info = 0x01, sect = #5, size = 48,
> addr = 0x118
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = acpi_ibm_driver, info = 0x01, sect = #5, size = 48, addr = 0x148
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = acpi_ibm_methods, info = 0x01, sect = #2, size = 80, addr =
> 0x220
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
>   Symbol = acpi_ibm_models, info = 0x01, sect = #5, size = 24, addr = 0x0
>     ver1 = 0x0 (0), ver2 = 0x0 (0), ver3 = 0x0 (0)
> Elf Section: name = .strtab, addr = 0x0, stab = #0
>   Elf Data: off = 0x0, size = 0x2485, type = 1
>
> Found 3 dependencies in file /boot/kernel/acpi_ibm.ko
>
>
>
> # diff -u kldinfo.c.OLD.geany kldinfo.c
> --- kldinfo.c.OLD.geany 2026-09-25 13:55:55.352795000 +0200
> +++ kldinfo.c   2026-09-25 13:54:02.349799000 +0200
> @@ -67,7 +67,10 @@
>    int dep_name_len = strlen(sym_name - mod_name_len -
>      sizeof(DEPEND_ON));
>
> -  printf("MODULE: %s\tDEPENDS: %s\tVERSION: %u %u %u\n",
> +  if (verbose)
> +    printf("\n");
> +
> +  printf("MODULE: %-28s DEPENDS: %-28s VERSION: %7u %7u %7u\n",
>      mod_name, dep_name, ver1, ver2, ver3);
>
>  }
> @@ -86,7 +89,7 @@
>
>    strncat(obj_name, sym_name, obj_name_len);
>
> -  printf("OBJECT: %s\tVERSION: %u\n", obj_name, ver1);
> +  printf("OBJECT: %-10s VERSION: %-10u\n", obj_name, ver1);
>  }
>
>  char *
> @@ -246,7 +249,7 @@
>
>      while ((elf_data = elf_getdata(elf_scn, elf_data))) {
>        if (verbose)
> -        printf("\tElf Data: off = 0x%lx, size = 0x%lu,"
> +        printf("  Elf Data: off = 0x%lx, size = 0x%lu,"
>            " type = %u\n",
>            elf_data->d_off, elf_data->d_size,
>            elf_data->d_type);
> @@ -270,7 +273,7 @@
>            elf_strptr(elf, stab, sym.st_name);
>
>          if (verbose)
> -          printf("\t\tSymbol = %s, info = 0x%02X,"
> +          printf("  Symbol = %s, info = 0x%02X,"
>              " sect = #%u, size = %lu,"
>              " addr = 0x%lx\n",
>              sym_name, sym.st_info, sym.st_shndx,
> @@ -283,7 +286,7 @@
>
>          if (scn == NULL) {
>            if (verbose)
> -            printf("\t\t"
> +            printf("    "
>                "Cannot get section #%u\n",
>                sym.st_shndx);
>            continue;
> @@ -291,7 +294,7 @@
>
>          if (gelf_getshdr(scn, &sh) == NULL) {
>            if (verbose)
> -            printf("\t\t"
> +            printf("    "
>                "Cannot get SH for #%u\n",
>                sym.st_shndx);
>            continue;
> @@ -301,7 +304,7 @@
>
>          if (data == NULL) {
>            if (verbose)
> -            printf("\t\t"
> +            printf("    "
>                "Cannot get data for #%u\n",
>                sym.st_shndx);
>            continue;
> @@ -309,7 +312,7 @@
>
>          if (data->d_buf == NULL) {
>            if (verbose)
> -            printf("\t\t"
> +            printf("    "
>                "No data buf for sec #%u\n",
>                sym.st_shndx);
>            continue;
> @@ -328,7 +331,7 @@
>            8 + sym.st_value - sh.sh_addr);
>
>          if (verbose)
> -          printf("\t\t"
> +          printf("    "
>              "ver1 = 0x%0x (%u), "
>              "ver2 = 0x%0x (%u), "
>              "ver3 = 0x%0x (%u)\n",
> @@ -338,7 +341,7 @@
>            uint8_t *c = (uint8_t *)data->d_buf +
>              sym.st_value - sh.sh_addr;
>            if (verbose) {
> -            printf("\t\tFirmware list: ");
> +            printf("    Firmware list: ");
>              for (int i = 0;
>                  i < sym.st_size; i++)
>                printf("%02X ", c[i]);
> @@ -364,6 +367,9 @@
>    }
>
>    elf_end(elf);
> +
> +  if (verbose)
> +     printf("\n");
>
>    if (deps_count)
>      fprintf(stderr, "Found %u dependencies in file %s\n",
>
>
>

-- 
Mario Lobo
http://www.mallavoodoo.com.br
FreeBSD since version 2.2.8 [not Pro-Audio.... YET!!]