Reputation:
I have the simple .c file that is supposed to fail(I know where it fails, I put the bug in there intentionally):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s argument\n", argv[0]);
return EXIT_FAILURE;
}
char *hello = "hello";
*hello = 'H';
fprintf(stdout, "%s, %s!\n", hello, argv[1]);
return EXIT_SUCCESS;
}
Part 1) I save it as "hello.c" and compile without debugging flags by gcc hello.c -o hello
.
Then, I wish to go line by line through the main function. I try to use gdb as follows:
Run gdb ./hello
Set breakpoint by break main
Run run 123
s
-> fails
Here is the outcome:
(gdb) info func
All defined functions:
Non-debugging symbols:
0x0000000000000568 _init
0x0000000000000590 fprintf@plt
0x00000000000005a0 __cxa_finalize@plt
0x00000000000005b0 _start
0x00000000000005e0 deregister_tm_clones
0x0000000000000620 register_tm_clones
0x0000000000000670 __do_global_dtors_aux
0x00000000000006b0 frame_dummy
0x00000000000006ba main
0x0000000000000740 __libc_csu_init
0x00000000000007b0 __libc_csu_fini
0x00000000000007b4 _fini
(gdb) break main
Breakpoint 1 at 0x6be
(gdb) r
Starting program: /mnt/c/Users/User/Documents/Debugging/hello
Breakpoint 1, 0x00000000080006be in main ()
(gdb) s
Single stepping until exit from function main,
which has no line number information.
__fprintf (stream=0x7fffff3ec680 <_IO_2_1_stderr_>, format=0x80007c4 "Usage: %s argument\n") at fprintf.c:27
27 fprintf.c: No such file or directory.
Why does this happen? Why does it fail like this by trying to find a file fprintf? Thought the preprocessed headers should deal with the required implementation code.
Part 2) When I however compile with the -g
, it works for some reason. But running the program in gdb does not yield a segmentation fault as expected :/ Why?
Again, see:
$ ./hello 123
Segmentation fault (core dumped)
but
(gdb) run 123
Starting program: /mnt/c/Users/NichlasDesktop/Documents/uni/Compsys/Exercises/Debugging/exercise_code/hello 123
Hello, 123!
[Inferior 1 (process 632) exited normally]
Upvotes: 2
Views: 1562
Reputation: 380
Part 1)
s -> fails
Without debugging information, gdb
is unable to map instructions to source code - file paths and line numbers. The s
/step
command tells gdb
to execute instructions that correspond to the current statement in the source language. gdb
has no way of telling what that is, so it continues till wherever in code the source position ("SPOS") information is available. That happens to be in libc where fprintf is defined. However the source code for fprintf is not available in your environment, hence that message.
You could step through the individual instructions using the si
/stepi
command, this does not need debugging information to be present.
You did not show what happens if you continue execution from that point, I suspect it would eventually hit the segmentation fault.
Why does this happen? Why does it fail like this by trying to find a file fprintf? Thought the preprocessed headers should deal with the required implementation code.
That is not what headers are. They don't contain source code.
Part 2) When I however compile with the -g, it works for some reason. But running the program in gdb does not yield a segmentation fault as expected :/ Why?
gdb
or any other debugger would arrange for the executable text segment to be mapped private instead of shared as in the usual run case (mmap
with MAP_PRIVATE
instead of MAP_SHARED
). This is because the debugger needs the text segment to be writable so that instructions can be overwritten to insert breakpoints etc.
The "hello" you put in there is a constant string literal that is stored in the read-only text segment of the executable. This is why writing to it causes a segmentation fault during the normal run - the text segment is mapped shared. Inside the debugger however the text segment is mapped private, so you are able to write to it.
Upvotes: 3