xref: /linux/tools/objtool/tests/x86/fixtures/alt_annotate.c (revision c4717a1628dda5b48e68544d82bddf2fe3465615)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * An x86 alternative whose replacement instruction carries a text annotation.
4  *
5  * The kernel does this wherever an ALTERNATIVE contains something objtool has
6  * to be told about -- a retpoline-safe indirect branch, an intentionally
7  * missing ENDBR -- so the .discard.annotate_insn entry references an address
8  * inside .altinstr_replacement rather than inside a function.
9  *
10  * Two things make that awkward for klp diff, and both are why this fixture
11  * exists.  Replacement code has no real symbol: objtool invents a NOTYPE fake
12  * symbol for it, so an annotation pointing there does not reference a FUNC.
13  * And .discard.annotate_insn has to be cloned after .altinstructions, or the
14  * replacement it names has no clone to point at yet.
15  *
16  * struct alt_instr is written out by hand as in empty_alternative.c: s32
17  * instr_offset, s32 repl_offset, u32 ft_flags, u8 instrlen, u8 replacementlen,
18  * with an entsize so klp diff can find the entry boundaries.
19  * .discard.annotate_insn entries are s32 offset, s32 type; type 2 is
20  * ANNOTYPE_RETPOLINE_SAFE.
21  *
22  * The replacement label is global so the relocations name it rather than
23  * .altinstr_replacement plus an addend, which klp diff cannot convert.  It is
24  * still NOTYPE, which is the shape that matters here.
25  */
26 
27 static const char __modinfo[]
28 	__attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
29 
30 int target(int x)
31 {
32 	asm volatile(
33 		"661:	nop\n\t"
34 		".pushsection .altinstr_replacement, \"ax\"\n\t"
35 		".globl target_repl\n\t"
36 		"target_repl:\n\t"
37 		"	nop\n\t"
38 		/* The annotation lands inside the replacement. */
39 		".pushsection .discard.annotate_insn, \"M\", @progbits, 8\n\t"
40 		".long target_repl - .\n\t"
41 		".long 2\n\t"
42 		".popsection\n\t"
43 		"target_repl_end:\n\t"
44 		".popsection\n\t"
45 		".pushsection .altinstructions, \"aM\", @progbits, 14\n\t"
46 		".long 661b - .\n\t"
47 		".long target_repl - .\n\t"
48 		".long 0\n\t"
49 		".byte 1\n\t"
50 		".byte target_repl_end - target_repl\n\t"
51 		".popsection\n\t");
52 #ifdef PATCHED
53 	return x + 2;
54 #else
55 	return x + 1;
56 #endif
57 }
58