How can I tell if a library was compiled with -g? - c

I have some compiled libraries on x86 Linux and I want to quickly determine whether they were compiled with debugging symbols.

If you're running on Linux, use objdump --debugging. There should be an entry for each object file in the library. For object files without debugging symbols, you'll see something like:
objdump --debugging libvoidincr.a
In archive libvoidincr.a:
voidincr.o: file format elf64-x86-64
If there are debugging symbols, the output will be much more verbose.

The suggested command
objdump --debugging libinspected.a
objdump --debugging libinspected.so
gives me always the same result at least on Ubuntu/Linaro 4.5.2:
libinspected.a: file format elf64-x86-64
libinspected.so: file format elf64-x86-64
no matter whether the archive/shared library was built with or without -g option
What really helped me to determine whether -g was used is readelf tool:
readelf --debug-dump=decodedline libinspected.so
or
readelf --debug-dump=line libinspected.so
This will print out set of lines consisting of source filename, line number and address if such debug info is included into library, otherwise it'll print nothing.
You may pass whatever value you'll find necessary for --debug-dump option instead of decodedline.

What helped is:
gdb mylib.so
It prints when debug symbols are not found:
Reading symbols from mylib.so...(no debugging symbols found)...done.
Or when found:
Reading symbols from mylib.so...done.
None of earlier answers were giving meaningful results for me: libs without debug symbols were giving lots of output, etc.

nm -a <lib> will print all symbols from library, including debug ones.
So you can compare the outputs of nm <lib> and nm -a <lib> - if they differ, your lib contains some debug symbols.

On OSX you can use dsymutil -s and dwarfdump.
Using dsymutil -s <lib_file> | more you will see source file paths in files that have debug symbols, but only the function names otherwise.

You can use objdump for this.
EDIT: From the man-page:
-W
--dwarf
Displays the contents of the DWARF debug sections in the file, if
any are present.

Answers suggesting the use of objdump --debugging or readelf --debug-dump=... don't work in the case that debug information is stored in a file separate from the binary, i.e. the binary contains a debug link section. Perhaps one could call that a bug in readelf.
The following code should handle this correctly:
# Test whether debug information is available for a given binary
has_debug_info() {
readelf -S "$1" | grep -q " \(.debug_info\)\|\(.gnu_debuglink\) "
}
See Separate Debug Files in the GDB manual for more information.

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/developer_guide/debugging
The command readelf -wi file is a good verification of debuginfo, compiled within your program.

Related

How to see the instructions inside of compiled language executable files?

When i compile a C/C++ source file the compiler generates another executable file. How to see the instructions of that file? What is the process known as?
gcc hello.c -o hello
./hello
Here, the first after executing the first line a file name 'hello' gets generated. I need to see the instructions of this 'hello' file.
The executable a.out file is in binary format.
You can open that in any text editor(Ex: vi, vim etc) or hex editor but you won't be able to understand the contents.
You can use some commands to get more information about what is contained in the executable file.
Some example commands are: nm, strings, objdump
Example:
$ nm a.out
$ strings a.out
$ objdump -xD --demangle a.out
Read their manual to know more about them

How to dump path to source from object-file

Assume I have a C object-file app.o compiled with gcc. How can I dump the file path to the original app.c from which app.o was compiled. My goal is to create a listing of all symbols + respective source file path using the binutils and gcc toolsuite.
By no means am I expecting an all-in-one solution. So I tried playing with multiple tools to gather the information I need.
Inspecting the object-file with a text-editor reveals that (appart from a lot of unreadable binary gibberish) the file does contain a reference to app.c as a string embedded into the object-file format. However I did not find a way to extract that string using objdump or nm.
I was hoping objdump would have some flag that could extract this source file string, but after trying virtually all options documented in the man page I still couldn't find it.
With the path of the source file I was hoping I could run gcc -M <path-to-source>. This would allow me to look through all the headers included by app.c and find the in-source declarations.
Suppose a simple app.c like this:
void foo(void) {
}
Compile it via gcc -c app.c -o app.o.
Running objdump -t app.o dumps the symbol table, but does not refer anywhere to the original app.c.
Running cat app.o does show that the object-file contains the file path to app.c (relative to pwd at compile-time). But I wasn't exactly planning on writing my own object-file parser just to get to that string.
To answer my own question minutes after posting it (duh!):
readelf -s app.o prints a symbol table including the name of the source file (app.c). With that I am able to run gcc -M app.c and then parse through all header files to gather the symbol declarations.

