summaryrefslogtreecommitdiff
path: root/tools/objtool/tests/x86/fixtures/special_sections.c
blob: d42798848fda04946f7d6ab908a12af46c6ed9e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// SPDX-License-Identifier: GPL-2.0
/*
 * A special section entry belonging to a patched function.  SPECIAL_SEC picks
 * which section, since klp diff treats eight of them alike and each needs
 * extracting for the patched function and no other.
 *
 * The entry is written out by hand so the fixture builds without kernel
 * headers.  Only the leading relocation matters to klp diff; the rest is
 * padded to the section's real entry size, because the entries have to be the
 * right length for the boundaries between them to fall in the right places.
 *
 * SPECIAL_RELOCS covers __ex_table, whose entries relocate both the faulting
 * instruction and its fixup; objtool rejects one with only the first.
 */

#ifndef SPECIAL_SEC
#define SPECIAL_SEC "__bug_table"
#endif
#ifndef SPECIAL_ENTSIZE
#define SPECIAL_ENTSIZE 12
#endif
#ifndef SPECIAL_RELOCS
#define SPECIAL_RELOCS 1
#endif

#define STR_(x) #x
#define STR(x) STR_(x)

static const char __modinfo[]
	__attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";

/*
 * other() gets an entry of its own, so that "the untouched function's entry
 * was not dragged in" is a question the section can actually answer.  With
 * only target() contributing, there is nothing for klp diff to leave behind
 * and the negative assertion holds however the extraction behaves.
 */
int other(int x)
{
	asm volatile(
		"3:	nop\n\t"
		"4:\n\t"
		".pushsection " SPECIAL_SEC ", \"aM\", @progbits, "
			STR(SPECIAL_ENTSIZE) "\n\t"
		".long 3b - .\n\t"
#if SPECIAL_RELOCS > 1
		".long 4b - .\n\t"
		".fill " STR(SPECIAL_ENTSIZE) " - 8, 1, 0\n\t"
#else
		".fill " STR(SPECIAL_ENTSIZE) " - 4, 1, 0\n\t"
#endif
		".popsection\n\t");

	return x + 9;
}

int target(int x)
{
	asm volatile(
		"1:	nop\n\t"
		"2:\n\t"
		".pushsection " SPECIAL_SEC ", \"aM\", @progbits, "
			STR(SPECIAL_ENTSIZE) "\n\t"
		".long 1b - .\n\t"
#if SPECIAL_RELOCS > 1
		".long 2b - .\n\t"
		".fill " STR(SPECIAL_ENTSIZE) " - 8, 1, 0\n\t"
#else
		".fill " STR(SPECIAL_ENTSIZE) " - 4, 1, 0\n\t"
#endif
		".popsection\n\t");
#ifdef PATCHED
	return x + 2;
#else
	return x + 1;
#endif
}