10

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

jotik
  • 17,044
  • 13
  • 58
  • 123
sjsam
  • 21,411
  • 5
  • 55
  • 102
  • 1
    Hrmm, I just tried this on clang. If you compile with the two .o files directly you get a duplicate symbol error, but if you put the two .o files into a .a and compile against that, then there's no error. I always thought a .a was just a convenient way to have a bunch of .o files, but it seems it's different in some ways. – xaxxon May 06 '16 at 07:14
  • 1
    The 'r' flag to ar seems like it means that things added to the archive later will replace the earlier ones, though running it with q instead, i still can't get a duplicate symbol error. Does the linker stop looking at a single file when it comes across the first entry for a symbol it's looking for maybe? – xaxxon May 06 '16 at 07:21
  • @xaxxon : `If you compile with the two .o files directly you get a duplicate symbol error,` . Yes, but I am not always in favour of this for convenience sake – sjsam May 06 '16 at 07:24
  • 1
    Im' in agreement with you -- I'm very confused by this behavior. I wasn't suggesting you change this, I was just stating an observation I made that surprised me. – xaxxon May 06 '16 at 07:27
  • @xaxxon : I see :D. Also the `q` states `add the files member... to the end of archive, without checking for replacement.` I didn't quite get what this mean. :( – sjsam May 06 '16 at 07:31

1 Answers1

2

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
user657267
  • 20,568
  • 5
  • 58
  • 77
  • Thankyou. I agree the I'm violating the ODR. But this was on purpose as far as this example is concerned. The larger interest was however in detecting this when archiving the object code. Thanks for the point on partial linking. I would also consider adding the objects in to different libraries and link them in the order I want. – sjsam May 06 '16 at 07:41