xref: /linux/tools/objtool/tests/generic/fixtures/jump_label.c (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Static branch in a patched function.  The jump table entry is written out by
4  * hand, mirroring JUMP_TABLE_ENTRY(), so the fixture builds without kernel
5  * headers.  The key is an STT_OBJECT; anything else is ignored by
6  * validate_special_section_klp_reloc().
7  *
8  * MODNAME selects whether the key is taken to belong to vmlinux or a module.
9  *
10  * NEW_KEY puts the whole static branch behind PATCHED, so the patch introduces
11  * one where the original had none -- a different question from patching code
12  * that already has a key, because the __jump_table entry itself is new.
13  *
14  * KEY_NAME renames the key.  Two names are special to
15  * validate_special_section_klp_reloc(): a __tracepoint_* key and the
16  * __UNIQUE_ID_ddebug_* one pr_debug() generates are both unsupported in a
17  * module, but are disabled with a warning rather than rejected, because the
18  * kernel is full of them and refusing outright would make ordinary functions
19  * unpatchable.
20  *
21  * STATIC_KEY makes the key file-local.  That changes the shape of the
22  * relocation rather than the meaning of the code: a reference to a static lands
23  * on the section symbol plus an addend, so the key has to be resolved from the
24  * section before it can be recognised as a key at all.
25  */
26 
27 #ifndef MODNAME
28 #define MODNAME "vmlinux"
29 #endif
30 
31 #ifndef KEY_NAME
32 #define KEY_NAME klp_test_key
33 #endif
34 
35 static const char __modinfo[]
36 	__attribute__((section(".modinfo"), used, aligned(1))) = "\0name=" MODNAME;
37 
38 #ifdef STATIC_KEY
39 static long KEY_NAME;
40 #else
41 long KEY_NAME;
42 #endif
43 
target(int x)44 int target(int x)
45 {
46 	int r = x;
47 
48 #if defined(NEW_KEY) && !defined(PATCHED)
49 	/* The original has no static branch at all. */
50 	return r + 1;
51 #else
52 	asm goto(
53 		"1:	nop\n\t"
54 		".pushsection	__jump_table, \"aw\"\n\t"
55 		".balign	8\n\t"
56 		"912:\n\t"
57 		".pushsection	.discard.annotate_data, \"M\", @progbits, 8\n\t"
58 		".long		912b - ., 1\n\t"
59 		".popsection\n\t"
60 		".long		1b - ., %l[l_yes] - .\n\t"
61 		".quad		%c0 - .\n\t"
62 		".popsection\n\t"
63 		: : "i" (&KEY_NAME) : : l_yes);
64 
65 	r += 1;
66 	goto out;
67 l_yes:
68 	r += 2;
69 out:
70 #endif
71 #ifdef PATCHED
72 	return r + 100;
73 #else
74 	return r;
75 #endif
76 }
77