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=-4.0 required=3.0 tests=AWL,BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,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 A68891F46C for ; Sat, 1 Feb 2020 06:27:33 +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:subject:to:cc:references:from:message-id:date :mime-version:in-reply-to:content-type :content-transfer-encoding; q=dns; s=default; b=NmOYePqKNl5Jti1E /Slznr3dzjE5ANU5VmqgeaNixXVuVhd3b5Bh82M7iC/33A3RJjKeUy9gOd1XaGcg h2ud43e3AadRZa7nuC0Y01zfmrtvjTNIwxhnmnAU7G1K0s4P2u7HT14PhctUCqlh CEUoLxTOlrE9Naw2QP1UtaYvDWo= 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:subject:to:cc:references:from:message-id:date :mime-version:in-reply-to:content-type :content-transfer-encoding; s=default; bh=Z9qlEJxzxbxdJXbTFZc8cR PCVak=; b=gpZQ+WHSE8luZ+vZpHeujSVvHV0VOeP59g0u2/b+o6LoYwP9G+/RJl E6i2rPbrspGfJIeVlehJBF4CjIU/Le6BAHZ5bWQkE9LpZlJ1pMEhMRLNonQRyY+c FzqFEBlvGXfnorGykNB7y3Npq6pIoaMhMobDM772w8WLrw97SOy3o= Received: (qmail 117034 invoked by alias); 1 Feb 2020 06:27:31 -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 117022 invoked by uid 89); 1 Feb 2020 06:27:31 -0000 Authentication-Results: sourceware.org; auth=none X-HELO: us-smtp-1.mimecast.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1580538448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KdPDR/H5VjWyRXacn2t3fXG3Kxfm7XAvKkkUHKHqJx0=; b=HaVlwUQR+/4VmQ1ppz899glc9jgj0FMh1bcOS7FGuYry+VcfM4Xav4k9RDgQLTPb2/xqZ6 duJGhlwkwJ0aOBVLOrfWDOCKZrT/i7LjIcz/KNmi8zC1aXZxLEIkvaFvES3LaR9zFpLaCu 2JvH6F2Gwkcn9ZISkbjmmM8eaCMQa/Q= Subject: Re: Are ifuncs intended to be allowed to resolve to symbols in another DSO? To: Florian Weimer , Zack Weinberg Cc: GNU C Library References: <87sgko4b91.fsf@oldenburg2.str.redhat.com> From: Carlos O'Donell Message-ID: <559bbced-2f06-4196-719a-923e6c804e1d@redhat.com> Date: Sat, 1 Feb 2020 01:27:23 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: <87sgko4b91.fsf@oldenburg2.str.redhat.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit On 1/9/20 3:37 PM, Florian Weimer wrote: > * Zack Weinberg: > >> Suppose I have two major versions of the same shared library >> (libfoo.so.1 and libfoo.so.2) and the only difference is that >> libfoo.so.2 drops a whole bunch of compatibility aliases. For >> instance, libfoo.so.1 defines two names, `blurf` and `xblurf`, for the >> same function, but libfoo.so.2 defines only the `blurf` name. >> >> Any program that winds up loading both shared libraries (via >> transitive dependencies) is going to have two copies of the actual >> code for `blurf` in memory. I could eliminate this duplication by >> having libfoo.so.1 be a thin wrapper around libfoo.so.2, providing >> only a definition for `xblurf` that calls `blurf`. Good so far, but >> now old applications are making two jumps through the PLT whenever >> they call `xblurf`. It occurred to me to wonder whether I could >> eliminate the extra indirection (on the second and subsequent calls) >> by making xblurf an ifunc: >> >> extern int blurf(char *arg1, int arg2); // defined in libfoo.so.2 >> static int (*resolve_xblurf(void))(char *, int) >> { >> return blurf; >> } >> int xblurf(char *, int) __attribute__((ifunc("resolve_xblurf"))); > > This only works if libfoo.so.1 has already been relocated when the IFUNC > resolver is called. Old glibcs always relocated objects in the wrong > order (bug 12892, fixed in glibc 2.15, probably not widely backported). > > Even with that fixed, missing DT_NEEDED entries and LD_PRELOAD can > result in calls to yet-unrelocated IFUNC resolvers. I had a patch to > mostly fix this, but it added quite a bit of complexity (delayed > relocation processing), and there are still difficult-to-describe > failure cases for complex dependency trees. The community wasn't > enthusiastic about it. > > Lazy binding obscures some of these problems, to the degree that some > programmers call getenv in IFUNC resolvers. If an IFUNC resolver calls a function which is not yet resolved then isn't that a defect in the IFUNC resolver? The code which contains such an IFUNC should have had a DT_NEEDED entry on all objects to which the resolver called into? In Zach's case it really means that the new libfoo.so.2 needs to depend on libfoo.so.1 so the latter is loaded and relocated first. There are some hairy scenarios with circular dependencies which can mean libfoo.so.1 is *not* relocated first, and Chung-Ling Tang's patches to fix the sort orders are a step in the right direction to solving this, but arguably you have undefined behaviour with circular dependencies which we're trying to make more deterministic. I like solutions that ensure that IFUNC resolvers, which are just foreign functions, run at a stage *after* their own dependencies have been resolved, but before their own initializers have run. In summary: - Zach's solution works if libfoo.so.2 depends on libfoo.so.1 and also doesn't invoke undefined behaviour with circular dependencies. - Yes, lazy binding hides these problems by deferring the complex ordering requirements until a point where it doesn't matter (all DSO relocation is complete). We should still fix the problem for BIND_NOW though. -- Cheers, Carlos.