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

Add support for windows/arm64 #3063

Merged
merged 14 commits into from
Sep 21, 2022
Merged

Add support for windows/arm64 #3063

merged 14 commits into from
Sep 21, 2022

Conversation

qmuntal
Copy link
Contributor

@qmuntal qmuntal commented Jul 13, 2022

This PR adds support for debugging on windows/arm64. There are some tests failing, but with these changes I can use dlv to debug big codebases without problems.

I could reuse all work done to support arm64 on linux. The only difference is that windows use BRK 0xF000 as breakpoint instruction instead of just BRK.

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:

Fixes #2129

Copy link
Member

@aarzilli aarzilli left a 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:

  1. 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.
  2. 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.
  3. 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.

pkg/proc/native/syscall_windows_arm64.go Outdated Show resolved Hide resolved
pkg/proc/native/threads_windows.go Outdated Show resolved Hide resolved
@qmuntal
Copy link
Contributor Author

qmuntal commented Jul 20, 2022

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.

Go provides official windows/arm64 since go1.17, so this should be a blocker.

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.

Will do that soon.

We would need to have some way to run CI on windows/arm64 otherwise it is going to break very soon

Agree. Could we at least merge the part of this PR that refactors windows to be more friendly to non-amd64 architectures? This will pave the path for when we have windows/arm64 CI and it will allow me, and other people wanting to debug arm64 using this branch, to patch arm64 support with minimal effort.

@derekparker derekparker self-requested a review July 20, 2022 22:35
@aarzilli
Copy link
Member

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.

Go provides official windows/arm64 since go1.17, so this should be a blocker.

I don't understand what you mean by this.

We would need to have some way to run CI on windows/arm64 otherwise it is going to break very soon

Agree. Could we at least merge the part of this PR that refactors windows to be more friendly to non-amd64 architectures? This will pave the path for when we have windows/arm64 CI and it will allow me, and other people wanting to debug arm64 using this branch, to patch arm64 support with minimal effort.

I think that's fine.

@qmuntal
Copy link
Contributor Author

qmuntal commented Jul 21, 2022

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.

Go provides official windows/arm64 since go1.17, so this should be a blocker.

I don't understand what you mean by this.

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?

@aarzilli
Copy link
Member

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.

@qmuntal qmuntal force-pushed the master branch 2 times, most recently from d235764 to 8405e78 Compare July 28, 2022 10:23
@qmuntal
Copy link
Contributor Author

qmuntal commented Jul 28, 2022

@aarzilli I've rebased this PR and gated windows/arm64 behind the exp.winarm64 tag. What do you think?

I'm also struggling to run the test suite locally either on amd64 and arm64 because proc.FindFileLocation always returns ErrCouldNotFindLine. There seems to be a mishandling of the file name casing on windows.

@derekparker
Copy link
Member

@aarzilli I've rebased this PR and gated windows/arm64 behind the exp.winarm64 tag. What do you think?

I'm also struggling to run the test suite locally either on amd64 and arm64 because proc.FindFileLocation always returns ErrCouldNotFindLine. There seems to be a mishandling of the file name casing on windows.

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.

@qmuntal
Copy link
Contributor Author

qmuntal commented Jul 29, 2022

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 proc.FindFileLocation is case sensitive, so it can't find the file even if it is there.

@@ -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")
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

.teamcity/settings.kts Outdated Show resolved Hide resolved
if entryPoint != 0 {
image.StaticBase = entryPoint - opth.ImageBase
} else {
if opth.DllCharacteristics&_IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE != 0 {
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

@qmuntal qmuntal Aug 17, 2022

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.

Copy link
Member

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.

@derekparker
Copy link
Member

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 proc.FindFileLocation is case sensitive, so it can't find the file even if it is there.

Ack, thanks for looking into that.

Copy link
Member

@derekparker derekparker left a 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 Show resolved Hide resolved
default:
rule.Offset += crosscall2SPOffsetNonWindows
}
rule.Offset += crosscall2SPOffsetNonWindows
Copy link
Member

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?

Copy link
Contributor Author

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.

@qmuntal
Copy link
Contributor Author

qmuntal commented Aug 19, 2022

@aarzilli @derekparker I'm mostly done with this PR and all tests in pkg/proc are passing. Could you do one final review?

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.
See the announcement here: https://azure.microsoft.com/en-us/blog/now-in-preview-azure-virtual-machines-with-ampere-altra-armbased-processors/

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.

Copy link
Member

@aarzilli aarzilli left a 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.

@@ -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()
Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link
Member

@aarzilli aarzilli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@derekparker derekparker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@derekparker derekparker merged commit 4455d6a into go-delve:master Sep 21, 2022
@nathanhammond
Copy link

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. 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for arm64 windows machines
4 participants