dlsym: Add RTLD_PROBE for situation when dlsym only wants to probe a symbol but not use it

Message ID efbc56f827194b87878392540b88fa12@huawei.com
State Changes Requested
Headers
Series dlsym: Add RTLD_PROBE for situation when dlsym only wants to probe a symbol but not use it |

Checks

Context Check Description
dj/TryBot-apply_patch fail Patch failed to apply to master at the time it was sent
dj/TryBot-32bit fail Patch series failed to apply

Commit Message

  dlsym with RTLD_DEFAULT add dependency for target symbol, if program use dlsym only to detect if a symbol exist, and will not use it.

this operation will make unable to dlclose so file containing target symbol, add RTLD_PROBE to support symbol probe.



commit f769328dba5351107097c3a3ad7e1192604318d0
Author: Wang Bing <wangbing6@huawei.com<mailto:wangbing6@huawei.com>>
Date:   Tue Sep 27 14:58:43 2022 +0800

    dlsym: Add RTLD_PROBE for situation when dlsym only wants to probe a symbol but not use it
  

Comments

Florian Weimer Sept. 27, 2022, 10:40 a.m. UTC | #1
* Wangbing via Libc-alpha:

> dlsym with RTLD_DEFAULT add dependency for target symbol, if program
> use dlsym only to detect if a symbol exist, and will not use it.
>
> this operation will make unable to dlclose so file containing target
> symbol, add RTLD_PROBE to support symbol probe.

I'd appreciate if you could write a test case for this functionality.

I'm not sure if the new functionality is needed.  If we document that
a struct link_map * obtained from _dl_find_object or via
_r_debug.r_map can be used as an argument to dlsym (and other places
where a DSO handle is currently accepted), programmers could use that
to get this effect.  I believe this works today (as an undocumented
feature) and does not record the dependency.
  

Patch

diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index fe181085..7ac0d5f1 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -39,6 +39,9 @@ 
    is returned.  */
# define RTLD_DEFAULT  ((void *) 0)

+/* If only find sym in the global scope, but will not use it, do not
+   set sym dependency. */
+# define RTLD_PROBE    ((void *) -2l)

/* Type for namespace indices.  */
typedef long int Lmid_t;
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index de5769f9..970f2028 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -92,10 +92,15 @@  do_sym (void *handle, const char *name, void *who,
   /* Link map of the caller if needed.  */
   struct link_map *match = NULL;

-  if (handle == RTLD_DEFAULT)
+  if (handle == RTLD_DEFAULT || handle == RTLD_PROBE)
     {
       match = _dl_sym_find_caller_link_map (caller);

+      int def_flags = flags;
+      if (handle == RTLD_DEFAULT)
+      {
+         def_flags |= DL_LOOKUP_ADD_DEPENDENCY;
+      }
       /* Search the global scope.  We have the simple case where
         we look up in the scope of an object which was part of
         the initial binary.  And then the more complex part
@@ -104,7 +109,7 @@  do_sym (void *handle, const char *name, void *who,
       if (RTLD_SINGLE_THREAD_P)
        result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
                                           match->l_scope, vers, 0,
-                                          flags | DL_LOOKUP_ADD_DEPENDENCY,
+                                          def_flags,
                                           NULL);
       else
        {
@@ -113,7 +118,7 @@  do_sym (void *handle, const char *name, void *who,
          args.map = match;
          args.vers = vers;
          args.flags
-           = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK;
+           = def_flags | DL_LOOKUP_GSCOPE_LOCK;
          args.refp = &ref;

          THREAD_GSCOPE_SET_FLAG ();