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;
pgpLNjRFFnoAL.pgp
Description: PGP signature