From owner-freebsd-bugs@FreeBSD.ORG Sun Feb 17 21:00:00 2013 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 95C3A568 for ; Sun, 17 Feb 2013 21:00:00 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 7BDC587B for ; Sun, 17 Feb 2013 21:00:00 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r1HL005m090040 for ; Sun, 17 Feb 2013 21:00:00 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r1HL00GN090039; Sun, 17 Feb 2013 21:00:00 GMT (envelope-from gnats) Resent-Date: Sun, 17 Feb 2013 21:00:00 GMT Resent-Message-Id: <201302172100.r1HL00GN090039@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Damjan Jovanovic Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id E65524B5 for ; Sun, 17 Feb 2013 20:57:24 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id A573D85C for ; Sun, 17 Feb 2013 20:57:24 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.5/8.14.5) with ESMTP id r1HKvOpm060556 for ; Sun, 17 Feb 2013 20:57:24 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.5/8.14.5/Submit) id r1HKvOnQ060555; Sun, 17 Feb 2013 20:57:24 GMT (envelope-from nobody) Message-Id: <201302172057.r1HKvOnQ060555@red.freebsd.org> Date: Sun, 17 Feb 2013 20:57:24 GMT From: Damjan Jovanovic To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Subject: kern/176216: [patch] Allow loading ELF libraries at their preferred base address (needed for Wine) X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Feb 2013 21:00:00 -0000 >Number: 176216 >Category: kern >Synopsis: [patch] Allow loading ELF libraries at their preferred base address (needed for Wine) >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Feb 17 21:00:00 UTC 2013 >Closed-Date: >Last-Modified: >Originator: Damjan Jovanovic >Release: 9.1 >Organization: >Environment: Any >Description: FreeBSD's dynamic linker (/libexec/ld-elf.so.1) currently loads libraries by calling mmap() with 0 as the first parameter, causing them to be loaded at whatever address the kernel chooses. But for maximum compatibility with Windows applications, Wine needs some of its DLLs to be loaded at particular memory addresses (see the comments on https://wiki.freebsd.org/Wine). With this patch, first mmap() is called with the base address of the library and MAP_FIXED, giving the library a chance to load at the base address it specified, and if this fails then mmap() is called without MAP_FIXED so the library can at least load somewhere else since its preferred memory region is unavailable. >How-To-Repeat: >Fix: Patch attached with submission follows: Index: libexec/rtld-elf/map_object.c =================================================================== --- libexec/rtld-elf/map_object.c (revision 246877) +++ libexec/rtld-elf/map_object.c (working copy) @@ -175,11 +175,22 @@ base_vaddr = trunc_page(segs[0]->p_vaddr); base_vlimit = round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz); mapsize = base_vlimit - base_vaddr; - base_addr = hdr->e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL; + base_addr = (caddr_t) base_vaddr; - mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE | - MAP_NOCORE, -1, 0); + /* + * Executables, and libraries whose base_addr isn't 0, + * should ideally be loaded at that base_addr. + */ + mapbase = (caddr_t) -1; + if (base_addr != 0) { + mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE | + MAP_NOCORE | MAP_FIXED, -1, 0); + } if (mapbase == (caddr_t) -1) { + mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE | + MAP_NOCORE, -1, 0); + } + if (mapbase == (caddr_t) -1) { _rtld_error("%s: mmap of entire address space failed: %s", path, rtld_strerror(errno)); goto error; >Release-Note: >Audit-Trail: >Unformatted: