summaryrefslogtreecommitdiff
path: root/find-requires.ksyms
blob: 42af85ff9f9b2093b78362efcc4b2d883d27301c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#! /bin/bash
#
# This script is called during external module building to create dependencies
# both upon the linux kernel, and on additional external modules. Symbols that
# cannot be reconciled against those provided by the kernel are assumed to be
# provided by an external module and "ksym" replaces th regular "kernel" dep.

IFS=$'\n'

# Extract all of the symbols provided by this module.
all_provides() {
    for module in "$@"; do
        tmpfile=""
        if [ "x${module%.ko}" = "x${module}" ]; then
            tmpfile=$(mktemp -t ${0##*/}.XXXXXX.ko)
            proc_bin=
            case "${module##*.}" in
            xz)
                    proc_bin=xz
                    ;;
            bz2)
                    proc_bin=bzip2
                    ;;
            gz)
                    proc_bin=gzip
                    ;;
            esac

            [ -n "$proc_bin" ] || continue

            "$proc_bin" -d -c - < "$module" > "$tmpfile" || continue
            module="$tmpfile"
        fi

        if [[ -n $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then
            nm "$module" \
            | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \
            | awk --non-decimal-data '{printf("%s:0x%08x\n", $2, $1)}'
        else
            ELFRODATA=$(readelf -R .rodata "$module" | awk '/0x/{printf $2$3$4$5}')
            if [[ -n $(readelf -h "$module" | grep "little endian") ]]; then
                RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g')
            else
                RODATA=$ELFRODATA
            fi
            for sym in $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) R __crc_(.+):0x\1 \2:p'); do
                echo $sym $RODATA
            done \
            | awk --non-decimal-data '{printf("%s:0x%08s\n", $2, substr($3,($1*2)+1,8))}'
        fi

        [ -z "$tmpfile" ] || rm -f -- "$tmpfile"
    done \
    | LC_ALL=C sort -k1,1 -u
}

# Extract all of the requirements of this module.
all_requires() {
    for module in "$@"; do
        set -- $(/sbin/modinfo -F vermagic "$module" | sed -e 's: .*::' -e q)
        /sbin/modprobe --dump-modversions "$module" \
        | awk --non-decimal-data '
            BEGIN { FS = "\t" ; OFS = "\t" }
            {printf("%s:0x%08x\n", $2, $1)}' \
        | sed -r -e 's:$:\t'"$1"':'
    done \
    | LC_ALL=C sort -k1,1 -u
}

# Filter out requirements fulfilled by the module itself.
mod_requires() {
    LC_ALL=C join -t $'\t' -j 1 -v 1 \
        <(all_requires "$@") \
        <(all_provides "$@") \
    | LC_ALL=C sort -k1,1 -u
}

if ! [ -e /sbin/modinfo -a -e /sbin/modprobe ]; then
    cat > /dev/null
    exit 0
fi

check_kabi() {
    arch=$(uname -m)
    kabi_file="/lib/modules/kabi-current/kabi_stablelist_$arch"

    # If not installed, output a warning and return (continue)
    if [ ! -f "$kabi_file" ]; then
        echo "" >&2
        echo "********************************************************************************" >&2
        echo "*********************** KERNEL ABI COMPATIBILITY WARNING ***********************" >&2
        echo "********************************************************************************" >&2
        echo "The kernel ABI reference files (provided by "kernel-abi-stablelists") were not found." >&2
        echo "No compatibility check was performed. Please install the kABI reference files" >&2
        echo "and rebuild if you would like to verify compatibility with kernel ABI." >&2
        echo "" >&2
        return
    fi

    unset non_kabi
    for symbol in "$@"; do
        if ! egrep "^$symbol\$" $kabi_file >/dev/null; then
            non_kabi=("${non_kabi[@]}" "$symbol")
        fi
    done

    if [ ${#non_kabi[@]} -gt 0 ]; then
        echo "" >&2
        echo "********************************************************************************" >&2
        echo "*********************** KERNEL ABI COMPATIBILITY WARNING ***********************" >&2
        echo "********************************************************************************" >&2
        echo "The following kernel symbols are not guaranteed to remain compatible with" >&2
        echo "future kernel updates to this RHEL release:" >&2
        echo "" >&2
        for symbol in "${non_kabi[@]}"; do
            printf "\t$symbol\n" >&2
        done
        echo "" >&2
        echo "@VENDOR@ recommends that you consider using only official kernel ABI symbols" >&2
        echo "where possible. Requests for additions to the kernel ABI can be filed with" >&2
        echo "your partner or customer representative (component: driver-update-program)." >&2
        echo "" >&2
    fi
}

modules=($(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz)?$'))
if [ ${#modules[@]} -gt 0 ]; then
    kernel=$(/sbin/modinfo -F vermagic "${modules[0]}" | sed -e 's: .*::' -e q)

    # get all that kernel provides
    symvers=$(mktemp -t ${0##*/}.XXXXX)

    cat /usr/src/kernels/$kernel/Module.symvers | awk '
        BEGIN { FS = "\t" ; OFS = "\t" }
        { print $2 ":" $1 }
    ' \
    | sed -r -e 's:$:\t'"$kernel"':' \
    | LC_ALL=C sort -k1,1 -u > $symvers

    # Symbols matching with the kernel get a "kernel" dependency
    mod_req=$(mktemp -t mod_req.XXXXX)
    mod_requires "${modules[@]}" > "$mod_req"
    LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \
    | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "kernel(" $1 ") = " $2 }'

    # Symbols from elsewhere get a "ksym" dependency
    LC_ALL=C join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | LC_ALL=C sort -u \
    | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "ksym(" $1 ") = " $2 }'

    # Check kABI if the kernel-abi-stablelists package is installed
    # Do this last so we can try to output this error at the end
    kabi_check_symbols=($(LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \
    | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print $1 }'))
    check_kabi "${kabi_check_symbols[@]}"
fi