#!/bin/sh
# Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
+# Copyright (c) 2015-2018 The strace developers.
# All rights reserved.
#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. The name of the author may not be used to endorse or promote products
-# derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -efu
+export LC_ALL=C
+
# This script processes header files containing ioctl command definitions in
# symbolic form, assuming that these definitions match the following regular
# expressions:
r_value='[[:space:]]\+'"$r_io"'[[:space:]]*([^)]'
regexp="${r_define}${r_cmd_name}${r_value}"
+: "${uname_m:=$(uname -m)}"
me="${0##*/}"
msg()
{
# list interesting files in $inc_dir.
cd "$inc_dir"
inc_dir="$(pwd -P)"
-find . -type f -name '*.h' -print0 |
- xargs -r0 grep -l "$r_value" -- > "$tmpdir"/headers1.list ||
- exit 0
+find . -type f -name '*.h' -exec grep -l "$r_value" -- '{}' + \
+ > "$tmpdir"/headers1.list ||:
+[ -s "$tmpdir"/headers1.list ] || exit 0
+
cd - > /dev/null
sed 's|^\./\(uapi/\)\?||' < "$tmpdir"/headers1.list > "$tmpdir"/headers.list
LC_COLLATE=C sort -u -o "$tmpdir"/headers.list "$tmpdir"/headers.list
msg "processing $(wc -l < "$tmpdir"/headers.list) header files from $inc_dir"
failed=0
+READELF="${READELF:-readelf}"
CC="${CC:-gcc}"
CPP="${CPP:-cpp}"
CPPFLAGS="${CPPFLAGS-} -D__EXPORTED_HEADERS__"
-CFLAGS="${CFLAGS:--Wall -O2} -D__EXPORTED_HEADERS__"
-LDFLAGS="${LDFLAGS-}"
+CFLAGS="${CFLAGS:--Wall -O2} -gdwarf-2 -D__EXPORTED_HEADERS__"
INCLUDES="-I$inc_dir/uapi -I$inc_dir ${INCLUDES-}"
-$CC $INCLUDES $CFLAGS -c -o "$tmpdir"/print_ioctlent.o "${0%/*}"/print_ioctlent.c
-
# Hook onto <asm-generic/ioctl.h> and <asm/ioctl.h>
for d in asm-generic asm; do
mkdir "$tmpdir/$d"
cat > "$tmpdir/$d"/ioctl.h <<__EOF__
#include_next <$d/ioctl.h>
+#undef _IOC_NONE
+#define _IOC_NONE (2<<7)
+#undef _IOC_READ
+#define _IOC_READ (2<<8)
+#undef _IOC_WRITE
+#define _IOC_WRITE (2<<9)
#undef _IOC
-#define _IOC(dir,type,nr,size) dir, type, nr, size
+#define _IOC(dir, type, nr, size) \
+ char \
+ d[1 + (dir)], \
+ n[1 + (((unsigned) (type) << _IOC_TYPESHIFT) | \
+ ((unsigned) (nr) << _IOC_NRSHIFT))], \
+ s[1 + (size)]
__EOF__
done
#include "$f"
-void print_ioctlent(const char *, const char *, unsigned short, unsigned short, unsigned short, unsigned short);
-
-int main(void)
-{
-
#include "defs.h"
-return 0;
-}
__EOF__
- # Soft workarounds for some processed files. Fragile.
+ # Soft pre-include workarounds for some processed files. Fragile.
case "$f" in
+ *asm/amigayle.h)
+ return 0 # false positive
+ ;;
*asm/cmb.h)
echo '#include <asm/dasd.h>'
;;
+ *asm/core_*.h)
+ return 0 # false positives
+ ;;
*asm/ioctls.h)
cat <<'__EOF__'
#include <asm/termios.h>
#include <linux/fb.h>
#undef FBIOGETCMAP
#undef FBIOPUTCMAP
+__EOF__
+ ;;
+ *linux/atm_zatm.h)
+ cat <<'__EOF__'
+#include <linux/atm.h>
+#ifndef _LINUX_TIME_H
+# define _LINUX_TIME_H
+#endif
+#ifndef _UAPI_LINUX_TIME_H
+# define _UAPI_LINUX_TIME_H
+#endif
__EOF__
;;
*linux/atm?*.h)
*linux/auto_fs*.h)
echo 'typedef u32 compat_ulong_t;'
;;
- *linux/btrfs.h)
- cat <<'__EOF__'
-struct btrfs_ioctl_defrag_range_args { __u32 unused[12]; };
-#define BTRFS_LABEL_SIZE 256
-__EOF__
- ;;
*linux/coda.h|*android_alarm.h)
cat <<'__EOF__'
#ifndef _LINUX_TIME_H
#include <linux/fiemap.h>
__EOF__
;;
+ *linux/ndctl.h)
+ echo '#define PAGE_SIZE 0'
+ ;;
*linux/if_pppox.h)
- cat <<'__EOF__'
-#include <linux/if.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-__EOF__
+ echo '#include <netinet/in.h>'
;;
*linux/if_tun.h|*linux/ppp-ioctl.h)
echo '#include <linux/filter.h>'
echo '#include <linux/videodev2.h>'
;;
*linux/kvm.h)
- cat <<'__EOF__'
-#if !(defined __powerpc__)
-struct kvm_allocate_rma { __u32 unused[2]; };
-struct kvm_create_spapr_tce { __u32 unused[3]; };
-struct kvm_create_spapr_tce_64 { __u32 unused[8]; };
-struct kvm_get_htab_fd { __u32 unused[8]; };
-struct kvm_rtas_token_args { __u8 unused[128]; };
-#endif
-
-#if !(defined __arm64__ || defined __arm__)
-struct kvm_vcpu_init { __u32 unused[8]; };
-#endif
-
-#if !(defined __x86_64__ || defined __i386__)
-struct kvm_cpuid { __u32 unused[2]; };
-struct kvm_cpuid2 { __u32 unused[2]; };
-struct kvm_debugregs { __u32 unused[32]; };
-struct kvm_lapic_state { __u32 unused[256]; };
-struct kvm_memory_alias { __u32 unused[8]; };
-struct kvm_msr_list { __u32 unused[1]; };
-struct kvm_msrs { __u32 unused[2]; };
-struct kvm_pit_state { __u32 unused[18]; };
-struct kvm_pit_state2 { __u32 unused[28]; };
-struct kvm_vcpu_events { __u32 unused[16]; };
-struct kvm_x86_mce { __u32 unused[16]; };
-struct kvm_xcrs { __u32 unused[98]; };
-struct kvm_xen_hvm_config { __u32 unused[14]; };
-struct kvm_xsave { __u32 unused[1024]; };
-#endif
-__EOF__
+ case "$uname_m" in
+ i?86|x86_64|aarch64|arm*|mips*|ppc*|s390*) ;;
+ *) return 0 ;; # not applicable
+ esac
+ ;;
+ *linux/omap3isp.h)
+ echo 'struct omap3isp_stat_data_time32 {uint32_t dummy32[4]; uint16_t dummy16[3]; };'
;;
*linux/sonet.h)
echo '#include <linux/atmioc.h>'
*video/sstfb.h)
echo 'struct fb_info;'
;;
- *xen/gntdev.h)
+ *xen/evtchn.h|*xen/gntdev.h)
cat <<'__EOF__'
typedef uint32_t grant_ref_t;
typedef uint16_t domid_t;
mkdir -p "$tmpdir/${f%/*}"
# Hard workarounds for some processed files. Very fragile.
case "$f" in
+ *asm-generic/ioctls.h)
+ # Filter out macros defined using unavailable types.
+ case "$uname_m" in
+ alpha*|ppc*)
+ grep -Fv 'struct termios2' < "$s" > "$tmpdir/$f"
+ ;;
+ esac
+ ;;
*acpi/*|*linux/i2o.h|*media*/exynos-fimc.h|*media/v4l2-subdev.h|*net/bluetooth/*|net/nfc/nci_core.h)
# Fetch macros only.
grep "${r_define}${r_cmd_name}" < "$s" > "$tmpdir/$f"
# Filter out the code that references unknown types.
sed '/^struct via_file_private/,/^}/d' < "$s" > "$tmpdir/$f"
;;
+ *linux/nilfs2_fs.h)
+ # Create the file it attempts to include.
+ touch "$tmpdir/asm/bug.h"
+ ;;
*linux/vmw_vmci_defs.h)
# Fetch ioctl macros only.
grep "${r_define}I" < "$s" > "$tmpdir/$f"
;;
*media/v4l2-common.h)
# Fetch one piece of code containing ioctls definitions.
- sed -n '/ remaining ioctls/,/ ---/p' < "$s" > "$tmpdir/$f"
- ;;
- *linux/nilfs2_fs.h)
- # Create the file it attempts to include.
- touch "$tmpdir/asm/bug.h"
+ sed -n '/\* s_config \*/,/ ---/p' < "$s" >> "$tmpdir/$f"
;;
openpromio.h|*/openpromio.h|fbio.h|*/fbio.h)
# Create the file it attempts to include.
# and the result of preprocessing.
$CPP $CPPFLAGS -dD $INCLUDES < "$tmpdir"/header.in > "$tmpdir"/header.out
+ # Soft post-preprocess workarounds. Fragile.
+ case "$f" in
+ *linux/btrfs.h)
+ sed -i '/[[:space:]]BTRFS_IOC_[GS]ET_FSLABEL[[:space:]]/d' \
+ "$tmpdir"/header.out
+ ;;
+ *linux/kvm.h)
+ arm_list='KVM_ARM_[A-Z_]+'
+ ppc_list='KVM_ALLOCATE_RMA|KVM_CREATE_SPAPR_TCE|KVM_CREATE_SPAPR_TCE_64|KVM_PPC_[A-Z1-9_]+'
+ s390_list='KVM_S390_[A-Z_]+'
+ x86_list='KVM_GET_CPUID2|KVM_GET_DEBUGREGS|KVM_GET_EMULATED_CPUID|KVM_GET_LAPIC|KVM_GET_MSRS|KVM_GET_MSR_FEATURE_INDEX_LIST|KVM_GET_MSR_INDEX_LIST|KVM_GET_NESTED_STATE|KVM_GET_PIT|KVM_GET_PIT2|KVM_GET_SUPPORTED_CPUID|KVM_GET_VCPU_EVENTS|KVM_GET_XCRS|KVM_GET_XSAVE|KVM_HYPERV_EVENTFD|KVM_SET_CPUID|KVM_SET_CPUID2|KVM_SET_DEBUGREGS|KVM_SET_LAPIC|KVM_SET_MEMORY_ALIAS|KVM_SET_MSRS|KVM_SET_NESTED_STATE|KVM_SET_PIT|KVM_SET_PIT2|KVM_SET_VCPU_EVENTS|KVM_SET_XCRS|KVM_SET_XSAVE|KVM_XEN_HVM_CONFIG|KVM_X86_[A-Z_]+'
+ case "$uname_m" in
+ aarch64|arm*) list="$ppc_list|$s390_list|$x86_list" ;;
+ ppc*) list="$arm_list|$s390_list|$x86_list" ;;
+ s390*) list="$arm_list|$ppc_list|$x86_list" ;;
+ i?86|x86_64*) list="$arm_list|$ppc_list|$s390_list" ;;
+ *) list="$arm_list|$ppc_list|$s390_list|$x86_list" ;;
+ esac
+ sed -r -i "/[[:space:]]($list)[[:space:]]/d" "$tmpdir"/header.out
+ ;;
+ *linux/v4l2-subdev.h)
+ sed -r -i '/[[:space:]]VIDIOC_SUBDEV_(DV_TIMINGS_CAP|ENUM_DV_TIMINGS|ENUMSTD|G_DV_TIMINGS|G_EDID|G_STD|QUERY_DV_TIMINGS|QUERYSTD|S_DV_TIMINGS|S_EDID|S_STD)[[:space:]]/d' \
+ "$tmpdir"/header.out
+ ;;
+ esac
+
# Need to exclude ioctl commands defined elsewhere.
local_defines='^[[:space:]]*#[[:space:]]*define[[:space:]]\+\('"$r_cmd_name"'\)[[:space:]]'
sed -n 's/'"$local_defines"'.*/\1\\/p' "$s" > "$tmpdir"/local_names
# Keep this in sync with $regexp by replacing $r_cmd_name with $r_local_names.
defs_regexp="${r_define}\($r_local_names\)${r_value}"
- qf="$(echo "$prefix$f" | sed 's/[&\/]/\\&/g')"
# This outputs lines in the following format:
- # print_ioctlent("filename.h", "IOCTL_CMD_NAME", IOCTL_CMD_NAME);
- sed -n 's/'"$defs_regexp"'.*/print_ioctlent("'"$qf"'", "\1", \1);/p' \
+ # struct {IOCTL_CMD_NAME;} ioc_IOCTL_CMD_NAME;
+ sed -n 's/'"$defs_regexp"'.*/struct {\1;} ioc_\1;/p' \
< "$tmpdir"/header.out > "$tmpdir"/defs.h
# If something is wrong with the file, this will fail.
$CC $INCLUDES $CFLAGS -c -o "$tmpdir"/printents.o "$tmpdir"/printents.c
- $CC $LDFLAGS -o "$tmpdir"/print_ioctlents \
- "$tmpdir"/printents.o "$tmpdir"/print_ioctlent.o
- "$tmpdir"/print_ioctlents > "$tmpdir"/ioctlents
+
+ $READELF --wide --debug-dump=info "$tmpdir"/printents.o \
+ > "$tmpdir"/debug-dump
+
+ sed -r -n '
+ /^[[:space:]]*<1>/,/^[[:space:]]*<1><[^>]+>: Abbrev Number: 0/!d
+ /^[[:space:]]*<[^>]*><[^>]*>: Abbrev Number: 0/d
+ s/^[[:space:]]*<[[:xdigit:]]+>[[:space:]]+//
+ s/^[[:space:]]*((<[[:xdigit:]]+>){2}):[[:space:]]+/\1\n/
+ s/[[:space:]]+$//
+ p' "$tmpdir"/debug-dump > "$tmpdir"/debug-info
+ gawk -v HEADER_NAME="$prefix$f" -f "${0%/*}"/ioctls_sym.awk \
+ "$tmpdir"/debug-info > "$tmpdir"/ioctlents
+
cat "$tmpdir"/ioctlents
msg "$f: fetched $(grep -c '^{' "$tmpdir"/ioctlents) ioctl entries"
}