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 34 __attribute__((noinline)) MOVED static int callee(int x) 35 { 36 return x * 5 + 1; 37 } 38 39 __attribute__((noinline)) MOVED int target(int x) 40 { 41 return callee(x) + callee(x + 1); 42 } 43