How to use the addr2line command in Linux? - c

I am trying to use addr2line command in Unix but everytime it is giving the same output as ??:0. I am giving command as addr2line -e a.out 0x4005BDC . I got this address while running this a.out executable with valgrind tool to find the memory leakage. I also compiled the source code with -g option.

You can also use gdb instead of addr2line to examine memory address. Load executable file in gdb and print the name of a symbol which is stored at the address. 16 Examining the Symbol Table.
(gdb) info symbol 0x4005BDC

You need to specify an offset to addr2line, not a virtual address (VA). Presumably if you had address space randomization turned off, you could use a full VA, but in most modern OSes, address spaces are randomized for a new process.
Given the VA 0x4005BDC by valgrind, find the base address of your process or library in memory. Do this by examining the /proc/<PID>/maps file while your program is running. The line of interest is the text segment of your process, which is identifiable by the permissions r-xp and the name of your program or library.
Let's say that the base VA is 0x0x4005000. Then you would find the difference between the valgrind supplied VA and the base VA: 0xbdc. Then, supply that to add2line:
addr2line -e a.out -j .text 0xbdc
And see if that gets you your line number.

That's exactly how you use it. There is a possibility that the address you have does not correspond to something directly in your source code though.
For example:
$ cat t.c
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
$ gcc -g t.c
$ addr2line -e a.out 0x400534
/tmp/t.c:3
$ addr2line -e a.out 0x400550
??:0
0x400534 is the address of main in my case. 0x400408 is also a valid function address in a.out, but it's a piece of code generated/imported by GCC, that has no debug info. (In this case, __libc_csu_init. You can see the layout of your executable with readelf -a your_exe.)
Other times when addr2line will fail is if you're including a library that has no debug information.

Try adding the -f option to show the function names :
addr2line -f -e a.out 0x4005BDC

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

What is the difference between executable files?

I have the following C program:
#include<stdio.h>
int main()
{
printf("hhhh");
return 0;
}
Commands to compile, copy and compare:
$ gcc print.c -o a.out
$ objcopy a.out b.out
$ cmp a.out b.out
I have compiled this program and created an executable. Then, I have used the objcopy command to make a copy of the executable. But, when I compare these files, I get this:
files differ: byte 41, line 1
How can I know what contents are missing?
Any help or pointers would be appreciated. Thanks!
How can I know what contents are missing?
What made you believe that any contents is missing?
The way objcopy works is:
parse the contents of the input file into internal representation.
copy parts of the original file to the output file as instructed by options
Nowhere does objdump guarantee that when "copy entire file" is given, the result will be bit-identical.
In particular, non-loadable sections could be reordered or changed in other ways.
The difference is EntSize of .init_array section is 0 bytes in a.out file and it is 8 bytes in the b.out
The EntSize of 0 doesn't make sense for a non-empty section. If you really have such section in your a.out, it's likely that your linker has a bug.

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.

Which library the program is linked to that provides a given function?

I have a program invoking function foo that is defined in a library. How can I know where the library is in the file system? (like is it a static library or a dynamically linked lib?)
Update: with using ldd, the program has a lot of dependency library. How to tell which lib contains function foo?
You didn't say which OS you are on, and the answer is system-dependent.
On Linux and most UNIX systems, you can simply ask the linker to tell you. For example, suppose you wanted to know where printf is coming from into this program:
#include <stdio.h>
int main()
{
return printf("Hello\n");
}
$ gcc -c t.c
$ gcc t.o -Wl,-y,printf
t.o: reference to printf
/lib/libc.so.6: definition of printf
This tells you that printf is referenced in t.o and defined in libc.so.6. Above solution will work for both static and shared libraries.
Since you tagged this question with gdb, here is what you can do in gdb:
gdb -q ./a.out
Reading symbols from /tmp/a.out...done.
(gdb) b main
Breakpoint 1 at 0x400528
(gdb) run
Breakpoint 1, 0x0000000000400528 in main ()
(gdb) info symbol &printf
printf in section .text of /lib/libc.so.6
If foo comes from a shared library, gdb will tell you which one. If it comes from a static library (in which case gdb will say in section .text of a.out), use the -Wl,-y,foo solution above. You could also do a "brute force" solution like this:
find / -name '*.a' -print0 | xargs -0 nm -A | grep ' foo$'
For shared libs try using ldd command line tool.
For static libs the library is in the program itself - there are no external dependencies, which is the whole point of using static libs.
You cannot list static libraries in the final binary. To list the linked dynamic libraries, use the commands: On Linux, use ldd [file]. On Mac OS X, use otool -L [file]. On Windows, I have no idea ;-)

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

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.

Resources