xref: /linux/tools/objtool/tests/generic/test-checksum-skip.sh (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
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