On Wed, Jun 13, 2012 at 03:17:56PM -0500, Alan Cox wrote:
> On Wed, Jun 13, 2012 at 2:12 PM, Konstantin Belousov 
> <kostik...@gmail.com>wrote:
> 
> > On Wed, Jun 13, 2012 at 07:14:09AM -0600, Ian Lepore wrote:
> > > http://lists.freebsd.org/pipermail/freebsd-arm/2012-January/003288.html
> >
> > The map_object.c patch is step in the almost right direction, I wanted
> > to remove the static page-sized buffer from get_elf_header for long time.
> > It works because rtld always holds bind_lock exclusively while loading
> > an object. There is no need to copy the first page after it is mapped.
> >
> > commit 0f6f8629af1345acded7c0c685d3ff7b4d9180d6
> > Author: Konstantin Belousov <k...@freebsd.org>
> > Date:   Wed Jun 13 22:04:18 2012 +0300
> >
> >    Eliminate the static buffer used to read the first page of the mapped
> >    object, and eliminate the pread(2) call as well. Mmap the first page
> >    of the object temporaly, and unmap it on error or last use.
> >
> >    Fix several cases were the whole mapping of the object leaked on error.
> >
> >    Potentially, this leaves one-page gap between succeeding dlopen(3),
> >    but there are other mmap(2) consumers as well.
> >
> >
> I suggest adding MAP_PREFAULT_READ to the mmap(2) call.  A heuristic in
> vm_map_pmap_enter() would trigger automatic mapping for small files, but if
> the object file is larger than 96 pages then you need to explicitly
> specific MAP_PREFAULT_READ.

Thank you for the suggestion.

commit 77de77b3124fb2742db1db72e9dfc47050c5ac36
Author: Konstantin Belousov <k...@freebsd.org>
Date:   Wed Jun 13 23:22:27 2012 +0300

    Use MAP_PREFAULT_READ for mmap(2) calls which map real object pages.
    
    Suggested by:       alc

diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index 2afc88c..437e7c2 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -200,7 +200,7 @@ map_object(int fd, const char *path, const struct stat *sb)
        data_prot = convert_prot(segs[i]->p_flags);
        data_flags = convert_flags(segs[i]->p_flags) | MAP_FIXED;
        if (mmap(data_addr, data_vlimit - data_vaddr, data_prot,
-         data_flags, fd, data_offset) == (caddr_t) -1) {
+         data_flags | MAP_PREFAULT_READ, fd, data_offset) == (caddr_t) -1) {
            _rtld_error("%s: mmap of data failed: %s", path,
                rtld_strerror(errno));
            goto error1;
@@ -307,7 +307,8 @@ get_elf_header(int fd, const char *path)
 {
        Elf_Ehdr *hdr;
 
-       hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
+       hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ,
+           fd, 0);
        if (hdr == (Elf_Ehdr *)MAP_FAILED) {
                _rtld_error("%s: read error: %s", path, rtld_strerror(errno));
                return NULL;

Attachment: pgpLNjRFFnoAL.pgp
Description: PGP signature

Reply via email to