public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* genksyms vs. opaque struct *
@ 2025-11-13 20:40 Philipp Hahn
  2025-11-26 15:22 ` Nicolas Schier
  2026-01-19 13:48 ` Philipp Hahn
  0 siblings, 2 replies; 3+ messages in thread
From: Philipp Hahn @ 2025-11-13 20:40 UTC (permalink / raw)
  To: Masahiro Yamada, Nicolas Schier; +Cc: linux-kernel

Hello,

while building a Linux kernel module I stumbled over an issue with 'genksyms': Basically my modules uses an "opaque struct" and only gets a pointer to such an object. The header file declaring that struct did *not* #include all needed header files recursively, so some types remained unresolved.
For compiling the module this was not an issue as the compiler only needs to allocate space for an pointer to that nested struct and does not need more details.
Another module exists which uses that symbol and recorded the calculated CRC.

Then I changed my module and added some more #includes, which resulted into `genksyms` getting *more* details on the next run while the implementation actually did not change.

I only found out root cause of my problem after digging into the genksyms-machinery myself, where I found the option `--warnings`, which actually prints out such a warning in my case:
> /home/pmhahn/prog/my-modver/my-modver.c:8: expand undefined struct bar

In my example below it makes a difference if `-DDETAIL` is given or not:
> cpp -E -D__GENKSYMS__ …my-modver.c -DDETAIL | scripts/genksyms/genksyms -r /dev/null -w
> #SYMVER my_function 0x0cdb4509
> cpp -E -D__GENKSYMS__ …my-modver.c  | scripts/genksyms/genksyms -r /dev/null -w
> #SYMVER my_function 0x87675506

I wonder, why that option is not enabled by default or if there is another solution to prevent such breaking changed by including more/less #includes? Are there any good/recommended practices?

Below is my simplified example with my two source files. Attached is the full output from running `genksyms`.

$ cat my-modver.c ####################
#include <linux/module.h>
#include <linux/printk.h>
#include "my-modver.h"
void my_function(struct foo *arg) {
	printk(KERN_INFO "Hello %d", arg->value);
}
EXPORT_SYMBOL(my_function);
MODULE_LICENSE("MIT");

$ cat my-modver.h ####################
struct bar;
#ifdef DETAIL
struct bar {
	int nested;
};
#endif
struct foo {
	int value;
	struct bar *nested;
};
void my_function(struct foo *arg);


Thanks in advance for your answer.
Philipp Hahn

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: genksyms vs. opaque struct *
  2025-11-13 20:40 genksyms vs. opaque struct * Philipp Hahn
@ 2025-11-26 15:22 ` Nicolas Schier
  2026-01-19 13:48 ` Philipp Hahn
  1 sibling, 0 replies; 3+ messages in thread
From: Nicolas Schier @ 2025-11-26 15:22 UTC (permalink / raw)
  To: Philipp Hahn; +Cc: Masahiro Yamada, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2471 bytes --]

On Thu, Nov 13, 2025 at 09:40:11PM +0100, Philipp Hahn wrote:
> Hello,
> 
> while building a Linux kernel module I stumbled over an issue with
> 'genksyms': Basically my modules uses an "opaque struct" and only gets
> a pointer to such an object. The header file declaring that struct did
> *not* #include all needed header files recursively, so some types
> remained unresolved.
> For compiling the module this was not an issue as the compiler only
> needs to allocate space for an pointer to that nested struct and does
> not need more details.
> Another module exists which uses that symbol and recorded the
> calculated CRC.
> 
> Then I changed my module and added some more #includes, which resulted
> into `genksyms` getting *more* details on the next run while the
> implementation actually did not change.
> 
> I only found out root cause of my problem after digging into the
> genksyms-machinery myself, where I found the option `--warnings`,
> which actually prints out such a warning in my case:
> > /home/pmhahn/prog/my-modver/my-modver.c:8: expand undefined struct bar
> 
> In my example below it makes a difference if `-DDETAIL` is given or not:
> > cpp -E -D__GENKSYMS__ …my-modver.c -DDETAIL | scripts/genksyms/genksyms -r /dev/null -w
> > #SYMVER my_function 0x0cdb4509
> > cpp -E -D__GENKSYMS__ …my-modver.c  | scripts/genksyms/genksyms -r /dev/null -w
> > #SYMVER my_function 0x87675506
> 
> I wonder, why that option is not enabled by default or if there is
> another solution to prevent such breaking changed by including
> more/less #includes? Are there any good/recommended practices?

FTR:  Philipp and I had a face-to-face conversation about the topic.
Some results for possible thread readers:

  * Running genksyms with --warnings breaks the kernel build; and the
    warning is output really often.

  * The described situation is easily reproducible with the given
    example, but it is not relevant:  Symbols for exported functions are
    hashed for their _source_ c module appearance; all users simply
    record the found hash to allow the loader to verify the recorded
    hash with the one provided by the function export.

  * The actual problem that has been described is probably related to
    some purely out-of-tree kmod organisation issues.

Nicolas


PS: Module symvers topic is probably better handled via
linux-modules@vger.kernel.org and linux-kbuild@vger.kernel.org

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: genksyms vs. opaque struct *
  2025-11-13 20:40 genksyms vs. opaque struct * Philipp Hahn
  2025-11-26 15:22 ` Nicolas Schier
@ 2026-01-19 13:48 ` Philipp Hahn
  1 sibling, 0 replies; 3+ messages in thread
From: Philipp Hahn @ 2026-01-19 13:48 UTC (permalink / raw)
  To: Masahiro Yamada, Nicolas Schier, linux-kernel

Hello,

to answer my own question from last year:

Am Thu, Nov 13, 2025 at 09:40:15PM +0100 schrieb Philipp Hahn:
> while building a Linux kernel module I stumbled over an issue with 'genksyms': Basically my modules uses an "opaque struct" and only gets a pointer to such an object. The header file declaring that struct did *not* #include all needed header files recursively, so some types remained unresolved.
> For compiling the module this was not an issue as the compiler only needs to allocate space for an pointer to that nested struct and does not need more details.
> Another module exists which uses that symbol and recorded the calculated CRC.
>
> Then I changed my module and added some more #includes, which resulted into `genksyms` getting *more* details on the next run while the implementation actually did not change.
...
> I wonder, why that option is not enabled by default or if there is another solution to prevent such breaking changed by including more/less #includes? Are there any good/recommended practices?

That problem is and can mostly be ignored:
- The CRC only tries to capture the ABI, but it is not perfect. You
  could also use a number and ask the developer to increment that
  manually each time the relevant ABI changes; just like it is done with
  the version number of shared libraries.
- You as the developer decide, how much of the ABI shoule be tracked:
  - if you include more header files, you get a deeper dependency tree
    and will detect more breaking changes - wanted or unwanted
  - if you include less header files, you will detect fewer changes.
- The CRC is only calculated when the experting module is "modpost"ed:
  The CRC is simply recorded then and any other module using it will
  just use that CRC. Including more or less headers at those using
  modules will not change anything as the CRC only depends on what was
  back than.

In summary you might change the CRC is you include more or less headers
when you re-compile the exporting module, but that is expected as the
detail level changes. Consider that part of the ABI.
If you do that you then have to just re-compile/link/modpost all
downstream modules so they can pick up the new CRC.

Philipp Hahn

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-01-19 13:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-13 20:40 genksyms vs. opaque struct * Philipp Hahn
2025-11-26 15:22 ` Nicolas Schier
2026-01-19 13:48 ` Philipp Hahn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox