1*ce30479fSSong Liu // SPDX-License-Identifier: GPL-2.0
2*ce30479fSSong Liu /*
3*ce30479fSSong Liu * A special section entry belonging to a patched function. SPECIAL_SEC picks
4*ce30479fSSong Liu * which section, since klp diff treats eight of them alike and each needs
5*ce30479fSSong Liu * extracting for the patched function and no other.
6*ce30479fSSong Liu *
7*ce30479fSSong Liu * The entry is written out by hand so the fixture builds without kernel
8*ce30479fSSong Liu * headers. Only the leading relocation matters to klp diff; the rest is
9*ce30479fSSong Liu * padded to the section's real entry size, because the entries have to be the
10*ce30479fSSong Liu * right length for the boundaries between them to fall in the right places.
11*ce30479fSSong Liu *
12*ce30479fSSong Liu * SPECIAL_RELOCS covers __ex_table, whose entries relocate both the faulting
13*ce30479fSSong Liu * instruction and its fixup; objtool rejects one with only the first.
14*ce30479fSSong Liu */
15*ce30479fSSong Liu
16*ce30479fSSong Liu #ifndef SPECIAL_SEC
17*ce30479fSSong Liu #define SPECIAL_SEC "__bug_table"
18*ce30479fSSong Liu #endif
19*ce30479fSSong Liu #ifndef SPECIAL_ENTSIZE
20*ce30479fSSong Liu #define SPECIAL_ENTSIZE 12
21*ce30479fSSong Liu #endif
22*ce30479fSSong Liu #ifndef SPECIAL_RELOCS
23*ce30479fSSong Liu #define SPECIAL_RELOCS 1
24*ce30479fSSong Liu #endif
25*ce30479fSSong Liu
26*ce30479fSSong Liu #define STR_(x) #x
27*ce30479fSSong Liu #define STR(x) STR_(x)
28*ce30479fSSong Liu
29*ce30479fSSong Liu static const char __modinfo[]
30*ce30479fSSong Liu __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
31*ce30479fSSong Liu
32*ce30479fSSong Liu /*
33*ce30479fSSong Liu * other() gets an entry of its own, so that "the untouched function's entry
34*ce30479fSSong Liu * was not dragged in" is a question the section can actually answer. With
35*ce30479fSSong Liu * only target() contributing, there is nothing for klp diff to leave behind
36*ce30479fSSong Liu * and the negative assertion holds however the extraction behaves.
37*ce30479fSSong Liu */
other(int x)38*ce30479fSSong Liu int other(int x)
39*ce30479fSSong Liu {
40*ce30479fSSong Liu asm volatile(
41*ce30479fSSong Liu "3: nop\n\t"
42*ce30479fSSong Liu "4:\n\t"
43*ce30479fSSong Liu ".pushsection " SPECIAL_SEC ", \"aM\", @progbits, "
44*ce30479fSSong Liu STR(SPECIAL_ENTSIZE) "\n\t"
45*ce30479fSSong Liu ".long 3b - .\n\t"
46*ce30479fSSong Liu #if SPECIAL_RELOCS > 1
47*ce30479fSSong Liu ".long 4b - .\n\t"
48*ce30479fSSong Liu ".fill " STR(SPECIAL_ENTSIZE) " - 8, 1, 0\n\t"
49*ce30479fSSong Liu #else
50*ce30479fSSong Liu ".fill " STR(SPECIAL_ENTSIZE) " - 4, 1, 0\n\t"
51*ce30479fSSong Liu #endif
52*ce30479fSSong Liu ".popsection\n\t");
53*ce30479fSSong Liu
54*ce30479fSSong Liu return x + 9;
55*ce30479fSSong Liu }
56*ce30479fSSong Liu
target(int x)57*ce30479fSSong Liu int target(int x)
58*ce30479fSSong Liu {
59*ce30479fSSong Liu asm volatile(
60*ce30479fSSong Liu "1: nop\n\t"
61*ce30479fSSong Liu "2:\n\t"
62*ce30479fSSong Liu ".pushsection " SPECIAL_SEC ", \"aM\", @progbits, "
63*ce30479fSSong Liu STR(SPECIAL_ENTSIZE) "\n\t"
64*ce30479fSSong Liu ".long 1b - .\n\t"
65*ce30479fSSong Liu #if SPECIAL_RELOCS > 1
66*ce30479fSSong Liu ".long 2b - .\n\t"
67*ce30479fSSong Liu ".fill " STR(SPECIAL_ENTSIZE) " - 8, 1, 0\n\t"
68*ce30479fSSong Liu #else
69*ce30479fSSong Liu ".fill " STR(SPECIAL_ENTSIZE) " - 4, 1, 0\n\t"
70*ce30479fSSong Liu #endif
71*ce30479fSSong Liu ".popsection\n\t");
72*ce30479fSSong Liu #ifdef PATCHED
73*ce30479fSSong Liu return x + 2;
74*ce30479fSSong Liu #else
75*ce30479fSSong Liu return x + 1;
76*ce30479fSSong Liu #endif
77*ce30479fSSong Liu }
78