From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS31976 209.132.180.0/23 X-Spam-Status: No, score=-3.3 required=3.0 tests=AWL,BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_GMAIL_RCVD, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 612F01F453 for ; Fri, 18 Jan 2019 13:25:45 +0000 (UTC) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:references:in-reply-to:from:date :message-id:subject:to:content-type; q=dns; s=default; b=ivy1QLG ZLdEpYRNnZEmMr9NHgEgmgeFbpoPYxRHlKTcoWTiJ+wnIKmLgbMxRg005K4Znqmb 9abh9WT1xsC68iJJYkQNBwM7x+vAoHaa17yeIGMX91LYyqemsunGXCHXsAEYPptW JcZXonEwL7w7RfL7gIO34pThEdS0mjrAh8DY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:references:in-reply-to:from:date :message-id:subject:to:content-type; s=default; bh=dTk2SE6m5C/Ee cfQgUXjqpet2oo=; b=YooIpOOHo/ip4c8gicEFuA9GuK94XRu1Wm4+ByDvJdJ4v wbhf14sNK2Dm5e5BAtKN94/QR9jeEuRoEEQ8Yp+TQTKpz2suc/8N3JE6Q2hXudZS yUVXsOZMwvloPTjzcRmZsJtEHKd6PwxLyp+DrpU1Uz/81/i20ogYIgqzJpziFE= Received: (qmail 33866 invoked by alias); 18 Jan 2019 13:25:43 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Received: (qmail 33854 invoked by uid 89); 18 Jan 2019 13:25:42 -0000 Authentication-Results: sourceware.org; auth=none X-HELO: mail-oi1-f196.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=pyN8zITl6OJH2v0Gz7Ug1fKfPR1m90jofp5OjFwSXow=; b=KhV6wVE6xcIkod0pXwNe/W6WZwNszpl9vFbZbNN5xVT/TS8/e/xNEMFk2jVCEXFtr/ MJyps67Hy+MKw0daFgyE6rff2M8kQ0gfIdMndRR3dVPrH/EV+VSah/P3TU2sJ436n62n 24BGWnVuY04vhfkoOZgtUOGHK8zuUldZ40RNng5+GuxUGnbZ12o4nidWp+fbzBOd1dWd +QdPjd8ZV84CQmdoEqE73IQAWHKOWUpdgFZPRhZDdjWR2S+iY2czc8Zglba2Dhv5xqwo emxB2zmxpoJTfbjbci0zUVcLseDT9tjIs5b8MbH7r2p9Aww6hWYvHIs7kSiTwwMrO/9E Nj3A== MIME-Version: 1.0 References: <20190117165351.25914-1-hjl.tools@gmail.com> <20190117165351.25914-2-hjl.tools@gmail.com> In-Reply-To: <20190117165351.25914-2-hjl.tools@gmail.com> From: "H.J. Lu" Date: Fri, 18 Jan 2019 05:25:01 -0800 Message-ID: Subject: Re: [PATCH 1/8] x86-64 memchr/wmemchr: Properly handle the length parameter [BZ# 24097] To: GNU C Library Content-Type: text/plain; charset="UTF-8" On Thu, Jan 17, 2019 at 8:54 AM H.J. Lu wrote: > > On x32, the size_t parameter may be passed in the lower 32 bits of a > 64-bit register with the non-zero upper 32 bits. The string/memory > functions written in assembly can only use the lower 32 bits of a > 64-bit register as length or must clear the upper 32 bits before using > the full 64-bit register for length. > > This pach fixes memchr/wmemchr for x32. Tested on x86-64 and x32. On > x86-64, libc.so is the same with and withou the fix. > > [BZ# 24097] > * sysdeps/x86_64/memchr.S: Use RDX_LP for length. Clear the > upper 32 bits of RDX register. > * sysdeps/x86_64/multiarch/memchr-avx2.S: Likewise. > * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memchr and > tst-size_t-wmemchr. > * sysdeps/x86_64/x32/test-size_t.h: New file. > * sysdeps/x86_64/x32/tst-size_t-memchr.c: Likewise. > * sysdeps/x86_64/x32/tst-size_t-wmemchr.c: Likewise. > diff --git a/sysdeps/x86_64/x32/test-size_t.h b/sysdeps/x86_64/x32/test-size_t.h > new file mode 100644 > index 0000000000..fbef565bda > --- /dev/null > +++ b/sysdeps/x86_64/x32/test-size_t.h > @@ -0,0 +1,170 @@ > +/* Test string/memory functions with size_t in the lower 32 bits of > + 64-bit register. > + Copyright (C) 2019 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + . */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* On x32, parameter_t may be passed in a 64-bit register with the LEN > + field in the lower 32 bits. When the LEN field of 64-bit register > + is passed to string/memory function as the size_t parameter, only > + the lower 32 bits can be used. */ > +typedef struct > +{ > + union > + { > + size_t len; > + void (*fn) (void); > + }; > + void *p; > +} parameter_t; > + > +typedef struct > +{ > + const char *name; > + void (*fn) (void); > + long test; > +} impl_t; > +extern impl_t __start_impls[], __stop_impls[]; > + > +#define IMPL(name, test) \ > + impl_t tst_ ## name \ > + __attribute__ ((section ("impls"), aligned (sizeof (void *)))) \ > + = { __STRING (name), (void (*) (void))name, test }; > + > +#ifndef _GNU_SOURCE > +#define _GNU_SOURCE > +#endif > + > +#undef __USE_STRING_INLINES > + > +/* We are compiled under _ISOMAC, so libc-symbols.h does not do this > + for us. */ > +#include "config.h" > +#ifdef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL > +# define inhibit_loop_to_libcall \ > + __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns"))) > +#else > +# define inhibit_loop_to_libcall > +#endif > + > +#define GL(x) _##x > +#define GLRO(x) _##x > + > +unsigned char *buf1, *buf2; > +size_t page_size; > + > +#define CALL(parm, ...) \ > + (* (proto_t) (parm).fn) (__VA_ARGS__) > + > +#ifdef TEST_NAME > +/* Increase size of FUNC_LIST if assert is triggered at run-time. */ > +static struct libc_ifunc_impl func_list[32]; > +static int func_count; > +static int impl_count = -1; > +static impl_t *impl_array; > + > +# define FOR_EACH_IMPL(impl, notall) \ > + impl_t *impl; \ > + int count; \ > + if (impl_count == -1) \ > + { \ > + impl_count = 0; \ > + if (func_count != 0) \ > + { \ > + int f; \ > + impl_t *skip = NULL, *a; \ > + for (impl = __start_impls; impl < __stop_impls; ++impl) \ > + if (strcmp (impl->name, TEST_NAME) == 0) \ > + skip = impl; \ > + else \ > + impl_count++; \ > + a = impl_array = malloc ((impl_count + func_count) * \ > + sizeof (impl_t)); \ > + for (impl = __start_impls; impl < __stop_impls; ++impl) \ > + if (impl != skip) \ > + *a++ = *impl; \ > + for (f = 0; f < func_count; f++) \ > + if (func_list[f].usable) \ > + { \ > + a->name = func_list[f].name; \ > + a->fn = func_list[f].fn; \ > + a->test = 1; \ > + a++; \ > + } \ > + impl_count = a - impl_array; \ > + } \ > + else \ > + { \ > + impl_count = __stop_impls - __start_impls; \ > + impl_array = __start_impls; \ > + } \ > + } \ > + impl = impl_array; \ > + for (count = 0; count < impl_count; ++count, ++impl) \ > + if (!notall || impl->test) > +#else > +# define FOR_EACH_IMPL(impl, notall) \ > + for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl) \ > + if (!notall || impl->test) > +#endif > + > +#ifndef BUF1PAGES > +# define BUF1PAGES 1 > +#endif > + > +static void > +test_init (void) > +{ > +#ifdef TEST_NAME > + func_count = __libc_ifunc_impl_list (TEST_NAME, func_list, > + (sizeof func_list > + / sizeof func_list[0])); > +#endif > + > + page_size = 2 * getpagesize (); > +#ifdef MIN_PAGE_SIZE > + if (page_size < MIN_PAGE_SIZE) > + page_size = MIN_PAGE_SIZE; > +#endif > + buf1 = mmap (0, (BUF1PAGES + 1) * page_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANON, -1, 0); > + if (buf1 == MAP_FAILED) > + error (EXIT_FAILURE, errno, "mmap failed"); > + if (mprotect (buf1 + BUF1PAGES * page_size, page_size, PROT_NONE)) > + error (EXIT_FAILURE, errno, "mprotect failed"); > + buf2 = mmap (0, 2 * page_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANON, -1, 0); > + if (buf2 == MAP_FAILED) > + error (EXIT_FAILURE, errno, "mmap failed"); > + if (mprotect (buf2 + page_size, page_size, PROT_NONE)) > + error (EXIT_FAILURE, errno, "mprotect failed"); > + > + memset (buf1, 0xa5, BUF1PAGES * page_size); > + memset (buf2, 0x5a, page_size); > +} We can reuse : #define TEST_MAIN #include /* On x32, parameter_t may be passed in a 64-bit register with the LEN field in the lower 32 bits. When the LEN field of 64-bit register is passed to string/memory function as the size_t parameter, only the lower 32 bits can be used. */ typedef struct { union { size_t len; void (*fn) (void); }; void *p; } parameter_t; -- H.J.