Various Essentials of Linux dynamic Library

Source: Internet
Author: User

The use of dynamic libraries under Linux, basic use is still very easy. But assuming that our program uses a lot of dynamic libraries to implement a variety of frameworks/plugins, there are holes in the pits that will help the program to perform more robustly.

This article first talks about the problem of dynamic library notation.

The test code can be found on GitHub.

Symbol Lookup

An application test will link a dynamic library libdy.so , assuming a symbol. For example, a function is callfn defined in libdy.so, and test uses that function to simply declare it:

Dy.cpp libdy.sovoid CALLFN () {    ...} Main.cpp Testextern void Callfn (); CALLFN ();

When the link test is linked, the linker checks it uniformly.

Similarly, there is the same rule in libdy.so that it can use an external symbol to check for the presence or absence of symbols when it is linked/loaded into a running program . This symbol can even be defined in test to form a two-way dependency or to be defined in another dynamic library:

Dy.cpp Libdy.soextern void Mfunc (); Mfunc ();//Main.cpp testvoid Mfunc () {    ...}

mfunccan not be found when generating libdy.so, there is mfunc no definition at this time:

$ nm libdy.so | grep Mfunu _Z5MFUNCV

However, when the libdy.so is linked into Test, it will be checked, try to mfunc remove the definition of the function, you will get a link error:

./libdy.so:undefined reference to ' Mfunc () '

Same. Let's say we dynamically load the libdy.so, and of course we can link through, but at the same time we get the wrong symbols when we load them:

#ifdef dy_load    void *DP = Dlopen ("./libdy.so", rtld_lazy);    typedef void (*CALLFN) ();    CALLFN f = (CALLFN) Dlsym (DP, "CALLFN");    f ();    Dlclose (DP); #else    CALLFN (); #endif

Get error:

./test:symbol Lookup error:./libdy.so:undefined symbol: _Z5MFUNCV

Conclusion: based on the above, we know that a dynamic library relies on some external symbols that can be located in other dynamic libraries and even applications.

We can link the dynamic library again by linking other libraries that depend on them, or by deferring them to the link application. A dynamically loaded library, it is guaranteed that the symbol already exists in the other dynamic libraries that are loaded in the process when the library is loaded.

Like what. The LD_PRELOAD environment variable allows a process to load the specified dynamic library, the above dynamic loading boot failure sample, can be resolved by pre mfunc -loading the dynamic library including the symbol:

$ ld_preload=libmfun.so./test.

However, it is not possible to assume that this symbol exists in a running program:

$ NM Test | grep mfunc0000000000400a00 T _z5mfuncv$ nm Test | grep mfunc0000000000400a00 T _z5mfuncv$./test..../test:symbol Lookup error:./libdy.so:undefined symbol: _Z5MFUNCV
Symbol Overlay

The main words above are the lack of symbols. Assume that there are multiple points for the same symbol. can cause problems more. The symbols mentioned here are all global symbols. A global symbol in a process is always globally unique. To ensure this. When you link or dynamically load a dynamic library. There is a case of ignoring repeated symbols.

This does not mention the same link units (such as running programs, dynamic libraries) in the sign of repeated problems

Function

What happens when a function with the same name is included in the dynamic library and the libdy.so run program test? Depending on whether the dynamic loading situation is different.

When you link a dynamic library directly, both libdy.so and test link include func the fun.o of the function. In order to differentiate. I have func compiled the different version numbers according to the conditions:

Fun.cpp#ifdef v2extern "C" void func () {    printf ("func v2\n");} #elseextern "C" void func () {    printf ("func v1\n");} #endif//Makefiletest:libdy obj.o mainfn    g++-g-wall-c fun.cpp-o fun.o # compiled to FUN.O g++-g-wall-c main.cpp #-d    Dy_load    g++-g-wall-o test main.o obj.o fun.o-ldl mfun.o-ldy-l.libdy:obj    g++-wall-fpic-c fun.cpp-dv2-o FUN-DY.O  # define V2 macros, compile to fun-dy.o    g++-wall-fpic-shared-o libdy.so dy.cpp-g obj.o fun-dy.o

In this case, the test will be output, and the func func v1 libdy.so func will be output func v2 .

