Summary: This is an exported API file (in kernel-headers for rpm-based distros). A compile-time test has unintended behaviour depending on user compiler. This issue appears to have been introduced with: http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.25.y.git;a=commit;h=af4cd3fe4cfa75ca74f8d8622867371289043a8d This patch distilled various includes into the current include/asm-generic/ioctl.h Hardware Environment: using i386 / x86_64 platforms (should be platform independent) Software Environment: Intel compiler 10.1.15 building user program with user-defined ioctl() calls. Problem Description: Building a program with debug (-g flag) can result in undefined reference to "__invalid_size_argument_for_IOC". This code from include/asm-generic/ioctl.h is the culprit: 50 /* provoke compile error for invalid uses of size argument */ 51 extern unsigned int __invalid_size_argument_for_IOC; 52 #define _IOC_TYPECHECK(t) \ 53 ((sizeof(t) == sizeof(t[1]) && \ 54 sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ 55 sizeof(t) : __invalid_size_argument_for_IOC) .... 61 #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) This gets used in the various _IO definitions. The comment indicates this was intended to throw a compiler error. It doesn't - it will always compile and end up generating a link-error for an undefined reference to __invalid_size_argument_for_IOC. In fact, lines 51-55 will only work *if* the compiler always optimizes away the reference to __invalid_size_argument_for_IOC. It turns out that gcc (currently) actually does optimize this out in all cases (even -g -O0), and never generates the undefined link reference. This isn't true for Intel's compilers (icc and icpc). If the -g flag is asserted the reference is generated and the error *always* occurs. It's hard to generate a debug image; The work-around hack is ugly - add a global def for __invalid_size_argument_for_IOC. This also disables the test. The intel compiler might not be the only one that has this behaviour. This fragment should be modified to generate an actual compile-time error, rather than an undefined linkage. I'm also going to give a heads-up to the intel compiler folks. Thanks for considering this. Steps to reproduce: Here's a short program: // Build with: // (OK) gcc -Wall ioctl_broke.c // (OK) gcc -g -Wall ioctl_broke.c // (OK) icc -Wall ioctl_broke.c // (Breaks) icc -g -Wall ioctl_broke.c // /tmp/iccRFH4Pa.o: In function `main': // /home/rda/ioctl_test.c:23: undefined reference to `__invalid_size_argument_for_IOC' // #include <string.h> #include <inttypes.h> #include <sys/ioctl.h> typedef struct my_ioctl { int32_t function, offset; void * bufaddr; int32_t bytes, status; } MYIOCTL; int main ( int argc, char *argv[] ) { MYIOCTL myio; ioctl ( 6, _IOWR('f',0x1, MYIOCTL), &myio ); return 0; }
Fixed by commit 5f8c3c8edff426fd87098f057688463107fcd9ce
When the ioctl command defined with _IOR etc. is used in a case statement, gcc (version 3.4.6) generates a compile time error: `__invalid_size_argument_for_IOC' cannot appear in a constant expression code example: #include <sys/ioctl.h> #define AQ_VERSION _IOR(0xa1, 0x14, int) ... switch (ioccmd) { case AQ_VERSION: ...; }
This was fixed by commit 5f8c3c8edff426fd87098f057688463107fcd9ce. It sounds like you're using old or broken kernel headers. In /usr/include/asm-generic/ioctl.h, the macro _IOC_TYPECHECK should be unconditionally defined as follows: #define _IOC_TYPECHECK(t) (sizeof(t)) If your distribution is not using the headers generated by running 'make headers_install' against a recent kernel, please file a bug against your distribution.
I can confirm that this commit shows up in Fedora 10. But it does not in Redhat 5.2 (I'll file a bug)