1*c8304204SSong Liu#!/bin/bash 2*c8304204SSong Liu# SPDX-License-Identifier: GPL-2.0 3*c8304204SSong Liu# 4*c8304204SSong Liu# Symbols which must not get a checksum entry of their own. 5*c8304204SSong Liu# 6*c8304204SSong Liu# .discard.sym_checksum is an array of { address, checksum } looked up by the 7*c8304204SSong Liu# address a relocation points at, so the invariant is one entry per address. 8*c8304204SSong Liu# calculate_checksums() skips three kinds of symbol to keep it: 9*c8304204SSong Liu# 10*c8304204SSong Liu# zero-length nothing to hash, and its address belongs to whatever really 11*c8304204SSong Liu# lives there 12*c8304204SSong Liu# alias a second name for an address already covered 13*c8304204SSong Liu# cold part hashed into its parent, which func_for_each_insn() walks 14*c8304204SSong Liu# into, so its own entry would double-count 15*c8304204SSong Liu# 16*c8304204SSong Liu# A duplicate entry is not a build failure. It makes the lookup ambiguous, and 17*c8304204SSong Liu# whichever checksum loses is simply never consulted again -- so a function 18*c8304204SSong Liu# whose code changed can be read as unchanged and dropped from the patch. 19*c8304204SSong Liu# 20*c8304204SSong Liu# Of the three, only the alias skip is isolated here: removing it makes this 21*c8304204SSong Liu# test fail. A zero-length symbol is excluded by more than one of the guards 22*c8304204SSong Liu# at once -- its section has no data either -- so no single change makes that 23*c8304204SSong Liu# assertion fail, and it stands as a check on the behaviour rather than on the 24*c8304204SSong Liu# line which produces it. Nothing here reaches the cold-part skip, which 25*c8304204SSong Liu# wants a compiler that splits functions; test-cold-function covers that 26*c8304204SSong Liu# symbol surviving into the patch, not its checksum. 27*c8304204SSong Liu# 28*c8304204SSong Liu# Covers the same ground as corpus/x86_64/checksum-zero-len-sym, 29*c8304204SSong Liu# checksum-alias-skip and checksum-cold-skip in Joe Lawrence's klp-build unit 30*c8304204SSong Liu# test corpus. 31*c8304204SSong Liu 32*c8304204SSong Liu. "$(dirname "$0")/../lib.sh" 33*c8304204SSong Liu 34*c8304204SSong Liusetup 35*c8304204SSong Liubuild_pair checksum_skip.c 36*c8304204SSong Liu 37*c8304204SSong Liuassert_input_symbol empty_marker 38*c8304204SSong Liuassert_input_symbol alias_function 39*c8304204SSong Liurun_checksum 40*c8304204SSong Liu 41*c8304204SSong Liu# entries_for <object> [-t] 42*c8304204SSong Liu# 43*c8304204SSong Liu# The symbol names .discard.sym_checksum has an entry for, one per line. With 44*c8304204SSong Liu# -t, what each entry points at instead: the name and its addend, which is the 45*c8304204SSong Liu# address the kernel looks the entry up by. A name alone is not that address, 46*c8304204SSong Liu# since a relocation against a section symbol names the section and puts the 47*c8304204SSong Liu# offset in the addend, and several entries can then share a name honestly. 48*c8304204SSong Liuentries_for() 49*c8304204SSong Liu{ 50*c8304204SSong Liu in_relocs "$1" | awk -v target="${2:-}" '/rela\.discard\.sym_checksum/,/^$/ { 51*c8304204SSong Liu if ($1 !~ /^[0-9a-f]{8,}/) 52*c8304204SSong Liu next 53*c8304204SSong Liu if (target == "-t") 54*c8304204SSong Liu print $5, $6, $7 55*c8304204SSong Liu else 56*c8304204SSong Liu print $5 57*c8304204SSong Liu }' 58*c8304204SSong Liu} 59*c8304204SSong Liu 60*c8304204SSong Liuentries="$(entries_for orig.o)" 61*c8304204SSong Liu 62*c8304204SSong Liu# The control: something real did get an entry, so an empty listing cannot 63*c8304204SSong Liu# make the rest of this pass by default. 64*c8304204SSong Liuecho "$entries" | grep -qx target || 65*c8304204SSong Liu fail "no checksum entry for target" 66*c8304204SSong Liu 67*c8304204SSong Liuecho "$entries" | grep -qx empty_marker && 68*c8304204SSong Liu fail "zero-length symbol got a checksum entry" 69*c8304204SSong Liu 70*c8304204SSong Liu# One of the two names for that address is kept and the other skipped; which 71*c8304204SSong Liu# one falls out of symbol table order and is not the point. Two would be. 72*c8304204SSong Liun="$(echo "$entries" | grep -cxE 'real_function|alias_function')" 73*c8304204SSong Liu[ "$n" = 1 ] || 74*c8304204SSong Liu fail "expected 1 checksum entry across real_function and its alias, found $n" 75*c8304204SSong Liu 76*c8304204SSong Liu# One entry per address, which is what the skipping is for. 77*c8304204SSong Liudupes="$(entries_for orig.o -t | sort | uniq -d)" 78*c8304204SSong Liu[ -z "$dupes" ] || 79*c8304204SSong Liu fail "two checksum entries for one address: $dupes" 80*c8304204SSong Liu 81*c8304204SSong Liupass "zero-length symbols and aliases get no checksum entry of their own" 82