Re: kldinfo: utility to display module objects deps and version info
- Reply: Christos Longros : "Re: kldinfo: utility to display module objects deps and version info"
- Reply: Mario Lobo : "Re: kldinfo: utility to display module objects deps and version info"
- In reply to: Ruslan Zalata : "kldinfo: utility to display module objects deps and version info"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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",