Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to compile links

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the knowledge of "how to compile links". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

I don't know whether dynamic link libraries are often used in programming. If a program references countless dynamic link libraries, it is possible to introduce the problem of symbol conflict. The questions are as follows:

In the imagination

Actually

Let's try to solve it:

At the beginning, the following basic command parameters are introduced:

Gmail +-c compiles the source file, but does not link-o specifies the name of the output file-s strip, removes symbol information-L instruction searches the path of the link library-l specifies the link library to be linked-shared produces a dynamic target file

Let's take a look at a piece of code:

# include void DoThing () {printf ("work\ n");}

Then define a simple main.cc program:

# include void DoThing (); int main () {printf ("start\ n"); DoThing (); printf ("finished\ n"); return 0;}

Compile the two files and package them into static libraries:

Gmail +-c work.cc-o work.o ar rc libwork.a work.o main.o ar rc libmain.a main.o +-c main.cc-o main.o ar rc libmain.a main.o

Now link the two static libraries into an executable file, and note that if the linker finds that undefined symbols are used in the current library, it will only look backwards, so libraries with no other dependencies at the lowest level should be placed on the far right. If there is a symbol conflict problem, the linker will use the leftmost symbol.

If you link like this:

$gathers +-s-L. -o main.exe-lwork-lmain. / libmain.a (main.o): In function `main': main.cc: (.text + 0x11): undefined reference to `DoThing () 'collect2: error: ld returned 1 exit status

The link failed because the DoThing symbol in the main library is not defined. The linker looks backward and does not find the corresponding symbol definition. Here, change the order of the link library:

Gathers +-s-L. -o main.exe-lmain-lwork $. / main.exe start work finished

Link successful.

Now write a simple file conflict.cc that is prone to symbol conflicts:

# include void DoThing () {printf ("conflict\ n");}

Compiled and packaged into static libraries:

Gmail +-c conflict.cc-o conflict.o ar rc libconflict.a conflict.o

If you link into an executable program in this order:

$gathers +-s-L. -o main.exe-lmain-lwork-lconflict $. / main.exe start work finished

If you change the order of the links slightly:

$gathers +-s-L. -o main.exe-lmain-lconflict-lwork $. / main.exe start conflict finished

It is found that the difference in order leads to different program output, which is due to the potential symbol conflict.

Now try dynamic libraries again, first introducing how to use dynamic libraries:

$rm libconflict.a $gathers +-shared conflict.o-o libconflict.so $gems +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start conflict finished

Now refer to a middle tier's file layer.cc that calls conflict in the dynamic link library

# include void DoThing (); void DoLayer () {printf ("layer\ n"); DoThing ();}

And package layer and conflict into a dynamic link library:

$Gmail +-c layer.cc-o layer.o $Gmail +-shared layer.o conflict.o-o libconflict.so

Then update the main.c program. Call conflict in layer,layer in main:

# include void DoLayer (); int main () {printf ("start\ n"); DoLayer (); printf ("finished\ n"); return 0;}

Compile link execution:

$gathers +-c main.cc-o main.o $ar rc libmain.a main.o $gems +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start layer conflict finished

Normal output, no problem. Now plug the previous work.cc into the main.cc to observe the conflict:

# include void DoThing (); void DoLayer (); int main () {printf ("start\ n"); DoThing (); DoLayer (); printf ("finished\ n"); return 0;}

Package work.o and main.o into a library, then link with conflict into an executable program, and run:

$gathers +-c main.cc-o main.o $ar rc libmain.a main.o work.o $gems +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start work layer work finished

Here are two work output, normally the second work should output conflict, how to solve it? Consider using-fvisibility=hidden to hide the internal symbol, the symbol used inside the link library to hide it from being exported, and the external will not change its calling path.

First use nm to take a look at the symbols in libconflict.so:

$nm-CD libconflict.so w _ ITM_deregisterTMCloneTable w _ ITM_registerTMCloneTable 0000000000065a T DoLayer () 0000000000000672 T DoThing () 00000000201030 B _ bss_start w _ _ cxa_finalize w _ gmon_start__ 00000000201030 D _ edata 0000000000201038 B _ end 0000000000000688 T _ fini 0000000000000528 T _ init U puts

If you hide the symbol,

$gems +-fvisibility=hidden-c layer.cc-o layer.o $gems +-fvisibility=hidden-c conflict.cc-o conflict.o $gems +-shared layer.o conflict.o-o libconflict.so use nm again to look at the symbols in libconflict.so: $nm-CD libconflict.so w _ ITM_deregisterTMCloneTable w _ ITM_registerTMCloneTable 000000201028 B _ _ bss_start w _ cxa_finalize W _ _ gmon_start__ 0000000000201028 D _ edata 0000000000201030 B _ end 0000000000000618 T _ fini 00000000000004c0 T _ init U puts

In that case, the main function certainly cannot call DoLayer, because the DoLayer symbol is not exposed:

$gathers +-s-L. -o main.exe-lmain-lconflict. / libmain.a (main.o): In function `main': main.cc: (.text + 0x16): undefined reference to `DoLayer () 'collect2: error: ld returned 1 exit statu

So how do you expose specific symbols? look directly at the code and change the layer.cc:

# include void DoThing (); _ _ attribute__ ((visibility ("default") void DoLayer () {printf ("layer\ n"); DoThing ();}

Then compile the link and run it to see the result:

$Gmail +-fvisibility=hidden-c layer.cxx-o layer.o $Gmail +-shared layer.o conflict.o-o libconflict.so $Gmail +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start work layer conflict finished

Discovery is already the result we expect, and the problem of symbolic conflict is solved.

Does it feel troublesome? should every symbol to be exposed have to be modified by _ _ attribute__? you can actually write an export file here to tell the compiler what all the symbols are to be exported.

Export.txt {global: * DoLayer*; local: *;}; libconflict.so +-Wl,--version-script=export.txt-s-shared layer.o conflict.o-o libconflict.so

But this method can only be used in gcc. I tried to use it in clang but failed, so for compatibility, it is not recommended to use _ _ attribute__ to solve the problem of symbol conflict.

This is the end of how to compile links. Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report