$ gdb ./example.o core
Reading symbols from ./example.o...done.
[New LWP 17137]
Core was generated by `./example.o'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055bc13b7b9a0 in getInputAndRun () at example.c:28
28 *result[1] = toupper(result[1][0]);
(gdb)
(gdb) bt
#0 0x000055bc13b7b9a0 in getInputAndRun () at example.c:28
#1 0x000055bc13b7ba1f in main () at example.c:37
(gdb) f 1
#1 0x000055bc13b7ba1f in main () at example.c:37
37 if (getInputAndRun() == -1) break;
(gdb) f 0
#0 0x000055bc13b7b9a0 in getInputAndRun () at example.c:28
28 *result[1] = toupper(result[1][0]);
ดูง่ายนะครับ แปลว่า stack ของ program เราปัจจุบันรัน 2 function อยู่คือ main() และ getInputRun() เราสามารถกระโดดไปมาด้วยด้วยคำสั่ง frame <stack_no> หรือ f <stack_no>
ต่อมาดู source code ด้วย list
(gdb) f 0
#0 0x000055bc13b7b9a0 in getInputAndRun () at example.c:28
28 *result[1] = toupper(result[1][0]);
(gdb) list
23 fgets(input, 100, stdin);
24 if (strcmp(input, "exit") == 0) return -1;
25 else {
26 char** result = split(input);
27 *result[0] = toupper(result[0][0]);
28 *result[1] = toupper(result[1][0]);
29 printf("First str: %s\n", result[0]);
30 printf("Second str: %s\n", result[1]);
31 return 0;
32 }
(gdb) f 1
#1 0x000055bc13b7ba1f in main () at example.c:37
37 if (getInputAndRun() == -1) break;
(gdb) list
32 }
33 }
34
35 int main() {
36 while (1) {
37 if (getInputAndRun() == -1) break;
38 }
39 return 0;
40 }
หรือสั่ง list แบบมี parameter เพื่ออ่านบรรทัดที่ระบุ หรือ function ที่ระบุก็ได้ครับ
(gdb) list 1,2
1 #include <stdio.h>
2 #include <stdlib.h>
(gdb) list main
30 printf("Second str: %s\n", result[1]);
31 return 0;
32 }
33 }
34
35 int main() {
36 while (1) {
37 if (getInputAndRun() == -1) break;
38 }
39 return 0;
นอกจาก list ที่เป็น source code ภาษา c แล้ว เรายังสามารถอ่านเป็นภาษา assembly ได้ด้วย อันนี้แล้วแต่ที่ถนัดเลยครับ ถ้า compile พร้อม debug flag (-g) แทบไม่ต้องลง assembly เลย แต่หลายครั้งการลงไปดู assembly ก็ทำให้เราเห็นรายละเอียดอะไรเยอะกว่าเช่นกัน
(gdb) disassemble main
Dump of assembler code for function main:
0x0000555555554a11 <+0>: push %rbp
0x0000555555554a12 <+1>: mov %rsp,%rbp
=> 0x0000555555554a15 <+4>: mov $0x0,%eax
0x0000555555554a1a <+9>: callq 0x555555554905 <getInputAndRun>
0x0000555555554a1f <+14>: cmp $0xffffffff,%eax
0x0000555555554a22 <+17>: je 0x555555554a26 <main+21>
0x0000555555554a24 <+19>: jmp 0x555555554a15 <main+4>
0x0000555555554a26 <+21>: nop
0x0000555555554a27 <+22>: mov $0x0,%eax
0x0000555555554a2c <+27>: pop %rbp
0x0000555555554a2d <+28>: retq
End of assembler dump.
เนื่องจาก stack ของ main ไม่มีอะไรให้เราดู เราจะดู stack getInputAndRun() กันนะครับ เริ่มจากอ่านตัวแปรต่างๆ ด้วย p <variable_name> หรือ x/<type> <variable_or_address> อาจจะงงๆ มาดูตัวอย่างเลยดีกว่า