Merge remote-tracking branch 'upstream/master' into 41884-fix

This commit is contained in:
Nuno Cruces 2021-01-27 19:00:24 +00:00
commit 92f02c9697
43 changed files with 9206 additions and 7531 deletions

View File

@ -464,6 +464,57 @@ Function is the top of the call stack. Traceback should stop at this function.
</li>
</ul>
<h3 id="data-offsets">Interacting with Go types and constants</h3>
<p>
If a package has any .s files, then <code>go build</code> will direct
the compiler to emit a special header called <code>go_asm.h</code>,
which the .s files can then <code>#include</code>.
The file contains symbolic <code>#define</code> constants for the
offsets of Go struct fields, the sizes of Go struct types, and most
Go <code>const</code> declarations defined in the current package.
Go assembly should avoid making assumptions about the layout of Go
types and instead use these constants.
This improves the readability of assembly code, and keeps it robust to
changes in data layout either in the Go type definitions or in the
layout rules used by the Go compiler.
</p>
<p>
Constants are of the form <code>const_<i>name</i></code>.
For example, given the Go declaration <code>const bufSize =
1024</code>, assembly code can refer to the value of this constant
as <code>const_bufSize</code>.
</p>
<p>
Field offsets are of the form <code><i>type</i>_<i>field</i></code>.
Struct sizes are of the form <code><i>type</i>__size</code>.
For example, consider the following Go definition:
</p>
<pre>
type reader struct {
buf [bufSize]byte
r int
}
</pre>
<p>
Assembly can refer to the size of this struct
as <code>reader__size</code> and the offsets of the two fields
as <code>reader_buf</code> and <code>reader_r</code>.
Hence, if register <code>R1</code> contains a pointer to
a <code>reader</code>, assembly can reference the <code>r</code> field
as <code>reader_r(R1)</code>.
</p>
<p>
If any of these <code>#define</code> names are ambiguous (for example,
a struct with a <code>_size</code> field), <code>#include
"go_asm.h"</code> will fail with a "redefinition of macro" error.
</p>
<h3 id="runtime">Runtime Coordination</h3>
<p>
@ -615,21 +666,15 @@ Here follow some descriptions of key Go-specific details for the supported archi
<p>
The runtime pointer to the <code>g</code> structure is maintained
through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
An OS-dependent macro <code>get_tls</code> is defined for the assembler if the source is
in the <code>runtime</code> package and includes a special header, <code>go_tls.h</code>:
In the runtime package, assembly code can include <code>go_tls.h</code>, which defines
an OS- and architecture-dependent macro <code>get_tls</code> for accessing this register.
The <code>get_tls</code> macro takes one argument, which is the register to load the
<code>g</code> pointer into.
</p>
<pre>
#include "go_tls.h"
</pre>
<p>
Within the runtime, the <code>get_tls</code> macro loads its argument register
with a pointer to the <code>g</code> pointer, and the <code>g</code> struct
contains the <code>m</code> pointer.
There's another special header containing the offsets for each
element of <code>g</code>, called <code>go_asm.h</code>.
The sequence to load <code>g</code> and <code>m</code> using <code>CX</code> looks like this:
For example, the sequence to load <code>g</code> and <code>m</code>
using <code>CX</code> looks like this:
</p>
<pre>
@ -642,8 +687,7 @@ MOVL g_m(AX), BX // Move g.m into BX.
</pre>
<p>
Note: The code above works only in the <code>runtime</code> package, while <code>go_tls.h</code> also
applies to <a href="#arm">arm</a>, <a href="#amd64">amd64</a> and amd64p32, and <code>go_asm.h</code> applies to all architectures.
The <code>get_tls</code> macro is also defined on <a href="#amd64">amd64</a>.
</p>
<p>

View File

