xref: /linux/tools/objtool/tests/generic/test-abs-and-addressable.sh (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# An absolute symbol and an __ADDRESSABLE() pointer must not disturb the
5# function being patched.
6#
7# A SHN_ABS symbol has no section, so any walk of sym->sec which does not check
8# dereferences NULL -- and the kernel has plenty, from linker scripts and from
9# .set in assembly.  __ADDRESSABLE() emits a pointer into .discard.addressable
10# to keep a symbol referenced; it means nothing to a livepatch and is discarded
11# at link time, but it is a relocation like any other and gets looked at.
12#
13# Neither is what the patch changes.  The failure this guards against is not a
14# wrong answer but a crash or an error on input the kernel produces routinely,
15# which would make any function near one unpatchable.
16#
17# Not isolated to a single guard: the absolute symbol here has zero length, so
18# it is excluded before the section check is reached and removing that check
19# alone changes nothing observable.  This stands as a check on the behaviour
20# rather than on the line which produces it.
21#
22# Covers the same ground as corpus/x86_64/checksum-abs-sym-skip and
23# addressable-symbols in Joe Lawrence's klp-build unit test corpus.
24
25. "$(dirname "$0")/../lib.sh"
26
27setup
28build_pair abs_and_addressable.c
29
30# The premise: the fixture really did produce both.
31in_symbols orig.o | grep -q 'ABS.*abs_sym' ||
32	probe_skip "assembler did not make abs_sym absolute here"
33assert_input_section .discard.addressable
34
35# Checksumming has to survive them, and still see the function that changed.
36run_checksum
37assert_checksum_differs target
38assert_checksum_matches helper
39
40# So does the diff.
41run_diff
42assert_patched target
43assert_not_patched helper
44
45# An absolute symbol has no address to record a checksum against, so it gets
46# no entry -- the reference to it is what mattered, not the symbol itself.
47in_relocs orig.o | awk '/rela\.discard\.sym_checksum/,/^$/' | grep -qw abs_sym &&
48	fail "absolute symbol got a checksum entry"
49
50pass "absolute and __ADDRESSABLE symbols do not disturb the patched function"
51