Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are external symbols resolved?

I have two files 37064544_p1.cpp & 37064544_p2.cpp with the same content as shown below :

int add(int x,int y)
{
return x+y;
}

I compiled them using

g++ -c 37064544_p2.cpp -o 37064544_p2.o
g++ -c 37064544_p2.cpp -o 37064544_p2.o

and added them to an archive using

ar -rsc lib37064544pf.a 37064544_p1.o 37064544_p2.o

And

$ nm -s lib37064544pf.a 

gives me :

Archive index:
_Z3addii in 37064544_p1.o
_Z3addii in 37064544_p2.o

37064544_p1.o:
0000000000000000 T _Z3addii

37064544_p2.o:
0000000000000000 T _Z3addii

and

$ ar -t lib37064544pf.a 

gives me

37064544_p1.o
37064544_p2.o

I have a driver which calls the _Z3addii function which is compiled with

g++ -static 37064544driver.cpp -o 37064544driver.elf -L. -l37064544pf

Result is

Sum : 11

Questions

  1. How is the symbol _Z3addii resolved ?

    • Is it according to archive index?
    • Is it according to the order in which we populate the archive using ar?
  2. How can I change this order?

  3. How can I prevent ar from having duplicate symbols?

Compiler : g++ 4.6.3

like image 831
sjsam Avatar asked May 06 '16 06:05

sjsam


Video Answer


1 Answers

How is the symbol _Z3addii resolved ?

The implementation is free to do whatever it likes, you are violating the one definition rule.

Realistically it'll stop looking for any given symbol after the first match, which presumably follows the order the files were inserted to the archive.

How can I change this order?

With ar you can use the a (after) and b (before) modifiers to position object files in the archive when inserting them, you're still violating the ODR though.

How can I prevent ar from having duplicate symbols?

You can't as far as I know, ar is relatively dumb and for good reason as some languages do allow for identical symbols, which is why you don't have any errors when linking with the archive (no diagnostic is required for ODR violations).

You can either force ld to read the entire archive

g++ -static 37064544driver.cpp -o 37064544driver.elf -L. \
-Wl,--whole-archive -l37064544pf -Wl,--no-whole-archive

Or you can do a partial link instead of a traditional archive which will give you an error if there are any duplicates

ld -r -o lib37064544pf.a 37064544_p1.o 37064544_p2.o
like image 192
user657267 Avatar answered Oct 12 '22 23:10

user657267