Hi all,
A recent LLVM change [1] introduces a call to wcslen() in fs/smb/client/smb2pdu.c through UniStrcat() via alloc_path_with_tree_prefix(). Similar to the bcmp() and stpcpy() additions that happened in 5f074f3e192f and 1e1b6d63d634, add wcslen() to fix the linkage failure.
The second change is RFC because it makes the first change a little more convoluted for the sake of making it externally available, which may or may not be desirable. See the commit message for more details.
[1]: https://github.com/llvm/llvm-project/commit/9694844d7e36fd5e01011ab56b64f27b...
--- Nathan Chancellor (2): lib/string.c: Add wcslen() [RFC] wcslen() prototype in string.h
drivers/firmware/efi/libstub/printk.c | 4 ++-- include/linux/string.h | 2 ++ lib/string.c | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) --- base-commit: 78ab93c78fb31c5dfe207318aa2b7bd4e41f8dba change-id: 20250324-string-add-wcslen-for-llvm-opt-705791db92c0
Best regards,
A recent optimization change in LLVM [1] aims to transform certain loop idioms into calls to strlen() or wcslen(). This change transforms the first while loop in UniStrcat() into a call to wcslen(), breaking the build when UniStrcat() gets inlined into alloc_path_with_tree_prefix():
ld.lld: error: undefined symbol: wcslen
referenced by nls_ucs2_utils.h:54 (fs/smb/client/../../nls/nls_ucs2_utils.h:54) vmlinux.o:(alloc_path_with_tree_prefix) referenced by nls_ucs2_utils.h:54 (fs/smb/client/../../nls/nls_ucs2_utils.h:54) vmlinux.o:(alloc_path_with_tree_prefix)
The kernel does not build with '-ffreestanding' (which would avoid this transformation) because it does want libcall optimizations in general and turning on '-ffreestanding' disables the majority of them. While '-fno-builtin-wcslen' would be more targeted at the problem, it does not work with LTO.
Add a basic wcslen() to avoid this linkage failure. While no architecture or FORTIFY_SOURCE overrides this, add it to string.c instead of string_helpers.c so that it is built with '-ffreestanding', otherwise the compiler might transform it into a call to itself. Give wcslen() an internal prototype to avoid -Wmissing-prototypes (a global prototype needs a little extra work and it is not currently needed).
Cc: stable@vger.kernel.org Link: https://github.com/llvm/llvm-project/commit/9694844d7e36fd5e01011ab56b64f27b... [1] Signed-off-by: Nathan Chancellor nathan@kernel.org --- lib/string.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/lib/string.c b/lib/string.c index eb4486ed40d2..bbee8a9e4d83 100644 --- a/lib/string.c +++ b/lib/string.c @@ -21,6 +21,7 @@ #include <linux/errno.h> #include <linux/limits.h> #include <linux/linkage.h> +#include <linux/nls.h> #include <linux/stddef.h> #include <linux/string.h> #include <linux/types.h> @@ -429,6 +430,17 @@ size_t strnlen(const char *s, size_t count) EXPORT_SYMBOL(strnlen); #endif
+size_t wcslen(const wchar_t *s); +size_t wcslen(const wchar_t *s) +{ + const wchar_t *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +EXPORT_SYMBOL(wcslen); + #ifndef __HAVE_ARCH_STRSPN /** * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept
linux-stable-mirror@lists.linaro.org