// SPDX-License-Identifier: GPL-2.0 /* * Three translation units linked with ThinLTO, two of which have a file-local * helper of the same name. * * TU_C calls into both of the others, so ThinLTO imports entry_a and entry_b * and with them the static helper each one calls. A file-local symbol which * has to become visible is renamed helper.llvm., and the hash is content * derived -- so the two helpers get different hashes from each other, and * TU_A's gets a different one again after the patch changes it. Only TU_A's * changes: were both bodies to change, both would be cloned whichever way * they were paired, and the pairing would not be observable. * * That leaves klp diff with two symbols in the original and two in the patched * object, all four named differently, which have to be paired up correctly. * Demangling alone gives "helper" for all of them; something else has to * decide which is which. * * Only TU_A's helper changes. That is what makes a wrong pairing observable: * paired correctly, one helper is changed and the other is not, so exactly one * is cloned. Paired the wrong way round, both look changed -- or the wrong * one does. If both bodies changed the outcome would be the same either way * and the test would prove nothing. * * BASE differs between the two so their bodies are not identical to begin * with. */ #if defined(TU_C) extern int entry_a(int x); extern int entry_b(int x); int glue(int x) { return entry_a(x) + entry_b(x + 1); } #else #ifdef TU_B #define ENTRY entry_b #define BASE 5 #else #define ENTRY entry_a #define BASE 10 static const char __modinfo[] __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux"; #endif static __attribute__((noinline)) int helper(int x, int len) { int sum = 0, i; for (i = 0; i < len; i++) #if defined(PATCHED) && !defined(TU_B) sum += i * 2 + BASE; /* only TU_A's helper changes */ #else sum += i + BASE; #endif return sum + x; } int ENTRY(int x) { return helper(x, 4); } #endif