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

zig cc creating incorrect amd64 binary #22463

Closed
cristeigabriel opened this issue Jan 11, 2025 · 5 comments
Closed

zig cc creating incorrect amd64 binary #22463

cristeigabriel opened this issue Jan 11, 2025 · 5 comments
Labels
question No questions on the issue tracker, please.

Comments

@cristeigabriel
Copy link

Zig Version

0.11.0

Steps to Reproduce and Observed Behavior

While working on an article, since I'm currently using my Steam Deck as a work machine, I decided to use Zig, as it is portable. I wrote my code, everything worked, and then I introduced an AND then IF check, and started getting illegal instruction outputs.

Code:

#include <stdint.h>
#include <stdio.h>

int main() {
    volatile uint32_t eax=0x1,ebx=0,ecx=0,edx=0;

    __asm__ __volatile__(
        "cpuid"
        : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
        : "a" (eax), "b" (0), "c" (0), "d" (0)
    );

    printf("0x%08x 0x%08x 0x%08x 0x%08x hv: %d\n", eax, ebx, ecx, edx, (ecx & (1<<31))!=0);
    return 1337;
}

(godbolt where issue can be seen aswell: https://godbolt.org/z/1vvdjvb5a ctrl+f ud1)

It is (ecx & (1<<31))!=0 that brings the trouble. Alternatives such as ecx >> 31 or removing the hv printf altogether work fine.

I decided to analyze what was going on and I checked the binary in IDAPro. Then I noticed the following code:

text:00000000002015DA                                                                 db      67h
.text:00000000002015DA 67 0F B9                                                        ud1
.text:00000000002015DA                                                 ; ---------------------------------------------------------------------------
.text:00000000002015DD 40 14                                                           db 40h, 14h

This is visibly wrong. You would never randomly see 40 14 in x86 code especially after an undefined instruction. 40 is just inc eax/rax and 14 is nothing we know of. 67 0f b9 is an undefined instruction, and it seems that it is disassembling 67 0f b9 as its own instruction.

I tried putting a larger block of code into defense.ca-s x64 assembler and it produced this

0:  8a 45 e3                mov    al,BYTE PTR [rbp-0x1d]
3:  24 01                   and    al,0x1
5:  a8 01                   test   al,0x1
7:  0f 85 05 00 00 00       jne    0x12
d:  67 0f b9 40 14          ud1    eax,DWORD PTR [eax+0x14]
12: 44 8b 45 d8             mov    r8d,DWORD PTR [rbp-0x28]

Seems that 0f b9 is just a good old undefined instruction, appropriately defined as ud1 r/m32, Raise invalid opcode exception..

Long story short, I do not think this is expected.

Expected Behavior

I would like the exact same behaviour as I got when i thought of alternatively trying using ecx>>31, which I think what gcc compiles to in this scenario aswell.

@cristeigabriel cristeigabriel added the bug Observed behavior contradicts documented or intended behavior label Jan 11, 2025
@alexrp
Copy link
Member

alexrp commented Jan 11, 2025

You're hitting a "shift out of bounds" UBSan trap. Your shift is at least incorrect in that it should be 1u << 31 instead.

@cristeigabriel
Copy link
Author

Oops, you're correct on that. I'm currently on my phone and thus I may be mistaken, but after applying your suggested change, the codegen apparent mistake produces the same output.

@alexrp
Copy link
Member

alexrp commented Jan 11, 2025

Then I suspect it may be an upstream Clang bug. I get the ~same LLVM IR and machine code with Zig and vanilla Clang using -O0 -fsanitize=undefined -fsanitize-trap=undefined.

@cristeigabriel
Copy link
Author

cristeigabriel commented Jan 11, 2025

Strange. https://godbolt.org/z/s4PbadEex multi-pane, zig and clang side by side, with the assembly code next to it. same build flags, same code (with @alexrp suggested change -- though if that failed i think a lot of other software would as well), still fails in the same way.

@alexrp
Copy link
Member

alexrp commented Jan 11, 2025

It's probably specific to -fsanitize-trap=undefined which is a less-used configuration, but which Zig uses because we don't (yet) have a UBSan runtime for the compiler to call into. (I think @Rexicon226 is working on this?)

@andrewrk andrewrk closed this as not planned Won't fix, can't repro, duplicate, stale Jan 25, 2025
@andrewrk andrewrk added question No questions on the issue tracker, please. and removed bug Observed behavior contradicts documented or intended behavior labels Jan 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question No questions on the issue tracker, please.
Projects
None yet
Development

No branches or pull requests

3 participants