diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2009-03-30 08:47:28 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2009-03-30 08:47:28 +0000 |
| commit | 2b0b4ee3592d5074ee6391bda886bdc48d168c5a (patch) | |
| tree | 7fa11a9c6f5eb076d989897ba5ab3e64c0101750 /libexec | |
| parent | dec9af5a2bd1a4e4d9796715772cb6b3b8ad0372 (diff) | |
Notes
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/rtld-elf/rtld.c | 22 | ||||
| -rw-r--r-- | libexec/rtld-elf/rtld.h | 2 |
2 files changed, 20 insertions, 4 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index d98ade7ce25a..07529b3091cf 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -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, diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index f47c21515973..1d7ffb267f10 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -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 (%) */ |
