cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

check-sysctl-docs (4472B)


      1#!/usr/bin/gawk -f
      2# SPDX-License-Identifier: GPL-2.0
      3
      4# Script to check sysctl documentation against source files
      5#
      6# Copyright (c) 2020 Stephen Kitt
      7
      8# Example invocation:
      9#	scripts/check-sysctl-docs -vtable="kernel" \
     10#		Documentation/admin-guide/sysctl/kernel.rst \
     11#		$(git grep -l register_sysctl_)
     12#
     13# Specify -vdebug=1 to see debugging information
     14
     15BEGIN {
     16    if (!table) {
     17	print "Please specify the table to look for using the table variable" > "/dev/stderr"
     18	exit 1
     19    }
     20}
     21
     22# The following globals are used:
     23# children: maps ctl_table names and procnames to child ctl_table names
     24# documented: maps documented entries (each key is an entry)
     25# entries: maps ctl_table names and procnames to counts (so
     26#          enumerating the subkeys for a given ctl_table lists its
     27#          procnames)
     28# files: maps procnames to source file names
     29# paths: maps ctl_path names to paths
     30# curpath: the name of the current ctl_path struct
     31# curtable: the name of the current ctl_table struct
     32# curentry: the name of the current proc entry (procname when parsing
     33#           a ctl_table, constructed path when parsing a ctl_path)
     34
     35
     36# Remove punctuation from the given value
     37function trimpunct(value) {
     38    while (value ~ /^["&]/) {
     39	value = substr(value, 2)
     40    }
     41    while (value ~ /[]["&,}]$/) {
     42	value = substr(value, 1, length(value) - 1)
     43    }
     44    return value
     45}
     46
     47# Print the information for the given entry
     48function printentry(entry) {
     49    seen[entry]++
     50    printf "* %s from %s", entry, file[entry]
     51    if (documented[entry]) {
     52	printf " (documented)"
     53    }
     54    print ""
     55}
     56
     57
     58# Stage 1: build the list of documented entries
     59FNR == NR && /^=+$/ {
     60    if (prevline ~ /Documentation for/) {
     61	# This is the main title
     62	next
     63    }
     64
     65    # The previous line is a section title, parse it
     66    $0 = prevline
     67    if (debug) print "Parsing " $0
     68    inbrackets = 0
     69    for (i = 1; i <= NF; i++) {
     70	if (length($i) == 0) {
     71	    continue
     72	}
     73	if (!inbrackets && substr($i, 1, 1) == "(") {
     74	    inbrackets = 1
     75	}
     76	if (!inbrackets) {
     77	    token = trimpunct($i)
     78	    if (length(token) > 0 && token != "and") {
     79		if (debug) print trimpunct($i)
     80		documented[trimpunct($i)]++
     81	    }
     82	}
     83	if (inbrackets && substr($i, length($i), 1) == ")") {
     84	    inbrackets = 0
     85	}
     86    }
     87}
     88
     89FNR == NR {
     90    prevline = $0
     91    next
     92}
     93
     94
     95# Stage 2: process each file and find all sysctl tables
     96BEGINFILE {
     97    delete children
     98    delete entries
     99    delete paths
    100    curpath = ""
    101    curtable = ""
    102    curentry = ""
    103    if (debug) print "Processing file " FILENAME
    104}
    105
    106/^static struct ctl_path/ {
    107    match($0, /static struct ctl_path ([^][]+)/, tables)
    108    curpath = tables[1]
    109    if (debug) print "Processing path " curpath
    110}
    111
    112/^static struct ctl_table/ {
    113    match($0, /static struct ctl_table ([^][]+)/, tables)
    114    curtable = tables[1]
    115    if (debug) print "Processing table " curtable
    116}
    117
    118/^};$/ {
    119    curpath = ""
    120    curtable = ""
    121    curentry = ""
    122}
    123
    124curpath && /\.procname[\t ]*=[\t ]*".+"/ {
    125    match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
    126    if (curentry) {
    127	curentry = curentry "/" names[1]
    128    } else {
    129	curentry = names[1]
    130    }
    131    if (debug) print "Setting path " curpath " to " curentry
    132    paths[curpath] = curentry
    133}
    134
    135curtable && /\.procname[\t ]*=[\t ]*".+"/ {
    136    match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
    137    curentry = names[1]
    138    if (debug) print "Adding entry " curentry " to table " curtable
    139    entries[curtable][curentry]++
    140    file[curentry] = FILENAME
    141}
    142
    143/\.child[\t ]*=/ {
    144    child = trimpunct($NF)
    145    if (debug) print "Linking child " child " to table " curtable " entry " curentry
    146    children[curtable][curentry] = child
    147}
    148
    149/register_sysctl_table\(.*\)/ {
    150    match($0, /register_sysctl_table\(([^)]+)\)/, tables)
    151    if (debug) print "Registering table " tables[1]
    152    if (children[tables[1]][table]) {
    153	for (entry in entries[children[tables[1]][table]]) {
    154	    printentry(entry)
    155	}
    156    }
    157}
    158
    159/register_sysctl_paths\(.*\)/ {
    160    match($0, /register_sysctl_paths\(([^)]+), ([^)]+)\)/, tables)
    161    if (debug) print "Attaching table " tables[2] " to path " tables[1]
    162    if (paths[tables[1]] == table) {
    163	for (entry in entries[tables[2]]) {
    164	    printentry(entry)
    165	}
    166    }
    167    split(paths[tables[1]], components, "/")
    168    if (length(components) > 1 && components[1] == table) {
    169	# Count the first subdirectory as seen
    170	seen[components[2]]++
    171    }
    172}
    173
    174
    175END {
    176    for (entry in documented) {
    177	if (!seen[entry]) {
    178	    print "No implementation for " entry
    179	}
    180    }
    181}