Skip to content
New issue

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

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

Already on GitHub? # 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
# for free to join this conversation on GitHub. Already have an account? # 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