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