-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add support for windows/arm64 #3063
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from the minidump problem and the comment on the CONTEXT interface I think there are three questions two answer:
- I think we should wait to merge this until we have a version of Go that we can test it on. It doesn't have to be a released version, it could be go built at tip.
- You say that some tests don't pass but made no changes to _test.go files, except core_test.go. Tests that don't pass should be skipped.
- We would need to have some way to run CI on windows/arm64 otherwise it is going to break very soon
Regarding function call injection, I would expect it to work effortlessly, I suspect the problem you are encountering is that the runtime uses BRK extensively to communicate with delve for this, all of those BRK instruction will have the same problem runtime.Breakpoint() has.
Go provides official
Will do that soon.
Agree. Could we at least merge the part of this PR that refactors |
I don't understand what you mean by this.
I think that's fine. |
Then I don't understand your initial concern. Go already supports windows/arm64, so there is a version of Go that we can test it on. What's missing other than the CI? |
I was thinking about the problem with runtime.Breakpoint, I think we should wait until there's a version of go with a fixed runtime.Breakpoint, a large number of tests depends on runtime.Breakpoint being handled correctly. |
d235764
to
8405e78
Compare
@aarzilli I've rebased this PR and gated windows/arm64 behind the I'm also struggling to run the test suite locally either on amd64 and arm64 because |
That's an odd one, our Windows builders seem to be running fine. Is there anything different about your test / development systems that could cause such an error? I don't have a Windows machine handy to test on right now. |
Found the culprit. I'm running the tests inside vscode, and for historical reasons they normalize the drive letter to lower-case. This shouldn't be a problem, because Windows file paths are case-insensitive, but |
.teamcity/settings.kts
Outdated
@@ -201,7 +204,11 @@ class TestBuild(val os: String, val arch: String, version: String, buildId: Abso | |||
scriptMode = file { | |||
path = "_scripts/test_windows.ps1" | |||
} | |||
param("jetbrains_powershell_scriptArguments", "-version ${"go$version"} -arch $arch") | |||
if (arch == "arm64") { | |||
param("jetbrains_powershell_scriptArguments", "-version ${"go$version"} -arch amd64 -winarm64") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how this change works. You are making test_windows.ps1 download the amd64 version of the toolchain and then run the tests by setting GOARCH manually to arm64? Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still don't have a windows arm64 builder to run tests, but at least we can cross-compile from the windows amd64 builder to check for compilation errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But is this going to work given that there are no arm64 agents? And when there will be (if there will be any) it definitely won't work because they will try to execute the amd64 version of the go toolchain. I'd just add a build command at the end of test_windows.ps1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add the build command at the end of the ps1 script.
pkg/proc/bininfo.go
Outdated
if entryPoint != 0 { | ||
image.StaticBase = entryPoint - opth.ImageBase | ||
} else { | ||
if opth.DllCharacteristics&_IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you remove this check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
windows/arm64 binaries are always PIE, even if built with -buildmode=exe
, so we need to support entryPoint==0
. I don't know why this check was added, but as per the TODO comment I supposed it was just that it still wasn't tested with a real program, which I'm doing now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TODO command was obsolete, we did end up checking that this worked on windows. AFAIK PIE binaries always have non-zero entryPoint, the check is to make sure that we don't proceed with a PIE binary for which we weren't able to retrieve the entryPoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some tests calling LoadBinaryInfo
with 0 as hardcoded entry point, namely TestDwarfVersion
and TestRegabiFlagSentinel
. These tests fail on windows/arm64 because the binary is PIE and the entry point is 0.
Anyway, I can revert this change and fix the tests by using a fake entry point, as they don't really need the entry point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's better to change the entry point used by the tests.
Ack, thanks for looking into that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass, just a couple things.
pkg/proc/arm64_arch.go
Outdated
default: | ||
rule.Offset += crosscall2SPOffsetNonWindows | ||
} | ||
rule.Offset += crosscall2SPOffsetNonWindows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need such specific constants now? E.g. can we get rid of Windows vs NonWindows specifiers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need these constants, but I've updated their name to be more specific.
@aarzilli @derekparker I'm mostly done with this PR and all tests in About the Windows ARM64 builder, anyone can register for the Azure Arm-based VMs public preview at https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbRyMSy8VejZVEo6yZykiPSHpURFRIQVY1QTcyWTlJNURUS1pNTktOUTUxVi4u. It is not free of cost, I can't do anything here, but I can help setting up the testing environment once the VM is up and running. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not free of cost, I can't do anything here
Steal an arm64 laptop and hide it in a closet.
pkg/proc/variables.go
Outdated
@@ -438,8 +438,15 @@ func getGVariable(thread Thread) (*Variable, error) { | |||
|
|||
gaddr, hasgaddr := regs.GAddr() | |||
if !hasgaddr { | |||
var err error | |||
gaddr, err = readUintRaw(thread.ProcessMemory(), regs.TLS()+thread.BinInfo().GStructOffset(), int64(thread.BinInfo().Arch.PtrSize())) | |||
offset := thread.BinInfo().GStructOffset() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this logic inside (*BinaryInfo).GStructOffset. Also instead of having a derefGStructOffset just check Arch.Name and BinaryInfo.GOOS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this logic inside (*BinaryInfo).GStructOffset.
If I understood you correctly, to do this I would have to update GStructOffset
to accept a MemoryReader
and return an error. Am I right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that would be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thank you all for your work in getting this change landed! This will make a tremendous difference for our team and we're very appreciative. 🎉 |
This PR adds support for debugging on
windows/arm64
. There are some tests failing, but with these changes I can usedlv
to debug big codebases without problems.I could reuse all work done to support
arm64
on linux. The only difference is that windows useBRK 0xF000
as breakpoint instruction instead of justBRK
.On the windows syscall side, I've redefined
CONTEXT
so it matches Windows ARM64 expectations.There are a couple of things that are still not supported:
runtime.Breakpoint()
fail due to runtime: runtime.Breakpoint() generates illegal instruction on windows/arm64 golang/go#53837Fixes #2129