cgo: do not allow capturing of external/exported functions

Instead of assuming all declared (but not defined) functions are CGo
functions, mark all pointer params of externally visible symbols
'nocapture'. This means you may not store pointers between function
calls.

This is already the case when calling CGo functions upstream:
https://golang.org/cmd/cgo/#hdr-Passing_pointers
Этот коммит содержится в:
Ayke van Laethem 2019-05-03 21:11:30 +02:00 коммит произвёл Ron Evans
родитель 2511aefac0
коммит a79edf416c
2 изменённых файлов: 12 добавлений и 12 удалений

Просмотреть файл

@ -629,6 +629,18 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame {
frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType)
}
// External/exported functions may not retain pointer values.
// https://golang.org/cmd/cgo/#hdr-Passing_pointers
if f.IsExported() {
nocaptureKind := llvm.AttributeKindID("nocapture")
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
for i, typ := range paramTypes {
if typ.TypeKind() == llvm.PointerTypeKind {
frame.fn.LLVMFn.AddAttributeAtIndex(i+1, nocapture)
}
}
}
return frame
}

Просмотреть файл

@ -307,18 +307,6 @@ func (c *Compiler) doesEscape(value llvm.Value) bool {
return true
}
} else if use.IsACallInst() != nilValue {
// Call only escapes when the (pointer) parameter is not marked
// "nocapture". This flag means that the parameter does not escape
// the give function.
if use.CalledValue().IsAFunction() != nilValue {
if use.CalledValue().IsDeclaration() {
// Kind of dirty: assume external functions don't let
// pointers escape.
// TODO: introduce //go:noescape that sets the 'nocapture'
// flag on each input parameter.
continue
}
}
if !c.hasFlag(use, value, "nocapture") {
return true
}