]> granicus.if.org Git - strace/blob - maint/ioctls_sym.sh
io: handle data_size of -1 as unlimited data in print_iovec
[strace] / maint / ioctls_sym.sh
1 #!/bin/sh
2 # Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1. Redistributions of source code must retain the above copyright
9 #    notice, this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright
11 #    notice, this list of conditions and the following disclaimer in the
12 #    documentation and/or other materials provided with the distribution.
13 # 3. The name of the author may not be used to endorse or promote products
14 #    derived from this software without specific prior written permission.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 set -efu
28
29 # This script processes header files containing ioctl command definitions in
30 # symbolic form, assuming that these definitions match the following regular
31 # expressions:
32
33 r_define='^[[:space:]]*#[[:space:]]*define[[:space:]]\+'
34 r_cmd_name='[A-Z][A-Z0-9_]*'
35 r_io='\([A-Z]\+\)\?_S\?\(IO\|IOW\|IOR\|IOWR\|IOC\)'
36 r_value='[[:space:]]\+'"$r_io"'[[:space:]]*([^)]'
37 regexp="${r_define}${r_cmd_name}${r_value}"
38
39 me="${0##*/}"
40 msg()
41 {
42         printf >&2 '%s\n' "$me: $*"
43 }
44
45 prefix=
46 case $# in
47         1)      inc_dir="$1"; shift
48                 ;;
49         2)      inc_dir="$1"; shift
50                 prefix="$1"; shift
51                 ;;
52         *)      echo >&2 "usage: $me include-directory [prefix]"
53                 exit 1
54                 ;;
55 esac
56
57 [ -z "$prefix" ] ||
58         prefix="${prefix%%/}/"
59
60 tmpdir=
61 cleanup()
62 {
63         trap - EXIT
64         [ -z "$tmpdir" ] ||
65                 rm -rf -- "$tmpdir"
66         exit "$@"
67 }
68
69 trap 'cleanup $?' EXIT
70 trap 'cleanup 1' HUP PIPE INT QUIT TERM
71 tmpdir="$(mktemp -dt "$me.XXXXXX")"
72
73 # list interesting files in $inc_dir.
74 cd "$inc_dir"
75 inc_dir="$(pwd -P)"
76 find . -type f -name '*.h' -print0 |
77         xargs -r0 grep -l "$r_value" -- > "$tmpdir"/headers1.list ||
78                 exit 0
79 cd - > /dev/null
80 sed 's|^\./\(uapi/\)\?||' < "$tmpdir"/headers1.list > "$tmpdir"/headers.list
81 LC_COLLATE=C sort -u -o "$tmpdir"/headers.list "$tmpdir"/headers.list
82
83 msg "processing $(wc -l < "$tmpdir"/headers.list) header files from $inc_dir"
84 failed=0
85
86 CC="${CC:-gcc}"
87 CPP="${CPP:-cpp}"
88 CPPFLAGS="${CPPFLAGS-} -D__EXPORTED_HEADERS__"
89 CFLAGS="${CFLAGS:--Wall -O2} -D__EXPORTED_HEADERS__"
90 LDFLAGS="${LDFLAGS-}"
91 INCLUDES="-I$inc_dir/uapi -I$inc_dir ${INCLUDES-}"
92
93 $CC $INCLUDES $CFLAGS -c -o "$tmpdir"/print_ioctlent.o "${0%/*}"/print_ioctlent.c
94
95 # Hook onto <asm-generic/ioctl.h> and <asm/ioctl.h>
96 for d in asm-generic asm; do
97         mkdir "$tmpdir/$d"
98         cat > "$tmpdir/$d"/ioctl.h <<__EOF__
99 #include_next <$d/ioctl.h>
100 #undef _IOC
101 #define _IOC(dir,type,nr,size) dir, type, nr, size
102 __EOF__
103 done
104
105 INCLUDES="-I$tmpdir $INCLUDES"
106
107 process_file()
108 {
109         local f="$1"; shift
110
111         # Common code for every processed file.
112         cat > "$tmpdir"/printents.c <<__EOF__
113 #include <asm/termbits.h>
114 #include <asm/ioctl.h>
115 #include <linux/types.h>
116 #include <linux/limits.h>
117 #include <linux/major.h>
118
119 #include <sys/types.h>
120 #include <sys/socket.h>
121 #include <stdint.h>
122 #include <stdbool.h>
123
124 #ifndef NULL
125 # define NULL ((void*)0)
126 #endif
127 #ifndef __user
128 # define __user
129 #endif
130 #ifndef __iomem
131 # define __iomem
132 #endif
133 #ifndef __noreturn
134 # define __noreturn __attribute__((noreturn))
135 #endif
136 #ifndef __packed
137 # define __packed __attribute__((packed))
138 #endif
139
140 typedef signed char s8;
141 typedef unsigned char u8;
142 typedef signed short s16;
143 typedef unsigned short u16;
144 typedef signed int s32;
145 typedef unsigned int u32;
146 typedef signed long long s64;
147 typedef unsigned long long u64;
148
149 #include "fixes.h"
150
151 #include <asm/bitsperlong.h>
152 #ifndef BITS_PER_LONG
153 # define BITS_PER_LONG __BITS_PER_LONG
154 #endif
155
156 #include "$f"
157
158 void print_ioctlent(const char *, const char *, unsigned short, unsigned short, unsigned short, unsigned short);
159
160 int main(void)
161 {
162
163 #include "defs.h"
164
165 return 0;
166 }
167 __EOF__
168
169         # Soft workarounds for some processed files.  Fragile.
170         case "$f" in
171                 *asm/cmb.h)
172                         echo '#include <asm/dasd.h>'
173                         ;;
174                 *asm/ioctls.h)
175                         cat <<'__EOF__'
176 #include <asm/termios.h>
177 #include <linux/serial.h>
178 __EOF__
179                         ;;
180                 drm/sis_drm.h)
181                         echo '#include <drm/drm.h>'
182                         ;;
183                 *drm/*_drm.h)
184                         echo '#include <drm/drm.h>' > "$tmpdir/drm.h"
185                         ;;
186                 fbio.h|*/fbio.h)
187                         cat <<'__EOF__'
188 #include <linux/fb.h>
189 #undef FBIOGETCMAP
190 #undef FBIOPUTCMAP
191 __EOF__
192                         ;;
193                 *linux/atm_zatm.h)
194                         cat <<'__EOF__'
195 #include <linux/atm.h>
196 #ifndef _LINUX_TIME_H
197 # define _LINUX_TIME_H
198 #endif
199 #ifndef _UAPI_LINUX_TIME_H
200 # define _UAPI_LINUX_TIME_H
201 #endif
202 __EOF__
203                         ;;
204                 *linux/atm?*.h)
205                         echo '#include <linux/atm.h>'
206                         ;;
207                 *linux/auto_fs*.h)
208                         echo 'typedef u32 compat_ulong_t;'
209                         ;;
210                 *linux/coda.h|*android_alarm.h)
211                         cat <<'__EOF__'
212 #ifndef _LINUX_TIME_H
213 # define _LINUX_TIME_H
214 #endif
215 #ifndef _UAPI_LINUX_TIME_H
216 # define _UAPI_LINUX_TIME_H
217 #endif
218 __EOF__
219                         ;;
220                 *linux/fs.h|*linux/ncp_fs.h)
221                         cat <<'__EOF__'
222 #include <linux/blktrace_api.h>
223 #include <linux/fiemap.h>
224 __EOF__
225                         ;;
226                 *linux/if_pppox.h)
227                         cat <<'__EOF__'
228 #include <linux/if.h>
229 #include <linux/in.h>
230 #include <linux/in6.h>
231 __EOF__
232                         ;;
233                 *linux/if_tun.h|*linux/ppp-ioctl.h)
234                         echo '#include <linux/filter.h>'
235                         ;;
236                 *linux/isdn_ppp.h|*linux/gsmmux.h)
237                         echo '#include <linux/if.h>'
238                         ;;
239                 *media*/saa6588.h)
240                         echo 'typedef struct poll_table_struct poll_table;'
241                         ;;
242                 *linux/ivtvfb.h|*linux/meye.h|*media/*.h)
243                         echo '#include <linux/videodev2.h>'
244                         ;;
245                 *linux/kvm.h)
246                         cat <<'__EOF__'
247 #if !(defined __powerpc__)
248 struct kvm_allocate_rma { __u32 unused[2]; };
249 struct kvm_create_spapr_tce { __u32 unused[3]; };
250 struct kvm_create_spapr_tce_64 { __u32 unused[8]; };
251 struct kvm_get_htab_fd { __u32 unused[8]; };
252 struct kvm_rtas_token_args { __u8 unused[128]; };
253 #endif
254
255 #if !(defined __arm64__ || defined __arm__)
256 struct kvm_vcpu_init { __u32 unused[8]; };
257 #endif
258
259 #if !(defined __x86_64__ || defined __i386__)
260 struct kvm_cpuid { __u32 unused[2]; };
261 struct kvm_cpuid2 { __u32 unused[2]; };
262 struct kvm_debugregs { __u32 unused[32]; };
263 struct kvm_lapic_state { __u32 unused[256]; };
264 struct kvm_memory_alias { __u32 unused[8]; };
265 struct kvm_msr_list { __u32 unused[1]; };
266 struct kvm_msrs { __u32 unused[2]; };
267 struct kvm_pit_state { __u32 unused[18]; };
268 struct kvm_pit_state2 { __u32 unused[28]; };
269 struct kvm_vcpu_events { __u32 unused[16]; };
270 struct kvm_x86_mce { __u32 unused[16]; };
271 struct kvm_xcrs { __u32 unused[98]; };
272 struct kvm_xen_hvm_config { __u32 unused[14]; };
273 struct kvm_xsave { __u32 unused[1024]; };
274 #endif
275 __EOF__
276                         ;;
277                 *linux/sonet.h)
278                         echo '#include <linux/atmioc.h>'
279                         ;;
280                 *linux/usbdevice_fs.h)
281                         cat <<'__EOF__'
282 struct usbdevfs_ctrltransfer32 { __u32 unused[4]; };
283 struct usbdevfs_bulktransfer32 { __u32 unused[4]; };
284 struct usbdevfs_disconnectsignal32 { __u32 unused[2]; };
285 struct usbdevfs_urb32 { __u8 unused[42]; };
286 struct usbdevfs_ioctl32 { __u32 unused[3]; };
287 __EOF__
288                         ;;
289                 logger.h|*/logger.h)
290                         echo 'typedef __u32 kuid_t;'
291                         ;;
292                 *sound/asequencer.h)
293                         cat <<'__EOF__'
294 #include <sound/asound.h>
295 struct snd_seq_queue_owner { __u32 unused[0]; };
296 __EOF__
297                         ;;
298                 *sound/emu10k1.h)
299                         cat <<'__EOF__'
300 #include <sound/asound.h>
301 #ifndef DECLARE_BITMAP
302 # define DIV_ROUND_UP(x,y) (((x) + ((y) - 1)) / (y))
303 # define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, 8 * sizeof(long))
304 # define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)]
305 #endif
306 __EOF__
307                         ;;
308                 *video/sstfb.h)
309                         echo 'struct fb_info;'
310                         ;;
311                 *xen/evtchn.h|*xen/gntdev.h)
312                         cat <<'__EOF__'
313 typedef uint32_t grant_ref_t;
314 typedef uint16_t domid_t;
315 __EOF__
316                         ;;
317                 *xen/interface/*.h)
318                         return 0 # false positives
319                         ;;
320                 *xen/privcmd.h)
321                         return 0 # too much work to make it compileable
322                         ;;
323         esac > "$tmpdir"/fixes.h
324
325         cat > "$tmpdir"/header.in <<__EOF__
326 #include <asm/bitsperlong.h>
327 #ifndef BITS_PER_LONG
328 # define BITS_PER_LONG __BITS_PER_LONG
329 #endif
330 #include "$f"
331 __EOF__
332
333         if [ -f "$inc_dir/uapi/$f" ]; then
334                 s="$inc_dir/uapi/$f"
335         elif [ -f "$inc_dir/$f" ]; then
336                 s="$inc_dir/$f"
337         else
338                 msg "$f: file not found"
339                 return 1
340         fi
341
342         [ -n "${f##*/*}" ] ||
343                 mkdir -p "$tmpdir/${f%/*}"
344         # Hard workarounds for some processed files.  Very fragile.
345         case "$f" in
346                 *acpi/*|*linux/i2o.h|*media*/exynos-fimc.h|*media/v4l2-subdev.h|*net/bluetooth/*|net/nfc/nci_core.h)
347                         # Fetch macros only.
348                         grep "${r_define}${r_cmd_name}" < "$s" > "$tmpdir/$f"
349                         ;;
350                 binder.h|*/binder.h)
351                         # Convert enums to macros.
352                         sed '/^enum binder/,/^};/d' < "$s" > "$tmpdir/$f"
353                         sed -n '/^enum binder/,/^};/ s/^[[:space:]].*/&/p' < "$s" |
354                         sed -e '
355 s/^[[:space:]]*\([A-Z][A-Z_0-9]*\)[[:space:]]*=[[:space:]]*_\(IO\|IOW\|IOR\|IOWR\|IOC\)[[:space:]]*(/#define \1 _\2(/
356 s/^\(#define .*)\),$/\1/
357 s/^\(#define .*,\)$/\1 \\/
358 s/^\([[:space:]]\+[^),]\+)\),$/\1/' >> "$tmpdir/$f"
359                         ;;
360                 *drm/r128_drm.h)
361                         # Filter out the code that references unknown types.
362                         sed '/drm_r128_clear2_t/d' < "$s" > "$tmpdir/$f"
363                         ;;
364                 *drm/sis_drm.h)
365                         # Filter out the code that references unknown types.
366                         sed '/^struct sis_file_private/,/^}/d' < "$s" > "$tmpdir/$f"
367                         ;;
368                 *drm/via_drm.h)
369                         # Create the file it attempts to include.
370                         touch "$tmpdir/via_drmclient.h"
371                         # Filter out the code that references unknown types.
372                         sed '/^struct via_file_private/,/^}/d' < "$s" > "$tmpdir/$f"
373                         ;;
374                 *linux/vmw_vmci_defs.h)
375                         # Fetch ioctl macros only.
376                         grep "${r_define}I" < "$s" > "$tmpdir/$f"
377                         ;;
378                 *media/v4l2-common.h)
379                         # Fetch one piece of code containing ioctls definitions.
380                         sed -n '/ remaining ioctls/,/ ---/p' < "$s" > "$tmpdir/$f"
381                         ;;
382                 *linux/nilfs2_fs.h)
383                         # Create the file it attempts to include.
384                         touch "$tmpdir/asm/bug.h"
385                         ;;
386                 openpromio.h|*/openpromio.h|fbio.h|*/fbio.h)
387                         # Create the file it attempts to include.
388                         mkdir -p "$tmpdir/linux"
389                         touch "$tmpdir/linux/compiler.h"
390         esac
391         if [ -f "$tmpdir/$f" ]; then
392                 s="$tmpdir/$f"
393         fi
394
395         # This may fail if the file includes unavailable headers.
396         # In case of success it outputs both the #define directives
397         # and the result of preprocessing.
398         $CPP $CPPFLAGS -dD $INCLUDES < "$tmpdir"/header.in > "$tmpdir"/header.out
399
400         # Need to exclude ioctl commands defined elsewhere.
401         local_defines='^[[:space:]]*#[[:space:]]*define[[:space:]]\+\('"$r_cmd_name"'\)[[:space:]]'
402         sed -n 's/'"$local_defines"'.*/\1\\/p' "$s" > "$tmpdir"/local_names
403         r_local_names="$(tr '\n' '|' < "$tmpdir"/local_names)"
404         r_local_names="${r_local_names%%|}"
405         r_local_names="${r_local_names%%\\}"
406
407         # Keep this in sync with $regexp by replacing $r_cmd_name with $r_local_names.
408         defs_regexp="${r_define}\($r_local_names\)${r_value}"
409
410         qf="$(echo "$prefix$f" | sed 's/[&\/]/\\&/g')"
411         # This outputs lines in the following format:
412         # print_ioctlent("filename.h", "IOCTL_CMD_NAME", IOCTL_CMD_NAME);
413         sed -n 's/'"$defs_regexp"'.*/print_ioctlent("'"$qf"'", "\1", \1);/p' \
414                 < "$tmpdir"/header.out > "$tmpdir"/defs.h
415
416         # If something is wrong with the file, this will fail.
417         $CC $INCLUDES $CFLAGS -c -o "$tmpdir"/printents.o "$tmpdir"/printents.c
418         $CC $LDFLAGS -o "$tmpdir"/print_ioctlents \
419                 "$tmpdir"/printents.o "$tmpdir"/print_ioctlent.o
420         "$tmpdir"/print_ioctlents > "$tmpdir"/ioctlents
421         cat "$tmpdir"/ioctlents
422         msg "$f: fetched $(grep -c '^{' "$tmpdir"/ioctlents) ioctl entries"
423 }
424
425 while read f; do
426         (process_file "$f" < /dev/null)
427         [ $? -eq 0 ] || {
428                 msg "$f: failed to process"
429                 failed=$((1 + $failed))
430         }
431 done < "$tmpdir"/headers.list
432
433 [ $failed -eq 0 ] ||
434         msg "failed to process $failed file(s)"