xref: /linux/tools/objtool/tests/generic/fixtures/checksum_insn.c (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
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