From owner-svn-src-all@FreeBSD.ORG Mon Mar 30 08:47:30 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9D59B106566C; Mon, 30 Mar 2009 08:47:30 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7E06E8FC0C; Mon, 30 Mar 2009 08:47:30 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2U8lTUR058516; Mon, 30 Mar 2009 08:47:29 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2U8lSGo058512; Mon, 30 Mar 2009 08:47:28 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200903300847.n2U8lSGo058512@svn.freebsd.org> From: Konstantin Belousov Date: Mon, 30 Mar 2009 08:47:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r190543 - in head: include libexec/rtld-elf sys/sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Mar 2009 08:47:31 -0000 Author: kib Date: Mon Mar 30 08:47:28 2009 New Revision: 190543 URL: http://svn.freebsd.org/changeset/base/190543 Log: Implement support for RTLD_NODELETE flag for dlopen() and -z nodelete static linker option. Do it by incrementing reference count on the loaded object and its dependencies. Reviewed by: davidxu, kan Modified: head/include/dlfcn.h head/libexec/rtld-elf/rtld.c head/libexec/rtld-elf/rtld.h head/sys/sys/elf_common.h Modified: head/include/dlfcn.h ============================================================================== --- head/include/dlfcn.h Mon Mar 30 08:44:29 2009 (r190542) +++ head/include/dlfcn.h Mon Mar 30 08:47:28 2009 (r190543) @@ -47,6 +47,7 @@ #define RTLD_GLOBAL 0x100 /* Make symbols globally available. */ #define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default. */ #define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */ +#define RTLD_NODELETE 0x01000 /* Do not remove members. */ /* * Request arguments for dlinfo(). Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Mon Mar 30 08:44:29 2009 (r190542) +++ head/libexec/rtld-elf/rtld.c Mon Mar 30 08:47:28 2009 (r190543) @@ -937,6 +937,8 @@ digest_dynamic(Obj_Entry *obj, int early /* XXX */; if (dynp->d_un.d_val & DF_1_BIND_NOW) obj->bind_now = true; + if (dynp->d_un.d_val & DF_1_NODELETE) + obj->z_nodelete = true; break; default: @@ -1422,15 +1424,21 @@ is_exported(const Elf_Sym *def) static int load_needed_objects(Obj_Entry *first) { - Obj_Entry *obj; + Obj_Entry *obj, *obj1; for (obj = first; obj != NULL; obj = obj->next) { Needed_Entry *needed; for (needed = obj->needed; needed != NULL; needed = needed->next) { - needed->obj = load_object(obj->strtab + needed->name, obj); - if (needed->obj == NULL && !ld_tracing) + obj1 = needed->obj = load_object(obj->strtab + needed->name, obj); + if (obj1 == NULL && !ld_tracing) return -1; + if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) { + dbg("obj %s nodelete", obj1->path); + init_dag(obj1); + ref_dag(obj1); + obj1->ref_nodel = true; + } } } @@ -1976,12 +1984,13 @@ dlopen(const char *name, int mode) Obj_Entry **old_obj_tail; Obj_Entry *obj; Objlist initlist; - int result, lockstate; + int result, lockstate, nodelete; LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; if (ld_tracing != NULL) environ = (char **)*get_program_var_addr("environ"); + nodelete = mode & RTLD_NODELETE; objlist_init(&initlist); @@ -2029,6 +2038,11 @@ dlopen(const char *name, int mode) if (ld_tracing) goto trace; } + if (obj != NULL && (nodelete || obj->z_nodelete) && !obj->ref_nodel) { + dbg("obj %s nodelete", obj->path); + ref_dag(obj); + obj->z_nodelete = obj->ref_nodel = true; + } } LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, Modified: head/libexec/rtld-elf/rtld.h ============================================================================== --- head/libexec/rtld-elf/rtld.h Mon Mar 30 08:44:29 2009 (r190542) +++ head/libexec/rtld-elf/rtld.h Mon Mar 30 08:47:28 2009 (r190543) @@ -217,6 +217,8 @@ typedef struct Struct_Obj_Entry { bool tls_done : 1; /* Already allocated offset for static TLS */ bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */ bool z_origin : 1; /* Process rpath and soname tokens */ + bool z_nodelete : 1; /* Do not unload the object and dependencies */ + bool ref_nodel : 1; /* refcount increased to prevent dlclose */ struct link_map linkmap; /* for GDB and dlinfo() */ Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ Modified: head/sys/sys/elf_common.h ============================================================================== --- head/sys/sys/elf_common.h Mon Mar 30 08:44:29 2009 (r190542) +++ head/sys/sys/elf_common.h Mon Mar 30 08:47:28 2009 (r190543) @@ -469,6 +469,7 @@ typedef struct { /* Values for DT_FLAGS_1 */ #define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ #define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ #define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ /* Values for n_type. Used in core files. */