Is there a way to know which compiler generated a static library?
Asked Answered
T

4

11

A third party provided me a static lib (.a) to link with on solaris station. I tried to compile with sunpro, and failed at link step.

I suppose the issue is coming from the compiler I use (gcc instead?) or simply its version (as the std lib provided by the compiler could change from the version expected by the library AFAIK it could leads to errors at link step).

How could I know which compiler was used to generate this lib? Is there some tools doing that? Some option in sunpro/gcc or whatever?

As an hint: I've read some time ago that compilers use different mangling conventions when generating object files (true?). Still, "nm --demangle" command line prints me well all function names from debug symbols in this static lib. How does it work ? If my assumption is ok, nm does have a way to resolve which convention is in use in a static library, isn't it? Or is it simply meaning that lib was generated by GNU gcc, as nm is a part of GNU binutils?

I am not close to my workstation so I can't copy & paste error output from the linker (not for the moment but I could copy them in a further edit)

Tippler answered 7/4, 2009 at 22:12 Comment(2)
Why don't you ask the "third party" who supplied the library for instructions on how to use it?Damiendamietta
I asked them. But no answer from their support team, which is reluctant to ask the dev team, it seems... :/Tippler
F
5

I tend to use the strings program (with the '-a' option, or my own variant where the '-a' behaviour is standard) and look for the tell-tale signs. For example, in one of my own libraries, I find:

/work1/gcc/v4.2.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.2.3/include
/work1/gcc/v4.3.0/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.0/include
/work1/gcc/v4.3.1/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.1/include
/work1/gcc/v4.3.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.3/include

