Bug 55872 - Crash issue with RTLD_DEEPBIND usage with stdc++ library
Summary: Crash issue with RTLD_DEEPBIND usage with stdc++ library
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.6.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-01-04 10:28 UTC by Yogesh Gaur
Modified: 2016-01-18 00:28 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
LD_DEBUG=all output of failure executable (27.90 KB, application/octet-stream)
2013-01-04 10:28 UTC, Yogesh Gaur
Details
LD_DEBUG=all output of working executable (27.94 KB, application/octet-stream)
2013-01-04 10:29 UTC, Yogesh Gaur
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Yogesh Gaur 2013-01-04 10:28:38 UTC
Created attachment 29080 [details]
LD_DEBUG=all output of failure executable

Hello All,

I faced crash issue while opening one library dynamically using RTLD_DEEPBIND flag.

Scenario:
I have one library.so which is having un-initiliazed variable of data type 'std::string' and main file is also having another variable of same data type i.e. 'std::string'.
Both files are written in C++ code.

If I execute this code then it result in crash resulting in free() call of libc.
crash log:
*** glibc detected *** ./a.out: free(): invalid pointer: 0x00007f1229894140 ***
======= Backtrace: =========
/lib/libc.so.6(+0x77806)[0x7f1228ded806]
/lib/libc.so.6(cfree+0x73)[0x7f1228df40d3]
/usr/lib/libstdc++.so.6(_ZNSs9_M_mutateEmmm+0x1ae)[0x7f122963cb0e]
/usr/lib/libstdc++.so.6(_ZNSs14_M_replace_auxEmmmc+0x4a)[0x7f122963cdaa]
./library.so(library_function+0x36)[0x7f1228b74a66]
./a.out[0x400a89]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f1228d94c4d]
./a.out[0x400959]

If I initiliazed std::string variable in library code like " std::string empty_lib=""; then no crash is obeserved.
I have checked output of LD_DEBUG=all for both case executable and checked that there is binding issue in crash scenario wrt to std::string.

Please find exact test code:
===============================================================
cat main.cpp
#include <dlfcn.h>
#include <iostream>

int main()
{
    char const * const library_name = "./library.so";
    void * handle = dlopen(library_name, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
    std::string empty_main="";
    typedef void (*library_function_type)();
    void * function = dlsym(handle, "library_function");
    reinterpret_cast<library_function_type>(function)();
    dlclose(handle);
    return 0;
}

cat library.cpp
#include <sstream>
#include <iostream>

extern "C"
{
void library_function()
{
    std::string empty_lib;
    char c = '/';
    empty_lib = c;
}
}
===============================================================
----------------------------------------------------------------
Compilation commands:
g++ -g -O2 -rdynamic -c  -Wall -Wextra -fPIC -o library.o library.cpp ; g++ -shared -Wl,-export-dynamic -o library.so library.o

g++ -g -O2 -Wall -Wextra main.cpp -ldl
----------------------------------------------------------------
Can someone please help in this regard and let me know what went wrong and how to solve this issue.

Please note that if I remove RTLD_DEEPBIND flag while opening this library then I didn't get any crash.
If I write same code in .c file instead of .cpp then no issues observed.

Thanks in advance.

Attached LD_DEBUG=all output for both working and non-working case:

--
Regards,
Yogesh Gaur.
Comment 1 Yogesh Gaur 2013-01-04 10:29:37 UTC
Created attachment 29081 [details]
LD_DEBUG=all output of working executable
Comment 2 Jonathan Wakely 2013-01-04 11:02:00 UTC
GCC 4.4 is no longer maintained or supported. 

Unles you can reproduce the problem with a current release of GCC (which I can't) then nothing is going to happen.

N.B. compiling main.cpp with -fPIC seems to fix the problem anyway.
Comment 3 Yogesh Gaur 2013-01-07 00:12:26 UTC
(In reply to comment #2)
> GCC 4.4 is no longer maintained or supported. 
> 
> Unles you can reproduce the problem with a current release of GCC (which I
> can't) then nothing is going to happen.
> 
Hello Jonathan,

I tried on GCC 4.6.4 also and still getting this issue on there, I didn't have any more latest copy of GCC with me.

> N.B. compiling main.cpp with -fPIC seems to fix the problem anyway.

Can you please explain that why it should work with -fPIE, I am able to work it using -fPIE while making my executable.
Please note that we should never use -fPIC with executable it will break prelink, if Thread Local Storage is used.
Comment 4 Yogesh Gaur 2013-01-07 10:31:19 UTC
Hello,

Actually issue is combination of copy_relocation plus RTLD_DEEPBIND flag.

If I didn't give -fPIE flag while compiling my executable and pass RTLD_DEEPBIND flag while opening library using dlopen(), then result is un-expected.

I checked similar issue exist on gcc also:
------------------------------Source Code -----------------------------
$ cat main.c
#include <dlfcn.h>
extern int alpha;
int main()
{
        char const * const name = "./lib1.so";
        void * handle = dlopen(name, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
        typedef void (*library_function_type)();
        library_function_type func1 = dlsym(handle, "func1");

        alpha = 10;
        (*func1)();
        func2();

        dlclose(handle);
        return 0;
}

$ cat lib1.c
#include <stdio.h>
extern int alpha;
void func1(){
        printf("lib1: Addr=%p, value=%d\n", &alpha, alpha);
}

$ cat lib2.c
#include <stdio.h>
int alpha;
void func2(){
        printf("lib2: Addr=%p, value=%d\n", &alpha, alpha);
}
-------------------------------- END ----------------------------------

Compilation command and output:

gcc -shared -fPIC lib2.c -o lib2.so
gcc -shared -fPIC lib1.c lib2.so -o lib1.so
gcc -ldl main.c lib2.so -o a.out
LD_LIBRARY_PATH=$PWD ./a.out 
         lib1: Addr=0x7f5a39663028, value=0
         lib2: Addr=0x601038, value=10
=========================================

Thus for same symbol, alpha, we get two addresses values.

If I remove RTLD_DEEPBIND while opening library, I didn't get this issue:
          lib1: Addr=0x601038, value=10
          lib2: Addr=0x601038, value=10

Reason for this also I know that in case of RTLD_DEEPBIND scope of search for lib1.so is its internal library first and then only global library's being searched.

I want to know that apart from usage of -fPIE flag at compilation time did any-other solution exist for this issue? As using -fPIE has it's own side-affect.

--
Regards,
Yogesh Gaur.