diff mbox

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

Message ID 201502201126341129631@gmail.com
State Superseded
Headers show

Commit Message

xiaoyur347@gmail.com Feb. 20, 2015, 3:26 a.m. UTC
Reason:
MIPS ELF strategy is so different from other architectures like x86 and arm. When fPIC enabled in x86 and arm, ".rel.plt" section is generated after ".rel.dyn" section, and the dependency of the library (like the function and object) . But MIPS only generates ".rel.dyn" section for the library when fPIC, and ".rel.dyn" section can only be generated in non-PIC executable.
This leads to a bug which other architectures will not have.

Description:
If you dlopen a library, uclibc only check the symbols defined in ".rel.dyn" section. And ".rel.dyn" section has no outer dependency, most flags have the type "R_MIPS_REL32". Only ".rel.plt" section generates call to R_MIPS_JUMP_SLOT and R_MIPS_COPY.
In my environment, I almost see the cplusplus virtual functions in ".rel.dyn".

Bug Demo:
use mipsel-linux-readelf -aW libxx.so to view the dependency.

Patch:
MIPS: Scan the symtab for the dependency of the library to avoid runtime empty function pointer. 
The dependency = SHN_UNDEF && STB_GLOBAL && (STT_FUNC || STT_OBJECT)
Signed-off-by: Jean Lee <xiaoyur347 at gmail.com>
---
ldso/ldso/mips/elfinterp.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
+ /* strtab always layout after symtab */
+ symtab_size = ((unsigned long)strtab - (unsigned long)symtab)
+ / tpnt->dynamic_info[DT_SYMENT];
+ for (i = 0, psym = symtab; i < symtab_size; ++i, ++psym) {
+ if (psym->st_name == 0) {
+ continue;
+ }
+
+ if (psym->st_shndx != SHN_UNDEF
+ || ELF_ST_BIND(psym->st_info) != STB_GLOBAL
+ || (ELF_ST_TYPE(psym->st_info) != STT_FUNC
+ && ELF_ST_TYPE(psym->st_info) != STT_OBJECT)) {
+ continue;
+ }
+ symname = strtab + psym->st_name;
+ 
+ sym_ref.tpnt = NULL;
+ sym_ref.sym = psym;
+ symbol_addr = (unsigned long)_dl_find_hash(symname,
+ scope,
+ tpnt,
+ ELF_RTYPE_CLASS_PLT, &sym_ref);
+ if (symbol_addr == 0) {
+ return 1;
+ }
+ }
for (i = 0; i < rel_size; i++, rpnt++) {
reloc_addr = (unsigned long *) (tpnt->loadaddr +




xiaoyur347@gmail.com

Comments

Andrew Bennett Feb. 20, 2015, 12:59 p.m. UTC | #1
> Reason:
> MIPS ELF strategy is so different from other architectures like x86 and arm.
> When fPIC enabled in x86 and arm, ".rel.plt" section is generated after
> ".rel.dyn" section, and the dependency of the library (like the function and
> object) . But MIPS only generates ".rel.dyn" section for the library when
> fPIC, and ".rel.dyn" section can only be generated in non-PIC executable.
> This leads to a bug which other architectures will not have.
> 
> Description:
> If you dlopen a library, uclibc only check the symbols defined in ".rel.dyn"
> section. And ".rel.dyn" section has no outer dependency, most flags have the
> type "R_MIPS_REL32". Only ".rel.plt" section generates call to
> R_MIPS_JUMP_SLOT and R_MIPS_COPY.
> In my environment, I almost see the cplusplus virtual functions in ".rel.dyn".
> 
> Bug Demo:
> use mipsel-linux-readelf -aW libxx.so to view the dependency.
> 
> Patch:
> MIPS: Scan the symtab for the dependency of the library to avoid runtime empty
> function pointer.
> The dependency = SHN_UNDEF && STB_GLOBAL && (STT_FUNC || STT_OBJECT)

Hi Jean,

I am a little unclear why this patch is required.  Could you provide me with a
more detailed explanation, and a testcase/example showing the problem?

Many thanks,


Andrew
xiaoyur347@gmail.com Feb. 21, 2015, 12:09 p.m. UTC | #2
Andrew, thanks for your reply. You are a mips engineer~
I have a following example for dlopen problem, which I tested a few days
ago, but I have no mips environment these days. Would you mind to test it
for me. Many thanks.

Example:
File main.cpp
#include <stdio.h>
#include <dlfcn.h>

typedef void (*init_function_t)(void);

int main()
{
#ifndef __mips__
const char *strLibName = "./libtest_x86.so";
#else
const char *strLibName = "./libtest_mips.so";
#endif
void *pHandle = dlopen(strLibName, RTLD_NOW);
if (pHandle == NULL)
{
printf("open %s fail. %s\n", strLibName, dlerror());
return 1;
}
init_function_t pFunc = (init_function_t)dlsym(pHandle, "init");
if (pFunc == NULL)
{
printf("libtest.so has no init function\n");
dlclose(pHandle);
return 2;
}
pFunc();
dlclose(pHandle);
return 0;
}

File libtest.cpp
extern "C" {
extern void not_exist_function(void);
extern void init(void)
{
not_exist_function();
}

} // extern "C"

File build.sh, run build.sh to get the library and the executable.
#!/bin/sh
g++ -shared -fPIC libtest.cpp -o libtest_x86.so
g++ main.cpp -o x86_test -ldl
mipsel-linux-g++ -shared -fPIC libtest.cpp -o libtest_mips.so
mipsel-linux-g++ main.cpp -o mips_test -ldl

Since I have no mips environment these days, I can only run the x86
environment(./x86_test)
And get the following result for x86
open ./libtest_x86.so fail. ./libtest_x86.so: undefined symbol:
not_exist_function

But in mips environment(./mips_test), the unexpected result is
"Segment Fault"
Which is expected to
open ./libtest_x86.so fail.File not found

2015-02-20 20:59 GMT+08:00 Andrew Bennett <Andrew.Bennett@imgtec.com>:

> > Reason:
> > MIPS ELF strategy is so different from other architectures like x86 and
> arm.
> > When fPIC enabled in x86 and arm, ".rel.plt" section is generated after
> > ".rel.dyn" section, and the dependency of the library (like the function
> and
> > object) . But MIPS only generates ".rel.dyn" section for the library when
> > fPIC, and ".rel.dyn" section can only be generated in non-PIC executable.
> > This leads to a bug which other architectures will not have.
> >
> > Description:
> > If you dlopen a library, uclibc only check the symbols defined in
> ".rel.dyn"
> > section. And ".rel.dyn" section has no outer dependency, most flags have
> the
> > type "R_MIPS_REL32". Only ".rel.plt" section generates call to
> > R_MIPS_JUMP_SLOT and R_MIPS_COPY.
> > In my environment, I almost see the cplusplus virtual functions in
> ".rel.dyn".
> >
> > Bug Demo:
> > use mipsel-linux-readelf -aW libxx.so to view the dependency.
> >
> > Patch:
> > MIPS: Scan the symtab for the dependency of the library to avoid runtime
> empty
> > function pointer.
> > The dependency = SHN_UNDEF && STB_GLOBAL && (STT_FUNC || STT_OBJECT)
>
> Hi Jean,
>
> I am a little unclear why this patch is required.  Could you provide me
> with a
> more detailed explanation, and a testcase/example showing the problem?
>
> Many thanks,
>
>
> Andrew
>
Andrew Bennett Feb. 23, 2015, 9:23 p.m. UTC | #3
> Andrew, thanks for your reply. You are a mips engineer~
> I have a following example for dlopen problem, which I tested a few days ago, 
> but I have no mips environment these days. Would you mind to test it for me. Many thanks.

Many thanks for the testcase I will give it a try.

Regards,


Andrew
Bernhard Reutner-Fischer Feb. 23, 2015, 10:18 p.m. UTC | #4
On February 23, 2015 10:23:21 PM GMT+01:00, Andrew Bennett <Andrew.Bennett@imgtec.com> wrote:
>> Andrew, thanks for your reply. You are a mips engineer~
>> I have a following example for dlopen problem, which I tested a few
>days ago, 
>> but I have no mips environment these days. Would you mind to test it
>for me. Many thanks.
>
>Many thanks for the testcase I will give it a try.

Which compiler and version do you use, which version of binutils and which MIPS ABI?

Thanks,
xiaoyur347@gmail.com Feb. 24, 2015, 1:06 a.m. UTC | #5
I tested the following environment with MIPS32, with CPU BCM7429(MIPS
r3000),
(1)
mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
uclibc 0.9.32-1
Segment fault.
(2)
mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
uclibc 0.9.34 git master
Segment fault.
(3)
mipsel-linux-uclibc-gcc 4.8 (compiled by Broadcom)
binutils ?
uclibc ?
No .rel.plt segment.
(4)
mipsel-linux-uclibc-gcc 4.9 (compiled by me)
binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
uclibc 0.9.32-1
Segment fault.
(5)
mips android ndk toolchain
No .rel.plt segment.


Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>于2015年2月24日星期二写道:

> On February 23, 2015 10:23:21 PM GMT+01:00, Andrew Bennett <
> Andrew.Bennett@imgtec.com> wrote:
> >> Andrew, thanks for your reply. You are a mips engineer~
> >> I have a following example for dlopen problem, which I tested a few
> >days ago,
> >> but I have no mips environment these days. Would you mind to test it
> >for me. Many thanks.
> >
> >Many thanks for the testcase I will give it a try.
>
> Which compiler and version do you use, which version of binutils and which
> MIPS ABI?
>
> Thanks,
>
>
Bernhard Reutner-Fischer Feb. 24, 2015, 8:57 a.m. UTC | #6
Please do not top-post.

On February 24, 2015 2:06:28 AM GMT+01:00, Jean Lee <xiaoyur347@gmail.com> wrote:
>I tested the following environment with MIPS32, with CPU BCM7429(MIPS
>r3000),
>(1)
>mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
>binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
>uclibc 0.9.32-1
>Segment fault.
>(2)
>mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
>binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
>uclibc 0.9.34 git master
>Segment fault.
>(3)
>mipsel-linux-uclibc-gcc 4.8 (compiled by Broadcom)
>binutils ?
>uclibc ?
>No .rel.plt segment.
>(4)
>mipsel-linux-uclibc-gcc 4.9 (compiled by me)
>binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
>uclibc 0.9.32-1
>Segment fault.
>(5)
>mips android ndk toolchain
>No .rel.plt segment.

binutils-2.19 is pretty old. Does current 2.25 or master behave the same?
Let's concentrate on gcc 4.9.2 (or trunk), binutils 2.25 (or master) and uClibc master.

Thanks,
xiaoyur347@gmail.com Feb. 24, 2015, 4:04 p.m. UTC | #7
2015年2月24日 下午4:57于 "Bernhard Reutner-Fischer" <rep.dot.nop@gmail.com>写道:
>
> Please do not top-post.
>
> On February 24, 2015 2:06:28 AM GMT+01:00, Jean Lee <xiaoyur347@gmail.com>
wrote:
> >I tested the following environment with MIPS32, with CPU BCM7429(MIPS
> >r3000),
> >(1)
> >mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
> >binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> >uclibc 0.9.32-1
> >Segment fault.
> >(2)
> >mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
> >binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> >uclibc 0.9.34 git master
> >Segment fault.
> >(3)
> >mipsel-linux-uclibc-gcc 4.8 (compiled by Broadcom)
> >binutils ?
> >uclibc ?
> >No .rel.plt segment.
> >(4)
> >mipsel-linux-uclibc-gcc 4.9 (compiled by me)
> >binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> >uclibc 0.9.32-1
> >Segment fault.
> >(5)
> >mips android ndk toolchain
> >No .rel.plt segment.
>
> binutils-2.19 is pretty old. Does current 2.25 or master behave the same?
> Let's concentrate on gcc 4.9.2 (or trunk), binutils 2.25 (or master) and
uClibc master.
>
> Thanks,
>

Sorry for top-post.
I'm not sure the compiler built(gcc 4.9) by myself is precisely right. The
compiler is built with original gcc 4.5.3 toolchain plus gcc configure to
ease the building of gcc since uclibc has been built.
If you have built this toolchain, would you mind to use
mipsel-linux-readelf -aW one lib built by that toolchain to see whether or
not there is a .rel.plt section? If there is always no .rel.plt section, I
guess this is the MIPS feature for PIC. Many thanks.
I will test android ndk MIPS toochain first, and then build the whole
toolchain myself.
Florian Fainelli Feb. 24, 2015, 5:36 p.m. UTC | #8
2015-02-23 17:06 GMT-08:00 Jean Lee <xiaoyur347@gmail.com>:
> I tested the following environment with MIPS32, with CPU BCM7429(MIPS
> r3000),

This is a BMIPS5000 CPU, fully compatible with the mips32r1 ISA, not a
R3000-class MIPS processor per-se.

> (1)
> mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
> binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> uclibc 0.9.32-1
> Segment fault.
> (2)
> mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
> binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> uclibc 0.9.34 git master
> Segment fault.

As another data point, you might want to try a newer toolchain from
Broadcom here:
http://www.broadcom.com/support/stb/

> (3)
> mipsel-linux-uclibc-gcc 4.8 (compiled by Broadcom)
> binutils ?
> uclibc ?
> No .rel.plt segment.
> (4)
> mipsel-linux-uclibc-gcc 4.9 (compiled by me)
> binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> uclibc 0.9.32-1
> Segment fault.
> (5)
> mips android ndk toolchain
> No .rel.plt segment.
>
>
> Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>于2015年2月24日星期二写道:
>
>> On February 23, 2015 10:23:21 PM GMT+01:00, Andrew Bennett <
>> Andrew.Bennett@imgtec.com> wrote:
>> >> Andrew, thanks for your reply. You are a mips engineer~
>> >> I have a following example for dlopen problem, which I tested a few
>> >days ago,
>> >> but I have no mips environment these days. Would you mind to test it
>> >for me. Many thanks.
>> >
>> >Many thanks for the testcase I will give it a try.
>>
>> Which compiler and version do you use, which version of binutils and which
>> MIPS ABI?
>>
>> Thanks,
>>
>>
> _______________________________________________
> uClibc mailing list
> uClibc@uclibc.org
> http://lists.busybox.net/mailman/listinfo/uclibc
xiaoyur347@gmail.com Feb. 25, 2015, 4:53 a.m. UTC | #9
2015-02-25 1:36 GMT+08:00 Florian Fainelli <f.fainelli@gmail.com>:

> 2015-02-23 17:06 GMT-08:00 Jean Lee <xiaoyur347@gmail.com>:
> > I tested the following environment with MIPS32, with CPU BCM7429(MIPS
> > r3000),
>
> This is a BMIPS5000 CPU, fully compatible with the mips32r1 ISA, not a
> R3000-class MIPS processor per-se.
>

Thank you for pointing it out. This is my mistake.

> (1)
> > mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
> > binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> > uclibc 0.9.32-1
> > Segment fault.
> > (2)
> > mipsel-linux-uclibc-gcc 4.5.3-2.4 (compiled by Broadcom)
> > binutils 2.19(GNU ld (GNU Binutils) 2.19.92.20091006)
> > uclibc 0.9.34 git master
> > Segment fault.
>
> As another data point, you might want to try a newer toolchain from
> Broadcom here:
> http://www.broadcom.com/support/stb/


Thanks. I download the toolchain stbgcc-4.8-1.0 for further testing.
For android, I update the test here.
https://github.com/xiaoyur347/issue/tree/master/mips-dlopen

(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 run the build.sh and mipsel-linux-readelf -aW libtest_mips.so, and no
.rel.plt too.
  [ 8] .rel.dyn          REL             000004c4 0004c4 000010 08   A  4
0  4
  [ 9] .init             PROGBITS        000004dc 0004dc 00008c 00  AX  0
0  4

Relocation section '.rel.dyn' at offset 0x4c4 contains 2 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name
00000000  00000000 R_MIPS_NONE
000108f0  00000003 R_MIPS_REL32

(2)android-ndk-r10d mipsel-linux-android-4.8
mipsel-linux-android-gcc 4.8
binutils 2.24 (GNU ld (GNU Binutils) 2.24)
bionic
I run the build.sh and mipsel-linux-readelf -aW libtest_mips.so, and no
.rel.plt too.
  [ 6] .rel.dyn          REL             00000394 000394 000018 08   A  4
0  4
  [ 7] .text             PROGBITS        000003c0 0003c0 000080 00  AX  0
0 16

Relocation section '.rel.dyn' at offset 0x394 contains 3 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name
00000000  00000000 R_MIPS_NONE
00010ee0  00000003 R_MIPS_REL32
00011000  00000003 R_MIPS_REL32

(3)android-ndk-r10d mipsel-linux-android-4.9
modify the
https://github.com/xiaoyur347/issue/tree/master/mips-dlopen/and/lib/jni/Application.mk
with
NDK_TOOLCHAIN_VERSION = 4.9

mipsel-linux-android-gcc 4.9 20140827 (prerelease)
binutils 2.24 (GNU ld (GNU Binutils) 2.24)
bionic
I run the build.sh and mipsel-linux-readelf -aW libtest_mips.so, and no
.rel.plt too.
  [ 6] .rel.dyn          REL             00000394 000394 000018 08   A  4
0  4
  [ 7] .text             PROGBITS        000003c0 0003c0 000080 00  AX  0
0 16

Relocation section '.rel.dyn' at offset 0x394 contains 3 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name
00000000  00000000 R_MIPS_NONE
00010ee0  00000003 R_MIPS_REL32
00011000  00000003 R_MIPS_REL32

Conclusion:
All MIPS platforms never generate .rel.plt section for dynamic libraries,
even for
GCC 4.9
binutils 2.24
any libc(uclibc, libc, bionic)
Bernhard Reutner-Fischer Feb. 25, 2015, 9:05 a.m. UTC | #10
On February 25, 2015 5:53:58 AM GMT+01:00, Jean Lee <xiaoyur347@gmail.com> wrote:

>
>Conclusion:
>All MIPS platforms never generate .rel.plt section for dynamic
>libraries,
>even for
>GCC 4.9
>binutils 2.24
>any libc(uclibc, libc, bionic)

Anyone remember what happened to https://gcc.gnu.org/ml/gcc/2008-06/msg00670.html

or

http://marc.info/?l=linux-mips&m=121494382925231&w=2

Andrew?
Andrew Bennett Feb. 25, 2015, 9:13 p.m. UTC | #11
> Anyone remember what happened to https://gcc.gnu.org/ml/gcc/2008-
> 06/msg00670.html
> 
> or
> 
> http://marc.info/?l=linux-mips&m=121494382925231&w=2
> 
> Andrew?

I think this support was added (I know that there is PLT support for MIPS in the
binutils linker).  I have cc'd Richard Sandiford to confirm.

Regards,


Andrew
Bernhard Reutner-Fischer March 14, 2015, 10:19 p.m. UTC | #12
On February 25, 2015 10:13:02 PM GMT+01:00, Andrew Bennett <Andrew.Bennett@imgtec.com> wrote:

Andrew, so what do you think about Jean Lee's patch?

TIA,
xiaoyur347@gmail.com March 15, 2015, 12:16 p.m. UTC | #13
> (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?
xiaoyur347@gmail.com March 16, 2015, 5:28 a.m. UTC | #14
2015-03-15 20:16 GMT+08:00 Jean Lee <xiaoyur347@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 };
Andrew Bennett March 16, 2015, 11:37 p.m. UTC | #15
> Andrew, so what do you think about Jean Lee's patch?

I am currently in the middle of the patch review, but a heavy 
work load at the moment is meaning this is taking longer than 
expected, so sorry about the delay.  I will get the review on 
the mailing list in the next couple of days.

Regards,


Andrew
diff mbox

Patch

diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index dfe37c5..00b136a 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -162,6 +162,8 @@  int _dl_parse_relocation_information(struct dyn_elf *xpnt,
#endif
struct symbol_ref sym_ref;
+ unsigned long symtab_size = 0;
+ ElfW(Sym) *psym = NULL;
/* Now parse the relocation information */
rel_size = rel_size / sizeof(ElfW(Rel));
rpnt = (ELF_RELOC *) rel_addr;
@@ -170,6 +172,32 @@  int _dl_parse_relocation_information(struct dyn_elf *xpnt,