Commit e0891269 authored by Mark Rutland's avatar Mark Rutland Committed by Will Deacon

linkage: add SYM_FUNC_ALIAS{,_LOCAL,_WEAK}()

Currently aliasing an asm function requires adding START and END
annotations for each name, as per Documentation/asm-annotations.rst:

	SYM_FUNC_START_ALIAS(__memset)
	SYM_FUNC_START(memset)
	    ... asm insns ...
	SYM_FUNC_END(memset)
	SYM_FUNC_END_ALIAS(__memset)

This is more painful than necessary to maintain, especially where a
function has many aliases, some of which we may wish to define
conditionally. For example, arm64's memcpy/memmove implementation (which
uses some arch-specific SYM_*() helpers) has:

	SYM_FUNC_START_ALIAS(__memmove)
	SYM_FUNC_START_ALIAS_WEAK_PI(memmove)
	SYM_FUNC_START_ALIAS(__memcpy)
	SYM_FUNC_START_WEAK_PI(memcpy)
	    ... asm insns ...
	SYM_FUNC_END_PI(memcpy)
	EXPORT_SYMBOL(memcpy)
	SYM_FUNC_END_ALIAS(__memcpy)
	EXPORT_SYMBOL(__memcpy)
	SYM_FUNC_END_ALIAS_PI(memmove)
	EXPORT_SYMBOL(memmove)
	SYM_FUNC_END_ALIAS(__memmove)
	EXPORT_SYMBOL(__memmove)
	SYM_FUNC_START(name)

It would be much nicer if we could define the aliases *after* the
standard function definition. This would avoid the need to specify each
symbol name twice, and would make it easier to spot the canonical
function definition.

This patch adds new macros to allow us to do so, which allows the above
example to be rewritten more succinctly as:

	SYM_FUNC_START(__pi_memcpy)
	    ... asm insns ...
	SYM_FUNC_END(__pi_memcpy)

	SYM_FUNC_ALIAS(__memcpy, __pi_memcpy)
	EXPORT_SYMBOL(__memcpy)
	SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
	EXPORT_SYMBOL(memcpy)

	SYM_FUNC_ALIAS(__pi_memmove, __pi_memcpy)
	SYM_FUNC_ALIAS(__memmove, __pi_memmove)
	EXPORT_SYMBOL(__memmove)
	SYM_FUNC_ALIAS_WEAK(memmove, __memmove)
	EXPORT_SYMBOL(memmove)

The reduction in duplication will also make it possible to replace some
uses of WEAK with more accurate Kconfig guards, e.g.

	#ifndef CONFIG_KASAN
	SYM_FUNC_ALIAS(memmove, __memmove)
	EXPORT_SYMBOL(memmove)
	#endif

... which should make it easier to ensure that symbols are neither used
nor overidden unexpectedly.

The existing SYM_FUNC_START_ALIAS() and SYM_FUNC_START_LOCAL_ALIAS() are
marked as deprecated, and will be removed once existing users are moved
over to the new scheme.