@ -275,7 +275,7 @@ Do not send CLs removing the interior tags from such phrases.
When the <code>-export</code> flag is specified, the <code>BuildID</code>
field is now set to the build ID of the compiled package. This is equivalent
to running <code>go</code> <code>tool</code> <code>buildid</code> on
<code>go</code> <code>list</code> <code>-exported</code> <code>-f</code> <code>{{.Export}</code>,
<code>go</code> <code>list</code> <code>-exported</code> <code>-f</code> <code>{{.Export}}</code>,
but without the extra step.
</p>
@ -461,10 +461,10 @@ func TestFoo(t *testing.T) {
<p>
The new <a href="/pkg/io/fs/"><code>io/fs</code></a> package
defines an abstraction for read-only trees of files,
the <a href="/pkg/io/fs/#FS"><code>fs.FS</code></a> interface,
and the standard library packages have
been adapted to make use of the interface as appropriate.
defines the <a href="/pkg/io/fs/#FS"><code>fs.FS</code></a> interface,
an abstraction for read-only trees of files.
The standard library packages have been adapted to make use
of the interface as appropriate.
</p>
<p>
@ -499,6 +499,44 @@ func TestFoo(t *testing.T) {
implementations.
</p>
<h3 id="ioutil">Deprecation of io/ioutil</h3>
<p>
The <a href="/pkg/io/ioutil/"><code>io/ioutil</code></a> package has
turned out to be a poorly defined and hard to understand collection
of things. All functionality provided by the package has been moved
to other packages. The <code>io/ioutil</code> package remains and
will continue to work as before, but we encourage new code to use
the new definitions in the <a href="/pkg/io/"><code>io</code></a> and
<a href="/pkg/os/"><code>os</code></a> packages.
Here is a list of the new locations of the names exported
by <code>io/ioutil</code>:
<ul>
<li><a href="/pkg/io/ioutil/#Discard"><code>Discard</code></a>
=> <a href="/pkg/io/#Discard"><code>io.Discard</code></a></li>
<li><a href="/pkg/io/ioutil/#NopCloser"><code>NopCloser</code></a>
=> <a href="/pkg/io/#NopCloser"><code>io.NopCloser</code></a></li>
<li><a href="/pkg/io/ioutil/#ReadAll"><code>ReadAll</code></a>
=> <a href="/pkg/io/#ReadAll"><code>io.ReadAll</code></a></li>
<li><a href="/pkg/io/ioutil/#ReadDir"><code>ReadDir</code></a>
=> <a href="/pkg/os/#ReadDir"><code>os.ReadDir</code></a>
(note: returns a slice of
<a href="/pkg/os/#DirEntry"><code>os.DirEntry</code></a>
rather than a slice of
<a href="/pkg/fs/#FileInfo"><code>fs.FileInfo</code></a>)
</li>
<li><a href="/pkg/io/ioutil/#ReadFile"><code>ReadFile</code></a>
=> <a href="/pkg/os/#ReadFile"><code>os.ReadFile</code></a></li>
<li><a href="/pkg/io/ioutil/#TempDir"><code>TempDir</code></a>
=> <a href="/pkg/os/#MkdirTemp"><code>os.MkdirTemp</code></a></li>
<li><a href="/pkg/io/ioutil/#TempFile"><code>TempFile</code></a>
=> <a href="/pkg/os/#CreateTemp"><code>os.CreateTemp</code></a></li>
<li><a href="/pkg/io/ioutil/#WriteFile"><code>WriteFile</code></a>
=> <a href="/pkg/os/#WriteFile"><code>os.WriteFile</code></a></li>
</ul>
</p>
<!-- okay-after-beta1
TODO: decide if any additional changes are worth factoring out from
"Minor changes to the library" and highlighting in "Core library"
@ -623,6 +661,14 @@ func TestFoo(t *testing.T) {
method allows accessing the <a href="/pkg/crypto/x509/#SystemRootsError.Err"><code>Err</code></a>
field through the <a href="/pkg/errors"><code>errors</code></a> package functions.
</p>
<p><!-- CL 230025 -->
On Unix systems, the <code>crypto/x509</code> package is now more
efficient in how it stores its copy of the system cert pool.
Programs that use only a small number of roots will use around a
half megabyte less memory.
</p>
</dd>
</dl><!-- crypto/x509 -->
@ -685,6 +731,37 @@ func TestFoo(t *testing.T) {
</dd>
</dl><!-- flag -->
<dl id="go/build"><dt><a href="/pkg/go/build/">go/build</a></dt>
<dd>
<p><!-- CL 243941, CL 283636 -->
The <a href="/pkg/go/build/#Package"><code>Package</code></a>
struct has new fields that report information
about <code>//go:embed</code> directives in the package:
<a href="/pkg/go/build/#Package.EmbedPatterns"><code>EmbedPatterns</code></a>,
<a href="/pkg/go/build/#Package.EmbedPatternPos"><code>EmbedPatternPos</code></a>,
<a href="/pkg/go/build/#Package.TestEmbedPatterns"><code>TestEmbedPatterns</code></a>,
<a href="/pkg/go/build/#Package.TestEmbedPatternPos"><code>TestEmbedPatternPos</code></a>,
<a href="/pkg/go/build/#Package.XTestEmbedPatterns"><code>XTestEmbedPatterns</code></a>,
<a href="/pkg/go/build/#Package.XTestEmbedPatternPos"><code>XTestEmbedPatternPos</code></a>.
</p>
<p><!-- CL 240551 -->
The <a href="/pkg/go/build/#Package"><code>Package</code></a> field
<a href="/pkg/go/build/#Package.IgnoredGoFiles"><code>IgnoredGoFiles</code></a>
will no longer include files that start with "_" or ".",
as those files are always ignored.
<code>IgnoredGoFiles</code> is for files ignored because of
build constraints.
</p>
<p><!-- CL 240551 -->
The new <a href="/pkg/go/build/#Package"><code>Package</code></a>
field <a href="/pkg/go/build/#Package.IgnoredOtherFiles"><code>IgnoredOtherFiles</code></a>
has a list of non-Go files ignored because of build constraints.
</p>
</dd>
</dl><!-- go/build -->
<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
<dd>
<p><!-- CL 243938 -->
@ -703,6 +780,15 @@ func TestFoo(t *testing.T) {
The package now defines a
<a href="/pkg/io/#ReadSeekCloser"><code>ReadSeekCloser</code></a> interface.
</p>
<p><!-- CL 263141 -->
The package now defines
<a href="/pkg/io/#Discard"><code>Discard</code></a>,
<a href="/pkg/io/#NopCloser"><code>NopCloser</code></a>, and
<a href="/pkg/io/#ReadAll"><code>ReadAll</code></a>,
to be used instead of the same names in the
<a href="/pkg/io/ioutil/"><code>io/ioutil</code></a> package.
</p>
</dd>
</dl><!-- io -->
@ -857,6 +943,52 @@ func TestFoo(t *testing.T) {
instead of the unexported <code>errFinished</code> when the process has
already finished.
</p>
<p><!-- CL 261540 -->
The package defines a new type
<a href="/pkg/os/#DirEntry"><code>DirEntry</code></a>
as an alias for <a href="/pkg/io/fs/#DirEntry"><code>fs.DirEntry</code></a>.
The new <a href="/pkg/os/#ReadDir"><code>ReadDir</code></a>
function and the new
<a href="/pkg/os/#File.ReadDir"><code>File.ReadDir</code></a>
method can be used to read the contents of a directory into a
slice of <a href="/pkg/os/#DirEntry"><code>DirEntry</code></a>.
The <a href="/pkg/os/#File.Readdir"><code>File.Readdir</code></a>
method (note the lower case <code>d</code> in <code>dir</code>)
still exists, returning a slice of
<a href="/pkg/os/#FileInfo"><code>FileInfo</code></a>, but for
most programs it will be more efficient to switch to
<a href="/pkg/os/#File.ReadDir"><code>File.ReadDir</code></a>.
</p>
<p><!-- CL 263141 -->
The package now defines
<a href="/pkg/os/#CreateTemp"><code>CreateTemp</code></a>,
<a href="/pkg/os/#MkdirTemp"><code>MkdirTemp</code></a>,
<a href="/pkg/os/#ReadFile"><code>ReadFile</code></a>, and
<a href="/pkg/os/#WriteFile"><code>WriteFile</code></a>,
to be used instead of functions defined in the
<a href="/pkg/io/ioutil/"><code>io/ioutil</code></a> package.
</p>
<p><!-- CL 243906 -->
The types <a href="/pkg/os/#FileInfo"><code>FileInfo</code></a>,
<a href="/pkg/os/#FileMode"><code>FileMode</code></a>, and
<a href="/pkg/os/#PathError"><code>PathError</code></a>
are now aliases for types of the same name in the
<a href="/pkg/io/fs/"><code>io/fs</code></a> package.
Function signatures in the <a href="/pkg/os/"><code>os</code></a>
package have been updated to refer to the names in the
<a href="/pkg/io/fs/"><code>io/fs</code></a> package.
This should not affect any existing code.
</p>
<p><!-- CL 243911 -->
The new <a href="/pkg/os/#DirFS"><code>DirFS</code></a> function
provides an implementation of
<a href="/pkg/io/fs/#FS"><code>fs.FS</code></a> backed by a tree
of operating system files.
</p>
</dd>
</dl><!-- os -->
@ -887,9 +1019,9 @@ func TestFoo(t *testing.T) {
<dd>
<p><!-- CL 267887 -->
The new function
<a href="/pkg/path/filepath/WalkDir"><code>WalkDir</code></a>
<a href="/pkg/path/filepath/#WalkDir"><code>WalkDir</code></a>
is similar to
<a href="/pkg/path/filepath/Walk"><code>Walk</code></a>,
<a href="/pkg/path/filepath/#Walk"><code>Walk</code></a>,
but is typically more efficient.
The function passed to <code>WalkDir</code> receives a
<a href="/pkg/io/fs/#DirEntry"><code>fs.DirEntry</code></a>
@ -975,6 +1107,25 @@ func TestFoo(t *testing.T) {
</dd>
</dl><!-- syscall -->
<dl id="testing/iotest"><dt><a href="/pkg/testing/iotest/">testing/iotest</a></dt>
<dd>
<p><!-- CL 199501 -->
The new
<a href="/pkg/testing/iotest/#ErrReader"><code>ErrReader</code></a>
function returns an
<a href="/pkg/io/#Reader"><code>io.Reader</code></a> that always
returns an error.
</p>
<p><!-- CL 243909 -->
The new
<a href="/pkg/testing/iotest/#TestReader"><code>TestReader</code></a>
function tests that an <a href="/pkg/io/#Reader"><code>io.Reader</code></a>
behaves correctly.
</p>
</dd>
</dl><!-- testing/iotest -->
<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
<dd>
<p><!-- CL 254257, golang.org/issue/29770 -->

View File

@ -8,8 +8,8 @@
# Consult https://www.iana.org/time-zones for the latest versions.
# Versions to use.
CODE=2020f
DATA=2020f
CODE=2021a
DATA=2021a
set -e
rm -rf work

Binary file not shown.

View File

@ -267,7 +267,7 @@ func walkstmt(n *Node) *Node {
if n.List.Len() == 0 {
break
}
if (Curfn.Type.FuncType().Outnamed && n.List.Len() > 1) || paramoutheap(Curfn) {
if (Curfn.Type.FuncType().Outnamed && n.List.Len() > 1) || paramoutheap(Curfn) || Curfn.Func.HasDefer() {
// assign to the function out parameters,
// so that reorder3 can fix up conflicts
var rl []*Node
@ -2233,7 +2233,15 @@ func aliased(r *Node, all []*Node) bool {
memwrite = true
continue
case PAUTO, PPARAM, PPARAMOUT:
case PPARAMOUT:
// Assignments to a result parameter in a function with defers
// becomes visible early if evaluation of any later expression
// panics (#43835).
if Curfn.Func.HasDefer() {
return true
}
fallthrough
case PAUTO, PPARAM:
if l.Name.Addrtaken() {
memwrite = true
continue

View File

@ -1,5 +1,12 @@
[!cgo] skip
# Set CC explicitly to something that requires a PATH lookup.
# Normally, the default is gcc or clang, but if CC was set during make.bash,
# that becomes the default.
[exec:clang] env CC=clang
[exec:gcc] env CC=gcc
[!exec:clang] [!exec:gcc] skip 'Unknown C compiler'
env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache.
[!windows] env PATH=.:$PATH
[!windows] chmod 0755 p/gcc p/clang

View File

@ -1,13 +1,14 @@
# Check that if the PATH directory containing the C compiler has a space,
# we can still use that compiler with cgo.
# Verifies #43808.
[!cgo] skip
# Check if default CC was set by make.bash.
# If it was, this test is not valid.
go env CC
stdout '^(clang|gcc)$'
# Set CC explicitly to something that requires a PATH lookup.
# Normally, the default is gcc or clang, but if CC was set during make.bash,
# that becomes the default.
[exec:clang] env CC=clang
[exec:gcc] env CC=gcc
[!exec:clang] [!exec:gcc] skip 'Unknown C compiler'
[!windows] chmod 0755 $WORK/'program files'/clang
[!windows] chmod 0755 $WORK/'program files'/gcc
@ -18,10 +19,10 @@ stdout '^(clang|gcc)$'
[windows] exists -exec $WORK/'program files'/clang.bat
[windows] env PATH=$WORK\'program files';%PATH%
! exists log.txt
! exists $WORK/log.txt
? go build -x
exists log.txt
rm log.txt
exists $WORK/log.txt
rm $WORK/log.txt
# TODO(#41400, #43078): when CC is set explicitly, it should be allowed to
# contain spaces separating arguments, and it should be possible to quote
@ -30,7 +31,7 @@ rm log.txt
[!windows] env CC=$WORK/'program files'/gcc
[windows] env CC=$WORK\'program files'\gcc.bat
! go build -x
! exists log.txt
! exists $WORK/log.txt
-- go.mod --
module m
@ -44,12 +45,12 @@ import "C"
-- $WORK/program files/gcc --
#!/bin/sh
echo ok >log.txt
echo ok >$WORK/log.txt
-- $WORK/program files/clang --
#!/bin/sh
echo ok >log.txt
echo ok >$WORK/log.txt
-- $WORK/program files/gcc.bat --
echo ok >log.txt
echo ok >%WORK%\log.txt
-- $WORK/program files/clang.bat --
echo ok >log.txt
echo ok >%WORK%\log.txt

View File

@ -2,7 +2,7 @@
# embedded in a package, that is referenced by a Go assembly function.
# See issue 33139.
[!gc] skip
[!exec:cc] skip
[!cgo] skip
# External linking is not supported on linux/ppc64.
# See: https://github.com/golang/go/issues/8912

View File

@ -1720,6 +1720,8 @@ var v = "v";
`
func TestEscapeRace(t *testing.T) {
t.Skip("this test currently fails with -race; see issue #39807")
tmpl := New("")
_, err := tmpl.New("templ.html").Parse(raceText)
if err != nil {
@ -1777,6 +1779,39 @@ func TestRecursiveExecute(t *testing.T) {
}
}
// recursiveInvoker is for TestRecursiveExecuteViaMethod.
type recursiveInvoker struct {
t *testing.T
tmpl *Template
}
func (r *recursiveInvoker) Recur() (string, error) {
var sb strings.Builder
if err := r.tmpl.ExecuteTemplate(&sb, "subroutine", nil); err != nil {
r.t.Fatal(err)
}
return sb.String(), nil
}
func TestRecursiveExecuteViaMethod(t *testing.T) {
tmpl := New("")
top, err := tmpl.New("x.html").Parse(`{{.Recur}}`)
if err != nil {
t.Fatal(err)
}
_, err = tmpl.New("subroutine").Parse(`<a href="/x?p={{"'a<b'"}}">`)
if err != nil {
t.Fatal(err)
}
r := &recursiveInvoker{
t: t,
tmpl: tmpl,
}
if err := top.Execute(io.Discard, r); err != nil {
t.Fatal(err)
}
}
// Issue 43295.
func TestTemplateFuncsAfterClone(t *testing.T) {
s := `{{ f . }}`

View File

@ -11,7 +11,6 @@ import (
"os"
"path"
"path/filepath"
"reflect"
"sync"
"text/template"
"text/template/parse"
@ -36,20 +35,18 @@ var escapeOK = fmt.Errorf("template escaped correctly")
// nameSpace is the data structure shared by all templates in an association.
type nameSpace struct {
mu sync.RWMutex
mu sync.Mutex
set map[string]*Template
escaped bool
esc escaper
// The original functions, before wrapping.
funcMap FuncMap
}
// Templates returns a slice of the templates associated with t, including t
// itself.
func (t *Template) Templates() []*Template {
ns := t.nameSpace
ns.mu.RLock()
defer ns.mu.RUnlock()
ns.mu.Lock()
defer ns.mu.Unlock()
// Return a slice so we don't expose the map.
m := make([]*Template, 0, len(ns.set))
for _, v := range ns.set {
@ -87,8 +84,8 @@ func (t *Template) checkCanParse() error {
if t == nil {
return nil
}
t.nameSpace.mu.RLock()
defer t.nameSpace.mu.RUnlock()
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
if t.nameSpace.escaped {
return fmt.Errorf("html/template: cannot Parse after Execute")
}
@ -97,16 +94,6 @@ func (t *Template) checkCanParse() error {
// escape escapes all associated templates.
func (t *Template) escape() error {
t.nameSpace.mu.RLock()
escapeErr := t.escapeErr
t.nameSpace.mu.RUnlock()
if escapeErr != nil {
if escapeErr == escapeOK {
return nil
}
return escapeErr
}
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
t.nameSpace.escaped = true
@ -134,8 +121,6 @@ func (t *Template) Execute(wr io.Writer, data interface{}) error {
if err := t.escape(); err != nil {
return err
}
t.nameSpace.mu.RLock()
defer t.nameSpace.mu.RUnlock()
return t.text.Execute(wr, data)
}
@ -151,8 +136,6 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
if err != nil {
return err
}
t.nameSpace.mu.RLock()
defer t.nameSpace.mu.RUnlock()
return tmpl.text.Execute(wr, data)
}
@ -160,27 +143,13 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
// is escaped, or returns an error if it cannot be. It returns the named
// template.
func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
t.nameSpace.mu.RLock()
tmpl = t.set[name]
var escapeErr error
if tmpl != nil {
escapeErr = tmpl.escapeErr
}
t.nameSpace.mu.RUnlock()
if tmpl == nil {
return nil, fmt.Errorf("html/template: %q is undefined", name)
}
if escapeErr != nil {
if escapeErr != escapeOK {
return nil, escapeErr
}
return tmpl, nil
}
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
t.nameSpace.escaped = true
tmpl = t.set[name]
if tmpl == nil {
return nil, fmt.Errorf("html/template: %q is undefined", name)
}
if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
return nil, tmpl.escapeErr
}
@ -286,13 +255,6 @@ func (t *Template) Clone() (*Template, error) {
}
ns := &nameSpace{set: make(map[string]*Template)}
ns.esc = makeEscaper(ns)
if t.nameSpace.funcMap != nil {
ns.funcMap = make(FuncMap, len(t.nameSpace.funcMap))
for name, fn := range t.nameSpace.funcMap {
ns.funcMap[name] = fn
}
}
wrapFuncs(ns, textClone, ns.funcMap)
ret := &Template{
nil,
textClone,
@ -307,13 +269,12 @@ func (t *Template) Clone() (*Template, error) {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
}
x.Tree = x.Tree.Copy()
tc := &Template{
ret.set[name] = &Template{
nil,
x,
x.Tree,
ret.nameSpace,
}
ret.set[name] = tc
}
// Return the template associated with the name of this template.
return ret.set[ret.Name()], nil
@ -382,43 +343,10 @@ type FuncMap map[string]interface{}
// type. However, it is legal to overwrite elements of the map. The return
// value is the template, so calls can be chained.
func (t *Template) Funcs(funcMap FuncMap) *Template {
t.nameSpace.mu.Lock()
if t.nameSpace.funcMap == nil {
t.nameSpace.funcMap = make(FuncMap, len(funcMap))
}
for name, fn := range funcMap {
t.nameSpace.funcMap[name] = fn
}
t.nameSpace.mu.Unlock()
wrapFuncs(t.nameSpace, t.text, funcMap)
t.text.Funcs(template.FuncMap(funcMap))
return t
}
// wrapFuncs records the functions with text/template. We wrap them to
// unlock the nameSpace. See TestRecursiveExecute for a test case.
func wrapFuncs(ns *nameSpace, textTemplate *template.Template, funcMap FuncMap) {
if len(funcMap) == 0 {
return
}
tfuncs := make(template.FuncMap, len(funcMap))
for name, fn := range funcMap {
fnv := reflect.ValueOf(fn)
wrapper := func(args []reflect.Value) []reflect.Value {
ns.mu.RUnlock()
defer ns.mu.RLock()
if fnv.Type().IsVariadic() {
return fnv.CallSlice(args)
} else {
return fnv.Call(args)
}
}
wrapped := reflect.MakeFunc(fnv.Type(), wrapper)
tfuncs[name] = wrapped.Interface()
}
textTemplate.Funcs(tfuncs)
}
// Delims sets the action delimiters to the specified strings, to be used in
// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
// definitions will inherit the settings. An empty delimiter stands for the
@ -432,8 +360,8 @@ func (t *Template) Delims(left, right string) *Template {
// Lookup returns the template with the given name that is associated with t,
// or nil if there is no such template.
func (t *Template) Lookup(name string) *Template {
t.nameSpace.mu.RLock()
defer t.nameSpace.mu.RUnlock()
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
return t.set[name]
}

View File

@ -67,7 +67,7 @@ package math
//
// One may easily use induction to prove (4) and (5).
// Note. Since the left hand side of (3) contain only i+2 bits,
// it does not necessary to do a full (53-bit) comparison
// it is not necessary to do a full (53-bit) comparison
// in (3).
// 3. Final rounding
// After generating the 53 bits result, we compute one more bit.

View File

@ -171,12 +171,9 @@ func (c *child) serve() {
defer c.cleanUp()
var rec record
for {
c.conn.mutex.Lock()
if err := rec.read(c.conn.rwc); err != nil {
c.conn.mutex.Unlock()
return
}
c.conn.mutex.Unlock()
if err := c.handleRecord(&rec); err != nil {
return
}

View File

@ -221,7 +221,11 @@ var cleanUpTests = []struct {
}
type nopWriteCloser struct {
io.ReadWriter
io.Reader
}
func (nopWriteCloser) Write(buf []byte) (int, error) {
return len(buf), nil
}
func (nopWriteCloser) Close() error {
@ -235,7 +239,7 @@ func TestChildServeCleansUp(t *testing.T) {
for _, tt := range cleanUpTests {
input := make([]byte, len(tt.input))
copy(input, tt.input)
rc := nopWriteCloser{bytes.NewBuffer(input)}
rc := nopWriteCloser{bytes.NewReader(input)}
done := make(chan bool)
c := newChild(rc, http.HandlerFunc(func(
w http.ResponseWriter,
@ -325,7 +329,7 @@ func TestChildServeReadsEnvVars(t *testing.T) {
for _, tt := range envVarTests {
input := make([]byte, len(tt.input))
copy(input, tt.input)
rc := nopWriteCloser{bytes.NewBuffer(input)}
rc := nopWriteCloser{bytes.NewReader(input)}
done := make(chan bool)
c := newChild(rc, http.HandlerFunc(func(
w http.ResponseWriter,
@ -375,7 +379,7 @@ func TestResponseWriterSniffsContentType(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
input := make([]byte, len(streamFullRequestStdin))
copy(input, streamFullRequestStdin)
rc := nopWriteCloser{bytes.NewBuffer(input)}
rc := nopWriteCloser{bytes.NewReader(input)}
done := make(chan bool)
var resp *response
c := newChild(rc, http.HandlerFunc(func(

View File

@ -66,6 +66,10 @@ type file struct {
// making it invalid; see runtime.SetFinalizer for more information on when
// a finalizer might be run. On Unix systems this will cause the SetDeadline
// methods to stop working.
// Because file descriptors can be reused, the returned file descriptor may
// only be closed through the Close method of f, or by its finalizer during
// garbage collection. Otherwise, during garbage collection the finalizer
// may close an unrelated file descriptor with the same (reused) number.
//
// As an alternative, see the f.SyscallConn method.
func (f *File) Fd() uintptr {
@ -90,6 +94,10 @@ func (f *File) Fd() uintptr {
// descriptor. On Unix systems, if the file descriptor is in
// non-blocking mode, NewFile will attempt to return a pollable File
// (one for which the SetDeadline methods work).
//
// After passing it to NewFile, fd may become invalid under the same
// conditions described in the comments of the Fd method, and the same
// constraints apply.
func NewFile(fd uintptr, name string) *File {
kind := kindNewFile
if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {

View File

@ -11,6 +11,7 @@ import (
"fmt"
"internal/testenv"
"io"
"io/fs"
"os"
. "os"
osexec "os/exec"
@ -2689,6 +2690,32 @@ func TestOpenFileKeepsPermissions(t *testing.T) {
}
func TestDirFS(t *testing.T) {
// On Windows, we force the MFT to update by reading the actual metadata from GetFileInformationByHandle and then
// explicitly setting that. Otherwise it might get out of sync with FindFirstFile. See golang.org/issues/42637.
if runtime.GOOS == "windows" {
if err := filepath.WalkDir("./testdata/dirfs", func(path string, d fs.DirEntry, err error) error {
if err != nil {
t.Fatal(err)
}
info, err := d.Info()
if err != nil {
t.Fatal(err)
}
stat, err := Stat(path) // This uses GetFileInformationByHandle internally.
if err != nil {
t.Fatal(err)
}
if stat.ModTime() == info.ModTime() {
return nil
}
if err := Chtimes(path, stat.ModTime(), stat.ModTime()); err != nil {
t.Log(err) // We only log, not die, in case the test directory is not writable.
}
return nil
}); err != nil {
t.Fatal(err)
}
}
if err := fstest.TestFS(DirFS("./testdata/dirfs"), "a", "b", "dir/x"); err != nil {
t.Fatal(err)
}

View File

@ -20,7 +20,7 @@ func nextRandom() string {
// opens the file for reading and writing, and returns the resulting file.
// The filename is generated by taking pattern and adding a random string to the end.
// If pattern includes a "*", the random string replaces the last "*".
// If dir is the empty string, TempFile uses the default directory for temporary files, as returned by TempDir.
// If dir is the empty string, CreateTemp uses the default directory for temporary files, as returned by TempDir.
// Multiple programs or goroutines calling CreateTemp simultaneously will not choose the same file.
// The caller can use the file's Name method to find the pathname of the file.
// It is the caller's responsibility to remove the file when it is no longer needed.
@ -71,7 +71,7 @@ func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
// and returns the pathname of the new directory.
// The new directory's name is generated by adding a random string to the end of pattern.
// If pattern includes a "*", the random string replaces the last "*" instead.
// If dir is the empty string, TempFile uses the default directory for temporary files, as returned by TempDir.
// If dir is the empty string, MkdirTemp uses the default directory for temporary files, as returned by TempDir.
// Multiple programs or goroutines calling MkdirTemp simultaneously will not choose the same directory.
// It is the caller's responsibility to remove the directory when it is no longer needed.
func MkdirTemp(dir, pattern string) (string, error) {

View File

@ -33,6 +33,11 @@ const (
_PTHREAD_CREATE_DETACHED = 0x1
_F_SETFD = 0x2
_F_GETFL = 0x3
_F_SETFL = 0x4
_FD_CLOEXEC = 0x1
_SIGHUP = 0x1
_SIGINT = 0x2
_SIGQUIT = 0x3

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,!amd64
// +build openbsd,!amd64,!arm64
package runtime

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,!amd64
// +build openbsd,!amd64,!arm64
package runtime

View File

@ -1213,7 +1213,7 @@ func usesLibcall() bool {
case "aix", "darwin", "illumos", "ios", "solaris", "windows":
return true
case "openbsd":
return GOARCH == "amd64"
return GOARCH == "amd64" || GOARCH == "arm64"
}
return false
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,amd64
// +build openbsd,amd64 openbsd,arm64
package runtime

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,amd64
// +build openbsd,amd64 openbsd,arm64
package runtime

113
src/runtime/sys_openbsd3.go Normal file
View File

@ -0,0 +1,113 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,amd64
package runtime
import "unsafe"
// The X versions of syscall expect the libc call to return a 64-bit result.
// Otherwise (the non-X version) expects a 32-bit result.
// This distinction is required because an error is indicated by returning -1,
// and we need to know whether to check 32 or 64 bits of the result.
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)
//go:linkname syscall_syscall syscall.syscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscall()
//go:linkname syscall_syscallX syscall.syscallX
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
entersyscall()
libcCall(unsafe.Pointer(funcPC(syscallX)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscallX()
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscall6()
//go:linkname syscall_syscall6X syscall.syscall6X
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscall6X()
//go:linkname syscall_syscall10 syscall.syscall10
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) {
entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall10)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscall10()
//go:linkname syscall_syscall10X syscall.syscall10X
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) {
entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall10X)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscall10X()
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
return
}
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
return
}
//go:linkname syscall_rawSyscall6X syscall.rawSyscall6X
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn))
return
}
//go:linkname syscall_rawSyscall10X syscall.rawSyscall10X
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(funcPC(syscall10X)), unsafe.Pointer(&fn))
return
}

View File

@ -445,3 +445,336 @@ TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
MOVL $0xf1, 0xf1 // crash
POPQ BP
RET
// syscall calls a function in libc on behalf of the syscall package.
// syscall takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall expects a 32-bit result and tests for 32-bit -1
// to decide there was an error.
TEXT runtime·syscall(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $16, SP
MOVQ (0*8)(DI), CX // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL CX
MOVQ (SP), DI
MOVQ AX, (4*8)(DI) // r1
MOVQ DX, (5*8)(DI) // r2
// Standard libc functions return -1 on error
// and set errno.
CMPL AX, $-1 // Note: high 32 bits are junk
JNE ok
// Get error code from libc.
CALL libc_errno(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (6*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
MOVQ BP, SP
POPQ BP
RET
// syscallX calls a function in libc on behalf of the syscall package.
// syscallX takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscallX must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscallX is like syscall but expects a 64-bit result
// and tests for 64-bit -1 to decide there was an error.
TEXT runtime·syscallX(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $16, SP
MOVQ (0*8)(DI), CX // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL CX
MOVQ (SP), DI
MOVQ AX, (4*8)(DI) // r1
MOVQ DX, (5*8)(DI) // r2
// Standard libc functions return -1 on error
// and set errno.
CMPQ AX, $-1
JNE ok
// Get error code from libc.
CALL libc_errno(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (6*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
MOVQ BP, SP
POPQ BP
RET
// syscall6 calls a function in libc on behalf of the syscall package.
// syscall6 takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall6 must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall6 expects a 32-bit result and tests for 32-bit -1
// to decide there was an error.
TEXT runtime·syscall6(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $16, SP
MOVQ (0*8)(DI), R11// fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
MOVQ (6*8)(DI), R9 // a6
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL R11
MOVQ (SP), DI
MOVQ AX, (7*8)(DI) // r1
MOVQ DX, (8*8)(DI) // r2
CMPL AX, $-1
JNE ok
CALL libc_errno(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (9*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
MOVQ BP, SP
POPQ BP
RET
// syscall6X calls a function in libc on behalf of the syscall package.
// syscall6X takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall6X must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall6X is like syscall6 but expects a 64-bit result
// and tests for 64-bit -1 to decide there was an error.
TEXT runtime·syscall6X(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $16, SP
MOVQ (0*8)(DI), R11// fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
MOVQ (6*8)(DI), R9 // a6
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL R11
MOVQ (SP), DI
MOVQ AX, (7*8)(DI) // r1
MOVQ DX, (8*8)(DI) // r2
CMPQ AX, $-1
JNE ok
CALL libc_errno(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (9*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
MOVQ BP, SP
POPQ BP
RET
// syscall10 calls a function in libc on behalf of the syscall package.
// syscall10 takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// a7 uintptr
// a8 uintptr
// a9 uintptr
// a10 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall10 must be called on the g0 stack with the
// C calling convention (use libcCall).
TEXT runtime·syscall10(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $48, SP
MOVQ (7*8)(DI), R10 // a7
MOVQ (8*8)(DI), R11 // a8
MOVQ (9*8)(DI), R12 // a9
MOVQ (10*8)(DI), R13 // a10
MOVQ R10, (1*8)(SP) // a7
MOVQ R11, (2*8)(SP) // a8
MOVQ R12, (3*8)(SP) // a9
MOVQ R13, (4*8)(SP) // a10
MOVQ (0*8)(DI), R11 // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
MOVQ (6*8)(DI), R9 // a6
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL R11
MOVQ (SP), DI
MOVQ AX, (11*8)(DI) // r1
MOVQ DX, (12*8)(DI) // r2
CMPL AX, $-1
JNE ok
CALL libc_errno(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (13*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
MOVQ BP, SP
POPQ BP
RET
// syscall10X calls a function in libc on behalf of the syscall package.
// syscall10X takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// a7 uintptr
// a8 uintptr
// a9 uintptr
// a10 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall10X must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall10X is like syscall10 but expects a 64-bit result
// and tests for 64-bit -1 to decide there was an error.
TEXT runtime·syscall10X(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $48, SP
MOVQ (7*8)(DI), R10 // a7
MOVQ (8*8)(DI), R11 // a8
MOVQ (9*8)(DI), R12 // a9
MOVQ (10*8)(DI), R13 // a10
MOVQ R10, (1*8)(SP) // a7
MOVQ R11, (2*8)(SP) // a8
MOVQ R12, (3*8)(SP) // a9
MOVQ R13, (4*8)(SP) // a10
MOVQ (0*8)(DI), R11 // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
MOVQ (6*8)(DI), R9 // a6
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL R11
MOVQ (SP), DI
MOVQ AX, (11*8)(DI) // r1
MOVQ DX, (12*8)(DI) // r2
CMPQ AX, $-1
JNE ok
CALL libc_errno(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (13*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
MOVQ BP, SP
POPQ BP
RET

View File

@ -15,17 +15,6 @@
#define CLOCK_REALTIME $0
#define CLOCK_MONOTONIC $3
// With OpenBSD 6.7 onwards, an arm64 syscall returns two instructions
// after the SVC instruction, to allow for a speculative execution
// barrier to be placed after the SVC without impacting performance.
// For now use hardware no-ops as this works with both older and newer
// kernels. After OpenBSD 6.8 is released this should be changed to
// speculation barriers.
#define INVOKE_SYSCALL \
SVC; \
NOOP; \
NOOP
// mstart_stub is the first function executed on a new thread started by pthread_create.
// It just does some low-level setup and then calls mstart.
// Note: called with the C calling convention.
@ -188,322 +177,229 @@ TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
ADD $16, RSP
RET
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0
MOVW code+0(FP), R0 // arg 1 - status
MOVD $1, R8 // sys_exit
INVOKE_SYSCALL
BCC 3(PC)
MOVD $0, R0 // crash on syscall failure
TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 - signal
MOVD $0, R2 // arg 3 - tcb
MOVW 0(R0), R0 // arg 1 - tid
CALL libc_thrkill(SB)
RET
TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 - clock_id
MOVD 16(R0), R2 // arg 3 - abstime
MOVD 24(R0), R3 // arg 4 - lock
MOVD 32(R0), R4 // arg 5 - abort
MOVD 0(R0), R0 // arg 1 - id
CALL libc_thrsleep(SB)
RET
TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 - count
MOVD 0(R0), R0 // arg 1 - id
CALL libc_thrwakeup(SB)
RET
TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
MOVW 0(R0), R0 // arg 1 - status
CALL libc_exit(SB)
MOVD $0, R0 // crash on failure
MOVD R0, (R0)
RET
// func exitThread(wait *uint32)
TEXT runtime·exitThread(SB),NOSPLIT,$0
MOVD wait+0(FP), R0 // arg 1 - notdead
MOVD $302, R8 // sys___threxit
INVOKE_SYSCALL
MOVD $0, R0 // crash on syscall failure
MOVD R0, (R0)
JMP 0(PC)
TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0
MOVD name+0(FP), R0 // arg 1 - path
MOVW mode+8(FP), R1 // arg 2 - mode
MOVW perm+12(FP), R2 // arg 3 - perm
MOVD $5, R8 // sys_open
INVOKE_SYSCALL
BCC 2(PC)
MOVW $-1, R0
MOVW R0, ret+16(FP)
TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
MOVD R0, R19 // pointer to args
CALL libc_getthrid(SB)
MOVW R0, 0(R19) // return value
RET
TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0
MOVW fd+0(FP), R0 // arg 1 - fd
MOVD $6, R8 // sys_close
INVOKE_SYSCALL
BCC 2(PC)
MOVW $-1, R0
MOVW R0, ret+8(FP)
TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
MOVD R0, R19 // pointer to args
CALL libc_getpid(SB) // arg 1 - pid
MOVW 0(R19), R1 // arg 2 - signal
CALL libc_kill(SB)
RET
TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0
MOVW fd+0(FP), R0 // arg 1 - fd
MOVD p+8(FP), R1 // arg 2 - buf
MOVW n+16(FP), R2 // arg 3 - nbyte
MOVD $3, R8 // sys_read
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, ret+24(FP)
TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
CALL libc_sched_yield(SB)
RET
// func pipe() (r, w int32, errno int32)
TEXT runtime·pipe(SB),NOSPLIT|NOFRAME,$0-12
MOVD $r+0(FP), R0
MOVW $0, R1
MOVD $101, R8 // sys_pipe2
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, errno+8(FP)
RET
// func pipe2(flags int32) (r, w int32, errno int32)
TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
MOVD $r+8(FP), R0
MOVW flags+0(FP), R1
MOVD $101, R8 // sys_pipe2
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, errno+16(FP)
RET
TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0
MOVD fd+0(FP), R0 // arg 1 - fd
MOVD p+8(FP), R1 // arg 2 - buf
MOVW n+16(FP), R2 // arg 3 - nbyte
MOVD $4, R8 // sys_write
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, ret+24(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$24-4
MOVWU usec+0(FP), R3
MOVD R3, R5
MOVW $1000000, R4
UDIV R4, R3
MOVD R3, 8(RSP) // tv_sec
MUL R3, R4
SUB R4, R5
MOVW $1000, R4
MUL R4, R5
MOVD R5, 16(RSP) // tv_nsec
ADD $8, RSP, R0 // arg 1 - rqtp
MOVD $0, R1 // arg 2 - rmtp
MOVD $91, R8 // sys_nanosleep
INVOKE_SYSCALL
RET
TEXT runtime·getthrid(SB),NOSPLIT,$0-4
MOVD $299, R8 // sys_getthrid
INVOKE_SYSCALL
MOVW R0, ret+0(FP)
RET
TEXT runtime·thrkill(SB),NOSPLIT,$0-16
MOVW tid+0(FP), R0 // arg 1 - tid
MOVD sig+8(FP), R1 // arg 2 - signum
MOVW $0, R2 // arg 3 - tcb
MOVD $119, R8 // sys_thrkill
INVOKE_SYSCALL
RET
TEXT runtime·raiseproc(SB),NOSPLIT,$0
MOVD $20, R8 // sys_getpid
INVOKE_SYSCALL
// arg 1 - pid, already in R0
MOVW sig+0(FP), R1 // arg 2 - signum
MOVD $122, R8 // sys_kill
INVOKE_SYSCALL
RET
TEXT runtime·mmap(SB),NOSPLIT,$0
MOVD addr+0(FP), R0 // arg 1 - addr
MOVD n+8(FP), R1 // arg 2 - len
MOVW prot+16(FP), R2 // arg 3 - prot
MOVW flags+20(FP), R3 // arg 4 - flags
MOVW fd+24(FP), R4 // arg 5 - fd
MOVW $0, R5 // arg 6 - pad
MOVW off+28(FP), R6 // arg 7 - offset
MOVD $197, R8 // sys_mmap
INVOKE_SYSCALL
TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
MOVD R0, R19 // pointer to args
MOVD 0(R19), R0 // arg 1 - addr
MOVD 8(R19), R1 // arg 2 - len
MOVW 16(R19), R2 // arg 3 - prot
MOVW 20(R19), R3 // arg 4 - flags
MOVW 24(R19), R4 // arg 5 - fid
MOVW 28(R19), R5 // arg 6 - offset
CALL libc_mmap(SB)
MOVD $0, R1
BCC 3(PC)
MOVD R0, R1 // if error, move to R1
CMP $-1, R0
BNE noerr
CALL libc_errno(SB)
MOVW (R0), R1 // errno
MOVD $0, R0
MOVD R0, p+32(FP)
MOVD R1, err+40(FP)
noerr:
MOVD R0, 32(R19)
MOVD R1, 40(R19)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
MOVD addr+0(FP), R0 // arg 1 - addr
MOVD n+8(FP), R1 // arg 2 - len
MOVD $73, R8 // sys_munmap
INVOKE_SYSCALL
BCC 3(PC)
TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - len
MOVD 0(R0), R0 // arg 1 - addr
CALL libc_munmap(SB)
CMP $-1, R0
BNE 3(PC)
MOVD $0, R0 // crash on failure
MOVD R0, (R0)
RET
TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
MOVD 8(R0), R1 // arg 2 - len
MOVW 16(R0), R2 // arg 3 - advice
MOVD 0(R0), R0 // arg 1 - addr
CALL libc_madvise(SB)
// ignore failure - maybe pages are locked
RET
TEXT runtime·open_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 - flags
MOVW 12(R0), R2 // arg 3 - mode
MOVD 0(R0), R0 // arg 1 - path
MOVD $0, R3 // varargs
CALL libc_open(SB)
RET
TEXT runtime·close_trampoline(SB),NOSPLIT,$0
MOVD 0(R0), R0 // arg 1 - fd
CALL libc_close(SB)
RET
TEXT runtime·read_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - buf
MOVW 16(R0), R2 // arg 3 - count
MOVW 0(R0), R0 // arg 1 - fd
CALL libc_read(SB)
CMP $-1, R0
BNE noerr
CALL libc_errno(SB)
MOVW (R0), R0 // errno
NEG R0, R0 // caller expects negative errno value
noerr:
RET
TEXT runtime·write_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - buf
MOVW 16(R0), R2 // arg 3 - count
MOVW 0(R0), R0 // arg 1 - fd
CALL libc_write(SB)
CMP $-1, R0
BNE noerr
CALL libc_errno(SB)
MOVW (R0), R0 // errno
NEG R0, R0 // caller expects negative errno value
noerr:
RET
TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 - flags
MOVD 0(R0), R0 // arg 1 - filedes
CALL libc_pipe2(SB)
CMP $-1, R0
BNE noerr
CALL libc_errno(SB)
MOVW (R0), R0 // errno
NEG R0, R0 // caller expects negative errno value
noerr:
RET
TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - new
MOVD 16(R0), R2 // arg 3 - old
MOVW 0(R0), R0 // arg 1 - which
CALL libc_setitimer(SB)
RET
TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
MOVD 0(R0), R0 // arg 1 - usec
CALL libc_usleep(SB)
RET
TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 - miblen
MOVD 16(R0), R2 // arg 3 - out
MOVD 24(R0), R3 // arg 4 - size
MOVD 32(R0), R4 // arg 5 - dst
MOVD 40(R0), R5 // arg 6 - ndst
MOVD 0(R0), R0 // arg 1 - mib
CALL libc_sysctl(SB)
RET
TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
CALL libc_kqueue(SB)
RET
TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - keventt
MOVW 16(R0), R2 // arg 3 - nch
MOVD 24(R0), R3 // arg 4 - ev
MOVW 32(R0), R4 // arg 5 - nev
MOVD 40(R0), R5 // arg 6 - ts
MOVW 0(R0), R0 // arg 1 - kq
CALL libc_kevent(SB)
CMP $-1, R0
BNE noerr
CALL libc_errno(SB)
MOVW (R0), R0 // errno
NEG R0, R0 // caller expects negative errno value
noerr:
RET
TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - tp
MOVD 0(R0), R0 // arg 1 - clock_id
CALL libc_clock_gettime(SB)
CMP $-1, R0
BNE 3(PC)
MOVD $0, R0 // crash on failure
MOVD R0, (R0)
RET
TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
MOVW 4(R0), R1 // arg 2 - cmd
MOVW 8(R0), R2 // arg 3 - arg
MOVW 0(R0), R0 // arg 1 - fd
MOVD $0, R3 // vararg
CALL libc_fcntl(SB)
RET
TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - new
MOVD 16(R0), R2 // arg 3 - old
MOVW 0(R0), R0 // arg 1 - sig
CALL libc_sigaction(SB)
CMP $-1, R0
BNE 3(PC)
MOVD $0, R0 // crash on syscall failure
MOVD R0, (R0)
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
MOVD addr+0(FP), R0 // arg 1 - addr
MOVD n+8(FP), R1 // arg 2 - len
MOVW flags+16(FP), R2 // arg 2 - flags
MOVD $75, R8 // sys_madvise
INVOKE_SYSCALL
BCC 2(PC)
MOVW $-1, R0
MOVW R0, ret+24(FP)
RET
TEXT runtime·setitimer(SB),NOSPLIT,$0
MOVW mode+0(FP), R0 // arg 1 - mode
MOVD new+8(FP), R1 // arg 2 - new value
MOVD old+16(FP), R2 // arg 3 - old value
MOVD $69, R8 // sys_setitimer
INVOKE_SYSCALL
RET
// func walltime1() (sec int64, nsec int32)
TEXT runtime·walltime1(SB), NOSPLIT, $32
MOVW CLOCK_REALTIME, R0 // arg 1 - clock_id
MOVD $8(RSP), R1 // arg 2 - tp
MOVD $87, R8 // sys_clock_gettime
INVOKE_SYSCALL
MOVD 8(RSP), R0 // sec
MOVD 16(RSP), R1 // nsec
MOVD R0, sec+0(FP)
MOVW R1, nsec+8(FP)
RET
// int64 nanotime1(void) so really
// void nanotime1(int64 *nsec)
TEXT runtime·nanotime1(SB),NOSPLIT,$32
MOVW CLOCK_MONOTONIC, R0 // arg 1 - clock_id
MOVD $8(RSP), R1 // arg 2 - tp
MOVD $87, R8 // sys_clock_gettime
INVOKE_SYSCALL
MOVW 8(RSP), R3 // sec
MOVW 16(RSP), R5 // nsec
MOVD $1000000000, R4
MUL R4, R3
ADD R5, R3
MOVD R3, ret+0(FP)
RET
TEXT runtime·sigaction(SB),NOSPLIT,$0
MOVW sig+0(FP), R0 // arg 1 - signum
MOVD new+8(FP), R1 // arg 2 - new sigaction
MOVD old+16(FP), R2 // arg 3 - old sigaction
MOVD $46, R8 // sys_sigaction
INVOKE_SYSCALL
BCC 3(PC)
MOVD $3, R0 // crash on syscall failure
TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - new
MOVD 16(R0), R2 // arg 3 - old
MOVW 0(R0), R0 // arg 1 - how
CALL libc_pthread_sigmask(SB)
CMP $-1, R0
BNE 3(PC)
MOVD $0, R0 // crash on syscall failure
MOVD R0, (R0)
RET
TEXT runtime·obsdsigprocmask(SB),NOSPLIT,$0
MOVW how+0(FP), R0 // arg 1 - mode
MOVW new+4(FP), R1 // arg 2 - new
MOVD $48, R8 // sys_sigprocmask
INVOKE_SYSCALL
BCC 3(PC)
MOVD $3, R8 // crash on syscall failure
MOVD R8, (R8)
MOVW R0, ret+8(FP)
RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$0
MOVD new+0(FP), R0 // arg 1 - new sigaltstack
MOVD old+8(FP), R1 // arg 2 - old sigaltstack
MOVD $288, R8 // sys_sigaltstack
INVOKE_SYSCALL
BCC 3(PC)
MOVD $0, R8 // crash on syscall failure
MOVD R8, (R8)
RET
TEXT runtime·osyield(SB),NOSPLIT,$0
MOVD $298, R8 // sys_sched_yield
INVOKE_SYSCALL
RET
TEXT runtime·thrsleep(SB),NOSPLIT,$0
MOVD ident+0(FP), R0 // arg 1 - ident
MOVW clock_id+8(FP), R1 // arg 2 - clock_id
MOVD tsp+16(FP), R2 // arg 3 - tsp
MOVD lock+24(FP), R3 // arg 4 - lock
MOVD abort+32(FP), R4 // arg 5 - abort
MOVD $94, R8 // sys___thrsleep
INVOKE_SYSCALL
MOVW R0, ret+40(FP)
RET
TEXT runtime·thrwakeup(SB),NOSPLIT,$0
MOVD ident+0(FP), R0 // arg 1 - ident
MOVW n+8(FP), R1 // arg 2 - n
MOVD $301, R8 // sys___thrwakeup
INVOKE_SYSCALL
MOVW R0, ret+16(FP)
RET
TEXT runtime·sysctl(SB),NOSPLIT,$0
MOVD mib+0(FP), R0 // arg 1 - mib
MOVW miblen+8(FP), R1 // arg 2 - miblen
MOVD out+16(FP), R2 // arg 3 - out
MOVD size+24(FP), R3 // arg 4 - size
MOVD dst+32(FP), R4 // arg 5 - dest
MOVD ndst+40(FP), R5 // arg 6 - newlen
MOVD $202, R8 // sys___sysctl
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, ret+48(FP)
RET
// int32 runtime·kqueue(void);
TEXT runtime·kqueue(SB),NOSPLIT,$0
MOVD $269, R8 // sys_kqueue
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
TEXT runtime·kevent(SB),NOSPLIT,$0
MOVW kq+0(FP), R0 // arg 1 - kq
MOVD ch+8(FP), R1 // arg 2 - changelist
MOVW nch+16(FP), R2 // arg 3 - nchanges
MOVD ev+24(FP), R3 // arg 4 - eventlist
MOVW nev+32(FP), R4 // arg 5 - nevents
MOVD ts+40(FP), R5 // arg 6 - timeout
MOVD $72, R8 // sys_kevent
INVOKE_SYSCALL
BCC 2(PC)
NEG R0, R0
MOVW R0, ret+48(FP)
RET
// func closeonexec(fd int32)
TEXT runtime·closeonexec(SB),NOSPLIT,$0
MOVW fd+0(FP), R0 // arg 1 - fd
MOVD $2, R1 // arg 2 - cmd (F_SETFD)
MOVD $1, R2 // arg 3 - arg (FD_CLOEXEC)
MOVD $92, R8 // sys_fcntl
INVOKE_SYSCALL
RET
// func runtime·setNonblock(int32 fd)
TEXT runtime·setNonblock(SB),NOSPLIT|NOFRAME,$0-4
MOVW fd+0(FP), R0 // arg 1 - fd
MOVD $3, R1 // arg 2 - cmd (F_GETFL)
MOVD $0, R2 // arg 3
MOVD $92, R8 // sys_fcntl
INVOKE_SYSCALL
MOVD $4, R2 // O_NONBLOCK
ORR R0, R2 // arg 3 - flags
MOVW fd+0(FP), R0 // arg 1 - fd
MOVD $4, R1 // arg 2 - cmd (F_SETFL)
MOVD $92, R8 // sys_fcntl
INVOKE_SYSCALL
TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 - old
MOVD 0(R0), R0 // arg 1 - new
CALL libc_sigaltstack(SB)
CMP $-1, R0
BNE 3(PC)
MOVD $0, R0 // crash on syscall failure
MOVD R0, (R0)
RET

View File

@ -1,4 +1,4 @@
// +build netbsd openbsd
// +build netbsd
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@ -8,7 +8,7 @@
#include "funcdata.h"
//
// Syscall9 support for AMD64, NetBSD and OpenBSD
// Syscall9 support for AMD64, NetBSD
//
// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64);

View File

@ -0,0 +1,32 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "textflag.h"
//
// System call support for AMD64, OpenBSD
//
// Provide these function names via assembly so they are provided as ABI0,
// rather than ABIInternal.
// func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP ·syscallInternal(SB)
// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP ·syscall6Internal(SB)
// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP ·rawSyscallInternal(SB)
// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP ·rawSyscall6Internal(SB)
// func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP ·syscall9Internal(SB)

View File

@ -1,4 +1,4 @@
// +build netbsd freebsd openbsd dragonfly
// +build netbsd freebsd dragonfly
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build dragonfly freebsd netbsd openbsd
// +build dragonfly freebsd netbsd openbsd,!amd64
package syscall

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin openbsd,amd64
package syscall
import (

View File

@ -272,6 +272,7 @@ func runtime_AfterExec()
// avoids a build dependency for other platforms.
var execveLibc func(path uintptr, argv uintptr, envp uintptr) Errno
var execveDarwin func(path *byte, argv **byte, envp **byte) error
var execveOpenBSD func(path *byte, argv **byte, envp **byte) error
// Exec invokes the execve(2) system call.
func Exec(argv0 string, argv []string, envv []string) (err error) {
@ -299,6 +300,9 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
} else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
// Similarly on Darwin.
err1 = execveDarwin(argv0p, &argvp[0], &envvp[0])
} else if runtime.GOOS == "openbsd" && runtime.GOARCH == "amd64" {
// Similarly on OpenBSD.
err1 = execveOpenBSD(argv0p, &argvp[0], &envvp[0])
} else {
_, _, err1 = RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(argv0p)),

View File

@ -125,13 +125,13 @@ darwin_amd64)
mkerrors="$mkerrors -m64"
mksyscall="./mksyscall.pl -darwin"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
mkasm="go run mkasm.go"
;;
darwin_arm64)
mkerrors="$mkerrors -m64"
mksyscall="./mksyscall.pl -darwin"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
mkasm="go run mkasm.go"
;;
dragonfly_amd64)
mkerrors="$mkerrors -m64"
@ -283,6 +283,7 @@ netbsd_arm64)
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
openbsd_386)
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
mkerrors="$mkerrors -m32"
mksyscall="./mksyscall.pl -l32 -openbsd"
mksysctl="./mksysctl_openbsd.pl"
@ -291,14 +292,17 @@ openbsd_386)
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
openbsd_amd64)
GOOSARCH_in="syscall_openbsd_libc.go syscall_openbsd_$GOARCH.go"
mkerrors="$mkerrors -m64"
mksyscall="./mksyscall.pl -openbsd"
mksyscall="./mksyscall.pl -openbsd -libc"
mksysctl="./mksysctl_openbsd.pl"
zsysctl="zsysctl_openbsd.go"
mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm.go"
;;
openbsd_arm)
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
mkerrors="$mkerrors"
mksyscall="./mksyscall.pl -l32 -openbsd -arm"
mksysctl="./mksysctl_openbsd.pl"
@ -309,6 +313,7 @@ openbsd_arm)
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
openbsd_arm64)
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
mkerrors="$mkerrors -m64"
mksyscall="./mksyscall.pl -openbsd"
mksysctl="./mksysctl_openbsd.pl"
@ -319,6 +324,7 @@ openbsd_arm64)
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
openbsd_mips64)
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
mkerrors="$mkerrors -m64"
mksyscall="./mksyscall.pl -openbsd"
mksysctl="./mksysctl_openbsd.pl"
@ -327,7 +333,6 @@ openbsd_mips64)
# Let the type of C char be signed to make the bare syscall
# API consistent between platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
GOOSARCH_in=syscall_openbsd_mips64.go
;;
plan9_386)
mkerrors=
@ -367,5 +372,5 @@ esac
# Therefore, "go run" tries to recompile syscall package but ztypes is empty and it fails.
echo "$mktypes types_$GOOS.go |go run mkpost.go >ztypes_$GOOSARCH.go.NEW && mv ztypes_$GOOSARCH.go.NEW ztypes_$GOOSARCH.go";
fi
if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi
if [ -n "$mkasm" ]; then echo "$mkasm $GOOS $GOARCH"; fi
) | $run

View File

@ -4,8 +4,8 @@
// +build ignore
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
//This program must be run after mksyscall.pl.
// mkasm.go generates assembly trampolines to call library routines from Go.
// This program must be run after mksyscall.pl.
package main
import (
@ -17,18 +17,25 @@ import (
)
func main() {
in1, err := os.ReadFile("syscall_darwin.go")
if err != nil {
log.Fatalf("can't open syscall_darwin.go: %s", err)
if len(os.Args) != 3 {
log.Fatalf("Usage: %s <goos> <arch>", os.Args[0])
}
arch := os.Args[1]
in2, err := os.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
goos, arch := os.Args[1], os.Args[2]
syscallFilename := fmt.Sprintf("syscall_%s.go", goos)
syscallArchFilename := fmt.Sprintf("syscall_%s_%s.go", goos, arch)
in1, err := os.ReadFile(syscallFilename)
if err != nil {
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
log.Fatalf("can't open syscall file: %s", err)
}
in3, err := os.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
in2, err := os.ReadFile(syscallArchFilename)
if err != nil {
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
log.Fatalf("can't open syscall file: %s", err)
}
in3, err := os.ReadFile("z" + syscallArchFilename)
if err != nil {
log.Fatalf("can't open syscall file: %s", err)
}
in := string(in1) + string(in2) + string(in3)
@ -36,7 +43,7 @@ func main() {
var out bytes.Buffer
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// go run mkasm.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
for _, line := range strings.Split(in, "\n") {
@ -50,8 +57,8 @@ func main() {
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
}
}
err = os.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
err = os.WriteFile(fmt.Sprintf("zsyscall_%s_%s.s", goos, arch), out.Bytes(), 0644)
if err != nil {
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
log.Fatalf("can't write syscall file: %s", err)
}
}

View File

@ -30,6 +30,7 @@ my $openbsd = 0;
my $netbsd = 0;
my $dragonfly = 0;
my $arm = 0; # 64-bit value should use (even, odd)-pair
my $libc = 0;
my $tags = ""; # build tags
if($ARGV[0] eq "-b32") {
@ -45,6 +46,7 @@ if($ARGV[0] eq "-plan9") {
}
if($ARGV[0] eq "-darwin") {
$darwin = 1;
$libc = 1;
shift;
}
if($ARGV[0] eq "-openbsd") {
@ -63,6 +65,10 @@ if($ARGV[0] eq "-arm") {
$arm = 1;
shift;
}
if($ARGV[0] eq "-libc") {
$libc = 1;
shift;
}
if($ARGV[0] eq "-tags") {
shift;
$tags = $ARGV[0];
@ -125,7 +131,7 @@ while(<>) {
# without reading the header.
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
if ($darwin && $func eq "ptrace1") {
if (($darwin || ($openbsd && $libc)) && $func eq "ptrace") {
# The ptrace function is called from forkAndExecInChild where stack
# growth is forbidden.
$text .= "//go:nosplit\n"
@ -176,7 +182,9 @@ while(<>) {
push @args, "uintptr(_p$n)", "uintptr(len($name))";
$n++;
} elsif($type eq "int64" && ($openbsd || $netbsd)) {
push @args, "0";
if (!$libc) {
push @args, "0";
}
if($_32bit eq "big-endian") {
push @args, "uintptr($name>>32)", "uintptr($name)";
} elsif($_32bit eq "little-endian") {
@ -220,7 +228,7 @@ while(<>) {
$asm = "RawSyscall";
}
}
if ($darwin) {
if ($libc) {
# Call unexported syscall functions (which take
# libc functions instead of syscall numbers).
$asm = lcfirst($asm);
@ -243,7 +251,7 @@ while(<>) {
print STDERR "$ARGV:$.: too many arguments to system call\n";
}
if ($darwin) {
if ($darwin || ($openbsd && $libc)) {
# Use extended versions for calls that generate a 64-bit result.
my ($name, $type) = parseparam($out[0]);
if ($type eq "int64" || ($type eq "uintptr" && $_32bit eq "")) {
@ -257,13 +265,13 @@ while(<>) {
$sysname = "SYS_$func";
$sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
$sysname =~ y/a-z/A-Z/;
if($darwin) {
if($libc) {
$sysname =~ y/A-Z/a-z/;
$sysname = substr $sysname, 4;
$funcname = "libc_$sysname";
}
}
if($darwin) {
if($libc) {
if($funcname eq "") {
$sysname = substr $sysname, 4;
$funcname = "libc_$sysname";
@ -338,17 +346,21 @@ while(<>) {
}
$text .= "\treturn\n";
$text .= "}\n\n";
if($darwin) {
if($libc) {
if (not exists $trampolines{$funcname}) {
$trampolines{$funcname} = 1;
# The assembly trampoline that jumps to the libc routine.
$text .= "func ${funcname}_trampoline()\n";
# Map syscall.funcname to just plain funcname.
# (The jump to this function is in the assembly trampoline, generated by mksyscallasm_darwin.go.)
# (The jump to this function is in the assembly trampoline, generated by mkasm.go.)
$text .= "//go:linkname $funcname $funcname\n";
# Tell the linker that funcname can be found in libSystem using varname without the libc_ prefix.
my $basename = substr $funcname, 5;
$text .= "//go:cgo_import_dynamic $funcname $basename \"/usr/lib/libSystem.B.dylib\"\n\n";
my $libc = "libc.so";
if ($darwin) {
$libc = "/usr/lib/libSystem.B.dylib";
}
$text .= "//go:cgo_import_dynamic $funcname $basename \"$libc\"\n\n";
}
}
}

View File

@ -182,7 +182,6 @@ func setattrlistTimes(path string, times []Timespec) error {
//sys Rename(from string, to string) (err error)
//sys Revoke(path string) (err error)
//sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
//sysnb Setegid(egid int) (err error)
//sysnb Seteuid(euid int) (err error)
@ -207,8 +206,4 @@ func setattrlistTimes(path string, times []Timespec) error {
//sys write(fd int, p []byte) (n int, err error)
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
//sys munmap(addr uintptr, length uintptr) (err error)
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
//sys getcwd(buf []byte) (n int, err error) = SYS___GETCWD
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL

View File

@ -0,0 +1,13 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,!amd64
package syscall
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys getcwd(buf []byte) (n int, err error) = SYS___GETCWD
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL

View File

@ -0,0 +1,93 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd,amd64
package syscall
import "unsafe"
//sys directSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr) (ret uintptr, err error) = SYS_syscall
func syscallInternal(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
return syscall6X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, 0, 0)
}
func syscall6Internal(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
return syscall10X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
}
func rawSyscallInternal(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
return rawSyscall6X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, 0, 0)
}
func rawSyscall6Internal(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
return rawSyscall10X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
}
func syscall9Internal(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
return rawSyscall10X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, a4, a5, a6, a7, a8, a9)
}
// Implemented in the runtime package (runtime/sys_openbsd3.go)
func syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func syscallX(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno)
func syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno)
func rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func rawSyscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno)
func syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
return syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, 0)
}
func syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
return syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, 0)
}
// Find the entry point for f. See comments in runtime/proc.go for the
// function of the same name.
//go:nosplit
func funcPC(f func()) uintptr {
return **(**uintptr)(unsafe.Pointer(&f))
}
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_lseek
//sys getcwd(buf []byte) (n int, err error)
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
//sysnb fork() (pid int, err error)
//sysnb ioctl(fd int, req int, arg int) (err error)
//sysnb execve(path *byte, argv **byte, envp **byte) (err error)
//sysnb exit(res int) (err error)
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
//sysnb getentropy(p []byte) (err error)
//sys fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_fcntl
//sys unlinkat(fd int, path string, flags int) (err error)
//sys openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
func init() {
execveOpenBSD = execve
}
func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
r0, _, e1 := syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
r0, _, e1 := syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@ -1,4 +1,4 @@
// go run mkasm_darwin.go amd64
// go run mkasm.go darwin amd64
// Code generated by the command above; DO NOT EDIT.
#include "textflag.h"
TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0

View File

@ -1,4 +1,4 @@
// go run mkasm_darwin.go arm64
// go run mkasm.go darwin arm64
// Code generated by the command above; DO NOT EDIT.
#include "textflag.h"
TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,233 @@
// go run mkasm.go openbsd amd64
// Code generated by the command above; DO NOT EDIT.
#include "textflag.h"
TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0
JMP libc_getgroups(SB)
TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0
JMP libc_setgroups(SB)
TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0
JMP libc_wait4(SB)
TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0
JMP libc_accept(SB)
TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0
JMP libc_bind(SB)
TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0
JMP libc_connect(SB)
TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0
JMP libc_socket(SB)
TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0
JMP libc_getsockopt(SB)
TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0
JMP libc_setsockopt(SB)
TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0
JMP libc_getpeername(SB)
TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0
JMP libc_getsockname(SB)
TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0
JMP libc_shutdown(SB)
TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0
JMP libc_socketpair(SB)
TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0
JMP libc_recvfrom(SB)
TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0
JMP libc_sendto(SB)
TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0
JMP libc_recvmsg(SB)
TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0
JMP libc_sendmsg(SB)
TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0
JMP libc_kevent(SB)
TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0
JMP libc_utimes(SB)
TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0
JMP libc_futimes(SB)
TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0
JMP libc_fcntl(SB)
TEXT ·libc_pipe2_trampoline(SB),NOSPLIT,$0-0
JMP libc_pipe2(SB)
TEXT ·libc_accept4_trampoline(SB),NOSPLIT,$0-0
JMP libc_accept4(SB)
TEXT ·libc_getdents_trampoline(SB),NOSPLIT,$0-0
JMP libc_getdents(SB)
TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0
JMP libc_access(SB)
TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0
JMP libc_adjtime(SB)
TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_chdir(SB)
TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0
JMP libc_chflags(SB)
TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0
JMP libc_chmod(SB)
TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0
JMP libc_chown(SB)
TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0
JMP libc_chroot(SB)
TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
JMP libc_close(SB)
TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup(SB)
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup2(SB)
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchdir(SB)
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchflags(SB)
TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchmod(SB)
TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchown(SB)
TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
JMP libc_flock(SB)
TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
JMP libc_fpathconf(SB)
TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstat(SB)
TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs(SB)
TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0
JMP libc_fsync(SB)
TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0
JMP libc_ftruncate(SB)
TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getegid(SB)
TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0
JMP libc_geteuid(SB)
TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getgid(SB)
TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getpgid(SB)
TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0
JMP libc_getpgrp(SB)
TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getpid(SB)
TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getppid(SB)
TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0
JMP libc_getpriority(SB)
TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0
JMP libc_getrlimit(SB)
TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0
JMP libc_getrusage(SB)
TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getsid(SB)
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
JMP libc_gettimeofday(SB)
TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
JMP libc_getuid(SB)
TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
JMP libc_issetugid(SB)
TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0
JMP libc_kill(SB)
TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0
JMP libc_kqueue(SB)
TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0
JMP libc_lchown(SB)
TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0
JMP libc_link(SB)
TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0
JMP libc_listen(SB)
TEXT ·libc_lstat_trampoline(SB),NOSPLIT,$0-0
JMP libc_lstat(SB)
TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_mkdir(SB)
TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0
JMP libc_mkfifo(SB)
TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0
JMP libc_mknod(SB)
TEXT ·libc_nanosleep_trampoline(SB),NOSPLIT,$0-0
JMP libc_nanosleep(SB)
TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0
JMP libc_open(SB)
TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0
JMP libc_pathconf(SB)
TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0
JMP libc_pread(SB)
TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0
JMP libc_pwrite(SB)
TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0
JMP libc_read(SB)
TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0
JMP libc_readlink(SB)
TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0
JMP libc_rename(SB)
TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0
JMP libc_revoke(SB)
TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_rmdir(SB)
TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0
JMP libc_select(SB)
TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setegid(SB)
TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0
JMP libc_seteuid(SB)
TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setgid(SB)
TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0
JMP libc_setlogin(SB)
TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setpgid(SB)
TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0
JMP libc_setpriority(SB)
TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setregid(SB)
TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setreuid(SB)
TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setsid(SB)
TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0
JMP libc_settimeofday(SB)
TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0
JMP libc_setuid(SB)
TEXT ·libc_stat_trampoline(SB),NOSPLIT,$0-0
JMP libc_stat(SB)
TEXT ·libc_statfs_trampoline(SB),NOSPLIT,$0-0
JMP libc_statfs(SB)
TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0
JMP libc_symlink(SB)
TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0
JMP libc_sync(SB)
TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0
JMP libc_truncate(SB)
TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0
JMP libc_umask(SB)
TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0
JMP libc_unlink(SB)
TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0
JMP libc_unmount(SB)
TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0
JMP libc_write(SB)
TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0
JMP libc_mmap(SB)
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
JMP libc_munmap(SB)
TEXT ·libc_utimensat_trampoline(SB),NOSPLIT,$0-0
JMP libc_utimensat(SB)
TEXT ·libc_syscall_trampoline(SB),NOSPLIT,$0-0
JMP libc_syscall(SB)
TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0
JMP libc_lseek(SB)
TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
JMP libc_getcwd(SB)
TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
JMP libc_sysctl(SB)
TEXT ·libc_fork_trampoline(SB),NOSPLIT,$0-0
JMP libc_fork(SB)
TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB)
TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
JMP libc_ptrace(SB)
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0
JMP libc_getentropy(SB)
TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
JMP libc_unlinkat(SB)
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
JMP libc_openat(SB)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func main() {
if f() {
panic("FAIL")
}
if bad, _ := g(); bad {
panic("FAIL")
}
}
func f() (bad bool) {
defer func() {
recover()
}()
var p *int
bad, _ = true, *p
return
}
func g() (bool, int) {
defer func() {
recover()
}()
var p *int
return true, *p
}