That suggests that the code in the library has been compiled with a variety of versions of GCC over a period of years (actually, I'm quite startled to find so many versions in a single library).

Another library contains:

cg: Sun Compiler Common 11 Patch 120760-06 2006/05/26
acomp: Sun C 5.8 Patch 121015-02 2006/03/29
iropt: Sun Compiler Common 11 Patch 120760-06 2006/05/26
/compilers/v11/SUNWspro/prod/bin/cc -O -v -Xa -xarch=v9 ...

So, there are usually fingerprints in the object files indicating which compiler was used. But you have to know how to look for them.

Foliose answered 8/4, 2009 at 4:31 Comment(8)
I am trying to find ways to extract the compiler version from clang compiled mac object files and static libraries. I was able to extract the compiler version from 4 out of 40 object files in the library by string dumping using strings command and grepping for "clang" which displayed "Apple LLVM version 9.0.0 (clang-900.0.39.2)" but other files did not have this string. On using mach-o-view tool to look inside the sections, the object file from which the compiler version was extracted had a Section64(__DWARF,__debug_str) which had the string "Apple LLVM version 9.0.0 (clang-900.0.39.2)"Abbess
Did you use strings -a or just strings? The -a is important, usually. I tend to use a home-built GCC (currently 9.2.0) on my MacBook Pros — one runs macOS Mojave 10.14.6 (work; grumble!) and the other macOS Catalina 10.15.3. I just recompiled a small library (9 source files) with clang 11.0.0 (Xcode 11.3.1), and the system strings reported 9 occurrences of Apple (/usr/bin/strings libdiag.a | grep -i apple | sort | uniq -c yielded 9 Apple clang version 11.0.0 (clang-1100.0.33.17). I'm not sure if that helps you.Foliose
Thanks for your comment, Jonathan. I tried using strings and strings -a. Both did not find it. I am able to reproduce the same in few files. But in few object files, the string is missing. Do you know of any compiler flags or somethings that will strip this out?Abbess
I'm not aware of an option to strip this metadata out of object files — I never bother. The otool command can list all sorts of information — that seems to be llvm-otool according to man otool, and is a cover for llvm-objdump. Classically, the strip command removes unnecessary material from object files – it has many options on macOS. I'm not sure what other commands might be of relevance.Foliose
Jonathan, here I have posted a simple hello world cpp which I converted to object file using clang++ -c. But, strings -a does not display the "clang-<version>". Why? #59677412Abbess
<iostream.h>? That's so nearly prehistoric it is … unexpected. Maybe it won't embed a version because it is ashamed to admit it compiled the code with that header.Foliose
Let us continue this discussion in chat.Abbess
When I change <iostream.h> to <iostream> and produce an object file, I can find /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/ and Apple clang version 11.0.0 (clang-1100.0.33.17) in the output with just /usr/bin/strings (no -a option). That may not clearly indicate C++, but the other symbols surely do.Foliose
P
6

Extract the object files from the archive then run the strings command on some of them (first on the smaller ones since there'd be less noise to sift through). Many compilers insert ASCII signatures in the object files.

For example, the following meaningless source file, foo.c:

extern void blah();

when compiled on my Fedora 10 machine into foo.o via gcc -c -o foo.o foo.c results in a 647 byte foo.o object file. Running strings on foo.o results in

GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)
.symtab
.strtab
.shstrtab
.text
.data
.bss
.comment
.note.GNU-stack
foo.c

which makes it clear the compiler was GCC. Even if I'd compiled it with -fno-ident, the .GNU-stack note ELF section would have still been present.

You can extract the object files using the ar utility, or using Midnight Commander (which integrates ar), or you can simply run strings on the archive (which might give you more noise and be less relevant, but would still help.)

Pasty answered 7/4, 2009 at 23:51 Comment(2)
Or just run 'strings' directly on the library - no need to extract the object files first.Foliose
Like I mentioned, there's a lot more output, especially in the case of C++ object files, and it's much easier to miss compiler signatures. Also, there is no requirement that all objects in an archive be from the same compiler...Halley
F
5

I tend to use the strings program (with the '-a' option, or my own variant where the '-a' behaviour is standard) and look for the tell-tale signs. For example, in one of my own libraries, I find:

/work1/gcc/v4.2.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.2.3/include
/work1/gcc/v4.3.0/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.0/include
/work1/gcc/v4.3.1/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.1/include
/work1/gcc/v4.3.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.3/include

That suggests that the code in the library has been compiled with a variety of versions of GCC over a period of years (actually, I'm quite startled to find so many versions in a single library).

Another library contains:

cg: Sun Compiler Common 11 Patch 120760-06 2006/05/26
acomp: Sun C 5.8 Patch 121015-02 2006/03/29
iropt: Sun Compiler Common 11 Patch 120760-06 2006/05/26
/compilers/v11/SUNWspro/prod/bin/cc -O -v -Xa -xarch=v9 ...

So, there are usually fingerprints in the object files indicating which compiler was used. But you have to know how to look for them.

Foliose answered 8/4, 2009 at 4:31 Comment(8)
I am trying to find ways to extract the compiler version from clang compiled mac object files and static libraries. I was able to extract the compiler version from 4 out of 40 object files in the library by string dumping using strings command and grepping for "clang" which displayed "Apple LLVM version 9.0.0 (clang-900.0.39.2)" but other files did not have this string. On using mach-o-view tool to look inside the sections, the object file from which the compiler version was extracted had a Section64(__DWARF,__debug_str) which had the string "Apple LLVM version 9.0.0 (clang-900.0.39.2)"Abbess
Did you use strings -a or just strings? The -a is important, usually. I tend to use a home-built GCC (currently 9.2.0) on my MacBook Pros — one runs macOS Mojave 10.14.6 (work; grumble!) and the other macOS Catalina 10.15.3. I just recompiled a small library (9 source files) with clang 11.0.0 (Xcode 11.3.1), and the system strings reported 9 occurrences of Apple (/usr/bin/strings libdiag.a | grep -i apple | sort | uniq -c yielded 9 Apple clang version 11.0.0 (clang-1100.0.33.17). I'm not sure if that helps you.Foliose
Thanks for your comment, Jonathan. I tried using strings and strings -a. Both did not find it. I am able to reproduce the same in few files. But in few object files, the string is missing. Do you know of any compiler flags or somethings that will strip this out?Abbess
I'm not aware of an option to strip this metadata out of object files — I never bother. The otool command can list all sorts of information — that seems to be llvm-otool according to man otool, and is a cover for llvm-objdump. Classically, the strip command removes unnecessary material from object files – it has many options on macOS. I'm not sure what other commands might be of relevance.Foliose
Jonathan, here I have posted a simple hello world cpp which I converted to object file using clang++ -c. But, strings -a does not display the "clang-<version>". Why? #59677412Abbess
<iostream.h>? That's so nearly prehistoric it is … unexpected. Maybe it won't embed a version because it is ashamed to admit it compiled the code with that header.Foliose
Let us continue this discussion in chat.Abbess
When I change <iostream.h> to <iostream> and produce an object file, I can find /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/ and Apple clang version 11.0.0 (clang-1100.0.33.17) in the output with just /usr/bin/strings (no -a option). That may not clearly indicate C++, but the other symbols surely do.Foliose
C
2

Is the library supposed to be a C or C++ library?

If it is a C library then name mangling can not be the problem, as there is none in C. It could be however in a wrong format. Unices used to have libraries in the a.out format but almost all newer versions switched to more powerful formats like ELF.

If it is a C++ library then name mangling can be an issue. Most compilers embed some symbols that are compiler specific into the code, so if you have a tool like nm to list the symbols you can hopefully deduce from what compiler it came.

For example g++ creates a symbol

__gxx_personality_v0

in it's libraries

Chun answered 7/4, 2009 at 23:27 Comment(0)
B
-1

You can try the unix utility file:

file foo.a
Breed answered 7/4, 2009 at 22:22 Comment(2)
I tried but I remember it only tells me that this file uses the ELF format for SPARC platform. Does sunpro generates ELF format, as GCC does?Tippler
The file tool will hardly return info about the compiler used!Nystagmus

© 2022 - 2024 — McMap. All rights reserved.