Test and LIBDY.O do have func symbols:

$ nm libdy.so | grep func0000000000000a60 T func$nm Test | grep FUNC0000000000400A80 T func

Functions are called in both Test and libdy.so func :

Main.cpp testint Main (int argc, char **argv) {    func ();    ...    CALLFN (); Call the function in libdy.so ...    } Dy.cpp libdy.soextern "C" void Callfn () {    ...     printf ("callfn\n");    Func ();    ...}

Found after execution. Are all called the same func :

$./test...func V1...callfnfunc v1

conclusion : When a dynamic library is directly linked, the symbol is overwritten when the entire program executes, and only one symbol is used. in practice , assuming that both the program and the linked dynamic library are dependent on a static library, and then the static library version number they link to is different, it is very likely that the symbol has been overwritten to cause problems. (The static library is the same as the normal. O Nature, reference analysis static Library link principle)

In more complex cases. Multiple dynamic libraries and programs have the same symbols. The same is true. A symbol overlay will occur. It is assumed that there is no such symbol in the program, and that the same symbol is covered in multiple dynamic libraries.

However, for dynamic loading, the situation is different. The same libdy.so we do not link in test, but dynamic loading:

int main (int argc, char **argv) {    func (); #ifdef dy_load    void *DP = Dlopen ("./libdy.so", rtld_lazy);    typedef void (*CALLFN) ();    CALLFN f = (CALLFN) Dlsym (DP, "CALLFN");    f ();    Func ();    Dlclose (DP); #else    CALLFN (); #endif    return 0;}

Execution gets:

$./testfunc V1...callfnfunc V2func v1

are correctly called to the respective links func .

conclusions . In practice, dynamically loaded dynamic libraries are usually used as plug-ins, so it is no problem to have a static library that links different version numbers with the program (the same symbol is implemented differently).

Variable

Variables are also symbols (symbol) in nature, but their processing rules and functions are somewhat different (not a bit to vomit ).

Object.hclass Object {public:    object () {#ifdef DF        s = malloc (+);        printf ("s addr%p\n", s); #endif        printf ("ctor%p\n", this);    }    ~object () {        printf ("Dtor%p\n", this); #ifdef DF        printf ("s addr%p\n", s);        Free (s); #endif    }    void *s;}; extern Object G_obj;

Our program test and dynamic library libdy.so will link OBJECT.O.

The first Test tests link libdy.so,test and libdy.so will have g_obj this symbol:

B G_obj indicates G_obj is located in BSS segment, uninitialized segment $ NM test | grep g_obj0000000000400a14 t _global__i_g_obj00000000006012c8 B g_obj$ nm libdy.so | grep g_obj000000000000097c T _global__i_g_obj0000000000200f30 B g_obj

Perform:

$./testctor 0x6012c8ctor 0x6012c8...dtor 0x6012c8dtor 0x6012c8

g_obj was constructed two times, but with the same address . Global variables have only one instance, which seems to be understandable.

Dynamically loading libdy.so, the variable address is the same:

$./testctor 0x6012a8...ctor 0x6012a8...dtor 0x6012a8dtor 0x6012a8

conclusion , unlike functions, global variable symbols are repeated. Regardless of whether the dynamic library is dynamically loaded or directly linked, the variable always has only one.

But the weird case is that the object was constructed and refactored two times. Construction two times do not matter, waste space, but the destruction of two times there is a problem. Because the same object is manipulated at the time of the destruction. So assuming that the object has allocated memory internally, it will cause double free for this memory because the pointer is the same. To open DF the macro experiment:

$./tests addr 0x20de010ctor 0x6012b8s addr 0x20de040ctor 0x6012b8...dtor 0x6012b8s addr 0x20de040dtor 0x6012b8s addr 0x20 de040

Since both of the destructors are the same object, the memory that its members point to has s been freed two times. The result is a double free, which makes the program coredump.

Summary . The global variable symbol is repeated. Always use only one, and will be initialized/released two times, is a more critical situation, you should avoid the use of dynamic libraries in the process of using global variables.

Finish

Original address: http://codemacro.com/2014/11/04/linux-dynamic-library/
Written by Kevin Lynx posted athttp://codemacro.com

Various Essentials of Linux dynamic Library

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.