mirror of https://github.com/golang/go.git
Merge remote-tracking branch 'upstream/master' into 41884-fix
This commit is contained in:
commit
92f02c9697
72
doc/asm.html
72
doc/asm.html
|
|
@ -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>
|
||||
|
|
|
|||
165
doc/go1.16.html
165
doc/go1.16.html
|
|
@ -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 -->
|
||||
|
|
|
|||
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 . }}`
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
Loading…
Reference in New Issue