xref: /linux/tools/objtool/tests/generic/fixtures/checksum_position.c (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
1*f55eae8fSSong Liu // SPDX-License-Identifier: GPL-2.0
2*f55eae8fSSong Liu /*
3*f55eae8fSSong Liu  * A function whose position in the section changes between the two builds,
4*f55eae8fSSong Liu  * without the function itself changing.
5*f55eae8fSSong Liu  *
6*f55eae8fSSong Liu  * target() calls callee() twice, and a call within the same section needs no
7*f55eae8fSSong Liu  * relocation: the displacement is in the instruction.  It is that displacement
8*f55eae8fSSong Liu  * which moves, and hashing those bytes makes the checksum move with it.  Both
9*f55eae8fSSong Liu  * must therefore share a section, which is why the test passes
10*f55eae8fSSong Liu  * -fno-function-sections.
11*f55eae8fSSong Liu  *
12*f55eae8fSSong Liu  * What has to change is the distance between the two, and PATCHED changes it
13*f55eae8fSSong Liu  * by aligning them rather than by inserting a function between them.  Where a
14*f55eae8fSSong Liu  * compiler puts an added function is its own business: gcc emits these in
15*f55eae8fSSong Liu  * source order, so a function written between callee() and target() separates
16*f55eae8fSSong Liu  * them, but clang emits target() immediately before callee() whatever the
17*f55eae8fSSong Liu  * source says, and an added function lands ahead of both.  That moves target()
18*f55eae8fSSong Liu  * without moving it relative to callee(), the displacement comes out identical
19*f55eae8fSSong Liu  * in both builds, and the test passes without having asked anything.
20*f55eae8fSSong Liu  *
21*f55eae8fSSong Liu  * Alignment moves the functions apart on both, and moves neither function's
22*f55eae8fSSong Liu  * own instructions -- which is exactly the distinction under test.
23*f55eae8fSSong Liu  */
24*f55eae8fSSong Liu 
25*f55eae8fSSong Liu #ifdef PATCHED
26*f55eae8fSSong Liu #define MOVED	__attribute__((aligned(64)))
27*f55eae8fSSong Liu #else
28*f55eae8fSSong Liu #define MOVED
29*f55eae8fSSong Liu #endif
30*f55eae8fSSong Liu 
31*f55eae8fSSong Liu static const char __modinfo[]
32*f55eae8fSSong Liu 	__attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
33*f55eae8fSSong Liu 
callee(int x)34*f55eae8fSSong Liu __attribute__((noinline)) MOVED static int callee(int x)
35*f55eae8fSSong Liu {
36*f55eae8fSSong Liu 	return x * 5 + 1;
37*f55eae8fSSong Liu }
38*f55eae8fSSong Liu 
target(int x)39*f55eae8fSSong Liu __attribute__((noinline)) MOVED int target(int x)
40*f55eae8fSSong Liu {
41*f55eae8fSSong Liu 	return callee(x) + callee(x + 1);
42*f55eae8fSSong Liu }
43