Oh, Man! This is REALLY cool! Thank you both!
On Fri, Sep 25, 2026 at 8:59 AM vermaden <[email protected]> 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!!]
