On Mon, 2009-03-30 at 08:47 +0000, Konstantin Belousov wrote:
> 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.

Cool, I can drop my patches to compiz now.

robert.

>   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. */
-- 
Robert Noland <rnol...@freebsd.org>
FreeBSD

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to