How do I emulate objdump --dwarf=decodedline in .bundle files?

I've been successfully using objdump --dwarf=decodedline to find the source location of each offset in a .so file on Linux.
Unfortunately on Mac-OS X. It seems that .bundle files (used as shared libraries) are not queriable in this manner.
I'm optimistic that there's something I can do, because gdb is able to correctly debug and step through code in these bundles — does anyone know what it's doing?
Further information:
The dwarfdump utility claims that the .bundle file contains no DWARF data, but that it does contain STABS data; however objdump --stabs cannot find any stabs data either.
(If it makes the question easier to answer, I don't actually need all of the offsets; being able to query the source location of any given offset would be good enough).
The bundle file I've been testing this on was generated using:
cc -dynamic -bundle -undefined suppress -flat_namespace -g -o c_location.bundle c_location.o -L. -L/Users/User/.rvm/rubies/ruby-1.8.7-p357/lib -L. -lruby -ldl -lobjc
The original c_location.o file does contain the necessary information for objdump --dwarf=decodedline to work.
So it turns out that one way to do this is to use Apple's nm -pa *.bundle to find the symbol name and the original object file for a given offset.
Once you have that, you can first use objdump -tT to find the offset of the symbol name in the original object file; and then use objdump --dwarf=decodedline as before.
Each step requires a little bit of simplistic output parsing, but it does seem to work™. I'd be interested if there are more robust approaches.

Why works addr2line only for functions

I've got addr2line working for function addresses:
$ nm -S executable | grep main
08048742 000000a0 T main
$ addr2line -e executable 08048742
/home/blablabla/src/main.c:80
Unfortunately it only works if I supply an address of a function, when passing an address of a data symbol (e.g. the address of a crc table) it can never resolve the file/line number:
$ nm -S executable | grep tableCRC
080491bc 00000200 r tableCRC
$ addr2line -e executable 080491bc
??:0
I guess that that kind of debug information just isn't included for data because this feature is probably intended for analyzing backtraces, but maybe there's a compiler/linker option to force this?
I want to use the output of addr2line to generate detailed information about how much memory size a file or module uses (instead of the global number reported by the 'size' tool).
The --print-size and --line-numbers options to nm are probably what you are looking for.
Please note that the ELF object needs to contain debugging information for the --line-numbers option to work.

How does objdump manage to display source code with the -S option?

Is there a reference to the source file in the binary? I tried running strings on the binary and couldn't find any reference to the source file listed...
objdump uses the DWARF debugging information compiled into the binary, which references the source file name. objdump tries to open the named source file to load the source and display it in the output. If the binary isn't compiled with debugging information, or objdump can't find the source file, then you don't get source code in your output - only assembly.
You don't see the source file name when you use strings on the binary, because DWARF uses compression.
The dwarf information in a binary stores the mapping between instructions(the instruction pointer or IP actually) and the source file and line number. The source file is specified using the complete path so it can be found even if the binary is moved around. To see this information you can use objdump --dwarf=decodedline <binary> (the binary ofcourse has to be compiled with -g).
Once you say objdump -S <binary> it use this dwarf info to give you source code along with the disassembly.
My understanding is that for objdump to display source code from the binary code, there is a precondition: the DWARF debugging information must be compiled into the binary. (by gcc -g sourcefile or gcc -gdwarf-2 sourcefile)
And by processing this DWARF information objdump is able to get the source code as #vlcekmi3 and #vkrnt answered

Resources