当前位置:网站首页>Resolve symbol conflicts for dynamic libraries

Resolve symbol conflicts for dynamic libraries

2022-06-24 13:19:00 Tiancun information

Icon

once debug The doubts I met

One day I found something wrong with a program . Sacrifice print Dafa , In the key lib_func() Add... To the function print Debugging information , Recompile run .

expect print There's no information out there , But the program was actually executed again libfunc() , Because in addition to the added debugging print No implementation ,libfunc() All the functions are performed . It's strange .

Programs don't cheat . Executive libfunc() It's definitely not the one we revised libfunc() , There must be an original somewhere else lib_func() Carried out . An investigation , Right enough . For the sake of illustration , Simplify the procedures and phenomena as follows :

The program contains the following code file ——

main.c #  The main program 
plugin.c #  Plugins 
lib.c lib.h #  A library 

Makefile as follows :

all:main plugin
main:
    cc -o main main.c lib.c -ldl -rdynamic
plugin:
    cc -shared -fPIC -o plugin.so plugin.c lib.c

After compiling , Generate executable main, And dynamic library files plugin.so. When the main program is running , The plug-in will be loaded dynamically plugin.so ( Called lib.c The procedure in ) And implement .

The suspected problem lies in lib.c in . The modified lib.c The contents are as follows , Added debug word .

void lib_func() {   
// fprintf(stderr, "%s()\n", __func__);
    fprintf(stderr, "debug:%s()\n", __func__);
}

Because the main program is OK , Just recompile plugin.so , Rerun .

Expect to get print The result is debug:libfunc() , The actual result is libfunc().

look , There are two in one program lib_func() Code . from Makefile It can be seen that , One in main In the program , One in plugin.so in . What actually works is main The one in the bag .

It suddenly became interesting : If a program contains multiple identical functions , Which one is actually executed ?

TIPS: Easy to use linux The order of nm < Program files > Look at the functions in the program

Dynamic libraries and symbol tables

Although the procedures are different , But there are always some features that are common . It's not cost-effective for every program to write code for them , So it became a library , Sharing between multiple programs . One library can also use other libraries . There are two ways to share : Static , Dynamic .

At compile time , Copy the library code and merge it into the executable file , Is a static library .

At run time , Load a copy of the library code into memory , It's a dynamic library .

Dynamic libraries save more resources , It doesn't have to be copied many times , It's easy to update .

Responsible for linking things , be called The linker (linker), The one responsible for loading is called loader (loader).

However, the computer does it according to the address , Every instruction must be addressed before it is executed . Before the dynamic library loads , No one knows where it will be loaded , I don't know the address of the instruction in the dynamic library , Only by symbols ( name ) To record the list of functions it provides to others ( Export table ), And the list of functions it expects others to provide him with ( The import table ). After the library is loaded , You get the address . Before the program runs , You need to parse the symbol table first , Determine the actual address of each symbol .

Our first example , Two with the same name libfunc() , In a main In the program , In a plugin.so in ,main Load first ,plugin.so The use of libfunc() It's resolved to main Of libfunc() . Executed the old libfunc() , Instead of the one we modified with debug edition .

TIPS: Students who are interested in program linking and loading can have a look at Linkers and Loaders This book , Very detailed .

Compiler options and environment variable options related to symbols

If conditions permit , Try not to have two copies of code in the same program , In the case of the same symbol , Cause conflict .

If there is a symbol conflict, it must be solved : In this case , hypothesis main immutable , Already included lib Code for .plugin.so It can be done by gcc Of -Wl,-Bsymbolic Option tells the loader to use its own symbol first , Instead of giving priority to global symbols . This option resolves symbol conflicts .

TIPS: If you want to see how the loader works , You can use environment variables LD_DEBUG=all ./main To execute the program , You'll get the detailed parsing process .manpage Of ld.so(8) There are more details .

Finally, the code for the example is attached :

*  sample cat lib.h
#ifndef UNTITLED_LIB_H
#define UNTITLED_LIB_H

void lib_func();

#endif //UNTITLED_LIB_H
*  sample cat lib.c
#include <stdio.h>
#include "lib.h"

void lib_func() {
    //fprintf(stderr, "%s()\n", __func__); 
    fprintf(stderr, "debug:%s()\n", __func__);
}
*  sample cat main.c  
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include "lib.h"

int main() {
    void *handle = dlopen("./plugin.so", RTLD_NOW);
    void (*plugin_func)() = (void (*)()) dlsym(handle, "plugin");
    plugin_func();
    return 0;
}
*  sample cat plugin.c 
#include "lib.h"

void plugin() {
    lib_func();
}
*  sample cat Makefile 
all:main plugin

main:
    cc -o main main.c lib.c -ldl -rdynamic
plugin:plugin.c lib.c
    #cc -shared -fPIC -o plugin.so plugin.c lib.c -Wl,-Bsymbolic
    cc -shared -fPIC -o plugin.so plugin.c lib.c

clean:
    rm -f main plugin.so
*  sample 

( Chen Guo | Tiancun information )

原网站

版权声明
本文为[Tiancun information]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/05/20210525165026767v.html