1

Let's compile the following program with gcc -g -O0 -o prog prog.c and run gdb on it. If we go step by step, we will see that after line

4 switch (c) { 

it goes straight to line

38 return 0; 

which is wrong, because it first must go to line

32 break; 

which is duly done on output produced with clang -g -O0 -o prog prog.c

GCC version: gcc (Debian 6.4.0-1) 6.4.0 20170704

clang version: 3.8.1-24 (tags/RELEASE_381/final)

int main(void) { char c = '\x1a'; switch (c) { case '\x18': /* C-x */ break; case '\x12': /* C-r */ break; case '\x13': /* C-s */ break; case '\x10': /* C-p */ break; case '\x0e': /* C-n */ break; case '\x02': /* C-b */ break; case '\x06': /* C-f */ break; case '\x05': /* C-e */ break; case '\x01': /* C-a */ break; case '\x04': /* C-d */ break; case '\x08': /* C-h */ break; case '\x1d': /* C-] */ break; case '\x16': /* C-v */ break; case '\x1a': /* C-z */ break; case '\x0d': /* C-m */ break; default: (void) c; } return 0; } 
4
  • is not it 0x1a instead of \x1a? Commented Jul 15, 2017 at 8:53
  • @dlmeetei I suppose these are equivalent Commented Jul 15, 2017 at 9:10
  • Because gcc and clang generate different code for this example. Commented Jul 15, 2017 at 9:29
  • @ks1322 This should be the answer. Do you know how to fix gcc? Commented Jul 15, 2017 at 9:35

1 Answer 1

3

gdb does not work incorrectly, it only steps over compiler generated code. For this dummy example which is doing nothing, gcc generates this code:

main: push rbp mov rbp, rsp mov BYTE PTR [rbp-1], 26 movsx eax, BYTE PTR [rbp-1] cmp eax, 29 ja .L2 mov eax, eax mov rax, QWORD PTR .L4[0+rax*8] jmp rax .L4: .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .quad .L2 .L2: mov eax, 0 pop rbp ret 

There is no corresponding code generated for break statements, so gdb can't walk over them because they does not exist.

On the other hand clang generated another more verbose code for break statements. That's why you can walk over them:

main: # @main push rbp mov rbp, rsp mov dword ptr [rbp - 4], 0 mov byte ptr [rbp - 5], 26 movsx eax, byte ptr [rbp - 5] dec eax mov ecx, eax sub eax, 28 mov qword ptr [rbp - 16], rcx # 8-byte Spill mov dword ptr [rbp - 20], eax # 4-byte Spill ja .LBB0_16 mov rax, qword ptr [rbp - 16] # 8-byte Reload mov rcx, qword ptr [8*rax + .LJTI0_0] jmp rcx .LBB0_1: jmp .LBB0_17 .LBB0_2: jmp .LBB0_17 .LBB0_3: jmp .LBB0_17 .LBB0_4: jmp .LBB0_17 .LBB0_5: jmp .LBB0_17 .LBB0_6: jmp .LBB0_17 .LBB0_7: jmp .LBB0_17 .LBB0_8: jmp .LBB0_17 .LBB0_9: jmp .LBB0_17 .LBB0_10: jmp .LBB0_17 .LBB0_11: jmp .LBB0_17 .LBB0_12: jmp .LBB0_17 .LBB0_13: jmp .LBB0_17 .LBB0_14: jmp .LBB0_17 .LBB0_15: jmp .LBB0_17 .LBB0_16: jmp .LBB0_17 .LBB0_17: xor eax, eax pop rbp ret .LJTI0_0: .quad .LBB0_9 .quad .LBB0_6 .quad .LBB0_16 .quad .LBB0_10 .quad .LBB0_8 .quad .LBB0_7 .quad .LBB0_16 .quad .LBB0_11 .quad .LBB0_16 .quad .LBB0_16 .quad .LBB0_16 .quad .LBB0_16 .quad .LBB0_15 .quad .LBB0_5 .quad .LBB0_16 .quad .LBB0_4 .quad .LBB0_16 .quad .LBB0_2 .quad .LBB0_3 .quad .LBB0_16 .quad .LBB0_16 .quad .LBB0_13 .quad .LBB0_16 .quad .LBB0_1 .quad .LBB0_16 .quad .LBB0_14 .quad .LBB0_16 .quad .LBB0_16 .quad .LBB0_12 

If you want gcc to generate code for break statements you should alter you example to do at least something in switch statement. For example add one more variable i and change it's value in switch statement:

int main(void) { int i = 0; char c = '\x1a'; switch (c) { case '\x18': /* C-x */ break; case '\x12': /* C-r */ break; case '\x13': /* C-s */ break; case '\x10': /* C-p */ break; case '\x0e': /* C-n */ break; case '\x02': /* C-b */ break; case '\x06': /* C-f */ break; case '\x05': /* C-e */ break; case '\x01': /* C-a */ break; case '\x04': /* C-d */ break; case '\x08': /* C-h */ break; case '\x1d': /* C-] */ break; case '\x16': /* C-v */ break; case '\x1a': /* C-z */ i = 1; break; case '\x0d': /* C-m */ break; default: (void) c; } return 0; } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.