I have a static library, say mystaticlib.a. I want to see its contents, such as the number of object files inside it.
How can I do this on gcc?
On gcc, use ar -t.
-t option of the gnu archiver (ar) writes a table of contents of archive to the standard output. Only the files specified by the file operands shall be included in the written list. If no file operands are specified, all files in archive shall be included in the order of the archive.
More info here.
You can see the contents (the .o files that went into it) and the defined symbols by using nm. If this contains C++ code you should use the -C option to demangle the symbol names:
nm -C libschnoeck.a | less
On a Mac, simply use
nm libschnoeck.a | less
There is no -C option with the Mac version of nm.
It just stumbled over this:
You can open an archive (.a) with 7zip.
Also works for the object files in the archive.
Listing all sorts of contents like .text, .bss, .data, etc. with their offset, length, type, ...
Furthermore its possible to unpack all, using a hex editor or notepad++ to view the contents.
I tested this with an archive created with GNUToolsARMEmbedded\2018-q4-major\bin\arm-none-eabi- Toolchain
and 7Zip 16.04 (64-bit)
I just discovered that you can use readelf -a to display the contents of all the object files in a static library.
Invoke the readelf command like this: $ readelf -a mystaticlib.a.
Related
I'm using Mingw64 for Windows(of course), and I usually statically link against libwinpthread.a. But I have noticed that there is also a library called libpthread.a (without the win). I can see that they have different sizes, so something must be different. If I create a very simple program with thread library included, I can see that the compiled code also is in different sizes, when I use the tag -libpthread instead of -libwinpthread.
I know that winpthread is using a BSD-license. And in Linux pthread is using the LGPL-license. So can it be something about the license? Maybe libpthread is using LGPL and libwinpthread is using BSD? I don't know.
I hope someone here can help me. Something must be different, because I get different result.
This is embarrassing, but I finally find the difference between libpthread.a and libwinpthread.a.
They are 99.9%(you could say 100%) identically.
The only difference is that libwinpthread.a is more compressed.
I tried to compile the winpthread-code with make-command.
And then I install it with "make install" command.
But if I instead install it with "make install-strip" it will install an a-file without symbols table.
With the exact same result as the already installed a-files.
So use the tag -lwinpthread if you want to use winpthread(static linking) with no symbols table.
If you do want to have the symbols table for winpthread, use the tag -lpthread.
A static library(a-file) is just an archive format(like tar) with o-files inside.
To view an a-file you will need for Windows either mingw-w64, cygwin or msys2 or similar.
So view an a-file by writing in a terminal: ar -t -file.a
If you want to extract the a-file you can write: ar -x file.a
Now you will have several o-files.
You can view the content inside an o-file by writing: nm -C file.o
If you want to diassembler an o-file you can just write: objdump -D file.o
Or write the data to a file: objdump -D file.o > obj_arm.txt
Do that with one o-file from libpthread and one o-file from libwinpthread.
And then compare the txt-files with your favorite software.
They will be 100% identically.
Say that I have three libraries: libMissingSymbol.so, libMiddle.so, and libSymbolHaver.so. libMissingSymbol contains a symbol defined in libSymbolHaver, but only has a dependency on libMiddle. libMiddle is supposed to have a dependency on libSymbolHaver, but it doesn't. I don't have the source code or unlinked object files that these libraries were assembled from. Is it possible for me to link libMiddle with libSymbolHaver so that libMissingSymbol can find the symbol it needs at load time? Is there any way that I can fix this using only these three shared object files and any necessary tools? I have to end up with libraries with the same contents (including SONAMEs) barring the dependency change to libMiddle in order to not break things further down the line in my project.
Hypothetical readelf output (trimmed for relevance) to clarify:
$ readelf -s libMissingSymbol.so
123: 00000000 0 OBJECT GLOBAL DEFAULT UND MangledSymbol
$ readelf -d libMissingSymbol.so
Dynamic section at offset 0x42434 contains 37 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libMiddle.so]
0x0000000e (SONAME) Library soname: [libMissingSymbol.so]
$ readelf -d libMiddle.so
Dynamic section at offset 0x75b28 contains 29 entries:
Tag Type Name/Value
0x0000000e (SONAME) Library soname: [libMiddle.so]
$ readelf -s libSymbolHaver.so
35: 00064d0c 4 OBJECT GLOBAL DEFAULT 22 MangledSymbol
Is it possible for me to link libMiddle with libSymbolHaver so that libMissingSymbol can find the symbol it needs at load time?
No: all UNIX linkers, except the AIX one, consider .so the final link product and no further modification is possible.
Update:
viability of doing this a different way (e.g. decompiling libMiddle and rebuilding it with the correct dependencies)?
I don't believe that is viable either -- it is really hard to modify a fully-linked ELF file and not violate myriad of internal consistency constraints.
I suggest the following approach, which is very likely to just work(TM).
Abandon your "only using these three libraries" restriction. It appears to be artificial and unnecessary.
Copy libMiddle.so -> libZiddle.so (be sure to make a copy of the original libMiddle.so somewhere else in case things go wrong).
binary-patch the SONAME in libZiddle.so to match the new name. The string "libMiddle.so" is in the .dynstr section of the library, and (I believe) is not hashed in any way, so changing one letter in it will not introduce any self-inconsistencies into the new library.
Once you've done this, compare readelf -a libMiddle.so and readelf -a libZiddle.so, the SONAME should be the only difference.
Remove libMiddle.so.
Link a new libMiddle.so containing some_unused_function(), and having dynamic dependency on both libZiddle.so and libSymbolHaver.so.
Now any binary that currently links against libMiddle.so and fails with missing symbol (e.g. libMissingSymbol.so) will find the new (empty) libMiddle.so, but because the new libMiddle.so requires both libZiddle.so (where most of the symbols are) and libSymbolHaver.so, it should just work.
I have two source files (in C) which have globals with the same name. The globals are static. If I use nm to dump the symbols from the object files, I can see that debug info is included:
hostname:ble_app_hrs username$ find Debug -name '*.o' -exec /usr/local/gcc-arm-none-eabi-4_8-2014q2/bin/arm-none-eabi-nm -o -l {} \; | grep m_user_array_size
Debug/components/libraries/gpiote/app_gpiote.o:00000000 b m_user_array_size GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/gpiote/app_gpiote.c:36
Debug/components/libraries/timer/app_timer.o:00000000 b m_user_array_size GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/timer/app_timer.c:131
However, if I dump the symbols from the ELF file after linking is finished, it appears that the debug info got stripped out for these duplicate symbols. Is this normal behavior--i.e. is what's described here happening automatically?
hostname:ble_app_hrs username$ /usr/local/gcc-arm-none-eabi-4_8-2014q2/bin/arm-none-eabi-nm -o -l Debug/ble_app_hrs.elf | grep user
Debug/ble_app_hrs.elf:0001cb50 T app_gpiote_user_enable GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/gpiote/app_gpiote.c:224
Debug/ble_app_hrs.elf:0001ca88 T app_gpiote_user_register GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/gpiote/app_gpiote.c:190
Debug/ble_app_hrs.elf:200020a4 B m_enabled_users_mask.6444
Debug/ble_app_hrs.elf:200020c0 B m_gpiote_user_id.6603
Debug/ble_app_hrs.elf:20002080 B m_user_array_size.5782
Debug/ble_app_hrs.elf:200020a8 B m_user_array_size.6446
Debug/ble_app_hrs.elf:200020a9 B m_user_count.6445
Debug/ble_app_hrs.elf:20002084 B mp_users.5783
Debug/ble_app_hrs.elf:200020ac B mp_users.6443
Debug/ble_app_hrs.elf:0001d688 t user_id_get.5752.4484 GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/timer/app_timer.c:1056
Debug/ble_app_hrs.elf:0001d2cc t user_op_alloc.5716.4521 GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/timer/app_timer.c:794
Debug/ble_app_hrs.elf:0001d2b4 t user_op_enque.5691.4546 GNU_ARM_Eclipse/nRF51_SDK_7/components/libraries/timer/app_timer.c:781
Notice that not all debug info is stripped--it's still there for symbols like app_gpiote_user_enable. If I try to print one of the duplicates, like m_user_array_size, gdb tells me, No symbol "m_user_array_size" in current context. However, if I print app_gpiote_user_enable, gdb is happy with that.
How should I print duplicate symbols in gdb? Do I have to use addresses instead of symbols?
What are the .5782, etc. numbers on the end of the duplicate symbols? Will that help me map symbols back to object files?
Note: I rather not just rename the variables--they're both defined in a 3rd party library.
Duplicate symbols are printed like this: p 'f2.c'::x. It is explained in this section of GDB manual.
Printing by using address can be done like this (assuming 0x60103c is the address of integer variable):
print *(int*)0x60103c
I have seen numbers at the end of symbols only when -flto flag was used to build executable. This (for default Ubuntu 14.04 toolchain) also breaks gdb's ability to print symbols from other files (it prints the wrong one). Kind of workaround for this would be to build without -flto when debugging.
I have got a abc.so lib from somewhere, while using gcc4.4.3 I got error that this abc.so is incompatible type. Any idea how to find the version of this lib.
Under Unix :
List the strings from the binary, and simply grep the GCC version :
strings -a <binary>| grep "GCC:"
This will give you the GCC version used to build the binary. But I'm not really sure it's what you want to know.
You can also get more informations about the binary by using readelf -h <binary>
How do I determine whether a function exists within a library, or list out the functions in a compiled library?
You can use the nm command to list the symbols in static libraries.
nm -g -C <libMylib.a>
For ELF binaries, you can use readelf:
readelf -sW a.out | awk '$4 == "FUNC"' | c++filt
-s: list symbols
-W: don't cut too long names
The awk command will then filter out all functions, and c++filt will unmangle them. That means it will convert them from an internal naming scheme so they are displayed in human readable form. It outputs names similar to this (taken from boost.filesystem lib):
285: 0000bef0 91 FUNC WEAK DEFAULT 11 boost::exception::~exception()
Without c++filt, the name is displayed as _ZN5boost9exceptionD0Ev
For Microsoft tools, "link /dump /symbols <filename>" will give you the gory details. There are probably other ways (or options) to give an easier to read listing.
Under Linux/Unix you can use objdump -T to list the exported symbols contained in a given object. Under Windows there's dumpbin (IIRC dumpbin /exports). Note that C++ function names are mangled in order to allow overloads.
EDIT: after seeing codelogic's anwser I remembered that objdump also understands -C to perform de-mangling.
use this command:
objdump -t "your-library"
It will print more than you want - not just function names, but the entire symbol table. Check the various attributes of the symbols you get, and you will be able to sort out the functions from variables and stuff.