From 27a9ce0a163be5da39cd2d15f4000f512f9b04bf Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 17 Jul 2023 08:39:13 -0700 Subject: [PATCH] QString: mark qustrchr() and qustrlen() Q_NEVER_INLINE Those are "public-ish" and exported functions (qstringalgorithms.h), so one wouldn't expect that they get inlined most of the time. But they can be inlined by other code inside qstring.cpp and if QtCore is compiled with LTO. More importantly, we want the compiler to inline qustrXXX_avx2() into it, instead of tail-calling into qustrXXX_avx2(). This may seem like a no-op but has one very important difference: backtraces will point to an exported, function instead of an internal symbol. This will then allow us to create valgrind suppressions. Before unstripped: ==12492== Invalid read of size 32 ==12492== at 0x53142EE: qustrchr_avx2(QStringView, char16_t) [clone .lto_priv.0] (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==12492== by 0x54A7AE6: QString::indexOf(QChar, long long, Qt::CaseSensitivity) const [clone .constprop.0] (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==12492== by 0x5218EC4: treatAsAbsolute(QString const&) (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==12492== by 0x5218FBA: QDir::filePath(QString const&) const (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) Before, stripped: ==19477== Invalid read of size 32 ==19477== at 0x5314395: ??? (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19477== by 0x54A7AE6: ??? (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19477== by 0x5218EC4: ??? (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19477== by 0x5218FBA: QDir::filePath(QString const&) const (in /home/tjmaciei/obj/qt/installed/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) After: ==19692== Invalid read of size 32 ==19692== at 0x53143C5: QtPrivate::qustrchr(QStringView, char16_t) (in /home/tjmaciei/obj/qt/qt6-release/qtbase/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19692== by 0x54ABA46: ??? (in /home/tjmaciei/obj/qt/qt6-release/qtbase/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19692== by 0x5218824: ??? (in /home/tjmaciei/obj/qt/qt6-release/qtbase/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19692== by 0x521891A: QDir::filePath(QString const&) const (in /home/tjmaciei/obj/qt/qt6-release/qtbase/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19692== Address 0x741919e is 2 bytes before a block of size 32 alloc'd ==19692== at 0x4843794: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==19692== by 0x54A8A84: ??? (in /home/tjmaciei/obj/qt/qt6-release/qtbase/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) ==19692== by 0x531EB1C: QString::fromLatin1(QByteArrayView) (in /home/tjmaciei/obj/qt/qt6-release/qtbase/lib64/glibc-hwcaps/x86-64-v3/libQt6Core.t.so.6.7.0) Recommended suppressions: { qustrchr_avx2 Memcheck:Addr32 fun:_ZN9QtPrivate8qustrchrE11QStringViewDs } { qustrchr_avx2-with-debuginfo Memcheck:Addr32 fun:UnknownInlinedFun fun:UnknownInlinedFun fun:_ZN9QtPrivate8qustrchrE11QStringViewDs } Change-Id: Ib84fc618ac204205bf7afffd1772b1d87343dfd0 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/text/qstring.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 4daca106ae5..d70ae5c7f46 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -683,6 +683,7 @@ static int ucstrncmp_sse2(const char16_t *a, const Char *b, size_t l) } #endif +Q_NEVER_INLINE qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept { #if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) @@ -711,6 +712,7 @@ qsizetype QtPrivate::qustrnlen(const char16_t *str, qsizetype maxlen) noexcept * character is not found, this function returns a pointer to the end of the * string -- that is, \c{str.end()}. */ +Q_NEVER_INLINE const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept { const char16_t *n = str.utf16();