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