Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Jul 2009 19:32:04 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r195743 - head/libexec/rtld-elf
Message-ID:  <200907171932.n6HJW4Pg079917@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Fri Jul 17 19:32:04 2009
New Revision: 195743
URL: http://svn.freebsd.org/changeset/base/195743

Log:
  Only perform .bss mapping and cleaning operations when segment file size
  is not equal to its memory size.
  
  This eliminates unneeded clearing of the text segment that often
  happens due to text end not being page-aligned.
  
  For instance,
  $ readelf -l /lib/libedit.so.6
  Program Headers:
    Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
    LOAD           0x000000 0x00000000 0x00000000 0x139e1 0x139e1 R E 0x1000
    LOAD           0x014000 0x00014000 0x00014000 0x00f04 0x00f14 RW  0x1000
    DYNAMIC        0x014cc4 0x00014cc4 0x00014cc4 0x000d0 0x000d0 RW  0x4
  $ procstat -v $$ (for /bin/sh)
  68585 0x28097000 0x280aa000 r-x    6    0  21  14 CN vn /lib/libedit.so.6
  68585 0x280aa000 0x280ab000 r-x    1    0   1   0 CN vn /lib/libedit.so.6 <==
  68585 0x280ab000 0x280ac000 rwx    1    0   1   0 CN vn /lib/libedit.so.6
  Note the splitted map entry marked by '<=='.
  
  Reviewed by:	kan
  Approved by:	re (kensmith)
  MFC after:	1 month

Modified:
  head/libexec/rtld-elf/map_object.c

Modified: head/libexec/rtld-elf/map_object.c
==============================================================================
--- head/libexec/rtld-elf/map_object.c	Fri Jul 17 18:35:45 2009	(r195742)
+++ head/libexec/rtld-elf/map_object.c	Fri Jul 17 19:32:04 2009	(r195743)
@@ -180,37 +180,43 @@ map_object(int fd, const char *path, con
 	    return NULL;
 	}
 
-	/* Clear any BSS in the last page of the segment. */
-	clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz;
-	clear_addr = mapbase + (clear_vaddr - base_vaddr);
-	clear_page = mapbase + (trunc_page(clear_vaddr) - base_vaddr);
-	if ((nclear = data_vlimit - clear_vaddr) > 0) {
-	    /* Make sure the end of the segment is writable */
-	    if ((data_prot & PROT_WRITE) == 0 &&
-		-1 ==  mprotect(clear_page, PAGE_SIZE, data_prot|PROT_WRITE)) {
+	/* Do BSS setup */
+	if (segs[i]->p_filesz != segs[i]->p_memsz) {
+
+	    /* Clear any BSS in the last page of the segment. */
+	    clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz;
+	    clear_addr = mapbase + (clear_vaddr - base_vaddr);
+	    clear_page = mapbase + (trunc_page(clear_vaddr) - base_vaddr);
+
+	    if ((nclear = data_vlimit - clear_vaddr) > 0) {
+		/* Make sure the end of the segment is writable */
+		if ((data_prot & PROT_WRITE) == 0 && -1 ==
+		     mprotect(clear_page, PAGE_SIZE, data_prot|PROT_WRITE)) {
 			_rtld_error("%s: mprotect failed: %s", path,
 			    strerror(errno));
 			return NULL;
-	    }
+		}
 
-	    memset(clear_addr, 0, nclear);
+		memset(clear_addr, 0, nclear);
 
-	    /* Reset the data protection back */
-	    if ((data_prot & PROT_WRITE) == 0)
-		 mprotect(clear_page, PAGE_SIZE, data_prot);
-	}
+		/* Reset the data protection back */
+		if ((data_prot & PROT_WRITE) == 0)
+		    mprotect(clear_page, PAGE_SIZE, data_prot);
+	    }
 
-	/* Overlay the BSS segment onto the proper region. */
-	bss_vaddr = data_vlimit;
-	bss_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_memsz);
-	bss_addr = mapbase +  (bss_vaddr - base_vaddr);
-	if (bss_vlimit > bss_vaddr) {	/* There is something to do */
-	    if (mprotect(bss_addr, bss_vlimit - bss_vaddr, data_prot) == -1) {
+	    /* Overlay the BSS segment onto the proper region. */
+	    bss_vaddr = data_vlimit;
+	    bss_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_memsz);
+	    bss_addr = mapbase +  (bss_vaddr - base_vaddr);
+	    if (bss_vlimit > bss_vaddr) {	/* There is something to do */
+		if (mprotect(bss_addr, bss_vlimit - bss_vaddr, data_prot) == -1) {
 		    _rtld_error("%s: mprotect of bss failed: %s", path,
 			strerror(errno));
-		return NULL;
+		    return NULL;
+		}
 	    }
 	}
+
 	if (phdr_vaddr == 0 && data_offset <= hdr->e_phoff &&
 	  (data_vlimit - data_vaddr + data_offset) >=
 	  (hdr->e_phoff + hdr->e_phnum * sizeof (Elf_Phdr))) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907171932.n6HJW4Pg079917>