Dmitry V. Levin
df7aa2b19e
Historically, only 16 bits (8-bit number and 8-bit type) of 32-bit ioctl commands were used for decoding, which was the source for numerous annoying collisions like this: ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(0, MGSL_IOCGPARAMS or MMTIMER_GETRES or MTIOCTOP or SNDCTL_MIDI_MPUMODE, 0x7fffd47f7338) = -1 ENOTTY (Inappropriate ioctl for device) The solution is to use all 32 bits for decoding, not just "number" and "type", but also "size" and "direction". As some architectures override defaults that come from asm-generic/ and provide alternative definitions for some ioctl commands, we support per-architecture ioctl definitions and merge them with common definitions at build time. During the merge, we used to keep both generic and architecture-specific definitions, now architecture-specific definitions have precedence over generic ones -- ioctlsort omits definitions from asm-generic/ for those ioctl names that have different definitions in asm/. Additional bits of "direction" are architecture specific -- the number of bits and their values differ between architectures. To reduce architecture differences in the source code, we keep "direction" in symbolic form and compile it in ioctlsort. Additional bits of "size" are also architecture specific -- not only the number of bits differ between architectures, but sizes of many types depend on sizeof(long). To reduce architecture differences in the source code, we keep 32-bit and 64-bit versions of common ioctl definitions, and use the appropriate version for each architecture and personality. To implement this, the tools for generating ioctl definitions from kernel headers have been rewritten, and the source format of ioctl definitions has been extended. The final ioctlent*.h files that are included by syscall.c are now generated from source ioctls_inc*.h and ioctls_arch*.h files at build time with ioctlsort. * ioctl.c (ioctl_lookup): Use all 32 bits of ioctl command code. * ioctlsort.c: Rewritten. * linux/32/ioctls_inc.h: New file. * linux/64/ioctls_inc.h: New file. * linux/aarch64/ioctls_arch0.h: New file. * linux/aarch64/ioctls_arch1.h: New file. * linux/aarch64/ioctls_inc0.h: New file. * linux/aarch64/ioctls_inc1.h: New file. * linux/alpha/ioctls_arch0.h: New file. * linux/alpha/ioctls_inc0.h: New file. * linux/arc/ioctls_arch0.h: New file. * linux/arc/ioctls_inc0.h: New file. * linux/arm/ioctls_arch0.h: New file. * linux/arm/ioctls_inc0.h: New file. * linux/avr32/ioctls_arch0.h: New file. * linux/avr32/ioctls_inc0.h: New file. * linux/bfin/ioctls_arch0.h: New file. * linux/bfin/ioctls_inc0.h: New file. * linux/hppa/ioctls_arch0.h: New file. * linux/hppa/ioctls_inc0.h: New file. * linux/i386/ioctls_arch0.h: New file. * linux/i386/ioctls_inc0.h: New file. * linux/ia64/ioctls_arch0.h: New file. * linux/ia64/ioctls_inc0.h: New file. * linux/m68k/ioctls_arch0.h: New file. * linux/m68k/ioctls_inc0.h: New file. * linux/metag/ioctls_arch0.h: New file. * linux/metag/ioctls_inc0.h: New file. * linux/microblaze/ioctls_arch0.h: New file. * linux/microblaze/ioctls_inc0.h: New file. * linux/mips/ioctls_arch0.h: New file. * linux/mips/ioctls_inc0.h: New file. * linux/or1k/ioctls_arch0.h: New file. * linux/or1k/ioctls_inc0.h: New file. * linux/powerpc/ioctls_arch0.h: New file. * linux/powerpc/ioctls_inc0.h: New file. * linux/powerpc64/ioctls_arch0.h: New file. * linux/powerpc64/ioctls_arch1.h: New file. * linux/powerpc64/ioctls_inc0.h: New file. * linux/powerpc64/ioctls_inc1.h: New file. * linux/s390/ioctls_arch0.h: New file. * linux/s390/ioctls_inc0.h: New file. * linux/s390x/ioctls_arch0.h: New file. * linux/s390x/ioctls_inc0.h: New file. * linux/sh/ioctls_arch0.h: New file. * linux/sh/ioctls_inc0.h: New file. * linux/sh64/ioctls_arch0.h: New file. * linux/sh64/ioctls_inc0.h: New file. * linux/sparc/ioctls_arch0.h: New file. * linux/sparc/ioctls_inc0.h: New file. * linux/sparc64/ioctls_arch0.h: New file. * linux/sparc64/ioctls_arch2.h: New file. * linux/sparc64/ioctls_inc0.h: New file. * linux/sparc64/ioctls_inc2.h: New file. * linux/tile/ioctls_arch0.h: New file. * linux/tile/ioctls_arch1.h: New file. * linux/tile/ioctls_inc0.h: New file. * linux/tile/ioctls_inc1.h: New file. * linux/x32/ioctls_arch0.h: New file. * linux/x32/ioctls_arch1.h: New file. * linux/x32/ioctls_inc0.h: New file. * linux/x32/ioctls_inc1.h: New file. * linux/x86_64/ioctls_arch0.h: New file. * linux/x86_64/ioctls_arch1.h: New file. * linux/x86_64/ioctls_inc0.h: New file. * linux/x86_64/ioctls_inc1.h: New file. * linux/xtensa/ioctls_arch0.h: New file. * linux/xtensa/ioctls_inc0.h: New file. * linux/aarch64/ioctlent.h.in: Remove. * linux/aarch64/ioctlent1.h: Remove. * linux/alpha/ioctlent.h.in: Remove. * linux/arc/ioctlent.h.in: Remove. * linux/arm/ioctlent.h.in: Remove. * linux/avr32/ioctlent.h.in: Remove. * linux/bfin/ioctlent.h.in: Remove. * linux/hppa/ioctlent.h.in: Remove. * linux/i386/ioctlent.h.in: Remove. * linux/ia64/ioctlent.h.in: Remove. * linux/ioctlent.h.in: Remove. * linux/ioctlent.sh: Remove. * linux/m68k/ioctlent.h.in: Remove. * linux/metag/ioctlent.h.in: Remove. * linux/microblaze/ioctlent.h.in: Remove. * linux/mips/ioctlent.h.in: Remove. * linux/mips/ioctlent.sh: Remove. * linux/or1k/ioctlent.h.in: Remove. * linux/powerpc/ioctlent.h.in: Remove. * linux/powerpc64/ioctlent.h: Remove. * linux/powerpc64/ioctlent1.h: Remove. * linux/s390/ioctlent.h.in: Remove. * linux/s390x/ioctlent.h.in: Remove. * linux/sh/ioctlent.h.in: Remove. * linux/sh64/ioctlent.h.in: Remove. * linux/sparc/ioctlent.h.in: Remove. * linux/sparc64/ioctlent.h.in: Remove. * linux/sparc64/ioctlent2.h: Remove. * linux/tile/ioctlent.h.in: Remove. * linux/tile/ioctlent1.h: Remove. * linux/x32/ioctlent.h.in: Remove. * linux/x32/ioctlent1.h: Remove. * linux/x86_64/ioctlent.h.in: Remove. * linux/x86_64/ioctlent1.h: Remove. * linux/xtensa/ioctlent.h.in: Remove. * linux/x86_64/ioctlent2.h: Include ioctlent0.h instead of ioctlent.h. * syscall.c (struct_ioctlent ioctlent0): Likewise. * Makefile.am: Remove all ioctlent-related definitions. Define the list of ioctlent*.h files that have to be generated by presence of $(srcdir)/$(OS)/$(ARCH)/ioctls_inc*.h files. Add rules for ioctlent*.h files generation. (EXTRA_DIST): Update. * maint/ioctls_gen.sh: New file. * maint/ioctls_hex.sh: New file. * maint/ioctls_sym.sh: New file. * maint/print_ioctlent.c: New file. * HACKING-scripts: Update for ioctlent.sh -> ioctls_gen.sh migration. * .gitignore: Add ioctlent[012].h and ioctls_all[012].h. * configure.ac (AC_CHECK_HEADERS): Add linux/hiddev.h and linux/mmtimer.h for tests. * tests/ioctl.c: New file. * tests/ioctl.test: New test. * tests/Makefile.am (check_PROGRAMS): Add ioctl. (TESTS): Add ioctl.test. * tests/.gitignore: Add ioctl.
59 lines
2.8 KiB
Plaintext
59 lines
2.8 KiB
Plaintext
Each strace port relies heavily on port-specific headers:
|
|
- errnoent.h - map error number to error name like strerror()
|
|
- ioctlent.h - map ioctl number to symbolic define
|
|
- signalent.h - map signal number to signal name like strsignal()
|
|
- syscallent.h - map syscall number to name and function signature
|
|
|
|
Since generating these headers from scratch (or even just updating them) can be
|
|
a big pain, there are a few scripts to help automate the process. Since each
|
|
port organizes their kernel sources differently, there may be a specific script
|
|
for your kernel.
|
|
|
|
We will use the Linux kernel (2.6.20+) as an example below (the Blackfin
|
|
architecture to be specific). Hopefully, it'll be obvious how to swap out a
|
|
different system or architecture as your circumstances apply.
|
|
|
|
ksrc=/usr/src/linux
|
|
asrc=$ksrc/arch/blackfin/include
|
|
|
|
To use the errnoent.sh script, give it all the headers that might contain
|
|
appropriate errno values. Excessive headers are not a problem. The resulting
|
|
output should be directly usable without modification.
|
|
sh ./errnoent.sh \
|
|
$ksrc/include/linux/*errno*.h \
|
|
$ksrc/include/asm-generic/*errno*.h \
|
|
$asrc/asm/*errno*.h \
|
|
> errnoent.h
|
|
|
|
To use the ioctls_gen.sh script, give it all the base include directories. The
|
|
script will crawl all the headers and try to discover appropriate ioctls.
|
|
Unlike the other scripts, this one creates files for further processing. This
|
|
is because ioctls tend to have a lot of define indirection, and the ioctlent0.h
|
|
header needs to be fully expanded into numeric form and sorted properly. So
|
|
first we process all of the ioctls with the ioctls_gen.sh into ioctls_inc.h and
|
|
ioctls_arch.h, and then we compile them into ioctlsort.c. The resulting
|
|
output, while directly usable, only contains definitions that match exactly the
|
|
current kernel version that the script ran against. That means older/newer
|
|
ioctl defines that might be present in the existing ioctlent0.h header will be
|
|
lost if things are copied directly. A little creative use of `diff` and manual
|
|
merging should be used to produce the final ioctlent0.h header.
|
|
sh ./maint/ioctls_gen.sh $ksrc/include $asrc
|
|
gcc -Wall -I. ioctlsort.c -o ioctlsort
|
|
./ioctlsort > ioctlent0.h
|
|
|
|
To use the signalent.sh script, give it all the headers that might contain
|
|
appropriate signal values. Excessive headers are not a problem. The resulting
|
|
output should be directly usable without modification.
|
|
sh ./signalent.sh \
|
|
$asrc/asm/signal.h \
|
|
> signalent.h
|
|
|
|
To use the syscallent.sh script, give it the header with the list of your
|
|
system call numbers. The resulting output is useful as a template for creating
|
|
a proper header as it can really only detect the system call number and its
|
|
name. It has no way of knowing the number of arguments or strace flags for
|
|
decoding them (yet?).
|
|
sh ./syscallent.sh \
|
|
$asrc/asm/unistd.h \
|
|
> syscallent.h
|