From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9394 invoked by alias); 23 May 2018 12:33:51 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Received: (qmail 9382 invoked by uid 89); 23 May 2018 12:33:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=BAYES_00,KAM_LAZY_DOMAIN_SECURITY,RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=Works, profiled X-HELO: mx0a-001b2d01.pphosted.com Subject: Re: [RFC] powerpc: restore TOC when static longjmp to shared object To: Alexander Monakov Cc: libc-alpha@sourceware.org References: <4c67a306-d447-1158-1b92-22ed1cfcfa0a@linux.vnet.ibm.com> From: Rogerio Alves Date: Wed, 23 May 2018 12:33:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 x-cbid: 18052312-0008-0000-0000-000009D776DD X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00009071; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000261; SDB=6.01036483; UDB=6.00530237; IPR=6.00815611; MB=3.00021256; MTD=3.00000008; XFM=3.00000015; UTC=2018-05-23 12:33:43 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18052312-0009-0000-0000-0000476B8706 Message-Id: <8ac334c6-bcf4-7c72-8d28-900fdd3b0bc4@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-05-23_05:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=20 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1805230128 X-SW-Source: 2018-05/txt/msg00755.txt.bz2 Em 23-05-2018 06:26, Alexander Monakov escreveu: > On Tue, 22 May 2018, Rogerio Alves wrote: > >> I've attached patch v2 to this email with the fixes suggested by Adhemerval. > > Why was it necessary to change the prototype of lbar(), and does the testcase > still demonstrate the issue with that change (does it fail without the patch)? > Yes it fails without the patch. The change on lbar() prototype was made only because glibc is being compiled with and it give me an error due a -Werror=strict-prototypes. But lbar(void) works fine but, you don't have a segmentation fault. The problem is that if you have a parameter area on the stack alloca/memset will set TOC to 0x0 and lbar() prototype doesn't mean "no parameters" in C it means "any arguments" - C Standard, subclause 6.7.6.3, paragraph 14 [ISO/IEC 9899:2011] - so the compiler ends up creating a parameter area for the function. This code works if you use lbar(void) or if you don't have a parameter save area on stack: lbar() - Segmentation fault lbar(void) - Works (no arguments). lbar(int a, int b, int c, int d, int e, int f, int g) - Works (less than 8 parameters, use registers, no parameter saving area) lbar(int a, int b, int c, int d, int e, int f, int g, int h, int i) - Segmentation fault > Note that as soon as gcc is capable of optimizing out the alloca-memset code > in the testcase, it will no longer serve the purpose (maybe it's alread > capable, when preparing the testcase I only checked -O0 IIRC). Surely there > are more direct and robust ways of checking that TOC is correctly restored? > I've tested with -O3 here and get the same problem here. If alloca/memset is optimized out or removed from the code the problem doesn't happens but, that's only if the caller stack frame doesn't change if don't, when longjmp execute you still have a valid TOC on the stack. But described in https://sourceware.org/bugzilla/show_bug.cgi?id=269 "In this (simple) case the appl calls [bsd]_setjmp() which transfers to __setjmp. Both are in libc.so. So by the time __setjmp() gets control libc.so's TOC is already loaded. In this case we need to reach back into the callers frame and retrieve the callers TOC from the TOC save area. But in the static case the TOC is not saved and has not changed. In GLIBC sysdeps/powerpc/powerpc64/setjmp.S is built 4 times (static, shared, profiled, and a special version (rtld-setjmp) for the dynamic linker. In the SHARED case (libc.so), external calls to setjmp will save the TOC on the stack, but internal libc calls will not. So the trick is to do the correct thing for each case." So your test has a example of a code that use a static function to call a longjmp that was set on a shared object called via (static) dlopen. In that case we should have to restore it to caller frame as the jump area is in shared object but, since longjmp is inside static compiled unit TOC is not restored. I don't think that alloca/memset should destroy the caller stack like is happening but, also I think we have to restore TOC to the caller frame after the longjmp in that case also. I don't know if there's any other more direct and robust ways to checking if TOC is correctly restored. I can't think in anything easier than always restore. Rogerio > Alexander >