2017-07-15 2 views
1

Compilons le programme suivant avec gcc -g -O0 -o prog prog.c et exécuter gdb dessus. Si nous allons étape par étape, nous verrons que, après la lignePourquoi fonctionne correctement gdb sur la sortie gcc?

4  switch (c) { 

il va à la ligne droite

38 return 0; 

ce qui est faux, car il faut d'abord aller à la ligne

32   break; 

qui est dûment effectué sur la sortie produite avec clang -g -O0 -o prog prog.c

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

version clang: 3.8.1-24 (balises/RELEASE_381/finale)

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; 
} 
+0

est pas '0x1a' au lieu de' \ x1a'? – dlmeetei

+0

@dlmeetei Je suppose que ceux-ci sont équivalentes –

+0

Parce que [gcc] (https://godbolt.org/g/4t7aL2) et [clang] (https://godbolt.org/g/z8Ck5s) générer un code différent pour cet exemple. – ks1322

Répondre

3

gdb ne fonctionne pas incorrectement, il ne marche que sur le code généré par le compilateur. Pour cet exemple fictif qui ne fait rien, gcc génère 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 

Il n'y a pas de code correspondant généré pour break déclarations, donc gdb ne peuvent pas marcher sur eux parce qu'ils n'existent pas.

D'autre part clang a généré une autre more verbose code pour break déclarations. Voilà pourquoi vous pouvez marcher sur eux:

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 

Si vous voulez gcc pour générer du code pour break déclarations que vous devez vous modifier par exemple pour faire au moins quelque chose dans switch déclaration. Par exemple ajouter une plus variable i et changer sa valeur dans switch déclaration:

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; 
}