[pvrusb2] Disagreeable symbols and CONFIG_MODVERSIONS

Mike Isely isely at isely.net
Sat Dec 10 01:48:25 CST 2005


I think I've figured out the last piece of this puzzle.

When CONFIG_MODVERSIONS is in use, the kernel build system generates these 
per-symbol CRCs by taking into account every aspect related to the 
symbol's declaration - like its argument types, the definition of those 
argument types, the return type, etc.  This is done for each symbol 
exported by a module (a definition) and for each symbol that needs to be 
imported into a module (a declaration).  The idea here is to make sure 
that the symbol has been defined in precisely the same way it has been 
declared.  If the declaration and definition disagree, then their CRCs 
won't match and the module loader catches this, prints that nasty message 
and aborts the load of the module in question.  Obviously if a symbol's 
declaration and definition do not match, then there may be an 
incompatibility and this is how the kernel CONFIG_MODVERSIONS mechanism 
prevents usage of incompatible symbols.

For example, if I declare and call function foobar this way:

   void foobar(short abc, char *def);

But the module actually defines foobar this way:

   void foobar(char *def) {
 	/* whatever */
   }

Obviously such a mismatched call will likely generate bad behavior and 
possibly a kernel oops.  But since the CRC for foobar stored in the module 
defining foobar won't match the CRC for foobar stored in the module using 
foobar, the mismatch will be caught and the kernel won't let you load that 
combination of modules at the same time.

In theory this all looks great.  But why, might you ask, is this mechanism 
not working for tveeprom_hauppauge_analog?  That's because we REALLY DO 
have conflicting definitions here.

Look back at my diatribe in pvrusb2-eeprom.html, and you'll see how I 
point out that the V4L defined version of this function uses a struct 
tveeprom that is different than the struct tveeprom used by the ivtv 
defined version of this function.  The CRC generation algorithm is 
apparently using the full definition of the tveeprom structure as input 
into the CRC value.  Now, in pvrusb2-eeprom.c I do some really ugly 
hackery to make a run time determination of which struct tveeprom is 
really the correct one so the code is actually fairly safe.  But this sort 
of thing still trips up the CRC generation.  It turns out that in the 
pvrusb2 driver build, pvrusb2-eeprom.c will see the V4L defined prototype 
for tveeprom_hauppauge_analog and struct tveeprom, so the expected CRC 
will be the V4L version of the function.  Thus we now see why we get this 
"disagrees about version of symbol" error when we try to load the ivtv 
version of tveeprom.ko with the other definition - and a different CRC.

Right now I don't see a good solution.  The simple fact is that I'm trying 
to make the pvrusb2 driver survive a screwed up situation between V4L and 
ivtv and there's only so much I can do here.  There's really only two 
choices here: (1) Don't enable CONFIG_MODVERSIONS in your kernel build (if 
you can), or (2) Don't bother trying to use the tveeprom.ko supplied with 
the pvrusb2 driver.  I should also point out here that the same problem 
should happen if you try to use the "real" ivtv driver's tveeprom.ko, for 
exactly the same reason.  This means that if you really do want ivtv to 
run co-resident with the pvrusb2 driver, then you are only really left 
with choice (1).

I'm going to bed now.  Next chance I get, after sleeping all this off, 
I'll see about updating the web pages to include this new information.

For some reason I seem to have acquired a nasty headache...

   -Mike


-- 
                         |         Mike Isely          |     PGP fingerprint
      Spammers Die!!     |                             | 03 54 43 4D 75 E5 CC 92
                         |   isely @ pobox (dot) com   | 71 16 01 E2 B5 F5 C1 E8
                         |                             |


More information about the pvrusb2 mailing list