| 1 | |
| 2 | |
| 3 | * Three translation units linked with ThinLTO, two of which have a file-local
|
| 4 | * helper of the same name.
|
| 5 | *
|
| 6 | * TU_C calls into both of the others, so ThinLTO imports entry_a and entry_b
|
| 7 | * and with them the static helper each one calls. A file-local symbol which
|
| 8 | * has to become visible is renamed helper.llvm.<hash>, and the hash is content
|
| 9 | * derived -- so the two helpers get different hashes from each other, and
|
| 10 | * TU_A's gets a different one again after the patch changes it. Only TU_A's
|
| 11 | * changes: were both bodies to change, both would be cloned whichever way
|
| 12 | * they were paired, and the pairing would not be observable.
|
| 13 | *
|
| 14 | * That leaves klp diff with two symbols in the original and two in the patched
|
| 15 | * object, all four named differently, which have to be paired up correctly.
|
| 16 | * Demangling alone gives "helper" for all of them; something else has to
|
| 17 | * decide which is which.
|
| 18 | *
|
| 19 | * Only TU_A's helper changes. That is what makes a wrong pairing observable:
|
| 20 | * paired correctly, one helper is changed and the other is not, so exactly one
|
| 21 | * is cloned. Paired the wrong way round, both look changed -- or the wrong
|
| 22 | * one does. If both bodies changed the outcome would be the same either way
|
| 23 | * and the test would prove nothing.
|
| 24 | *
|
| 25 | * BASE differs between the two so their bodies are not identical to begin
|
| 26 | * with.
|
| 27 |
|
| 28 |
|
| 29 | #if defined(TU_C)
|
| 30 | extern int entry_a(int x);
|
| 31 | extern int entry_b(int x);
|
| 32 | int glue(int x) { return entry_a(x) + entry_b(x + 1); }
|
| 33 | #else
|
| 34 | #ifdef TU_B
|
| 35 | #define ENTRY entry_b
|
| 36 | #define BASE 5
|
| 37 | #else
|
| 38 | #define ENTRY entry_a
|
| 39 | #define BASE 10
|
| 40 | static const char __modinfo[]
|
| 41 | __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
|
| 42 | #endif
|
| 43 | static __attribute__((noinline)) int helper(int x, int len)
|
| 44 | {
|
| 45 | int sum = 0, i;
|
| 46 |
|
| 47 | for (i = 0; i < len; i++)
|
| 48 | #if defined(PATCHED) && !defined(TU_B)
|
| 49 | sum += i * 2 + BASE;
|
| 50 | #else
|
| 51 | sum += i + BASE;
|
| 52 | #endif
|
| 53 | return sum + x;
|
| 54 | }
|
| 55 |
|
| 56 | int ENTRY(int x) { return helper(x, 4); }
|
| 57 | #endif
|