KMIDIFF(1)

๐Ÿ“ฆ version 3.0, in arch rolling

๐Ÿ’… KMIDIFF(1) ๐Ÿ’…

okay so this is kmidiff, and it ships as part of Libabigail (that's the manual name, bestie โ€” remember it, it comes up) ๐Ÿซถ


โœจ NAME โœจ

kmidiff โ€” compare KMIs of Linux Kernel trees ๐ŸŒณ๐Ÿฆ‹

kmidiff compares the binary Kernel Module Interfaces of two Linux Kernel trees. The binary KMI is, like, literally the interface that the Linux Kernel exposes to its modules. And the trees we're talking about here? They're the result of building the Linux Kernel source tree. no cap โœจ


๐ŸŒˆ GENERAL APPROACH ๐ŸŒˆ

So here's an example of how to build your kernel if you want to compare it to another one using kmidiff โ€” screenshot this, it's giving tutorial:

git clone -b v4.5 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux/v4.5
cd linux/v4.5
make allyesconfig all

Then install the modules into a directory โ€” for instance, the build/modules sub-directory of your kernel source tree:

mkdir build/modules
make modules_install INSTALL_MOD_PATH=build/modules

Then construct a list of interfaces exported by the kernel that you want to compare:

cat > kmi-whitelist << EOF
[kernel_4.5_kmi_whitelist]
 init_task
 schedule
 dev_queue_xmit
 __kmalloc
 printk
EOF

Suppose you've done something similar for the v4.6 branch of the Linux kernel ๐Ÿ˜Œ you now have these two directories: linux/v4.5 and linux/v4.6. Their modules are present under the directories linux/v4.5/build/modules and linux/v4.6/build/modules.

To compare their KMI, kmidiff needs to know where to find the vmlinux binaries and their associated modules. Here's what the command line looks like โ€” iconic behavior only:

kmidiff                                     \
  --kmi-whitelist  linux/v4.6/kmi-whitelist \
  --vmlinux1       linux/v4.5/vmlinux       \
  --vmlinux2       linux/v4.6/vmlinux       \
                   linux/v4.5/build/modules \
                   linux/v4.6/build/modules

This tool uses the libabigail library to analyze the binary as well as its associated debug information. Here's its general mode of operation, and honestly? it ate ๐Ÿ’…

When instructed to do so, a binary and its associated debug information is read and analyzed. To that effect, libabigail analyzes by default the descriptions of the types reachable by the interfaces (functions and variables) that are visible outside of their translation unit. Once that analysis is done, an Application Binary Interface Corpus is constructed by only considering the subset of types reachable from interfaces associated to ELF symbols (http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) that are defined and exported by the binary. It's that final ABI corpus which libabigail considers as representing the ABI of the analyzed binary. ๐ŸŽ€

Libabigail then has capabilities to generate textual representations of ABI Corpora, compare them, analyze their changes and report about them. main character energy fr fr โœจ


๐Ÿ”ฅ INVOCATION ๐Ÿ”ฅ

More generally, kmidiff is invoked under the form:

kmidiff [options] <first-modules-dir> <second-modules-dir>

๐ŸŒธ ENVIRONMENT ๐ŸŒธ

๐Ÿ’– General considerations ๐Ÿ’–

  • General considerations โ€” hmm wait, let's actually talk about it ๐Ÿ‘‡

By default, kmidiff compares all the interfaces (exported functions and variables) between the Kernel and its modules. In practice, though, some users might want to compare a subset of those interfaces. valid ๐Ÿ™ˆ

By default, kmidiff uses debug information in the DWARF debug info format (http://www.dwarfstd.org), if present, otherwise it compares interfaces using CTF (https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf) or BTF (https://docs.kernel.org/bpf/btf.html) debug info formats, if present. Finally, if no debug info in these formats is found, it only considers ELF symbols (http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) and reports about their addition or removal. lowkey a whole fallback chain ๐Ÿซถ

Users can then define a "white list" of the interfaces to compare. Such a white list is just a file in the "INI" format that looks like:

[kernel_version_x86_64_whitelist]
  function1_name
  function2_name
  global_variable1_name
  ....

Note that the name of the section (the name that's between the two brackets) of that INI file just has to end with the string whitelist. So you can define the name you want โ€” for instance [kernel_46_x86_64_whitelist]. your file, your rules ๐Ÿ’…

Then each line of that whitelist file is the name of an exported function or variable. Only those interfaces, along with the types reachable from their signatures, are going to be compared by kmidiff recursively. obsessed with the recursion ngl ๐ŸŒ€

Note that by default kmidiff analyzes the types reachable from the interfaces associated with ELF symbols (http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) that are defined and exported by the Linux Kernel (https://kernel.org) as being the union of the vmlinux binary and all its compiled modules. It then compares those interfaces (along with their types). ๐Ÿ‘‘

โšก Parallel processing โšก

The environment variable ABIGAIL_THREAD_POOL_SIZE can be set to either an integer, or a percentage value, e.g, 10%. The integer value defines the number of threads used by Libabigail to perform parallel processing when applicable. The percentage defines the percentage of the total available cores to use by Libabigail to perform the parallel processing when applicable. do the math, bestie ๐Ÿงฎโœจ

By default, Libabigail uses all the available cores to perform its parallel processing. go big or go home ๐Ÿ”ฅ

โœจ OPTIONS โœจ

  • --allow-non-exported-interfaces โ€” okay so with this one on, the tool analyzes the descriptions of the types reachable by the interfaces (functions and variables) that are visible outside of their translation unit. Once that analysis is done, an ABI Corpus is constructed by only considering the subset of types reachable from interfaces associated to ELF <http://en.wikipedia.org/wiki/Executable_and_Linkable_Format> symbols that are defined and exported by the binary. And that final ABI corpus is what gets compared against another one. ๐Ÿ’…

The problem tho? Analyzing all the interfaces visible from outside their translation unit can amount to a lot of data, which leads to very slow operations. ๐Ÿ˜ญ

Heads up bestie: this option is turned off by default.
  • --btf โ€” extract ABI information from BTF <https://docs.kernel.org/bpf/btf.html> debug information, if present, in the Kernel and Modules. ๐Ÿฆ‹
  • --ctf โ€” extract ABI information from CTF <https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf> debug information, if present, in the Kernel and Modules. ๐Ÿฆ‹
  • --debug-info-dir1 | --d1 <di-path1> โ€” for cases where the debug information for the binaries of the first Linux kernel is split out into separate files, this tells kmidiff where to find those separate debug info files.

Note that di-path must point to the root directory under which the debug information is arranged in a tree-like manner. On Red Hat based systems, that directory is usually <root>/usr/lib/debug. ๐ŸŒธ

  • --debug-info-dir2 | --d2 <di-path2> โ€” like --debug-info-dir1, but this one tells kmidiff where to find the split debug information for the binaries of the second Linux kernel. ๐Ÿซถ
  • --exported-interfaces-only โ€” with this option, the tool analyzes the descriptions of the types reachable by the interfaces (functions and variables) associated with ELF <http://en.wikipedia.org/wiki/Executable_and_Linkable_Format> symbols that are defined and exported by the Linux Kernel <https://kernel.org>.

Otherwise, the tool also has the ability to analyze the descriptions of the types reachable by the interfaces associated with ELF <http://en.wikipedia.org/wiki/Executable_and_Linkable_Format> symbols that are visible outside their translation unit. That later possibility is however much more resource intensive and results in much slower operations. ๐Ÿ’€

That is why this option is enabled by default. ๐Ÿ‘‘

  • --full-impact | -f โ€” emit a change report that shows the full impact of each change on exported interfaces. This is the default kind of report emitted by tools like abidiff or abipkgdiff. โœจ
  • --help | -h โ€” display a short help about the command and exit. Simple, iconic. ๐ŸŽ€
  • --impacted-interfaces | -i โ€” tell what interfaces got impacted by each individual ABI change. ๐Ÿ”ฅ
  • --kmi-whitelist | -w <path-to-interface-whitelist> โ€” set the path to the white list of interfaces to compare while comparing the Kernel Module Interface of the first kernel against the one of the second kernel.

If this option is not provided, all the exported interfaces of the two kernels are compared. That takes a lot of time and is not necessarily meaningful because many interfaces are probably meant to see their reachable types change. ๐Ÿซ 

So please, make sure you always use this option unless you really know what you are doing. fr fr.
  • --no-change-categorization | -x โ€” this disables the categorization of changes into harmless and harmful changes. Note that this categorization is a pre-requisite for the filtering of changes, so this option disables that filtering too. The goal of this option is to speed up execution of the program for cases where the graph of changes is huge and where the user is just interested in looking at, for instance, leaf node changes without caring about their possible impact on interfaces. โšก
  • --show-bits โ€” show sizes and offsets in bits, not bytes. By default, sizes and offsets are shown in bytes. ๐Ÿ”ข
  • --show-bytes โ€” show sizes and offsets in bytes, not bits. This option is activated by default. ๐Ÿ’–
  • --show-dec โ€” show sizes and offsets in decimal base.
  • --show-hex โ€” show sizes and offsets in hexadecimal base. This option is activated by default. ๐Ÿ’œ
  • --suppressions | --suppr <path-to-suppressions> โ€” use a suppression specification <#suppr-spec-label> file located at path-to-suppressions. Note that this option can appear multiple times on the command line โ€” in that case, all of the provided suppression specification files are taken into account. ๐ŸŒˆ
Please note that, by default, if this option is not provided, then the default suppression specification files <#abidiff-default-supprs-label> are loaded. (yes, with a lil space before that period, we don't judge ๐Ÿ˜Œ)
  • --thread-pool-size <N|N%> | -j <N|N%> โ€” set the size of the thread pool used by Libabigail for parallel processing. The size is either the number of threads or a percentage of the total number of available cores on the machine. By default, all the available cores of the machine are used for parallel processing. ๐Ÿงš

Note that the environment variable ABIGAIL_THREAD_POOL_SIZE can also be set to similar values. This command line option, if present, supersedes the value of the environment variable. ๐Ÿ‘‘

  • --verbose โ€” display some verbose messages while executing. Chatty era. ๐Ÿ—ฃ๏ธ
  • --version | -v โ€” display the version of the program and exit. ๐ŸŽ€
  • --vmlinux1 | --l1 <path-to-first-vmlinux> โ€” sets the path to the first vmlinux binary to consider. This has to be the uncompressed vmlinux binary compiled with debug info. ๐Ÿง
  • --vmlinux2 | --l2 <path-to-first-vmlinux> โ€” sets the path to the second vmlinux binary to consider. This has to be the uncompressed vmlinux binary compiled with debug info. ๐Ÿง

๐ŸŒธ Author ๐ŸŒธ

Dodji Seketeli โ€” the main character who wrote this, we stan. ๐Ÿ‘‘

2014-2025, Red Hat, Inc.


And that's the whole page bestie, you ate that ๐Ÿซถ โ€” this little scroll of wisdom is the KMIDIFF(1) page dated Oct 08, 2026, and it's been giving iconic Unix energy the entire time. Now go diff those kernels ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from