The tools/perf/ copy of linkage.h is updated to match. A subsequent
patch will depend upon this when updating the x86 asm annotations.
Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
Acked-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Acked-by: default avatarMark Brown <broonie@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220216162229.1076788-2-mark.rutland@arm.comSigned-off-by: default avatarWill Deacon <will@kernel.org>
parent dfd42fac
......@@ -130,8 +130,20 @@ denoting a range of code via ``SYM_*_START/END`` annotations.
In fact, this kind of annotation corresponds to the now deprecated ``ENTRY``
and ``ENDPROC`` macros.
* ``SYM_FUNC_START_ALIAS`` and ``SYM_FUNC_START_LOCAL_ALIAS`` serve for those
who decided to have two or more names for one function. The typical use is::
* ``SYM_FUNC_ALIAS``, ``SYM_FUNC_ALIAS_LOCAL``, and ``SYM_FUNC_ALIAS_WEAK`` can
be used to define multiple names for a function. The typical use is::
SYM_FUNC_START(__memset)
... asm insns ...
SYN_FUNC_END(__memset)
SYM_FUNC_ALIAS(memset, __memset)
In this example, one can call ``__memset`` or ``memset`` with the same
result, except the debug information for the instructions is generated to
the object file only once -- for the non-``ALIAS`` case.
* ``SYM_FUNC_START_ALIAS`` and ``SYM_FUNC_START_LOCAL_ALIAS`` are deprecated
ways to define two or more names for one function. The typical use is::
SYM_FUNC_START_ALIAS(__memset)
SYM_FUNC_START(memset)
......
......@@ -165,7 +165,18 @@
#ifndef SYM_END
#define SYM_END(name, sym_type) \
.type name sym_type ASM_NL \
.size name, .-name
.set .L__sym_size_##name, .-name ASM_NL \
.size name, .L__sym_size_##name
#endif
/* SYM_ALIAS -- use only if you have to */
#ifndef SYM_ALIAS
#define SYM_ALIAS(alias, name, sym_type, linkage) \
linkage(alias) ASM_NL \
.set alias, name ASM_NL \
.type alias sym_type ASM_NL \
.set .L__sym_size_##alias, .L__sym_size_##name ASM_NL \
.size alias, .L__sym_size_##alias
#endif
/* === code annotations === */
......@@ -275,6 +286,30 @@
SYM_END(name, SYM_T_FUNC)
#endif
/*
* SYM_FUNC_ALIAS -- define a global alias for an existing function
*/
#ifndef SYM_FUNC_ALIAS
#define SYM_FUNC_ALIAS(alias, name) \
SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_GLOBAL)
#endif
/*
* SYM_FUNC_ALIAS_LOCAL -- define a local alias for an existing function
*/
#ifndef SYM_FUNC_ALIAS_LOCAL
#define SYM_FUNC_ALIAS_LOCAL(alias, name) \
SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_LOCAL)
#endif
/*
* SYM_FUNC_ALIAS_WEAK -- define a weak global alias for an existing function
*/
#ifndef SYM_FUNC_ALIAS_WEAK
#define SYM_FUNC_ALIAS_WEAK(alias, name) \
SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_WEAK)
#endif
/* SYM_CODE_START -- use for non-C (special) functions */
#ifndef SYM_CODE_START
#define SYM_CODE_START(name) \
......
......@@ -50,9 +50,20 @@
#ifndef SYM_END
#define SYM_END(name, sym_type) \
.type name sym_type ASM_NL \
.set .L__sym_size_##name, .-name ASM_NL \
.size name, .-name
#endif
/* SYM_ALIAS -- use only if you have to */
#ifndef SYM_ALIAS
#define SYM_ALIAS(alias, name, sym_type, linkage) \
linkage(alias) ASM_NL \
.set alias, name ASM_NL \
.type alias sym_type ASM_NL \
.set .L__sym_size_##alias, .L__sym_size_##name ASM_NL \
.size alias, .L__sym_size_##alias
#endif
/*
* SYM_FUNC_START_ALIAS -- use where there are two global names for one
* function
......@@ -101,4 +112,28 @@
SYM_END(name, SYM_T_FUNC)
#endif
/*
* SYM_FUNC_ALIAS -- define a global alias for an existing function
*/
#ifndef SYM_FUNC_ALIAS
#define SYM_FUNC_ALIAS(alias, name) \
SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_GLOBAL)
#endif
/*
* SYM_FUNC_ALIAS_LOCAL -- define a local alias for an existing function
*/
#ifndef SYM_FUNC_ALIAS_LOCAL
#define SYM_FUNC_ALIAS_LOCAL(alias, name) \
SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_LOCAL)
#endif
/*
* SYM_FUNC_ALIAS_WEAK -- define a weak global alias for an existing function
*/
#ifndef SYM_FUNC_ALIAS_WEAK
#define SYM_FUNC_ALIAS_WEAK(alias, name) \
SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_WEAK)
#endif
#endif /* PERF_LINUX_LINKAGE_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment