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