mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/cgo: add #cgo noescape/nocallback annotations
When passing pointers of Go objects from Go to C, the cgo command generate _Cgo_use(pN) for the unsafe.Pointer type arguments, so that the Go compiler will escape these object to heap.
Since the C function may callback to Go, then the Go stack might grow/shrink, that means the pointers that the C function have will be invalid.
After adding the #cgo noescape annotation for a C function, the cgo command won't generate _Cgo_use(pN), and the Go compiler won't force the object escape to heap.
After adding the #cgo nocallback annotation for a C function, which means the C function won't callback to Go, if it do callback to Go, the Go process will crash.
Fixes #56378
Change-Id: Ifdca070584e0d349c7b12276270e50089e481f7a
GitHub-Last-Rev: f1a17b08b0
GitHub-Pull-Request: golang/go#60399
Reviewed-on: https://go-review.googlesource.com/c/go/+/497837
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
1a01cb22f9
commit
24b9ef1a73
15 changed files with 312 additions and 33 deletions
|
|
@ -73,18 +73,32 @@ func cname(s string) string {
|
|||
return s
|
||||
}
|
||||
|
||||
// DiscardCgoDirectives processes the import C preamble, and discards
|
||||
// all #cgo CFLAGS and LDFLAGS directives, so they don't make their
|
||||
// way into _cgo_export.h.
|
||||
func (f *File) DiscardCgoDirectives() {
|
||||
// ProcessCgoDirectives processes the import C preamble:
|
||||
// 1. discards all #cgo CFLAGS, LDFLAGS, nocallback and noescape directives,
|
||||
// so they don't make their way into _cgo_export.h.
|
||||
// 2. parse the nocallback and noescape directives.
|
||||
func (f *File) ProcessCgoDirectives() {
|
||||
linesIn := strings.Split(f.Preamble, "\n")
|
||||
linesOut := make([]string, 0, len(linesIn))
|
||||
f.NoCallbacks = make(map[string]bool)
|
||||
f.NoEscapes = make(map[string]bool)
|
||||
for _, line := range linesIn {
|
||||
l := strings.TrimSpace(line)
|
||||
if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
|
||||
linesOut = append(linesOut, line)
|
||||
} else {
|
||||
linesOut = append(linesOut, "")
|
||||
|
||||
// #cgo (nocallback|noescape) <function name>
|
||||
if fields := strings.Fields(l); len(fields) == 3 {
|
||||
directive := fields[1]
|
||||
funcName := fields[2]
|
||||
if directive == "nocallback" {
|
||||
f.NoCallbacks[funcName] = true
|
||||
} else if directive == "noescape" {
|
||||
f.NoEscapes[funcName] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
f.Preamble = strings.Join(linesOut, "\n")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue