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

From: vermaden <vermaden_at_interia.pl>
Date: Fri, 25 Sep 2026 11:58:43 UTC
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",