When I tried to debug an executable:
(gdb) break +1
No symbol table is loaded. Use the "file" command.
What does that mean exactly?
Is the symbol table appended to the executable?
There are two sets of symbols that gdb uses.
The -g set are debugging symbols, which make things a lot easier as they allow you to see your code and look at variables while debugging.
Another set of symbols is included by default when you compile. These are the linking symbols and live in the ELF (executable linkable format) symbol table. This contains a lot less info than the debug symbols, but contain the most important stuff, such as the addresses of the things in your executable (or library or object file). Without this information gdb won't even know where main is, so (gdb) break main would fail.
If you don't have the debugging symbols ( -g ) then you will still be able to (gdb) break main but you gdb will not have any concept of the lines of code in your source file. When you try to step through the code you will only advance 1 machine instruction at a time, rather than a line at a time.
The strip command is often used to strip off symbols from an executable (or other object file).
This is often used if you don't want someone to be able to see the symbols or if you want to save space in the file. Symbol tables can get big. Strip removes both the debug symbols and the linker symbols, but it has several command line switches which can limit what it removes.
If you run the file command on your program one of the things it will tell you is weather or not the executable is has been stripped.
$ gcc my_prog.c -o my_prog
$ file my_prog
my_prog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
$ strip my_prog
my_prog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
$
It's because you didn't compile with debugging turned on. Try gcc -g file.c
The symbol table contains debugging information that tells a debugger what memory locations correspond to which symbols (like function names and variable names) in the original source code file. The symbol table is usually stored inside the executable, yes.
gdb is telling you that it can't find that table. If you compiled with gcc, unless you used the -g flag, it will not include the symbol table in the file. The easiest method is probably to recompile your file with -g. gdb should then automatically find the symbol table information.
Either add the -g flag to the command line arguments of gcc or to the Makefile that you used to compile the program. (A lot of times, there will be a variable called CFLAGS or similar inside the Makefile).
If you are trying to debug an arbitrary third-party program, a lot of times the information will have been "stripped" out of it. This is done to make reverse engineering harder and to make the size of the executable file smaller. Unless you have access to the source code and can compile the program yourself, you will have a very hard time using gdb on it.
Find the entry point of the application.
objdump -f main
main: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048054
Put a breakpoint there using the gnu debugger
gdb
exec-file main
break *0x8048054
set disassemble-next-line on
run
Then step through the code
gdb
stepi
Special Notes
If you are using the latest version of Ubuntu you would not be affected by this, but you may run into this bug if you are running Ubuntu 10.04 or older.
https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/151518G
The solution would be to start debugging at the entry point address plus one.
Related
I'm working on a toy bootloader/kernel written in assembly and run on the qemu emulator. I can run qemu with -s -S option and debug with gdb using remote target, but I don't have any debug symbols loaded with gdb. How can I generate a symbol file from my assembly?
I'm using nasm to generate a binary image for qemu to run from my assembly file, but I haven't found anyway to include debug information in the image itself (I'm not sure if that even makes sense). I also found that gdb allows you to load an separate symbol file for debugging, so now my issue is how to generate a symbol file from my assembly code.
I've seen suggestions to use objcopy, but I believe that only works on elf files, not binary. I've tried getting nasm to generate an elf, but it keeps barfing because of my (necessary) org directive in the assembly file.
It would say try it like this:
use "-f elf -F dwarf -g" switches when assembling. This should produce elf file that contains debug symbols (and code and everything else).
Use objcopy to generate binary file.
Load binary file to your system.
Attach debugger, then tell it to load symbols from your .elf file (symbol-file yourfile.elf)
You need to solve why nasm can't generate .elf file with .org you have in there. I have no idea. GNA as is fine with this.
$ nasm -g -f elf64 -l 2.lst 2.asm
$ gcc -m64 -o 2.exe 2.o
I have tried to use the ltrace. I tried to use the following command to profile the library.so file which is used by a program sampleapp, ltrace -c -T --library=library.so --output=out.txt ./SampleApp. But it shows the above error. But library.so is a debug build. So the symbol table should be there. I have tried to verify it with objdump --source library.so | grep CreateSocket(). It returns codes that uses that CreateSocket() function. Which means it contains a symbol table. Than why that error occurs?
Related post: measure CPU usage per second of a dynamically linked library
It depends on how the executable SampleApp was created. You will see that error if it was statically linked. ltrace only works for dynamically linked applications.
You can run ldd SampleApp to show the shared object dependencies. It is was dynamically linked and has a dependence to libc, the output of ldd will contain a line like this:
libc.so.6 => /usr/lib/libc.so.6 (0x00007fb24ac53000)
In that case, you can use the ltrace option --library=libc.so.6 and it should work. However, --library=libc.so will not match (you will not get an error, but no library call will be matched).
When statically linked, ldd SampleApp will instead show this output:
not a dynamic executable
My guess that it is because of static linking could be wrong. The important point, however, is that if ltrace shows this error, you have to start the diagnosis at the executable itself (the binary) and how it was created (linker options), not at the shared library.
The question How does ltrace (library tracing tool) work? has some good references to understand more about the internals of the ltrace.
I'm working on a toy bootloader/kernel written in assembly and run on the qemu emulator. I can run qemu with -s -S option and debug with gdb using remote target, but I don't have any debug symbols loaded with gdb. How can I generate a symbol file from my assembly?
I'm using nasm to generate a binary image for qemu to run from my assembly file, but I haven't found anyway to include debug information in the image itself (I'm not sure if that even makes sense). I also found that gdb allows you to load an separate symbol file for debugging, so now my issue is how to generate a symbol file from my assembly code.
I've seen suggestions to use objcopy, but I believe that only works on elf files, not binary. I've tried getting nasm to generate an elf, but it keeps barfing because of my (necessary) org directive in the assembly file.
It would say try it like this:
use "-f elf -F dwarf -g" switches when assembling. This should produce elf file that contains debug symbols (and code and everything else).
Use objcopy to generate binary file.
Load binary file to your system.
Attach debugger, then tell it to load symbols from your .elf file (symbol-file yourfile.elf)
You need to solve why nasm can't generate .elf file with .org you have in there. I have no idea. GNA as is fine with this.
$ nasm -g -f elf64 -l 2.lst 2.asm
$ gcc -m64 -o 2.exe 2.o
List items 1- 4 are the steps that I did.
List item 5 describes the problem
List item 6 provides additional information
I have compiled a C source code say c1.c with -g flag.
I have also a
dynamic shared library say liba1.so built with -g for all the source
files that it has.
I built the executable say exe1 by linking c1.o (c1.c object code) with the liba1.so .
I do gdb exe1. and am able to step through the sources of c1.c. When c1 calls the shared library, I am also able to put a breakpoint on a function in the shared library.
However, when I try to step through the function, it says that "Single stepping until exit from function foo1 ,which has no line number information" Also it should ordinarily show the value of the parameters passed into the function foo1 but does not do that. This happens for all functions in the shared library including some very big ones so the values cannot be optimized out
I did an objdump -t on the shared library AND the executable - it shows the symbol table (the fact that I can set a breakpoint on the function also supports this). Also, I can see the values of the variables used in the file c1.c So what should I do in order to ensure that I can see the values of the local variables inside the shared library. Here are the other arguments that are being used to compile the shared library "-O2 -std=gnu99 -Werror -fno-stack-protector -Wstack-protector --param ssp-buffer-size=1 -g -nostdinc". doing info f and trying to look at memory addresses on the frame also does not give any information.
I am looking for some suggestion to at least troubleshoot it. Can I know using objdump (or any other utility) if a shared library has line number information.
I am looking for some suggestion to at least troubleshoot it.
The most likely reason for no line number information, is that there is in fact no line number information, and the most likely reason for that is that you have two copies of liba1.so -- one that has debug info, and one that doesn't, and you are loading at runtime the latter.
First step: (gdb) info shared will tell you exactly which liba1.so is loaded.
If it is in fact the version that you've just built with -g, you should verify that it does have the debug info you are expecting. The exact commands for doing so are platform specific (and you didn't tell which platform you are on). On an ELF platform, objdump -g liba1.so or readelf -w liba1.so should work.
One common reason for -g code to not have debug info is presence of -s (strip) flag on the link line; make sure you don't have "stray" flags on your link line. Some platforms also require -g to be used at link time in addition to compile time.
How do I analyze the core dump (using gdb)
which is not compiled with -g GCC option ?
Generate a map file. The map file will tell you the address that each function starts at (as an offset from the start of the exe so you will need to know the base address its loaded too). So you then look at the instruction pointer and look up where it falls in the map file. This gives you a good idea of the location in a given function.
Manually unwinding a stack is a bit of a black art, however, as you have no idea what optimisations the compiler has performed. When you know, roughly, where you are in the code you can generally work out what ought to be on the stack and scan through memory to find the return pointer. its quite involved however. You effectively spend a lot of time reading memory data and looking for numbers that look like memory addresses and then checking that to see if its logical. Its perfectly doable and I, and I'm sure many others, have done it lots of times :)
With ELF binaries it is possible to separate the debug symbols into a separate file. Quoting from objcopy man pages:
Link the executable as normal (using the -g flag). Assuming that is is called foo then...
Run objcopy --only-keep-debug foo foo.dbg to create a file containing the debugging info.
Run objcopy --strip-debug foo to create a stripped executable.
Run objcopy --add-gnu-debuglink=foo.dbg foo to add a link to the debugging info into the stripped executable.
that should not be a problem , you can compile the source again with -g option and pass gdb the core and the new compiled debug binary, it should work without any problem.
BTW You can generate a map file with the below command in gcc
gcc -Wl,-Map=system.map file.c
The above line should generate the map file system.map, Once the map file is generated you can map the address as mentioned above but i am not sure how are you going to map the share library, this is very difficult