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