-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
delve: add linux-riscv64 support #3785
Conversation
_scripts/make.go
Outdated
@@ -51,6 +51,8 @@ func NewMakeCommands() *cobra.Command { | |||
envflags = append(envflags, "GOOS="+OS) | |||
} | |||
if len(envflags) > 0 { | |||
// Add -mod=vendor to envflags due to riscv arch package has not upstream yet. | |||
envflags = append(envflags, "-mod=vendor") |
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 can't do this. We either wait for this to be merged upstream or use a different package.
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.
This is just a workaround, we will remove that once the arch package support was upstream.
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.
Removed this workaround, riscv64 support is already merged into x/arch, see golang/arch@7874f23
@@ -1,4 +1,4 @@ | |||
//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) | |||
//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) && !riscv64 |
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.
If we don't have a build agent for riscv64 this needs to be guarded with a build flag like ppc64le.
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 was wondering whether we could add riscv64 to delve CI support? I have saw the portnotes, maybe we could donate some kinds of riscv hardware for this purpose?
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.
That could be done. The instructions to add a teamcity agent are here: https://www.jetbrains.com/help/teamcity/install-teamcity-agent.html.
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.
Thanks, we could provide riscv hardware for this, does this ci machine need to be controled by delve dev team directly or we could host it in a third-party organization?
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.
You can host it yourself. The link above has the instructions to install and configure an agent. You can also download the installer from https://delve.teamcity.com/agents/overview, by clicking on the "Install agent" button. Then .teamcity/settings.kts
will have to be modified (you can basically copy the changes made for ppc64le) and the agent will have to be authorized (which we will do once it's online).
return fpregs, riscv64_fpregs.Fregs, err | ||
} | ||
|
||
func pokeMemory(pid int, addr uintptr, data []byte) (count int, err error) { |
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 is this needed instead of using the normal way we write to memory?
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.
Originally I think we might have a TOCTOU issue when emulate singlestep by insert a ebreak instruction, so I use it for sync the cache to avoid that, but seems that delve will stop every other threads while debugging, if so we don't need it.
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 just runs the test without this custom pokeMemory
, and it's works well, so we can safely restore using sys.PtracePokeData
.
pkg/proc/riscv64_arch.go
Outdated
return false | ||
} | ||
switch it.frame.Current.Fn.Name { | ||
case "runtime.cgocallback_gofunc", "runtime.cgocallback": |
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.
This stuff doesn't work or the cgo stacktrace tests would work, delete it.
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.
Deleted.
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 meant all of it: runtime.asmcgocall and crosscall2 are the same thing as is the switch at the bottom of this function.
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.
runtime.asmcgocall
and crosscall2
removed.
58b3942
to
b32dcc0
Compare
@aarzilli I was working on cgostacktrace for riscv64, it seems that both Moreover, ppc64le do follows the numbers found in |
I don't remember how the values for arm64 were derived and, as far as I know, the ppc64 implementation never worked so it's possible that the logic is wrong. |
b32dcc0
to
d56368d
Compare
@aarzilli Hi, riscv64 x/arch support is already merged in upstream, you could find that in golang/arch@7874f23, I have also updated the code, could you please give this patch another look? Thanks a lot. |
"golang.org/x/arch/riscv64/riscv64asm" | ||
) | ||
|
||
// Regs is wrapper for sys.PtraceRegs |
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 comment needs to start with "RISCV64Registers is..."
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.
Fixed.
} | ||
} | ||
|
||
// Refer to the definition of struct __riscv_d_ext_state in the kernel ptrace.h |
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 comment needs to start with "RISCV64PtraceFpRegs is..."
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.
Fixed.
pkg/proc/core/linux_core.go
Outdated
@@ -333,6 +367,15 @@ func readNote(r io.ReadSeeker, machineType elf.Machine) (*note, error) { | |||
} | |||
note.Desc = fpregs | |||
} | |||
|
|||
if machineType == _EM_RISCV { |
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.
else if or convert to a switch.
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.
Fixed.
pkg/proc/native/proc.go
Outdated
@@ -372,7 +372,7 @@ func (dbp *nativeProcess) initialize(path string, debugInfoDirs []string) (*proc | |||
// with gdb once AsyncPreempt was enabled. While implementing the port, | |||
// few tests failed while it was enabled, but cannot be warrantied that | |||
// disabling it fixed the issues. | |||
DisableAsyncPreempt: runtime.GOOS == "windows" || (runtime.GOOS == "linux" && runtime.GOARCH == "arm64") || (runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le"), | |||
DisableAsyncPreempt: runtime.GOOS == "windows" || (runtime.GOOS == "linux" && runtime.GOARCH == "arm64") || (runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le") || (runtime.GOOS == "linux" && runtime.GOARCH == "riscv64"), |
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 is a comment above explaining why we disable async preempt, if it really needs to be disable on riscv64 it should be updated to describe 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.
Some tests failed like the TestTraceDirRecursion, the symptom which seems to cause by async preempt but disable it doesn't work just like I said, so I'll enable it, until we find the exact reason.
Most of tests were passed, the few failed tests seems to be related with riscv64 go compiler itself, for example, the strange repetition in
TestTraceDirRecursion
, just like this:> goroutine(1): main.A(5, 5) > goroutine(1): main.A(4, 4) > goroutine(1): main.A(4, 4) > goroutine(1): main.A(3, 3) > goroutine(1): main.A(2, 2) > goroutine(1): main.A(2, 2) > goroutine(1): main.A(1, 1) > goroutine(1): main.A(1, 1) >> goroutine(1): main.A => (1) >> goroutine(1): main.A => (2) >> goroutine(1): main.A => (6) >> goroutine(1): main.A => (24) >> goroutine(1): main.A => (120) 120
I tried to disable the asyncpreemt, but unfortunately, It doesn't work.
@@ -1,4 +1,4 @@ | |||
//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) | |||
//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) && !riscv64 |
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.
That could be done. The instructions to add a teamcity agent are here: https://www.jetbrains.com/help/teamcity/install-teamcity-agent.html.
pkg/proc/riscv64_arch.go
Outdated
return false | ||
} | ||
switch it.frame.Current.Fn.Name { | ||
case "runtime.cgocallback_gofunc", "runtime.cgocallback": |
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 meant all of it: runtime.asmcgocall and crosscall2 are the same thing as is the switch at the bottom of this function.
d56368d
to
c330f5a
Compare
@aarzilli Hi, the CI machine is ready and I've modified the
BTW, this machine runs openEuler 24.09, is it has to be Ubuntu or other distro is just fine? Thanks. |
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 agent was approved.
PS. note that the changes to the teamcity configuration will not take effect until we merge this PR.
There are merge conflicts with go.mod and vendor/modules.txt, aside from that I think everything is fine. |
Resolved, now everything should be okay. |
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
Thanks for the contribution! |
This patch adds linux-riscv64 support to delve, tested under go 1.22.5/ubuntu 24.04 riscv64 & go 1.21.4/openEuler 24.03 riscv64.
It's worth noticing that due to riscv64 do not support
PTRACE_SINGLESTEP
, just like arm32, so we insertebreak
to emulate it. The__NR_riscv_flush_icache
syscall is used to avoid self modify code's TOCTOU error, but I wasn't able to find any difference withsys.PtracePokeData
. So it still needs some kinds of validation.To support CGO, we have to insert
c.ebreak
instead ofebreak
as breakpoint due to gcc/clang will enable c extension by default, and useebreak
as altbreakpoint, but due to a arm64 specific workaround, it can not handle hardcoded breakpoint correctly, so I disabled it on riscv64 platform.Most of tests were passed, the few failed tests seems to be related with riscv64 go compiler itself, for example, the strange repetition in
TestTraceDirRecursion
, just like this:I tried to disable the asyncpreemt, but unfortunately, It doesn't work.
Also, the riscv64 x/arch support hasn't been merged to upstream, so I use
-mod=vendor
here as a workaround.