-
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/vet: move asm checks into cmd/asm #17544
Comments
/cc @josharian, since you have the perhaps dubious distinction of having the most recent commits to cmd/vet. :) Probably the way to do this would be to add a flag to the cmd/asm that causes it to just run the lexer and dump the post-preprocessed output back out. |
A dubious distinction indeed. :) This seems like a good idea. It'd also solve another annoyance with the current asmdecl check, which is poor handling of comments. The preprocessing would remove them. I'd have to investigate implementation. Running cmd/asm with a flag would be slow and flags upset Rob. It might be better to just share an internal package with cmd/asm, or extract a standalone preprocessor. |
If we just use cmd/asm to preprocess the input, we also need to make
cmd/asm to emit #line pragmas to redefine the line number for better (read,
non-confusing) error reports.
|
I would be fine with that. Would vet's asm checks then work on the token stream instead of the text? That would require some rewriting, but may ultimately be a better approach. |
Yes, probably. The current code is a highly functional but rather unreadable pile of regexps and loops. |
I have a tentative plan here, but I'd like to run it by @robpike before I start putting together CLs. Proposal:
Rob, what do you think? |
@rsc and I were chatting a bit about this and he suggested considering making the assembler just do the checks that vet does now. |
That's appealing. I see a few hitches:
Thoughts? |
As for 1, I think the idea was to emit these from the compiler along with go_asm.h. The build system already has to run the compiler before the assembler to generate go_asm.h. We've been talking about doing something similar as a possible part of registerizing the calling convention and dealing with existing assembly code. |
I just ran across a few more issues with vet's assembly checks. It doesn't understand hex in the frame size, so it parses the frame size as 0. And it doesn't understand expressions in offsets, so, e.g., |
Change https://golang.org/cl/147097 mentions this issue: |
2 similar comments
Change https://golang.org/cl/147097 mentions this issue: |
Change https://golang.org/cl/147097 mentions this issue: |
Currently cmd/asm's Parser.line both consumes a line of assembly from the lexer and assembles it. This CL separates these two steps so that the line parser can be reused for purposes other than generating a Prog stream. For #27539. Updates #17544. Change-Id: I452c9a2112fbcc1c94bf909efc0d1fcc71014812 Reviewed-on: https://go-review.googlesource.com/c/147097 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Change https://golang.org/cl/259338 mentions this issue: |
The signature of call16 is currently missing the "typ" parameter. This CL fixes this. This wasn't caught by vet because call16 is defined by macro expansion (see #17544), and we didn't notice the mismatch with the other call* functions because call16 is defined only on 32-bit architectures and lives alone in stubs32.go. Unfortunately, this means its GC signature is also wrong: the "arg" parameter is treated as a scalar rather than a pointer, so GC won't trace it and stack copying won't adjust it. This turns out to matter in exactly one case right now: on 32-bit architectures (which are the only architectures where call16 is defined), a stack-allocated defer of a function with a 16-byte or smaller argument frame including a non-empty result area can corrupt memory if the deferred function grows the stack and is invoked during a panic. Whew. All other current uses of reflectcall pass a heap-allocated "arg" frame (which happens to be reachable from other stack roots, so tracing isn't a problem). Curiously, in 2016, the signatures of all call* functions were wrong in exactly this way. CL 31654 fixed all of them in stubs.go, but missed the one in stubs32.go. Fixes #41795. Change-Id: I31e3c0df201f79ee5707eeb8dc4ff0d13fc10ada Reviewed-on: https://go-review.googlesource.com/c/go/+/259338 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Change https://golang.org/cl/259597 mentions this issue: |
Change https://golang.org/cl/259598 mentions this issue: |
The signature of call16 is currently missing the "typ" parameter. This CL fixes this. This wasn't caught by vet because call16 is defined by macro expansion (see #17544), and we didn't notice the mismatch with the other call* functions because call16 is defined only on 32-bit architectures and lives alone in stubs32.go. Unfortunately, this means its GC signature is also wrong: the "arg" parameter is treated as a scalar rather than a pointer, so GC won't trace it and stack copying won't adjust it. This turns out to matter in exactly one case right now: on 32-bit architectures (which are the only architectures where call16 is defined), a stack-allocated defer of a function with a 16-byte or smaller argument frame including a non-empty result area can corrupt memory if the deferred function grows the stack and is invoked during a panic. Whew. All other current uses of reflectcall pass a heap-allocated "arg" frame (which happens to be reachable from other stack roots, so tracing isn't a problem). Curiously, in 2016, the signatures of all call* functions were wrong in exactly this way. CL 31654 fixed all of them in stubs.go, but missed the one in stubs32.go. Updates #41795. Fixes #41797. Change-Id: I31e3c0df201f79ee5707eeb8dc4ff0d13fc10ada Reviewed-on: https://go-review.googlesource.com/c/go/+/259338 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/259598
The signature of call16 is currently missing the "typ" parameter. This CL fixes this. This wasn't caught by vet because call16 is defined by macro expansion (see #17544), and we didn't notice the mismatch with the other call* functions because call16 is defined only on 32-bit architectures and lives alone in stubs32.go. Unfortunately, this means its GC signature is also wrong: the "arg" parameter is treated as a scalar rather than a pointer, so GC won't trace it and stack copying won't adjust it. This turns out to matter in exactly one case right now: on 32-bit architectures (which are the only architectures where call16 is defined), a stack-allocated defer of a function with a 16-byte or smaller argument frame including a non-empty result area can corrupt memory if the deferred function grows the stack and is invoked during a panic. Whew. All other current uses of reflectcall pass a heap-allocated "arg" frame (which happens to be reachable from other stack roots, so tracing isn't a problem). Curiously, in 2016, the signatures of all call* functions were wrong in exactly this way. CL 31654 fixed all of them in stubs.go, but missed the one in stubs32.go. Updates #41795. Fixes #41796. Change-Id: I31e3c0df201f79ee5707eeb8dc4ff0d13fc10ada Reviewed-on: https://go-review.googlesource.com/c/go/+/259338 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/259597
The signature of call16 is currently missing the "typ" parameter. This CL fixes this. This wasn't caught by vet because call16 is defined by macro expansion (see golang#17544), and we didn't notice the mismatch with the other call* functions because call16 is defined only on 32-bit architectures and lives alone in stubs32.go. Unfortunately, this means its GC signature is also wrong: the "arg" parameter is treated as a scalar rather than a pointer, so GC won't trace it and stack copying won't adjust it. This turns out to matter in exactly one case right now: on 32-bit architectures (which are the only architectures where call16 is defined), a stack-allocated defer of a function with a 16-byte or smaller argument frame including a non-empty result area can corrupt memory if the deferred function grows the stack and is invoked during a panic. Whew. All other current uses of reflectcall pass a heap-allocated "arg" frame (which happens to be reachable from other stack roots, so tracing isn't a problem). Curiously, in 2016, the signatures of all call* functions were wrong in exactly this way. CL 31654 fixed all of them in stubs.go, but missed the one in stubs32.go. Updates golang#41795. Fixes golang#41797. Change-Id: I31e3c0df201f79ee5707eeb8dc4ff0d13fc10ada Reviewed-on: https://go-review.googlesource.com/c/go/+/259338 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/259598
With the addition of ABIInternal assembly functions in runtime, vet is increasingly getting confused by the use of preprocessor in the runtime assembly code. It also doesn't know how to check the calling conventions for ABIInternal functions and I don't think we want to put more knowledge like that into vet (for example, it doesn't know about ABIInternal when computing argument frame sizes, it gets the stack offsets of stack-assigned arguments and results wrong, and it doesn't have any mechanism for checking argument-assigned arguments or results). The compiler, of course, knows all these things, so to me this argues strongly for moving these checks into cmd/asm with a back-channel from the compiler. |
Currently cmd/vet does not expand preprocessor macros in assembly code. As a result, it missed several issues in the runtime (a73d68e) and x/crypto (golang/crypto@5953a47, golang/crypto@e67f5ec, golang/crypto@3c0d69f). It would be nice if it could preprocess the assembly code before vetting it.
The text was updated successfully, but these errors were encountered: