Add testcese// [PATCH] dlsym: Add RTLD_PROBE for situation when dlsym only wants to probe a symbol but not use it

Message ID 7cad26c73f5b4172bbcf570882bf9d3d@huawei.com
State New
Headers
Series Add testcese// [PATCH] 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

  Sorry for the delay

The reason why not useing struct link_map * as an argument to dlsym is that there may be more than one same-named symbol in different so files(provided by different vendors or components) in one process, 
and by -Wl,-z,now,only the first symbol is needed, and we cannot be sure which struct link_map* should be send to dlsym.

So we would like use dlsym(0, symbol) to get the first found symbol. 

And add testcase for RTLD_PROBE:

dlsym: Add RTLD_PROBE to dlsym only probe symbol without add dependency.

    Signed-off-by: Wang Bing <wangbing6@huawei.com>

发送时间: 2022年9月27日 18:41
收件人: Wangbing(wangbing, RTOS/Poincare Lab) via Libc-alpha <libc-alpha@sourceware.org>
抄送: Wangbing(wangbing,RTOS/Poincare Lab) <wangbing6@huawei.com>; Nixiaoming <nixiaoming@huawei.com>
主题: Re: [PATCH] dlsym: Add RTLD_PROBE for situation when dlsym only wants to probe a symbol but not use it

* 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.
  

Comments

Szabolcs Nagy Nov. 21, 2022, 2:33 p.m. UTC | #1
The 11/21/2022 14:06, Wangbing(wangbing, RTOS/Poincare Lab) via Libc-alpha wrote:
> diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h index 6f7cad8682..ab709883a6 100644
> --- a/dlfcn/dlfcn.h
> +++ b/dlfcn/dlfcn.h
> @@ -49,6 +49,10 @@ typedef long int Lmid_t;
>     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)
> +
>  __BEGIN_DECLS
> 
>  /* Open the shared object FILE and map it in; return a handle that can be diff --git a/elf/Makefile b/elf/Makefile index eca7b28ab5..f9fc9fbebb 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile

looks like the patch got corrupted.

i think it would help if you could resend it.
  
Florian Weimer Nov. 21, 2022, 4:05 p.m. UTC | #2
* Wangbing via Libc-alpha:

> The reason why not useing struct link_map * as an argument to dlsym is
> that there may be more than one same-named symbol in different so
> files(provided by different vendors or components) in one process, and
> by -Wl,-z,now,only the first symbol is needed, and we cannot be sure
> which struct link_map* should be send to dlsym.

You should be able to use the link map of the main program (which is
available through the global _r_debug variable).

Access to _r_debug is currently broken in case of copy relocations, but
I have posted a series that should fix it again.  Then we just need to
document how to access _r_debug, and that the link maps found there can
be used as arguments to dlsym.

For the time being, you can still experiment by building everything with
-fPIC, or an architecture without copy relocations.

Thanks,
Florian
  

Patch

diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h index 6f7cad8682..ab709883a6 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -49,6 +49,10 @@  typedef long int Lmid_t;
    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)
+
 __BEGIN_DECLS

 /* Open the shared object FILE and map it in; return a handle that can be diff --git a/elf/Makefile b/elf/Makefile index eca7b28ab5..f9fc9fbebb 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -472,6 +472,7 @@  tests += \
   unload7 \
   unload8 \
   valgrind-test \
+  tst-dlsym-rtld-probe \
   # tests
 tests-cxx = \
   tst-dlopen-nodelete-reloc \
diff --git a/elf/dl-sym.c b/elf/dl-sym.c index b1cf42f36d..bc95b12a19 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -92,10 +92,17 @@  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)
+  int def_flags;
+
+  if (handle == RTLD_DEFAULT || handle == RTLD_PROBE)
     {
       match = _dl_sym_find_caller_link_map (caller);

+      def_flags = flags
+      if (def_flags == 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 +111,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 +120,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 ();
diff --git a/elf/tst-dlsym-rtld-probe.c b/elf/tst-dlsym-rtld-probe.c new file mode 100644 index 0000000000..84ba92c6c8
--- /dev/null
+++ b/elf/tst-dlsym-rtld-probe.c
@@ -0,0 +1,50 @@ 
+/* Test RTLD_PROBE for dlsym.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <gnu/lib-names.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+  int *iptr;
+  int ret;
+  void *handle;
+
+  handle = dlopen (LIBM_SO, RTLD_LAZY);  TEST_VERIFY (handle == NULL);  
+ iptr = (int *)dlsym (RTLD_PROBE, "finite");  ret = dlclose (handle);  
+ TEST_VERIFY (ret != 0);  ret = 0;
+
+  handle = dlopen (LIBM_SO, RTLD_LAZY);
+  TEST_VERIFY (handle == NULL);
+  iptr = (int *)dlsym (RTLD_DEFAULT, "finite");
+  ret = dlcose (handle);
+  TEST_VERIFY (ret == 0);
+  return 0;
+}
+
+
+#include <support/test-driver.c>


-----邮件原件-----
发件人: Florian Weimer [mailto:fw@deneb.enyo.de]