I want to debug my C program with GDB on assembly level. By default, GDB
is to execute the program statement by statement, rather than
instruction by instruction. I learned from a book about assembly
programming if the program is compiled from a assembly source file (.s
file), then GDB will read source information from the assembly source
file. That is I can debug the C program on assembly level.
So, I write a simple C program like this:
root@kali:~# cat hello.c
#include <stdio.h>
int main(){
printf("Hello, world!\n");
return 0;
}
First, I compiled it as following:
root@kali:~# gcc -S hello.c
root@kali:~# as -g -o hello.o hello.s
root@kali:~# ld -g -o hello hello.o
ld: warning: cannot find entry symbol _start; defaulting to
0000000008048074
hello.o: In function `main':
/root/hello.s:19: undefined reference to `puts'
Somebody tell me that hello.o should link with libc, so I query gcc's
actions:
root@kali:~# gcc -v hello.c
... ... ...
/usr/lib/gcc/i486-linux-gnu/4.7/collect2 --sysroot=/ --build-id
--no-add-needed --eh-frame-hdr -m elf_i386 --hash-style=both
-dynamic-linker /lib/ld-linux.so.2
/usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o
/usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/crti.o
/usr/lib/gcc/i486-linux-gnu/4.7/crtbegin.o
-L/usr/lib/gcc/i486-linux-gnu/4.7
-L/usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu
-L/usr/lib/gcc/i486-linux-gnu/4.7/../../../../lib -L/lib/i386-linux-gnu
-L/lib/../lib -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib
-L/usr/lib/gcc/i486-linux-gnu/4.7/../../.. /tmp/ccIzw75a.o -lgcc
--as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s
--no-as-needed /usr/lib/gcc/i486-linux-gnu/4.7/crtend.o
/usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/crtn.o
Then, I got that crt1.o, crti.o, and crtn.o are at:
/usr/lib/i386-linux-gnu/crt1.o
/usr/lib/i386-linux-gnu/crti.o
/usr/lib/i386-linux-gnu/crtn.o
So, I re-link like this:
root@kali:~# ld /usr/lib/i386-linux-gnu/crt1.o
/usr/lib/i386-linux-gnu/crti.o /usr/lib/i386-linux-gnu/crtn.o -g -o
hello hello.o -lc -dynamic-linker /lib/ld-linux.so.2
root@kali:~# ./hello
Hello, world!
Finally, I eventually GDB with hello at assembly level.
In this course, I wondered three things:
1. To debug at assembly level, the steps to compile is so complicated
that is somewhat impractical. Is there any way make the process easily?
2. With ld command, I used '-dynamic-linker /lib/ld-linux.so.2' option,
but change it to '-static', the prgram didn't woke any more.
root@kali:~# ld /usr/lib/i386-linux-gnu/crt1.o
/usr/lib/i386-linux-gnu/crti.o /usr/lib/i386-linux-gnu/crtn.o -g -o
hello hello.o -lc -static
root@kali:~# ./hello
bash: ./hello: No such file or directory
Why static library does not work? Why Bash give me 'No such file or
directory', rather than other messages such as 'Segmentation fault'?
3. While compiling with gcc, the collect2 is used rather than ld. What
is the role collect2? What is the difference between collect2 and ld?