Received: by 2002:a05:6359:c8b:b0:c7:702f:21d4 with SMTP id go11csp3651209rwb; Sun, 9 Oct 2022 08:39:59 -0700 (PDT) X-Google-Smtp-Source: AMsMyM57Ra4WMnXKP9A3UBdxPpVagD/m1yshvh1slyKe9Na8Ka2g4nAIH5nNVo9+1+FhfD4mbxkl X-Received: by 2002:a05:6a02:192:b0:43c:a0cb:44d3 with SMTP id bj18-20020a056a02019200b0043ca0cb44d3mr13377029pgb.139.1665329999090; Sun, 09 Oct 2022 08:39:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665329999; cv=none; d=google.com; s=arc-20160816; b=eWio/3cYB3L9yfJ5n1akM3bUa869hTNJtIo81qDScD+BCF+qSdKYSWGK8LQevRQs55 5ciL3Mvtd7qE+HVmBFrUzmjt5cgdH7/CmE1Y62K3w+XLrzo/hMa/g6od8kGaD8jO1QgU lT9JE+jVeJHTgZ8PWVD3U4zx4au44nmAK2nUnXGHScd+O8LqIspJZR3XY5sr3Y2JPMVx hqo0STJ12USEoHRWrojQQheVbRVuwS4vbm88QZX4vw+qxbBjHWIgxlOR9ndmZfb4/GNa 4+d3dHipIBwinRmX09d+wNX9P042uGThAcHr5/Oi7evkTjDYEVDculs3QlGRUJW/GZiu GZwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=yliPr9X6wfOJ6LNViQX5y8mwrxgQqRPw5/uQ/HIIDBs=; b=wVwKscL/JOAh/NN52sl9Z+DTTlLJ2iQ6b6BUFk47HTtoauhCG19/5mdfl1y3CYcs8c MnaQixX4PbbC64fT9kabsdXeO50ctGPQS8Zy7vB8YqRnHaYyN42hGTbwF0CKK+Wx0DEj 97B++IjRvOFfh+rec+LSd/WNv0A9JX95B2+4d9hMCPJfjF0fzA3ydVvYEmIjZH8MlVYH ncqONq76g/mhPnRQarv6ALj10dy9kdIXHK/rCI1frx/f8i8Y7oC8cDv99wtGYaf30Xxf +0Q/2VhoWbmNOu8dtEs/lK/2gdFwOmrZiqvzAFItfESxT9XbgVcPM/1HYp/ysmWHgWfx 1j+g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d6-20020a17090a8d8600b0020ad5d0a3cfsi8560121pjo.22.2022.10.09.08.39.32; Sun, 09 Oct 2022 08:39:59 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229590AbiJIPUA (ORCPT + 99 others); Sun, 9 Oct 2022 11:20:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48864 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229710AbiJIPT4 (ORCPT ); Sun, 9 Oct 2022 11:19:56 -0400 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7FD4BE012; Sun, 9 Oct 2022 08:19:53 -0700 (PDT) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 299FJifX028312; Sun, 9 Oct 2022 17:19:44 +0200 From: Willy Tarreau To: "Paul E. McKenney" Cc: kernel test robot , linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Willy Tarreau Subject: tools/nolibc: fix missing strlen() definition and infinite loop with gcc-12 Date: Sun, 9 Oct 2022 17:19:39 +0200 Message-Id: <20221009151939.28270-1-w@1wt.eu> X-Mailer: git-send-email 2.17.5 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_PASS, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When built at -Os, gcc-12 recognizes an strlen() pattern in nolibc_strlen() and replaces it with a jump to strlen(), which is not defined as a symbol and breaks compilation. Worse, when the function is called strlen(), the function is simply replaced with a jump to itself, hence becomes an infinite loop. One way to avoid this is to always set -ffreestanding, but the calling code doesn't know this and there's no way (either via attributes or pragmas) to globally enable it from include files, effectively leaving a painful situation for the caller. It turns out that -fno-tree-loop-distribute-patterns disables replacement of strlen-like loops with calls to strlen and that this option is accepted in the optimize() function attribute. Thus at least it allows us to make sure our local definition is not replaced with a self jump. The function only needs to be renamed back to strlen() so that the symbol exists, which implies that nolibc_strlen() which is used on variable strings has to be declared as a macro that points back to it before the strlen() macro is redifined. It was verified to produce valid code with gcc 3.4 to 12.1 at different optimization levels, and both with constant and variable strings. Reported-by: kernel test robot Link: https://lore.kernel.org/r/202210081618.754a77db-yujie.liu@intel.com Fixes: 66b6f755ad45 ("rcutorture: Import a copy of nolibc") Fixes: 96980b833a21 ("tools/nolibc/string: do not use __builtin_strlen() at -O0") Cc: "Paul E. McKenney" Signed-off-by: Willy Tarreau --- tools/include/nolibc/string.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index bef35bee9c44..5ef8778cd16f 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -125,10 +125,16 @@ char *strcpy(char *dst, const char *src) } /* this function is only used with arguments that are not constants or when - * it's not known because optimizations are disabled. + * it's not known because optimizations are disabled. Note that gcc 12 + * recognizes an strlen() pattern and replaces it with a jump to strlen(), + * thus itself, hence the optimize() attribute below that's meant to disable + * this confusing practice. */ +#if defined(__GNUC__) && (__GNUC__ >= 12) +__attribute__((optimize("no-tree-loop-distribute-patterns"))) +#endif static __attribute__((unused)) -size_t nolibc_strlen(const char *str) +size_t strlen(const char *str) { size_t len; @@ -140,13 +146,12 @@ size_t nolibc_strlen(const char *str) * the two branches, then will rely on an external definition of strlen(). */ #if defined(__OPTIMIZE__) +#define nolibc_strlen(x) strlen(x) #define strlen(str) ({ \ __builtin_constant_p((str)) ? \ __builtin_strlen((str)) : \ nolibc_strlen((str)); \ }) -#else -#define strlen(str) nolibc_strlen((str)) #endif static __attribute__((unused)) -- 2.35.3