From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 68640 invoked by alias); 27 Mar 2017 16:15:43 -0000 Mailing-List: contact gnu-gabi-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: gnu-gabi-owner@sourceware.org Received: (qmail 68234 invoked by uid 89); 27 Mar 2017 16:15:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.2 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=thereby, whoever, ah, totally X-Spam-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: mail-qt0-f181.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=09RgXBtfY3DAbV+7szGHmV9IDiaZ9J/gtpKMzW0bCw8=; b=sAhnKav2Kuavy24ACfJld8tmGGBfjKA9QvT+86JrVMHZshMQZGEeeqtOTbbcbUGJfk bgNqFZ6nyQfOYdW4J1Yy5HOqUDR7P3b6w/zPGmjDqHg5RjTATVAk+Gml/O6SEw+JHg48 1mtNjmevWcCmjCQQp8d40UUGpuvT0piQhUuDxQLIsshEhySOUNZ8uWQcyOq2ZMwdV5IA eJ1fcvaP2YIb8cjEChdn5z5NQ0iPFLDzxazEZQ/6PjAh5iADXtUcYvTu2zGHJccJtsoO YhVo1N/FnvLwkk7LY0vbc+DEo376kBjxZIijY3pkwjdCeNCSPI71ti9NGJ9rymrRtbV3 bumA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=09RgXBtfY3DAbV+7szGHmV9IDiaZ9J/gtpKMzW0bCw8=; b=oLf61G07d6KJe4xGNqVySzJA+CDGGOM0+nUmbiPGX/VCirj6XFLmUs+ydsJVWb6NMV D20ZVNav/Bq+CsNTaz0EjjdpS778JigpcMncGvNv0KAWzGws8qBdzyjbnnHBHDAVjZTx sMd50QrjYoyM72BAk3R5nGzmXhvprzXdRYN15c2UC9oBeSztRr3wAoY7IsjG4gA7pcYl 32zqQw88PJX6e/tHj7bJvlUrjmq7hd8n960NEZcY1gDXMVzzYptNJhW++Ha7jbVnS+ps U9rrxafGHThyU9ko6jEO6a7dh1Tz20a/kpX5Jx2+FjtgZBIUMYllR9r98MDHT9yE7O69 5KPw== X-Gm-Message-State: AFeK/H2FcmN15j8Eh68nAiZ2d8MXivQLgKGxLjyNiN2J3/K7Y4wgt1fD1dJmQb6MtDEMGYjg8W/mAwZL1fDoQA== X-Received: by 10.200.35.36 with SMTP id a33mr21050299qta.216.1490631324235; Mon, 27 Mar 2017 09:15:24 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <88608944-14c9-9d28-80d1-32283521683b@gmail.com> <1d183289-5789-8443-7db8-59816bfdd44c@gmail.com> <7deac251-8f93-9241-3902-daf2abfdef29@gmail.com> From: "H.J. Lu" Date: Sun, 01 Jan 2017 00:00:00 -0000 Message-ID: Subject: Re: RFC: ABI support for special memory area To: Suprateeka R Hegde Cc: "Carlos O'Donell" , gnu-gabi@sourceware.org Content-Type: text/plain; charset=UTF-8 X-SW-Source: 2017-q1/txt/msg00026.txt.bz2 On Wed, Mar 22, 2017 at 9:18 AM, Suprateeka R Hegde wrote: > > > On 03/20/17 23:52, H.J. Lu wrote: >> On Fri, Mar 17, 2017 at 11:12 AM, Suprateeka R Hegde >> wrote: >>> On Friday 17 March 2017 02:55 AM, H.J. Lu wrote: >>>>> Since ld.so is not meant only for programs with C style linkage, what if >>>>> the real implementation library is written in C++ and wants to export >>>>> only mangled names (interfaces) without any "extern C" kludge? Or is >>>>> this considered to be a standard C library call just like mmap etc.? >>>> >>>> Only the __gnu_mbind_setup symbol is used. We can change the >>>> second argument to "void *data" and make it dependent on memory >>>> type. But to support a new memory type, we have to update ld.so. I'd >>>> like to use the same ld.so binary to support any memory types even if >>>> it means that we need to pass info to __gnu_mbind_setup which isn't >>>> used by all memory types. >>> >>> Ah! Now I understand the design completely (I think). Looks like Carlos >>> understood this quite earlier in the discussion. >>> >>> You are saying that the interface - >>> >>> int __gnu_mbind_setup (unsigned int type, void *addr, size_t length); >>> >>> - is fixed in ld.so and also in the real implementation library. And, >>> the real implementation in turn calls the actual-real-implementation, as >>> shown in your libmbind code: >>> >>> int >>> __gnu_mbind_setup (unsigned int type, void *addr, size_t length) >>> { >>> // in turn calls actual implementation >>> return vendor_specific_mbind_setup (vendor specific types); >>> } >>> >>> >>> All these while, based on the current description, I was of the >>> impression that your design allows __gnu_mbind_setup interface itself to >>> be overridden in the real implementation, something like: >>> >>> int >>> __gnu_mbind_setup (__nvm_kmem_t *nvm_obj, void *nvm_handle) >>> { >>> // actual implementation directly here in the body >>> } >>> >>> So I was wondering how and hence most of my points were out-of-phase. >>> >>>> The question is what the possible info needed >>>> for all memory types is. >>> >>> Thats too much to predict right now. And the current interface you >>> defined also does not seem to be generic. For instance, my NVM >>> implementation, though not complete, needs a totally different set of >>> arguments. So going by the current design, I will have to use >>> __gnu_mbind_setup (unsigned int type, void *addr, size_t length) just to >>> call my real setup, without using any of the arguments passed by ld.so. >>> >>> Assuming I am in sync with you now, I would say that the pseudo code I >>> showed earlier works for you as well as for me as well as for anybody >>> else. In other words it is more generic. >>> >>> With that approach, there is >>> >>> 1. No need to update ld.so every time for every new mem type >>> 2. No need to know all possible info needed for all mem types >>> 3. No need to encode all types in the API (as Carlos said) >>> >>> We just use pointer to implementation interface - struct >>> __gnu_mbind_context that I showed. And we can have a default struct >>> instantiated in ld.so and a global pointer pointing to that. And later >>> the global pointer can be made to point to the vendor specific struct, >>> before ld.so actually calls __gnu_mbind_setup, thereby completing a >>> successful override (if necessary, that is when special memory types are >>> in use). >>> >>> Or similar mechanisms to override default struct instantiated in ld.so. >>> There are many well known ways to override the default struct as we all >>> know. >>> >>> Personally I think this would be a better way to provide the ABI support >>> in a generic way. >> >> ld.so needs to call the real __gnu_mbind_setup implementation >> with the correct argument. > > Yes and with my example code, ld.so calls with correct argument always. > And its always only one argument -- a pointer to struct. By default > pointing to default struct, and when overridden pointing to > implementation specific struct. > >> We can keep it ASIS and add a new >> new one, __gnu_mbind_setup_v2, if needed. > > Hmm :-) > > This also looks good. Though whoever adds this _v2 (assuming its me > right now :-)), gets to ensure all the herculean compatibility hooks for > _v1 are in place. But thats OK I believe. > >> >>> That said, I am OK to live with minor kludges and we can keep the design >>> as is. >>> >>>> >>>>> And you may also want to define the flow for fully archive bound static >>>>> binaries. >>>> >>>> For static executable, __gnu_mbind_setup will be called on all MBIND >>>> segments before constructors are called. __gnu_mbind_setup in libc.a >>>> is weak and will be overridden by the real one in libmbind.a. >>> >>> Lets add this also in the ABI support document. >>> >> >> How about this: >> >> Run-time support >> >> int __gnu_mbind_setup_v1 (unsigned int type, void *addr, size_t length); >> >> It sets up special memory area of 'type' and 'length' at 'addr' where >> 'addr' is a multiple of page size. It returns zero for success, positive >> value of ERRNO for non-fatal error and negative value of ERRNO for fatal >> error. >> >> After all shared objects and the executable file are loaded, relocations >> are processed, for each GNU_MBIND segment in a shared object or the >> executable file, run-time loader calls __gnu_mbind_setup_v1 with type, >> address and length. If __gnu_mbind_setup_v1 must be defined in run-time >> loader, it should be implemented as a weak function: >> >> int >> __gnu_mbind_setup_v1 (unsigned int type, void *addr, size_t length) >> { >> return 0; >> } >> >> in run-time loader so that the GNU_MBIND run-time library isn't required >> for normal executable nor shared object. The real implementation of >> __gnu_mbind_setup_v1 should be in the GNU_MBIND run-time library and >> overridde the weak one in run-time loader. > > Looks good to me. > > -- > Supra There is a way to support GNU_MBIND segments without the glibc changes. Instead, dl_iterate_phdr int dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data); is called via the .init_array section to process GNU_MBIND segments in executable and shared objects: static int callback (struct dl_phdr_info *info, size_t size, void *data) { Compute the load address of the current module. if info->dlpi_addr == the load address of the current module { check ELF program headers and process GNU_MBIND segments return 1; } return 0; } static void call_gnu_mbind_setup (void) { dl_iterate_phdr (callback, NULL); } static void (*init_array) (void) __attribute__ ((section (".init_array"), used)) = &call_gnu_mbind_setup; -- H.J.