How to generate gdb symbol file with nasm? - gdb

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

Related

NASM and gdbgui [duplicate]

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

Enable debug-tools for lldb

I'm having trouble using lldb to debug on MacOsX with clang++. I'm using a makefile to compile a projet in C++, and I don't know if the debug option has to be enabled in the compilation command.
Here is an extract of my makefile
FLAGS =-g -Wall -O0
[...]
clang++ $(FLAGS) $^ -o $#
When I try running lldb with this configuration of my makefile, it return an error :
Breakpoint 1: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
I suppose I have to enable the debug tools on my makefile, but I haven't found how to do this on internet. I tried with the -g and the -ggdb options, without success.
However, when I try to set a breakpoint differently, it works (but setting a breakpoint on a specific fonction doesn't interest me...) :
breakpoint set -n fonction
Breakpoint 1: [...]
I didn't manage to find answers on internet, so I would be interested in having some help ! Thank you !
It looks like somewhere along the way the debug information is getting lost. One possibility is that your CFLAGS are getting reset before you get to building the .o files you care about, so the .o files don't have debug info. One easy way to check that is run
$ otool -l my_file.o | grep debug_info
sectname __debug_info
If you don't see that "sectname" output, then your .o file has no debug information.
Run your makefile and look at the build line for my_file.c and make sure there really is a -g option being passed. -ggdb doesn't actually do anything special for clang so -g is all you need...
If the .o file has debug information, then it must be getting lost when you build the final binary.
Mac OS X is a little funny in how it handles debug information. It doesn't write the debug information into the final image, but rather writes a "debug-map" into the executable, and leaves the debug info in the .o file. That debug-map gets stripped when you strip a binary, so if you strip your executable that will remove the link to the debug information. And of course, if you delete the .o files after building, that will also remove the debug information.
I finally installed gdb, and I managed to debug normally. But after reading your post, you make me realize I have maybe delete the .o when compiling. I didn't thought about it, as lldb was able to set break point in some cases (at a specific fonction) but not in other cases (at a specific line).
As I am using a makefile, I forgot to delete the auto delete of all the .o after compiling, and I think that may cause the issue. Now, if I let the .o, that works perfectly. But this is surprising me a lot, as my makefile was the same as my colleague and he was able to debug with gdb without any kind of problem.
Thanks a lot for all your informations.

How to develop with both Assembly and C/C++ on FASM?

So, I am developing an OS and for now I've been only writing code in assembly. I wish to continue making it with C/C++.
The compiler/editor I use is FASM (for Windows). I've tried using MinGW with it, but it gives error when linking fasm's .o file.
How can I continue developing with both Assembly and C/C++?
Also, I've searched on the Internet a lot, but I didn't find a solution.
Edit:
this is the make batch file i'm using:
cls
echo off
fasm.exe los.asm losasm.o
pause
cls
"C:\MinGW\bin\gcc.exe" -nostdlib los.cpp -o loscpp.o
pause
cls
"C:\MinGW\bin\gcc.exe" -o "C:\Users\helder\Desktop\Lemperyum OperativeSystem I\los" -o -nostdlib losasm.o loscpp.o
pause
cls
pause
FASM is biased toward generating executable files directly as its output, the default being "flat binary output" (see manual). To create object files, you have to use one of the command line options
format COFF or
format ELF
Which you choose depends on the other tools. Offhand, I am not sure what type of file MinGW outputs.

call stack for code compiled without -g option (gcc compiler)

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

What is symbol table and how is it integrated into the executable?

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.