[PATCH]mips: ldso: dlopen with flag RTLD_NOW should look up the symbols

Jean Lee xiaoyur347 at gmail.com
Mon Mar 16 05:28:36 UTC 2015


2015-03-15 20:16 GMT+08:00 Jean Lee <xiaoyur347 at gmail.com>:

> > (1)mipsel-linux-gnu 4.8.4(compiled by Broadcom)
> > mipsel-linux-gnu-gcc 4.8.4
> > binutils 2.24 (GNU ld (GNU Binutils) 2.24.0.20140801 Linaro 2014.08)
> > libc 2.18-2013.10
> > It's not uclibc.
>
> I do further test in this platform.
> (1) If dlopen with flag RTLD_NOW, the result is:
> open ./libtest_mips.so fail. ./libtest_mips.so: undefined symbol:
> not_exist_function
> And the program continues running.
> (2) If dlopen with flag RTLD_LAZY, the result is:
> ./mips_test: symbol lookup error: ./libtest_mips.so: undefined symbol:
> not_exist_function
> And the program exits.
>
> So I guess eglibc may do something more for mips dlopen.
> Does anyone know it?
>

I lookup the eglic source 2.18, and find these difference, maybe it is
useful for MIPS dlopen bug. See the biggest comment below.

diff -u http://www.eglibc.org/svn/branches/eglibc-2_18/libc/elf/dl-lookup.c
http://www.eglibc.org/svn/branches/eglibc-2_18/libc/ports/sysdeps/mips/dl-lookup.c

--- /opt/tool/eglibc/elf/dl-lookup.c    2015-03-15 20:32:46.862824714 +0800
+++ /opt/tool/eglibc/ports/sysdeps/mips/dl-lookup.c     2015-03-16
13:17:09.981423929 +0800
@@ -1,4 +1,5 @@
 /* Look up a symbol in the loaded objects.
+   MIPS/Linux version - special handling of non-PIC undefined symbol rules.
    Copyright (C) 1995-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.

@@ -110,9 +111,10 @@
        continue;

       /* Print some debugging info if wanted.  */
-      if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_SYMBOLS, 0))
+      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS, 0))
        _dl_debug_printf ("symbol=%s;  lookup in file=%s [%lu]\n",
-                         undef_name, DSO_FILENAME (map->l_name),
+                         undef_name,
+                         DSO_FILENAME (map->l_name),
                          map->l_ns);

       /* If the hash table is empty there is nothing to do here.  */
@@ -131,8 +133,24 @@
       {
        unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
        assert (ELF_RTYPE_CLASS_PLT == 1);
+       /* The semantics of zero/non-zero values of undefined symbols
+          differs depending on whether the non-PIC ABI is in use.
+          Under the non-PIC ABI, a non-zero value indicates that
+          there is an address reference to the symbol and thus it
+          must always be resolved (except when resolving a jump slot
+          relocation) to the PLT entry whose address is provided as
+          the symbol's value; a zero value indicates that this
+          canonical-address behaviour is not required.  Yet under the
+          classic MIPS psABI, a zero value indicates that there is an
+          address reference to the function and the dynamic linker
+          must resolve the symbol immediately upon loading.  To avoid
+          conflict, symbols for which the dynamic linker must assume
+          the non-PIC ABI semantics are marked with the STO_MIPS_PLT
+          flag.  */
        if (__builtin_expect ((sym->st_value == 0 /* No value.  */
                               && stt != STT_TLS)
+                             || (sym->st_shndx == SHN_UNDEF
+                                 && !(sym->st_other & STO_MIPS_PLT))
                              || (type_class & (sym->st_shndx ==
SHN_UNDEF)),
                              0))
          return NULL;
@@ -414,7 +432,7 @@
                     hash table.  */
                  if (__builtin_expect (tab->size, 0))
                    {
-                     assert (GLRO_dl_debug_mask & DL_DEBUG_PRELINK);
+                     assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
                      __rtld_lock_unlock_recursive (tab->lock);
                      goto success;
                    }
@@ -663,7 +681,7 @@
        }

       /* Display information if we are debugging.  */
-      if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_FILES, 0))
+      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
        _dl_debug_printf ("\
 \nfile=%s [%lu];  needed by %s [%lu] (relocation dependency)\n\n",
                          DSO_FILENAME (map->l_name),
@@ -838,7 +856,7 @@
   if (__builtin_expect (current_value.m->l_used == 0, 0))
     current_value.m->l_used = 1;

-  if (__builtin_expect (GLRO_dl_debug_mask
+  if (__builtin_expect (GLRO(dl_debug_mask)
                        & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
     _dl_debug_bindings (undef_name, undef_map, ref,
                        &current_value, version, type_class, protected);
@@ -903,7 +921,7 @@
 {
   const char *reference_name = undef_map->l_name;

-  if (GLRO_dl_debug_mask & DL_DEBUG_BINDINGS)
+  if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
     {
       _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol
`%s'",
                        DSO_FILENAME (reference_name),
@@ -917,7 +935,7 @@
        _dl_debug_printf_c ("\n");
     }
 #ifdef SHARED
-  if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK)
+  if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
     {
       int conflict = 0;
       struct sym_val val = { NULL, NULL };


More information about the uClibc mailing list