diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2011-06-16 17:05:39 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2011-06-16 17:05:39 +0000 |
commit | f3b686285127db1c5fa79a17f2158cd4f25efb97 (patch) | |
tree | e7fe990b2ad8d399d5b1bbbdda58c74d05bed035 /usr.bin | |
parent | c9d6a2f99d79509833c31e13bba6c9e74a13af9a (diff) |
mksubr from freebsd, to be used to generate flags to name translation
for kdump. Added missing license to the file, with the kind
permission of the author David Kirchner. Not used yet. ok miod@
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/kdump/mksubr | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/usr.bin/kdump/mksubr b/usr.bin/kdump/mksubr new file mode 100644 index 00000000000..26425f8bb1e --- /dev/null +++ b/usr.bin/kdump/mksubr @@ -0,0 +1,467 @@ +#!/bin/sh +# $OpenBSD: mksubr,v 1.1 2011/06/16 17:05:38 otto Exp $ +# +# Copyright (c) 2006 David Kirchner <dpk@dpk.net> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# $FreeBSD: src/usr.bin/kdump/mksubr,v 1.17 2011/06/06 19:00:38 dchagin Exp $ +# +# Generates kdump_subr.c +# mkioctls is a special-purpose script, and works fine as it is +# now, so it remains independent. The idea behind how it generates +# its list was heavily borrowed here. +# +# Some functions here are automatically generated. This can mean +# the user will see unusual kdump output or errors while building +# if the underlying .h files are changed significantly. +# +# Key: +# AUTO: Completely auto-generated with either the "or" or the "switch" +# method. +# AUTO - Special: Generated automatically, but with some extra commands +# that the auto_*_type() functions are inappropriate for. +# MANUAL: Manually entered and must therefore be manually updated. + +set -e + +LC_ALL=C; export LC_ALL + +if [ -z "$1" ] +then + echo "usage: sh $0 include-dir" + exit 1 +fi +include_dir=$1 + +# +# Automatically generates a C function that will print out the +# numeric input as a pipe-delimited string of the appropriate +# #define keys. ex: +# S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH +# The XOR is necessary to prevent including the "0"-value in every +# line. +# +auto_or_type () { + local name grep file + name=$1 + grep=$2 + file=$3 + + cat <<_EOF_ +/* AUTO */ +void +$name (int arg) +{ + int or = 0; + printf("%#x<", arg); +_EOF_ + egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ + $include_dir/$file | \ + awk '{ for (i = 1; i <= NF; i++) \ + if ($i ~ /define/) \ + break; \ + ++i; \ + printf "\tif(!((arg>0)^((%s)>0)))\n\t\tif_print_or(arg, %s, or);\n", $i, $i }' +cat <<_EOF_ + printf(">"); + if (or == 0) + (void)printf("<invalid>%ld", (long)arg); +} + +_EOF_ +} + +# +# Automatically generates a C function used when the argument +# maps to a single, specific #definition +# +auto_switch_type () { + local name grep file + name=$1 + grep=$2 + file=$3 + + cat <<_EOF_ +/* AUTO */ +void +$name (int arg) +{ + switch (arg) { +_EOF_ + egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ + $include_dir/$file | \ + awk '{ for (i = 1; i <= NF; i++) \ + if ($i ~ /define/) \ + break; \ + ++i; \ + printf "\tcase %s:\n\t\t(void)printf(\"%s\");\n\t\tbreak;\n", $i, $i }' +cat <<_EOF_ + default: /* Should not reach */ + (void)printf("<invalid=%ld>", (long)arg); + } +} + +_EOF_ +} + +# +# Automatically generates a C function used when the argument +# maps to a #definition +# +auto_if_type () { + local name grep file + name=$1 + grep=$2 + file=$3 + + cat <<_EOF_ +/* AUTO */ +void +$name (int arg) +{ +_EOF_ + egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ + $include_dir/$file | \ + awk '{ printf "\t"; \ + if (NR > 1) \ + printf "else " ; \ + printf "if (arg == %s) \n\t\tprintf(\"%s\");\n", $2, $2 }' +cat <<_EOF_ + else /* Should not reach */ + (void)printf("<invalid=%ld>", (long)arg); +} + +_EOF_ +} + +# C start + +cat <<_EOF_ +#include <stdio.h> +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <sys/unistd.h> +#include <sys/mman.h> +#include <sys/wait.h> +#define _KERNEL +#include <sys/socket.h> +#undef _KERNEL +#include <netinet/in.h> +#include <sys/param.h> +#include <sys/mount.h> +#include <sys/ptrace.h> +#include <sys/resource.h> +#include <sys/reboot.h> +#include <sched.h> +#include <sys/linker.h> +#define _KERNEL +#include <sys/thr.h> +#undef _KERNEL +#include <sys/extattr.h> +#include <sys/acl.h> +#include <aio.h> +#include <sys/sem.h> +#include <sys/ipc.h> +#include <sys/rtprio.h> +#include <sys/shm.h> +#include <nfsserver/nfs.h> +#include <ufs/ufs/quota.h> + +#include "kdump_subr.h" + +/* + * These are simple support macros. print_or utilizes a variable + * defined in the calling function to track whether or not it should + * print a logical-OR character ('|') before a string. if_print_or + * simply handles the necessary "if" statement used in many lines + * of this file. + */ +#define print_or(str,orflag) do { \\ + if (orflag) putchar('|'); else orflag = 1; \\ + printf (str); } \\ + while (0) +#define if_print_or(i,flag,orflag) do { \\ + if ((i & flag) == flag) \\ + print_or(#flag,orflag); } \\ + while (0) + +/* MANUAL */ +extern char *signames[]; /* from kdump.c */ +void +signame (int sig) +{ + if (sig > 0 && sig < NSIG) + (void)printf("SIG%s",signames[sig]); + else + (void)printf("SIG %d", sig); +} + +/* MANUAL */ +void +semctlname (int cmd) +{ + switch (cmd) { + case GETNCNT: + (void)printf("GETNCNT"); + break; + case GETPID: + (void)printf("GETPID"); + break; + case GETVAL: + (void)printf("GETVAL"); + break; + case GETALL: + (void)printf("GETALL"); + break; + case GETZCNT: + (void)printf("GETZCNT"); + break; + case SETVAL: + (void)printf("SETVAL"); + break; + case SETALL: + (void)printf("SETALL"); + break; + case IPC_RMID: + (void)printf("IPC_RMID"); + break; + case IPC_SET: + (void)printf("IPC_SET"); + break; + case IPC_STAT: + (void)printf("IPC_STAT"); + break; + default: /* Should not reach */ + (void)printf("<invalid=%ld>", (long)cmd); + } +} + +/* MANUAL */ +void +shmctlname (int cmd) { + switch (cmd) { + case IPC_RMID: + (void)printf("IPC_RMID"); + break; + case IPC_SET: + (void)printf("IPC_SET"); + break; + case IPC_STAT: + (void)printf("IPC_STAT"); + break; + default: /* Should not reach */ + (void)printf("<invalid=%ld>", (long)cmd); + } +} + +/* MANUAL */ +void +semgetname (int flag) { + int or = 0; + if_print_or(flag, IPC_CREAT, or); + if_print_or(flag, IPC_EXCL, or); + if_print_or(flag, SEM_R, or); + if_print_or(flag, SEM_A, or); + if_print_or(flag, (SEM_R>>3), or); + if_print_or(flag, (SEM_A>>3), or); + if_print_or(flag, (SEM_R>>6), or); + if_print_or(flag, (SEM_A>>6), or); +} + +/* + * MANUAL + * + * Only used by SYS_open. Unless O_CREAT is set in flags, the + * mode argument is unused (and often bogus and misleading). + */ +void +flagsandmodename (int flags, int mode, int decimal) { + flagsname (flags); + (void)putchar(','); + if ((flags & O_CREAT) == O_CREAT) { + modename (mode); + } else { + if (decimal) { + (void)printf("<unused>%ld", (long)mode); + } else { + (void)printf("<unused>%#lx", (long)mode); + } + } +} + +/* + * MANUAL + * + * [g|s]etsockopt's level argument can either be SOL_SOCKET or a value + * referring to a line in /etc/protocols . It might be appropriate + * to use getprotoent(3) here. + */ +void +sockoptlevelname (int level, int decimal) +{ + if (level == SOL_SOCKET) { + (void)printf("SOL_SOCKET"); + } else { + if (decimal) { + (void)printf("%ld", (long)level); + } else { + (void)printf("%#lx", (long)level); + } + } +} + +_EOF_ + +auto_or_type "modename" "S_[A-Z]+[[:space:]]+[0-6]{7}" "sys/stat.h" +auto_or_type "flagsname" "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h" +auto_or_type "accessmodename" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/unistd.h" +auto_or_type "mmapprotname" "PROT_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h" +auto_or_type "mmapflagsname" "MAP_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h" +auto_or_type "wait4optname" "W[A-Z]+[[:space:]]+[0-9]+" "sys/wait.h" +auto_or_type "getfsstatflagsname" "MNT_[A-Z]+[[:space:]]+[1-9][0-9]*" "sys/mount.h" +auto_or_type "mountflagsname" "MNT_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mount.h" +auto_or_type "rebootoptname" "RB_[A-Z]+[[:space:]]+0x[0-9]+" "sys/reboot.h" +auto_or_type "flockname" "LOCK_[A-Z]+[[:space:]]+0x[0-9]+" "sys/fcntl.h" +auto_or_type "thrcreateflagsname" "THR_[A-Z]+[[:space:]]+0x[0-9]+" "sys/thr.h" +auto_or_type "mlockallname" "MCL_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" +auto_or_type "shmatname" "SHM_[A-Z]+[[:space:]]+[0-9]{6}+" "sys/shm.h" +auto_or_type "rforkname" "RF[A-Z]+[[:space:]]+\([0-9]+<<[0-9]+\)" "sys/unistd.h" +auto_or_type "nfssvcname" "NFSSVC_[A-Z]+[[:space:]]+0x[0-9]+" "nfsserver/nfs.h" + +auto_switch_type "whencename" "SEEK_[A-Z]+[[:space:]]+[0-9]+" "sys/unistd.h" +auto_switch_type "rlimitname" "RLIMIT_[A-Z]+[[:space:]]+[0-9]+" "sys/resource.h" +auto_switch_type "shutdownhowname" "SHUT_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h" +auto_switch_type "prioname" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h" +auto_switch_type "madvisebehavname" "_?MADV_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h" +auto_switch_type "msyncflagsname" "MS_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" +auto_switch_type "schedpolicyname" "SCHED_[A-Z]+[[:space:]]+[0-9]+" "sched.h" +auto_switch_type "kldunloadfflagsname" "LINKER_UNLOAD_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" +auto_switch_type "extattrctlname" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h" +auto_switch_type "kldsymcmdname" "KLDSYM_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" +auto_switch_type "sendfileflagsname" "SF_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h" +auto_switch_type "acltypename" "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+" "sys/acl.h" +auto_switch_type "sigprocmaskhowname" "SIG_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +auto_switch_type "lio_listioname" "LIO_(NO)?WAIT[[:space:]]+[0-9]+" "aio.h" +auto_switch_type "minheritname" "INHERIT_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h" +auto_switch_type "quotactlname" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h" +auto_if_type "sockdomainname" "PF_[[:alnum:]]+[[:space:]]+" "sys/socket.h" +auto_if_type "sockfamilyname" "AF_[[:alnum:]]+[[:space:]]+" "sys/socket.h" +auto_if_type "sockipprotoname" "IPPROTO_[[:alnum:]]+[[:space:]]+" "netinet/in.h" +auto_switch_type "sockoptname" "SO_[A-Z]+[[:space:]]+0x[0-9]+" "sys/socket.h" +auto_switch_type "socktypename" "SOCK_[A-Z]+[[:space:]]+[1-9]+[0-9]*" "sys/socket.h" +auto_switch_type "ptraceopname" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h" + +cat <<_EOF_ +/* + * AUTO - Special + * F_ is used to specify fcntl commands as well as arguments. Both sets are + * grouped in fcntl.h, and this awk script grabs the first group. + */ +void +fcntlcmdname (int cmd, int arg, int decimal) +{ + switch (cmd) { +_EOF_ +egrep "^#[[:space:]]*define[[:space:]]+F_[A-Z]+[[:space:]]+[0-9]+[[:space:]]*" \ + $include_dir/sys/fcntl.h | \ + awk 'BEGIN { o=0 } { for (i = 1; i <= NF; i++) \ + if ($i ~ /define/) \ + break; \ + ++i; \ + if (o <= $(i+1)) \ + printf "\tcase %s:\n\t\t(void)printf(\"%s\");\n\t\tbreak;\n", $i, $i; \ + else \ + exit; \ + o = $(i+1) }' +cat <<_EOF_ + default: /* Should not reach */ + (void)printf("<invalid=%ld>", (long)cmd); + } + (void)putchar(','); + if (cmd == F_GETFD || cmd == F_SETFD) { + if (arg == FD_CLOEXEC) + (void)printf("FD_CLOEXEC"); + else if (arg == 0) + (void)printf("0"); + else { + if (decimal) + (void)printf("<invalid>%ld", (long)arg); + else + (void)printf("<invalid>%#lx", (long)arg); + } + } else if (cmd == F_SETFL) { + flagsname(arg); + } else { + if (decimal) + (void)printf("%ld", (long)arg); + else + (void)printf("%#lx", (long)arg); + } +} + +/* + * AUTO - Special + * + * The only reason this is not fully automated is due to the + * grep -v RTP_PRIO statement. A better egrep line should + * make this capable of being a auto_switch_type() function. + */ +void +rtprioname (int func) +{ + switch (func) { +_EOF_ +egrep "^#[[:space:]]*define[[:space:]]+RTP_[A-Z]+[[:space:]]+0x[0-9]+[[:space:]]*" \ + $include_dir/sys/rtprio.h | grep -v RTP_PRIO | \ + awk '{ for (i = 1; i <= NF; i++) \ + if ($i ~ /define/) \ + break; \ + ++i; \ + printf "\tcase %s:\n\t\t(void)printf(\"%s\");\n\t\tbreak;\n", $i, $i }' +cat <<_EOF_ + default: /* Should not reach */ + (void)printf("<invalid=%ld>", (long)func); + } +} + +/* + * AUTO - Special + * + * The send and recv functions have a flags argument which can be + * set to 0. There is no corresponding #define. The auto_ functions + * detect this as "invalid", which is incorrect here. + */ +void +sendrecvflagsname (int flags) +{ + int or = 0; + + if (flags == 0) { + (void)printf("0"); + return; + } + + printf("%#x<", flags); +_EOF_ +egrep "^#[[:space:]]*define[[:space:]]+MSG_[A-Z]+[[:space:]]+0x[0-9]+[[:space:]]*" $include_dir/sys/socket.h | \ + awk '{ for (i = 1; i <= NF; i++) \ + if ($i ~ /define/) \ + break; \ + ++i; \ + printf "\tif(!((flags>0)^((%s)>0)))\n\t\tif_print_or(flags, %s, or);\n", $i, $i }' +cat <<_EOF_ + printf(">"); +} + +_EOF_ |