-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
cmd/link: incorrect DOS header on Go-built Windows binaries #57834
Comments
Change https://go.dev/cl/462054 mentions this issue: |
cc @golang/windows |
It would be good to fix this as I fear this might trip off some virus scanners. |
I tried to test your fix. I run I built test.exe twice. First test.exe I built on top of e587a76 commit and copied it into c:\after.exe on FreeDOS. Second test.exe I built on top of b08d5ee commit (the commit before e587a76) and I copied it into c:\before.exe on FreeDOS. When I run c:\before.exe on Free DOS it outputs nothing. When I run c:\after.exe FreeDOS output I expected that FreeDOS will output Thank you. Alex |
Interesting, I'm not able to repro that. The "after" version does print Here's what I've tried: Set up Go toolchains
Build test binaries
Run in FreeDOS
Extra info
|
@alexbrainman from your screenshot it seems the |
That was my problem, @cherrymui . If I run
exactly like @kevpar described at #57834 (comment) . So all is good here. Thank you for fixing this bug. Alex |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
GOOS=windows
as hello.exe.What did you expect to see?
Program should print
This program cannot be run in DOS mode.
and exit.What did you see instead?
DOSBox crashed when the program was run. On FreeDOS the program appeared to do nothing.
Details
First, off, it likely goes without saying this is a very inconsequential bug. I imagine the number of users who will run a Go-built binary on a DOS system these days is quite small. :)
Windows PE binaries contain a old DOS-style (MZ) header at the front. This is generally used to point to a short amount of code that prints out a message saying the program cannot run under DOS. Go embeds a DOS header into binaries it builds, but this header appears to be invalid.
The structure of the header, per the Windows SDK, looks like this:
In a Go program, most of the values are correct, but the
e_crlc
(number of relocations) is set to 4, ande_cparhdr
(size of header in 16-bit words) is set to 0. On other Windows programs I examined, these values were flipped. Havinge_cparhdr
set to 0 appears to mean that execution will start at offset 0 in the file, rather than 0x40 where executable code actually appears. This results in the program executing invalid instructions.Using a
e_crlc
of 0 ande_cparhdr
of 4 should fix the issue. This change can be made here: https://github.com/golang/go/blob/master/src/cmd/link/internal/ld/pe.go#L155As far as I can tell, this PE header has been incorrect as long as it has existed in Go. If anyone has context on whether this has ever worked, I'd be curious to know.
The text was updated successfully, but these errors were encountered: