blob: 9336d74bfa9265eb737811d430d2f0b16cbd5fe0 [file] [edit]
// SPDX-License-Identifier: GPL-2.0
/*
* An x86 alternative with an empty replacement, as the second entry of
* ALTERNATIVE_2("orig", "repl", ft1, "", ft2) produces. Its replacement
* offset still gets a relocation, but the label it points at is the end of the
* previous replacement, which is also where the *next* one begins -- here,
* neighbor()'s. The value is meaningless; it is only ever used with a length
* of zero.
*
* struct alt_instr is written out by hand so the fixture builds without kernel
* headers: s32 instr_offset, s32 repl_offset, u32 ft_flags, u8 instrlen,
* u8 replacementlen. The section carries an entsize because klp diff needs
* either that or an ANNOTATE_DATA_SPECIAL annotation to find entry boundaries.
*
* The replacement labels are global so the relocations name them rather than
* .altinstr_replacement plus an addend.
*/
static const char __modinfo[]
__attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
extern int neighbor_only(int x);
int target(int x)
{
asm volatile(
"661: nop\n\t"
".pushsection .altinstr_replacement, \"ax\"\n\t"
".globl target_repl\n\t"
"target_repl:\n\t"
" nop\n\t"
"target_repl_end:\n\t"
".popsection\n\t"
".pushsection .altinstructions, \"aM\", @progbits, 14\n\t"
/* a real replacement */
".long 661b - .\n\t"
".long target_repl - .\n\t"
".long 0\n\t"
".byte 1\n\t"
".byte target_repl_end - target_repl\n\t"
/* an empty one, pointing at neighbor()'s replacement */
".long 661b - .\n\t"
".long neighbor_repl - .\n\t"
".long 0\n\t"
".byte 1\n\t"
".byte 0\n\t"
".popsection\n\t");
#ifdef PATCHED
return x + 2;
#else
return x + 1;
#endif
}
/*
* Unrelated, unpatched, and referencing a symbol nothing else does, so that
* dragging its replacement in is visible.
*/
int neighbor(int x)
{
asm volatile(
"771: nop\n\t"
".pushsection .altinstr_replacement, \"ax\"\n\t"
".globl neighbor_repl\n\t"
"neighbor_repl:\n\t"
" call neighbor_only\n\t"
"neighbor_repl_end:\n\t"
".popsection\n\t"
".pushsection .altinstructions, \"aM\", @progbits, 14\n\t"
".long 771b - .\n\t"
".long neighbor_repl - .\n\t"
".long 0\n\t"
".byte 1\n\t"
".byte neighbor_repl_end - neighbor_repl\n\t"
".popsection\n\t");
return x;
}