Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x86_64+elf: "packed struct fields modification" test fails when compiled with -fstrip #17513

Closed
Tracked by #17748
kubkon opened this issue Oct 13, 2023 · 3 comments · Fixed by #18169
Closed
Tracked by #17748

x86_64+elf: "packed struct fields modification" test fails when compiled with -fstrip #17513

kubkon opened this issue Oct 13, 2023 · 3 comments · Fixed by #18169
Labels
arch-x86_64 64-bit x86 backend-self-hosted bug Observed behavior contradicts documented or intended behavior miscompilation The compiler reports success but produces semantically incorrect code.
Milestone

Comments

@kubkon
Copy link
Member

kubkon commented Oct 13, 2023

Zig Version

0.12.0-dev.903+7aa85691b

Steps to Reproduce and Observed Behavior

test "packed struct fields modification" {
    // Originally reported at https://github.com/ziglang/zig/issues/16615

    const Small = packed struct {
        val: u8 = 0,
        lo: u4 = 0,
        hi: u4 = 0,

        var p: @This() = undefined;
    };
    Small.p = .{
        .val = 0x12,
        .lo = 3,
        .hi = 4,
    };
    try expect(@as(u16, @bitCast(Small.p)) == 0x4312);

    Small.p.val -= Small.p.lo;
    Small.p.val += Small.p.hi;
    Small.p.hi -= Small.p.lo;
    try expect(@as(u16, @bitCast(Small.p)) == 0x1313);
}
$ zig test test.zig -fno-llvm -fno-lld --test-no-exec -femit-bin=test1
All 1 tests passed.

$ zig test test.zig -fno-llvm -fno-lld -fstrip --test-no-exec -femit-bin=test2
Test [1/1] test.packed struct field modification... FAIL (TestUnexpectedResult)
0 passed; 0 skipped; 1 failed.

Zooming into emitted code for each version we get:

  • test1
