1*065f09c8SSong Liu // SPDX-License-Identifier: GPL-2.0
2*065f09c8SSong Liu /*
3*065f09c8SSong Liu * Instruction operands whose change must move a function's checksum even
4*065f09c8SSong Liu * though the instruction bytes themselves do not.
5*065f09c8SSong Liu *
6*065f09c8SSong Liu * checksum_update_insn() hashes the raw bytes and then, when the instruction
7*065f09c8SSong Liu * carries a relocation, what that relocation refers to: a string section
8*065f09c8SSong Liu * contributes the string's contents, anything else the target symbol's name
9*065f09c8SSong Liu * and the adjusted addend. A reference to a static arrives as a section
10*065f09c8SSong Liu * symbol and has to be resolved back to the object first.
11*065f09c8SSong Liu *
12*065f09c8SSong Liu * The bytes are identical in every case below -- a rel32 operand is zero in
13*065f09c8SSong Liu * the object and supplied by the relocation -- so a checksum that stopped at
14*065f09c8SSong Liu * the bytes would call all of these unchanged.
15*065f09c8SSong Liu *
16*065f09c8SSong Liu * Each variant applies to the patched build only:
17*065f09c8SSong Liu *
18*065f09c8SSong Liu * WHICH_CALL calls a different function
19*065f09c8SSong Liu * STR_CONTENT passes a literal whose text was edited
20*065f09c8SSong Liu * WHICH_SLOT reads a different index of a global array: addend only
21*065f09c8SSong Liu * WHICH_PRIV the same, for a static, reached through its section symbol
22*065f09c8SSong Liu */
23*065f09c8SSong Liu
24*065f09c8SSong Liu static const char __modinfo[]
25*065f09c8SSong Liu __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
26*065f09c8SSong Liu
27*065f09c8SSong Liu int callee_a(int x);
28*065f09c8SSong Liu int callee_b(int x);
29*065f09c8SSong Liu int sink(const char *s);
30*065f09c8SSong Liu
31*065f09c8SSong Liu int slots[4];
32*065f09c8SSong Liu
33*065f09c8SSong Liu /*
34*065f09c8SSong Liu * A file-local array, plus a writer the compiler cannot see through. Without
35*065f09c8SSong Liu * one it can prove the array is never written, folds every read to zero, and
36*065f09c8SSong Liu * emits no relocation at all -- so the reference this is here to exercise does
37*065f09c8SSong Liu * not exist.
38*065f09c8SSong Liu */
39*065f09c8SSong Liu static int priv_slots[4];
40*065f09c8SSong Liu
41*065f09c8SSong Liu void set_priv(int i, int v);
set_priv(int i,int v)42*065f09c8SSong Liu void set_priv(int i, int v)
43*065f09c8SSong Liu {
44*065f09c8SSong Liu priv_slots[i] = v;
45*065f09c8SSong Liu }
46*065f09c8SSong Liu
47*065f09c8SSong Liu #if defined(PATCHED) && defined(STR_CONTENT)
48*065f09c8SSong Liu #define MESSAGE "edited"
49*065f09c8SSong Liu #else
50*065f09c8SSong Liu #define MESSAGE "original"
51*065f09c8SSong Liu #endif
52*065f09c8SSong Liu
target(int x)53*065f09c8SSong Liu int target(int x)
54*065f09c8SSong Liu {
55*065f09c8SSong Liu int r;
56*065f09c8SSong Liu
57*065f09c8SSong Liu #if defined(PATCHED) && defined(WHICH_CALL)
58*065f09c8SSong Liu r = callee_b(x);
59*065f09c8SSong Liu #else
60*065f09c8SSong Liu r = callee_a(x);
61*065f09c8SSong Liu #endif
62*065f09c8SSong Liu
63*065f09c8SSong Liu r += sink(MESSAGE);
64*065f09c8SSong Liu
65*065f09c8SSong Liu #if defined(PATCHED) && defined(WHICH_SLOT)
66*065f09c8SSong Liu r += slots[2];
67*065f09c8SSong Liu #else
68*065f09c8SSong Liu r += slots[1];
69*065f09c8SSong Liu #endif
70*065f09c8SSong Liu
71*065f09c8SSong Liu #if defined(PATCHED) && defined(WHICH_PRIV)
72*065f09c8SSong Liu r += priv_slots[3];
73*065f09c8SSong Liu #else
74*065f09c8SSong Liu r += priv_slots[1];
75*065f09c8SSong Liu #endif
76*065f09c8SSong Liu
77*065f09c8SSong Liu return r;
78*065f09c8SSong Liu }
79