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; }
0x1ainstead of\x1a?