000000000500004d <packed_struct_fields_mod.test.packed struct field modification>:
 500004d:       55                      push   rbp
 500004e:       41 57                   push   r15
 5000050:       41 56                   push   r14
 5000052:       41 55                   push   r13
 5000054:       41 54                   push   r12
 5000056:       53                      push   rbx
 5000057:       48 89 e5                mov    rbp,rsp
 500005a:       48 83 ec 18             sub    rsp,0x18
 500005e:       48 8b 04 25 08 00 00    mov    rax,QWORD PTR ds:0x9000008
 5000065:       09
 5000066:       66 8b 0c 25 00 00 00    mov    cx,WORD PTR ds:0xd000000
 500006d:       0d
 500006e:       66 89 08                mov    WORD PTR [rax],cx
 5000071:       48 8b 14 25 08 00 00    mov    rdx,QWORD PTR ds:0x9000008
 5000078:       09
 5000079:       66 8b 02                mov    ax,WORD PTR [rdx]
 500007c:       66 3d 12 43             cmp    ax,0x4312
 5000080:       0f 94 44 24 10          sete   BYTE PTR [rsp+0x10]
 5000085:       8a 44 24 10             mov    al,BYTE PTR [rsp+0x10]
 5000089:       88 04 24                mov    BYTE PTR [rsp],al
 500008c:       ff 14 25 00 00 00 09    call   QWORD PTR ds:0x9000000
 5000093:       66 89 c1                mov    cx,ax
 5000096:       81 e1 ff ff 00 00       and    ecx,0xffff
 500009c:       66 83 f9 00             cmp    cx,0x0
 50000a0:       0f 86 05 00 00 00       jbe    50000ab <packed_struct_fields_mod.test.packed struct field modification+0x5e>
 50000a6:       e9 57 01 00 00          jmp    5000202 <packed_struct_fields_mod.test.packed struct field modification+0x1b5>
 50000ab:       48 8b 14 25 08 00 00    mov    rdx,QWORD PTR ds:0xd000008
 50000b2:       0d
 50000b3:       8a 02                   mov    al,BYTE PTR [rdx]
 50000b5:       48 8b 1c 25 08 00 00    mov    rbx,QWORD PTR ds:0x9000008
 50000bc:       09
 50000bd:       66 8b 13                mov    dx,WORD PTR [rbx]
 50000c0:       48 c1 ea 08             shr    rdx,0x8
 50000c4:       83 e2 0f                and    edx,0xf
 50000c7:       83 e2 0f                and    edx,0xf
 50000ca:       88 c1                   mov    cl,al
 50000cc:       28 d1                   sub    cl,dl
 50000ce:       0f 92 c0                setb   al
 50000d1:       88 4c 24 11             mov    BYTE PTR [rsp+0x11],cl
 50000d5:       0f 92 44 24 12          setb   BYTE PTR [rsp+0x12]
 50000da:       3c 00                   cmp    al,0x0
 50000dc:       0f 85 05 00 00 00       jne    50000e7 <packed_struct_fields_mod.test.packed struct field modification+0x9a>
 50000e2:       e9 02 00 00 00          jmp    50000e9 <packed_struct_fields_mod.test.packed struct field modification+0x9c>
 50000e7:       0f 0b                   ud2
 50000e9:       8a 44 24 11             mov    al,BYTE PTR [rsp+0x11]
 50000ed:       48 8b 0c 25 08 00 00    mov    rcx,QWORD PTR ds:0xd000008
 50000f4:       0d
 50000f5:       88 01                   mov    BYTE PTR [rcx],al
 50000f7:       48 8b 14 25 08 00 00    mov    rdx,QWORD PTR ds:0xd000008
 50000fe:       0d
 50000ff:       8a 02                   mov    al,BYTE PTR [rdx]
 5000101:       48 8b 1c 25 08 00 00    mov    rbx,QWORD PTR ds:0x9000008
 5000108:       09
 5000109:       66 8b 13                mov    dx,WORD PTR [rbx]
 500010c:       48 c1 ea 0c             shr    rdx,0xc
 5000110:       83 e2 0f                and    edx,0xf
 5000113:       83 e2 0f                and    edx,0xf
 5000116:       88 c1                   mov    cl,al
 5000118:       00 d1                   add    cl,dl
 500011a:       0f 92 c0                setb   al
 500011d:       88 4c 24 13             mov    BYTE PTR [rsp+0x13],cl
 5000121:       0f 92 44 24 14          setb   BYTE PTR [rsp+0x14]
 5000126:       3c 00                   cmp    al,0x0
 5000128:       0f 85 05 00 00 00       jne    5000133 <packed_struct_fields_mod.test.packed struct field modification+0xe6>
 500012e:       e9 02 00 00 00          jmp    5000135 <packed_struct_fields_mod.test.packed struct field modification+0xe8>
 5000133:       0f 0b                   ud2
 5000135:       8a 44 24 13             mov    al,BYTE PTR [rsp+0x13]
 5000139:       48 8b 0c 25 08 00 00    mov    rcx,QWORD PTR ds:0xd000008
 5000140:       0d
 5000141:       88 01                   mov    BYTE PTR [rcx],al
 5000143:       48 8b 14 25 18 00 00    mov    rdx,QWORD PTR ds:0xd000018
 500014a:       0d
 500014b:       66 8b 42 01             mov    ax,WORD PTR [rdx+0x1]
 500014f:       66 c1 e8 04             shr    ax,0x4
 5000153:       83 e0 0f                and    eax,0xf
 5000156:       48 8b 1c 25 08 00 00    mov    rbx,QWORD PTR ds:0x9000008
 500015d:       09
 500015e:       66 8b 13                mov    dx,WORD PTR [rbx]
 5000161:       48 c1 ea 08             shr    rdx,0x8
 5000165:       83 e2 0f                and    edx,0xf
 5000168:       88 c1                   mov    cl,al
 500016a:       28 d1                   sub    cl,dl
 500016c:       0f 92 c3                setb   bl
 500016f:       40 88 ce                mov    sil,cl
 5000172:       83 e6 0f                and    esi,0xf
 5000175:       40 38 ce                cmp    sil,cl
 5000178:       40 0f 95 c7             setne  dil
 500017c:       40 08 fb                or     bl,dil
 500017f:       40 88 74 24 15          mov    BYTE PTR [rsp+0x15],sil
 5000184:       88 5c 24 16             mov    BYTE PTR [rsp+0x16],bl
 5000188:       8a 44 24 16             mov    al,BYTE PTR [rsp+0x16]
 500018c:       83 e0 01                and    eax,0x1
 500018f:       3c 00                   cmp    al,0x0
 5000191:       0f 85 05 00 00 00       jne    500019c <packed_struct_fields_mod.test.packed struct field modification+0x14f>
 5000197:       e9 02 00 00 00          jmp    500019e <packed_struct_fields_mod.test.packed struct field modification+0x151>
 500019c:       0f 0b                   ud2
 500019e:       8a 44 24 15             mov    al,BYTE PTR [rsp+0x15]
 50001a2:       83 e0 0f                and    eax,0xf
 50001a5:       48 8b 0c 25 18 00 00    mov    rcx,QWORD PTR ds:0xd000018
 50001ac:       0d
 50001ad:       66 81 21 ff 0f          and    WORD PTR [rcx],0xfff
 50001b2:       66 89 c2                mov    dx,ax
 50001b5:       66 c1 e2 0c             shl    dx,0xc
 50001b9:       66 81 e2 00 f0          and    dx,0xf000
 50001be:       66 09 11                or     WORD PTR [rcx],dx
 50001c1:       48 8b 14 25 08 00 00    mov    rdx,QWORD PTR ds:0x9000008
 50001c8:       09
 50001c9:       66 8b 02                mov    ax,WORD PTR [rdx]
 50001cc:       66 3d 13 13             cmp    ax,0x1313
 50001d0:       0f 94 44 24 17          sete   BYTE PTR [rsp+0x17]
 50001d5:       8a 44 24 17             mov    al,BYTE PTR [rsp+0x17]
 50001d9:       88 04 24                mov    BYTE PTR [rsp],al
 50001dc:       ff 14 25 00 00 00 09    call   QWORD PTR ds:0x9000000
 50001e3:       66 89 c1                mov    cx,ax
 50001e6:       81 e1 ff ff 00 00       and    ecx,0xffff
 50001ec:       66 83 f9 00             cmp    cx,0x0
 50001f0:       0f 86 05 00 00 00       jbe    50001fb <packed_struct_fields_mod.test.packed struct field modification+0x1ae>
 50001f6:       e9 07 00 00 00          jmp    5000202 <packed_struct_fields_mod.test.packed struct field modification+0x1b5>
 50001fb:       31 c0                   xor    eax,eax
 50001fd:       e9 00 00 00 00          jmp    5000202 <packed_struct_fields_mod.test.packed struct field modification+0x1b5>
 5000202:       48 89 ec                mov    rsp,rbp
 5000205:       5b                      pop    rbx
 5000206:       41 5c                   pop    r12
 5000208:       41 5d                   pop    r13
 500020a:       41 5e                   pop    r14
 500020c:       41 5f                   pop    r15
 500020e:       5d                      pop    rbp
 500020f:       c3                      ret
  • `test2*
000000000500004d <packed_struct_fields_mod.test.packed struct field modification>:
 500004d:       55                      push   rbp
 500004e:       41 57                   push   r15
 5000050:       41 56                   push   r14
 5000052:       41 55                   push   r13
 5000054:       41 54                   push   r12
 5000056:       53                      push   rbx
 5000057:       48 89 e5                mov    rbp,rsp
 500005a:       48 83 ec 18             sub    rsp,0x18
 500005e:       48 8b 04 25 00 00 00    mov    rax,QWORD PTR ds:0xd000000
 5000065:       0d
 5000066:       c6 00 12                mov    BYTE PTR [rax],0x12
 5000069:       48 8b 04 25 10 00 00    mov    rax,QWORD PTR ds:0xd000010
 5000070:       0d
 5000071:       66 81 20 ff f0          and    WORD PTR [rax],0xf0ff
 5000076:       66 b9 03 00             mov    cx,0x3
 500007a:       66 c1 e1 08             shl    cx,0x8
 500007e:       66 81 e1 00 0f          and    cx,0xf00
 5000083:       66 09 08                or     WORD PTR [rax],cx
 5000086:       48 8b 04 25 20 00 00    mov    rax,QWORD PTR ds:0xd000020
 500008d:       0d
 500008e:       66 81 20 ff 0f          and    WORD PTR [rax],0xfff
 5000093:       66 b9 04 00             mov    cx,0x4
 5000097:       66 c1 e1 0c             shl    cx,0xc
 500009b:       66 81 e1 00 f0          and    cx,0xf000
 50000a0:       66 09 08                or     WORD PTR [rax],cx
 50000a3:       48 8b 14 25 08 00 00    mov    rdx,QWORD PTR ds:0x9000008
 50000aa:       09
 50000ab:       66 8b 02                mov    ax,WORD PTR [rdx]
 50000ae:       66 3d 12 43             cmp    ax,0x4312
 50000b2:       0f 94 44 24 10          sete   BYTE PTR [rsp+0x10]
 50000b7:       8a 44 24 10             mov    al,BYTE PTR [rsp+0x10]
 50000bb:       88 04 24                mov    BYTE PTR [rsp],al
 50000be:       ff 14 25 00 00 00 09    call   QWORD PTR ds:0x9000000
 50000c5:       66 89 c1                mov    cx,ax
 50000c8:       81 e1 ff ff 00 00       and    ecx,0xffff
 50000ce:       66 83 f9 00             cmp    cx,0x0
 50000d2:       0f 86 05 00 00 00       jbe    50000dd <packed_struct_fields_mod.test.packed struct field modification+0x90>
 50000d8:       e9 57 01 00 00          jmp    5000234 <packed_struct_fields_mod.test.packed struct field modification+0x1e7>
 50000dd:       48 8b 14 25 00 00 00    mov    rdx,QWORD PTR ds:0xd000000
 50000e4:       0d
 50000e5:       8a 02                   mov    al,BYTE PTR [rdx]
 50000e7:       48 8b 1c 25 08 00 00    mov    rbx,QWORD PTR ds:0x9000008
 50000ee:       09
 50000ef:       66 8b 13                mov    dx,WORD PTR [rbx]
 50000f2:       48 c1 ea 08             shr    rdx,0x8
 50000f6:       83 e2 0f                and    edx,0xf
 50000f9:       83 e2 0f                and    edx,0xf
 50000fc:       88 c1                   mov    cl,al
 50000fe:       28 d1                   sub    cl,dl
 5000100:       0f 92 c0                setb   al
 5000103:       88 4c 24 11             mov    BYTE PTR [rsp+0x11],cl
 5000107:       0f 92 44 24 12          setb   BYTE PTR [rsp+0x12]
 500010c:       3c 00                   cmp    al,0x0
 500010e:       0f 85 05 00 00 00       jne    5000119 <packed_struct_fields_mod.test.packed struct field modification+0xcc>
 5000114:       e9 02 00 00 00          jmp    500011b <packed_struct_fields_mod.test.packed struct field modification+0xce>
 5000119:       0f 0b                   ud2
 500011b:       8a 44 24 11             mov    al,BYTE PTR [rsp+0x11]
 500011f:       48 8b 0c 25 00 00 00    mov    rcx,QWORD PTR ds:0xd000000
 5000126:       0d
 5000127:       88 01                   mov    BYTE PTR [rcx],al
 5000129:       48 8b 14 25 00 00 00    mov    rdx,QWORD PTR ds:0xd000000
 5000130:       0d
 5000131:       8a 02                   mov    al,BYTE PTR [rdx]
 5000133:       48 8b 1c 25 08 00 00    mov    rbx,QWORD PTR ds:0x9000008
 500013a:       09
 500013b:       66 8b 13                mov    dx,WORD PTR [rbx]
 500013e:       48 c1 ea 0c             shr    rdx,0xc
 5000142:       83 e2 0f                and    edx,0xf
 5000145:       83 e2 0f                and    edx,0xf
 5000148:       88 c1                   mov    cl,al
 500014a:       00 d1                   add    cl,dl
 500014c:       0f 92 c0                setb   al
 500014f:       88 4c 24 13             mov    BYTE PTR [rsp+0x13],cl
 5000153:       0f 92 44 24 14          setb   BYTE PTR [rsp+0x14]
 5000158:       3c 00                   cmp    al,0x0
 500015a:       0f 85 05 00 00 00       jne    5000165 <packed_struct_fields_mod.test.packed struct field modification+0x118>
 5000160:       e9 02 00 00 00          jmp    5000167 <packed_struct_fields_mod.test.packed struct field modification+0x11a>
 5000165:       0f 0b                   ud2
 5000167:       8a 44 24 13             mov    al,BYTE PTR [rsp+0x13]
 500016b:       48 8b 0c 25 00 00 00    mov    rcx,QWORD PTR ds:0xd000000
 5000172:       0d
 5000173:       88 01                   mov    BYTE PTR [rcx],al
 5000175:       48 8b 14 25 20 00 00    mov    rdx,QWORD PTR ds:0xd000020
 500017c:       0d
 500017d:       66 8b 42 01             mov    ax,WORD PTR [rdx+0x1]
 5000181:       66 c1 e8 04             shr    ax,0x4
 5000185:       83 e0 0f                and    eax,0xf
 5000188:       48 8b 1c 25 08 00 00    mov    rbx,QWORD PTR ds:0x9000008
 500018f:       09
 5000190:       66 8b 13                mov    dx,WORD PTR [rbx]
 5000193:       48 c1 ea 08             shr    rdx,0x8
 5000197:       83 e2 0f                and    edx,0xf
 500019a:       88 c1                   mov    cl,al
 500019c:       28 d1                   sub    cl,dl
 500019e:       0f 92 c3                setb   bl
 50001a1:       40 88 ce                mov    sil,cl
 50001a4:       83 e6 0f                and    esi,0xf
 50001a7:       40 38 ce                cmp    sil,cl
 50001aa:       40 0f 95 c7             setne  dil
 50001ae:       40 08 fb                or     bl,dil
 50001b1:       40 88 74 24 15          mov    BYTE PTR [rsp+0x15],sil
 50001b6:       88 5c 24 16             mov    BYTE PTR [rsp+0x16],bl
 50001ba:       8a 44 24 16             mov    al,BYTE PTR [rsp+0x16]
 50001be:       83 e0 01                and    eax,0x1
 50001c1:       3c 00                   cmp    al,0x0
 50001c3:       0f 85 05 00 00 00       jne    50001ce <packed_struct_fields_mod.test.packed struct field modification+0x181>
 50001c9:       e9 02 00 00 00          jmp    50001d0 <packed_struct_fields_mod.test.packed struct field modification+0x183>
 50001ce:       0f 0b                   ud2
 50001d0:       8a 44 24 15             mov    al,BYTE PTR [rsp+0x15]
 50001d4:       83 e0 0f                and    eax,0xf
 50001d7:       48 8b 0c 25 20 00 00    mov    rcx,QWORD PTR ds:0xd000020
 50001de:       0d
 50001df:       66 81 21 ff 0f          and    WORD PTR [rcx],0xfff
 50001e4:       66 89 c2                mov    dx,ax
 50001e7:       66 c1 e2 0c             shl    dx,0xc
 50001eb:       66 81 e2 00 f0          and    dx,0xf000
 50001f0:       66 09 11                or     WORD PTR [rcx],dx
 50001f3:       48 8b 14 25 08 00 00    mov    rdx,QWORD PTR ds:0x9000008
 50001fa:       09
 50001fb:       66 8b 02                mov    ax,WORD PTR [rdx]
 50001fe:       66 3d 13 13             cmp    ax,0x1313
 5000202:       0f 94 44 24 17          sete   BYTE PTR [rsp+0x17]
 5000207:       8a 44 24 17             mov    al,BYTE PTR [rsp+0x17]
 500020b:       88 04 24                mov    BYTE PTR [rsp],al
 500020e:       ff 14 25 00 00 00 09    call   QWORD PTR ds:0x9000000
 5000215:       66 89 c1                mov    cx,ax
 5000218:       81 e1 ff ff 00 00       and    ecx,0xffff
 500021e:       66 83 f9 00             cmp    cx,0x0
 5000222:       0f 86 05 00 00 00       jbe    500022d <packed_struct_fields_mod.test.packed struct field modification+0x1e0>
 5000228:       e9 07 00 00 00          jmp    5000234 <packed_struct_fields_mod.test.packed struct field modification+0x1e7>
 500022d:       31 c0                   xor    eax,eax
 500022f:       e9 00 00 00 00          jmp    5000234 <packed_struct_fields_mod.test.packed struct field modification+0x1e7>
 5000234:       48 89 ec                mov    rsp,rbp
 5000237:       5b                      pop    rbx
 5000238:       41 5c                   pop    r12
 500023a:       41 5d                   pop    r13
 500023c:       41 5e                   pop    r14
 500023e:       41 5f                   pop    r15
 5000240:       5d                      pop    rbp
 5000241:       c3                      ret

I have run all behavior tests with -fstrip and this is the only one that fails. As to the reason, I am not yet sure.

Expected Behavior

Test passes with and without debug info stripped.

@kubkon kubkon added bug Observed behavior contradicts documented or intended behavior arch-x86_64 64-bit x86 backend-self-hosted labels Oct 13, 2023
@Vexu Vexu added this to the 0.13.0 milestone Oct 13, 2023
@andrewrk
Copy link
Member

-fstrip does more than strip debug info at the end; it's also a comptime flag that is the basis for decisions such as including the stack trace printing code, for example here:

zig/lib/std/debug.zig

Lines 119 to 122 in 7aa8569

if (builtin.strip_debug_info) {
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
return;
}

So it is not necessarily a bug if the machine code differs.

@kubkon
Copy link
Member Author

kubkon commented Oct 13, 2023

-fstrip does more than strip debug info at the end; it's also a comptime flag that is the basis for decisions such as including the stack trace printing code, for example here:

zig/lib/std/debug.zig

Lines 119 to 122 in 7aa8569

if (builtin.strip_debug_info) {
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
return;
}

So it is not necessarily a bug if the machine code differs.

Yeah, @jacobly0 already pointed that out to me, amongst other things. Still an interesting bug to be had!

@xdBronch
Copy link
Contributor

#17119 related? they mentioned -fstrip

@kubkon kubkon changed the title x86_64+elf: differing machine code emitted for "packed struct fields modification" test with and without -fstrip x86_64+elf: "packed struct fields modification" test fails when compiled with -fstrip Oct 13, 2023
jacobly0 added a commit to jacobly0/zig that referenced this issue Nov 30, 2023
@jacobly0 jacobly0 added the miscompilation The compiler reports success but produces semantically incorrect code. label Nov 30, 2023
jacobly0 added a commit to jacobly0/zig that referenced this issue Dec 1, 2023
mlugg pushed a commit that referenced this issue Dec 1, 2023
geooot pushed a commit to geooot/zig that referenced this issue Dec 1, 2023
geooot pushed a commit to geooot/zig that referenced this issue Dec 1, 2023
RossComputerGuy pushed a commit to ExpidusOS-archive/zig that referenced this issue Jan 6, 2024
@andrewrk andrewrk modified the milestones: 0.13.0, 0.12.0 Jan 9, 2024
@mlugg mlugg moved this to Ditch LLVM in Performance Aug 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-x86_64 64-bit x86 backend-self-hosted bug Observed behavior contradicts documented or intended behavior miscompilation The compiler reports success but produces semantically incorrect code.
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants