--- /dev/null
+#!/bin/gawk -f
+#
+# Copyright (c) 2015 Elvira Khabirova <lineprinter0@gmail.com>
+# Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
+# Copyright (c) 2017 Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
+# Copyright (c) 2015-2017 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.
+
+BEGIN {
+ dirmap[2^8] = "_IOC_NONE"
+ dirmap[2^9] = "_IOC_READ"
+ dirmap[2^10] = "_IOC_WRITE"
+ dirmap[2^10 + 2^9] = "_IOC_READ|_IOC_WRITE"
+}
+function array_get(array_idx, array_member, \
+ array_return)
+{
+ array_return = array[array_idx][array_member]
+ if ("" == array_return) {
+ printf("%s: index [%s] without %s\n",
+ FILENAME, array_idx, array_member) > "/dev/stderr"
+ exit 1
+ }
+ return array_return
+}
+function dir2str(dir, \
+ r) {
+ r = dirmap[dir]
+ if (r == "") {
+ printf("%s: ioctl direction %d is not known\n",
+ FILENAME, dir) > "/dev/stderr"
+ exit 1
+ }
+ return r
+}
+/^<[[:xdigit:]]+>/ {
+ match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches)
+ level = matches[1]
+ idx = "0x" matches[2]
+ parent[level] = idx
+}
+/^DW_AT_name/ {
+ match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/,
+ temparray)
+ array[idx]["name"] = temparray[1]
+}
+/^DW_AT_type/ {
+ match($0, /:[[:space:]]+<(0x[[:xdigit:]]*)>$/, temparray)
+ array[idx]["type"] = temparray[1]
+}
+/^DW_AT_upper_bound/ {
+ match($0, /[[:digit:]]+/, temparray)
+ array[array[idx]["parent"]]["size"] = temparray[0]
+}
+/^DW_AT_count/ {
+ match($0, /[[:digit:]]+/, temparray)
+ array[array[idx]["parent"]]["size"] = temparray[0] - 1
+}
+/^Abbrev Number:[^(]+\(DW_TAG_/ {
+ if (match($0, /member|subrange_type|variable/, temparray)) {
+ array[idx]["special"] = temparray[0]
+ if (level > 1 && ("member" == temparray[0] ||
+ "subrange_type" == temparray[0]))
+ array[idx]["parent"] = parent[level-1]
+ }
+}
+END {
+ for (i in array) {
+ if (array[i]["special"] == "variable" &&
+ index(array_get(i, "name"), "ioc_") == 1) {
+ ioc_name = substr(array_get(i, "name"),
+ length("ioc_") + 1)
+ type = array_get(i, "type")
+ delete sizemap
+ for (j in array) {
+ if ("parent" in array[j] &&
+ type == array_get(j, "parent")) {
+ t = array_get(j, "type")
+
+ field_name = array_get(j, "name")
+ sizemap[field_name] = \
+ array_get(t, "size")
+ }
+ }
+ if (sizemap["d"] == "" ||
+ sizemap["n"] == "" ||
+ sizemap["s"] == "") {
+ printf("%s: failed to parse %s ioctl info\n",
+ FILENAME, ioc_name) > "/dev/stderr"
+ exit 1
+ }
+ printf("{ \"%s\", \"%s\", %s, 0x%04x, 0x%02x },\n",
+ HEADER_NAME, ioc_name, dir2str(sizemap["d"]),
+ sizemap["n"], sizemap["s"])
+ }
+ }
+}
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)"
+: "${uname_m:=$(uname -m)}"
me="${0##*/}"
msg()
{
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 pre-include workarounds for some processed files. Fragile.
# 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"
}
+++ /dev/null
-/*
- * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
- * 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.
- */
-
-#include <stdio.h>
-#include <asm/ioctl.h>
-
-typedef unsigned short u16;
-
-static const char *
-dir2str(const char *name, u16 dir)
-{
- switch (dir) {
-#define CASE(x) case x: return #x
- CASE(_IOC_NONE);
- CASE(_IOC_READ);
- CASE(_IOC_WRITE);
- CASE(_IOC_READ|_IOC_WRITE);
- }
-
- static char buf[3 + sizeof(dir) * 2];
- fprintf(stderr,
- "print_ioctlents: WARNING: invalid dir 0x%02x in %s\n",
- dir, name);
- snprintf(buf, sizeof(buf), "0x%02x", dir);
- return buf;
-}
-
-void
-print_ioctlent(const char *info, const char *name,
- u16 dir, u16 type, u16 nr, u16 size)
-{
- unsigned int type_nr =
- ((unsigned) type << _IOC_TYPESHIFT) |
- ((unsigned) nr << _IOC_NRSHIFT);
-
- if (dir & ~_IOC_DIRMASK)
- fprintf(stderr,
- "print_ioctlents: WARNING: dir 0x%02x is out of mask 0x%02x in %s\n",
- dir, _IOC_DIRMASK, name);
- if (type & ~_IOC_TYPEMASK)
- fprintf(stderr,
- "print_ioctlents: WARNING: type 0x%02x is out of mask 0x%02x in %s\n",
- type, _IOC_TYPEMASK, name);
- if (nr & ~_IOC_NRMASK)
- fprintf(stderr,
- "print_ioctlents: WARNING: nr 0x%02x is out of mask 0x%02x in %s\n",
- nr, _IOC_NRMASK, name);
- if (size & ~_IOC_SIZEMASK)
- fprintf(stderr,
- "print_ioctlents: WARNING: size 0x%02x is out of mask 0x%02x in %s\n",
- size, _IOC_SIZEMASK, name);
-
- printf("{ \"%s\", \"%s\", %s, 0x%04x, 0x%02x },\n",
- info, name, dir2str(name, dir), type_nr, size);
-}