summaryrefslogtreecommitdiffstats
path: root/src/cmd/internal/objabi
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/objabi')
-rw-r--r--src/cmd/internal/objabi/autotype.go38
-rw-r--r--src/cmd/internal/objabi/flag.go201
-rw-r--r--src/cmd/internal/objabi/flag_test.go26
-rw-r--r--src/cmd/internal/objabi/funcdata.go47
-rw-r--r--src/cmd/internal/objabi/funcid.go100
-rw-r--r--src/cmd/internal/objabi/head.go109
-rw-r--r--src/cmd/internal/objabi/line.go125
-rw-r--r--src/cmd/internal/objabi/line_test.go50
-rw-r--r--src/cmd/internal/objabi/path.go63
-rw-r--r--src/cmd/internal/objabi/path_test.go33
-rw-r--r--src/cmd/internal/objabi/reloctype.go291
-rw-r--r--src/cmd/internal/objabi/reloctype_string.go83
-rw-r--r--src/cmd/internal/objabi/stack.go33
-rw-r--r--src/cmd/internal/objabi/symkind.go79
-rw-r--r--src/cmd/internal/objabi/symkind_string.go41
-rw-r--r--src/cmd/internal/objabi/typekind.go40
-rw-r--r--src/cmd/internal/objabi/util.go201
17 files changed, 1560 insertions, 0 deletions
diff --git a/src/cmd/internal/objabi/autotype.go b/src/cmd/internal/objabi/autotype.go
new file mode 100644
index 0000000..f9d17a3
--- /dev/null
+++ b/src/cmd/internal/objabi/autotype.go
@@ -0,0 +1,38 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+// Auto.name
+const (
+ A_AUTO = 1 + iota
+ A_PARAM
+ A_DELETED_AUTO
+)
diff --git a/src/cmd/internal/objabi/flag.go b/src/cmd/internal/objabi/flag.go
new file mode 100644
index 0000000..3fd73f3
--- /dev/null
+++ b/src/cmd/internal/objabi/flag.go
@@ -0,0 +1,201 @@
+// Copyright 2015 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 objabi
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "strconv"
+ "strings"
+)
+
+func Flagcount(name, usage string, val *int) {
+ flag.Var((*count)(val), name, usage)
+}
+
+func Flagfn1(name, usage string, f func(string)) {
+ flag.Var(fn1(f), name, usage)
+}
+
+func Flagprint(w io.Writer) {
+ flag.CommandLine.SetOutput(w)
+ flag.PrintDefaults()
+}
+
+func Flagparse(usage func()) {
+ flag.Usage = usage
+ os.Args = expandArgs(os.Args)
+ flag.Parse()
+}
+
+// expandArgs expands "response files" arguments in the provided slice.
+//
+// A "response file" argument starts with '@' and the rest of that
+// argument is a filename with CR-or-CRLF-separated arguments. Each
+// argument in the named files can also contain response file
+// arguments. See Issue 18468.
+//
+// The returned slice 'out' aliases 'in' iff the input did not contain
+// any response file arguments.
+//
+// TODO: handle relative paths of recursive expansions in different directories?
+// Is there a spec for this? Are relative paths allowed?
+func expandArgs(in []string) (out []string) {
+ // out is nil until we see a "@" argument.
+ for i, s := range in {
+ if strings.HasPrefix(s, "@") {
+ if out == nil {
+ out = make([]string, 0, len(in)*2)
+ out = append(out, in[:i]...)
+ }
+ slurp, err := ioutil.ReadFile(s[1:])
+ if err != nil {
+ log.Fatal(err)
+ }
+ args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n")
+ for i, arg := range args {
+ args[i] = DecodeArg(arg)
+ }
+ out = append(out, expandArgs(args)...)
+ } else if out != nil {
+ out = append(out, s)
+ }
+ }
+ if out == nil {
+ return in
+ }
+ return
+}
+
+func AddVersionFlag() {
+ flag.Var(versionFlag{}, "V", "print version and exit")
+}
+
+var buildID string // filled in by linker
+
+type versionFlag struct{}
+
+func (versionFlag) IsBoolFlag() bool { return true }
+func (versionFlag) Get() interface{} { return nil }
+func (versionFlag) String() string { return "" }
+func (versionFlag) Set(s string) error {
+ name := os.Args[0]
+ name = name[strings.LastIndex(name, `/`)+1:]
+ name = name[strings.LastIndex(name, `\`)+1:]
+ name = strings.TrimSuffix(name, ".exe")
+
+ // If there's an active experiment, include that,
+ // to distinguish go1.10.2 with an experiment
+ // from go1.10.2 without an experiment.
+ p := Expstring()
+ if p == DefaultExpstring() {
+ p = ""
+ }
+ sep := ""
+ if p != "" {
+ sep = " "
+ }
+
+ // The go command invokes -V=full to get a unique identifier
+ // for this tool. It is assumed that the release version is sufficient
+ // for releases, but during development we include the full
+ // build ID of the binary, so that if the compiler is changed and
+ // rebuilt, we notice and rebuild all packages.
+ if s == "full" {
+ if strings.HasPrefix(Version, "devel") {
+ p += " buildID=" + buildID
+ }
+ }
+
+ fmt.Printf("%s version %s%s%s\n", name, Version, sep, p)
+ os.Exit(0)
+ return nil
+}
+
+// count is a flag.Value that is like a flag.Bool and a flag.Int.
+// If used as -name, it increments the count, but -name=x sets the count.
+// Used for verbose flag -v.
+type count int
+
+func (c *count) String() string {
+ return fmt.Sprint(int(*c))
+}
+
+func (c *count) Set(s string) error {
+ switch s {
+ case "true":
+ *c++
+ case "false":
+ *c = 0
+ default:
+ n, err := strconv.Atoi(s)
+ if err != nil {
+ return fmt.Errorf("invalid count %q", s)
+ }
+ *c = count(n)
+ }
+ return nil
+}
+
+func (c *count) Get() interface{} {
+ return int(*c)
+}
+
+func (c *count) IsBoolFlag() bool {
+ return true
+}
+
+func (c *count) IsCountFlag() bool {
+ return true
+}
+
+type fn1 func(string)
+
+func (f fn1) Set(s string) error {
+ f(s)
+ return nil
+}
+
+func (f fn1) String() string { return "" }
+
+// DecodeArg decodes an argument.
+//
+// This function is public for testing with the parallel encoder.
+func DecodeArg(arg string) string {
+ // If no encoding, fastpath out.
+ if !strings.ContainsAny(arg, "\\\n") {
+ return arg
+ }
+
+ // We can't use strings.Builder as this must work at bootstrap.
+ var b bytes.Buffer
+ var wasBS bool
+ for _, r := range arg {
+ if wasBS {
+ switch r {
+ case '\\':
+ b.WriteByte('\\')
+ case 'n':
+ b.WriteByte('\n')
+ default:
+ // This shouldn't happen. The only backslashes that reach here
+ // should encode '\n' and '\\' exclusively.
+ panic("badly formatted input")
+ }
+ } else if r == '\\' {
+ wasBS = true
+ continue
+ } else {
+ b.WriteRune(r)
+ }
+ wasBS = false
+ }
+ return b.String()
+}
diff --git a/src/cmd/internal/objabi/flag_test.go b/src/cmd/internal/objabi/flag_test.go
new file mode 100644
index 0000000..935b9c2
--- /dev/null
+++ b/src/cmd/internal/objabi/flag_test.go
@@ -0,0 +1,26 @@
+// 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.
+
+package objabi
+
+import "testing"
+
+func TestDecodeArg(t *testing.T) {
+ t.Parallel()
+ tests := []struct {
+ arg, want string
+ }{
+ {"", ""},
+ {"hello", "hello"},
+ {"hello\\n", "hello\n"},
+ {"hello\\nthere", "hello\nthere"},
+ {"hello\\\\there", "hello\\there"},
+ {"\\\\\\n", "\\\n"},
+ }
+ for _, test := range tests {
+ if got := DecodeArg(test.arg); got != test.want {
+ t.Errorf("decodoeArg(%q) = %q, want %q", test.arg, got, test.want)
+ }
+ }
+}
diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go
new file mode 100644
index 0000000..faa2863
--- /dev/null
+++ b/src/cmd/internal/objabi/funcdata.go
@@ -0,0 +1,47 @@
+// Copyright 2013 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 objabi
+
+// This file defines the IDs for PCDATA and FUNCDATA instructions
+// in Go binaries.
+//
+// These must agree with ../../../runtime/funcdata.h and
+// ../../../runtime/symtab.go.
+
+const (
+ PCDATA_UnsafePoint = 0
+ PCDATA_StackMapIndex = 1
+ PCDATA_InlTreeIndex = 2
+
+ FUNCDATA_ArgsPointerMaps = 0
+ FUNCDATA_LocalsPointerMaps = 1
+ FUNCDATA_StackObjects = 2
+ FUNCDATA_InlTree = 3
+ FUNCDATA_OpenCodedDeferInfo = 4
+
+ // ArgsSizeUnknown is set in Func.argsize to mark all functions
+ // whose argument size is unknown (C vararg functions, and
+ // assembly code without an explicit specification).
+ // This value is generated by the compiler, assembler, or linker.
+ ArgsSizeUnknown = -0x80000000
+)
+
+// Special PCDATA values.
+const (
+ // PCDATA_UnsafePoint values.
+ PCDATA_UnsafePointSafe = -1 // Safe for async preemption
+ PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption
+
+ // PCDATA_Restart1(2) apply on a sequence of instructions, within
+ // which if an async preemption happens, we should back off the PC
+ // to the start of the sequence when resuming.
+ // We need two so we can distinguish the start/end of the sequence
+ // in case that two sequences are next to each other.
+ PCDATA_Restart1 = -3
+ PCDATA_Restart2 = -4
+
+ // Like PCDATA_Restart1, but back to function entry if async preempted.
+ PCDATA_RestartAtEntry = -5
+)
diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go
new file mode 100644
index 0000000..1d098ee
--- /dev/null
+++ b/src/cmd/internal/objabi/funcid.go
@@ -0,0 +1,100 @@
+// Copyright 2018 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 objabi
+
+// A FuncID identifies particular functions that need to be treated
+// specially by the runtime.
+// Note that in some situations involving plugins, there may be multiple
+// copies of a particular special runtime function.
+// Note: this list must match the list in runtime/symtab.go.
+type FuncID uint8
+
+const (
+ FuncID_normal FuncID = iota // not a special function
+ FuncID_runtime_main
+ FuncID_goexit
+ FuncID_jmpdefer
+ FuncID_mcall
+ FuncID_morestack
+ FuncID_mstart
+ FuncID_rt0_go
+ FuncID_asmcgocall
+ FuncID_sigpanic
+ FuncID_runfinq
+ FuncID_gcBgMarkWorker
+ FuncID_systemstack_switch
+ FuncID_systemstack
+ FuncID_cgocallback
+ FuncID_gogo
+ FuncID_externalthreadhandler
+ FuncID_debugCallV1
+ FuncID_gopanic
+ FuncID_panicwrap
+ FuncID_handleAsyncEvent
+ FuncID_asyncPreempt
+ FuncID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
+)
+
+// Get the function ID for the named function in the named file.
+// The function should be package-qualified.
+func GetFuncID(name string, isWrapper bool) FuncID {
+ if isWrapper {
+ return FuncID_wrapper
+ }
+ switch name {
+ case "runtime.main":
+ return FuncID_runtime_main
+ case "runtime.goexit":
+ return FuncID_goexit
+ case "runtime.jmpdefer":
+ return FuncID_jmpdefer
+ case "runtime.mcall":
+ return FuncID_mcall
+ case "runtime.morestack":
+ return FuncID_morestack
+ case "runtime.mstart":
+ return FuncID_mstart
+ case "runtime.rt0_go":
+ return FuncID_rt0_go
+ case "runtime.asmcgocall":
+ return FuncID_asmcgocall
+ case "runtime.sigpanic":
+ return FuncID_sigpanic
+ case "runtime.runfinq":
+ return FuncID_runfinq
+ case "runtime.gcBgMarkWorker":
+ return FuncID_gcBgMarkWorker
+ case "runtime.systemstack_switch":
+ return FuncID_systemstack_switch
+ case "runtime.systemstack":
+ return FuncID_systemstack
+ case "runtime.cgocallback":
+ return FuncID_cgocallback
+ case "runtime.gogo":
+ return FuncID_gogo
+ case "runtime.externalthreadhandler":
+ return FuncID_externalthreadhandler
+ case "runtime.debugCallV1":
+ return FuncID_debugCallV1
+ case "runtime.gopanic":
+ return FuncID_gopanic
+ case "runtime.panicwrap":
+ return FuncID_panicwrap
+ case "runtime.handleAsyncEvent":
+ return FuncID_handleAsyncEvent
+ case "runtime.asyncPreempt":
+ return FuncID_asyncPreempt
+ case "runtime.deferreturn":
+ // Don't show in the call stack (used when invoking defer functions)
+ return FuncID_wrapper
+ case "runtime.runOpenDeferFrame":
+ // Don't show in the call stack (used when invoking defer functions)
+ return FuncID_wrapper
+ case "runtime.reflectcallSave":
+ // Don't show in the call stack (used when invoking defer functions)
+ return FuncID_wrapper
+ }
+ return FuncID_normal
+}
diff --git a/src/cmd/internal/objabi/head.go b/src/cmd/internal/objabi/head.go
new file mode 100644
index 0000000..48ff292
--- /dev/null
+++ b/src/cmd/internal/objabi/head.go
@@ -0,0 +1,109 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+import "fmt"
+
+// HeadType is the executable header type.
+type HeadType uint8
+
+const (
+ Hunknown HeadType = iota
+ Hdarwin
+ Hdragonfly
+ Hfreebsd
+ Hjs
+ Hlinux
+ Hnetbsd
+ Hopenbsd
+ Hplan9
+ Hsolaris
+ Hwindows
+ Haix
+)
+
+func (h *HeadType) Set(s string) error {
+ switch s {
+ case "aix":
+ *h = Haix
+ case "darwin", "ios":
+ *h = Hdarwin
+ case "dragonfly":
+ *h = Hdragonfly
+ case "freebsd":
+ *h = Hfreebsd
+ case "js":
+ *h = Hjs
+ case "linux", "android":
+ *h = Hlinux
+ case "netbsd":
+ *h = Hnetbsd
+ case "openbsd":
+ *h = Hopenbsd
+ case "plan9":
+ *h = Hplan9
+ case "illumos", "solaris":
+ *h = Hsolaris
+ case "windows":
+ *h = Hwindows
+ default:
+ return fmt.Errorf("invalid headtype: %q", s)
+ }
+ return nil
+}
+
+func (h *HeadType) String() string {
+ switch *h {
+ case Haix:
+ return "aix"
+ case Hdarwin:
+ return "darwin"
+ case Hdragonfly:
+ return "dragonfly"
+ case Hfreebsd:
+ return "freebsd"
+ case Hjs:
+ return "js"
+ case Hlinux:
+ return "linux"
+ case Hnetbsd:
+ return "netbsd"
+ case Hopenbsd:
+ return "openbsd"
+ case Hplan9:
+ return "plan9"
+ case Hsolaris:
+ return "solaris"
+ case Hwindows:
+ return "windows"
+ }
+ return fmt.Sprintf("HeadType(%d)", *h)
+}
diff --git a/src/cmd/internal/objabi/line.go b/src/cmd/internal/objabi/line.go
new file mode 100644
index 0000000..0733b65
--- /dev/null
+++ b/src/cmd/internal/objabi/line.go
@@ -0,0 +1,125 @@
+// Copyright 2009 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 objabi
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// WorkingDir returns the current working directory
+// (or "/???" if the directory cannot be identified),
+// with "/" as separator.
+func WorkingDir() string {
+ var path string
+ path, _ = os.Getwd()
+ if path == "" {
+ path = "/???"
+ }
+ return filepath.ToSlash(path)
+}
+
+// AbsFile returns the absolute filename for file in the given directory,
+// as rewritten by the rewrites argument.
+// For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT".
+// If the resulting path is the empty string, the result is "??".
+//
+// The rewrites argument is a ;-separated list of rewrites.
+// Each rewrite is of the form "prefix" or "prefix=>replace",
+// where prefix must match a leading sequence of path elements
+// and is either removed entirely or replaced by the replacement.
+func AbsFile(dir, file, rewrites string) string {
+ abs := file
+ if dir != "" && !filepath.IsAbs(file) {
+ abs = filepath.Join(dir, file)
+ }
+
+ abs, rewritten := ApplyRewrites(abs, rewrites)
+ if !rewritten && hasPathPrefix(abs, GOROOT) {
+ abs = "$GOROOT" + abs[len(GOROOT):]
+ }
+
+ if abs == "" {
+ abs = "??"
+ }
+ return abs
+}
+
+// ApplyRewrites returns the filename for file in the given directory,
+// as rewritten by the rewrites argument.
+//
+// The rewrites argument is a ;-separated list of rewrites.
+// Each rewrite is of the form "prefix" or "prefix=>replace",
+// where prefix must match a leading sequence of path elements
+// and is either removed entirely or replaced by the replacement.
+func ApplyRewrites(file, rewrites string) (string, bool) {
+ start := 0
+ for i := 0; i <= len(rewrites); i++ {
+ if i == len(rewrites) || rewrites[i] == ';' {
+ if new, ok := applyRewrite(file, rewrites[start:i]); ok {
+ return new, true
+ }
+ start = i + 1
+ }
+ }
+
+ return file, false
+}
+
+// applyRewrite applies the rewrite to the path,
+// returning the rewritten path and a boolean
+// indicating whether the rewrite applied at all.
+func applyRewrite(path, rewrite string) (string, bool) {
+ prefix, replace := rewrite, ""
+ if j := strings.LastIndex(rewrite, "=>"); j >= 0 {
+ prefix, replace = rewrite[:j], rewrite[j+len("=>"):]
+ }
+
+ if prefix == "" || !hasPathPrefix(path, prefix) {
+ return path, false
+ }
+ if len(path) == len(prefix) {
+ return replace, true
+ }
+ if replace == "" {
+ return path[len(prefix)+1:], true
+ }
+ return replace + path[len(prefix):], true
+}
+
+// Does s have t as a path prefix?
+// That is, does s == t or does s begin with t followed by a slash?
+// For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true.
+// Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true.
+// We do not allow full Unicode case folding, for fear of causing more confusion
+// or harm than good. (For an example of the kinds of things that can go wrong,
+// see http://article.gmane.org/gmane.linux.kernel/1853266.)
+func hasPathPrefix(s string, t string) bool {
+ if len(t) > len(s) {
+ return false
+ }
+ var i int
+ for i = 0; i < len(t); i++ {
+ cs := int(s[i])
+ ct := int(t[i])
+ if 'A' <= cs && cs <= 'Z' {
+ cs += 'a' - 'A'
+ }
+ if 'A' <= ct && ct <= 'Z' {
+ ct += 'a' - 'A'
+ }
+ if cs == '\\' {
+ cs = '/'
+ }
+ if ct == '\\' {
+ ct = '/'
+ }
+ if cs != ct {
+ return false
+ }
+ }
+ return i >= len(s) || s[i] == '/' || s[i] == '\\'
+}
diff --git a/src/cmd/internal/objabi/line_test.go b/src/cmd/internal/objabi/line_test.go
new file mode 100644
index 0000000..1fa0ff1
--- /dev/null
+++ b/src/cmd/internal/objabi/line_test.go
@@ -0,0 +1,50 @@
+// Copyright 2019 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 objabi
+
+import (
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+// On Windows, "/foo" is reported as a relative path
+// (it is relative to the current drive letter),
+// so we need add a drive letter to test absolute path cases.
+func drive() string {
+ if runtime.GOOS == "windows" {
+ return "c:"
+ }
+ return ""
+}
+
+var absFileTests = []struct {
+ dir string
+ file string
+ rewrites string
+ abs string
+}{
+ {"/d", "f", "", "/d/f"},
+ {"/d", drive() + "/f", "", drive() + "/f"},
+ {"/d", "f/g", "", "/d/f/g"},
+ {"/d", drive() + "/f/g", "", drive() + "/f/g"},
+
+ {"/d", "f", "/d/f", "??"},
+ {"/d", "f/g", "/d/f", "g"},
+ {"/d", "f/g", "/d/f=>h", "h/g"},
+ {"/d", "f/g", "/d/f=>/h", "/h/g"},
+ {"/d", "f/g", "/d/f=>/h;/d/e=>/i", "/h/g"},
+ {"/d", "e/f", "/d/f=>/h;/d/e=>/i", "/i/f"},
+}
+
+func TestAbsFile(t *testing.T) {
+ for _, tt := range absFileTests {
+ abs := filepath.FromSlash(AbsFile(filepath.FromSlash(tt.dir), filepath.FromSlash(tt.file), tt.rewrites))
+ want := filepath.FromSlash(tt.abs)
+ if abs != want {
+ t.Errorf("AbsFile(%q, %q, %q) = %q, want %q", tt.dir, tt.file, tt.rewrites, abs, want)
+ }
+ }
+}
diff --git a/src/cmd/internal/objabi/path.go b/src/cmd/internal/objabi/path.go
new file mode 100644
index 0000000..fd1c998
--- /dev/null
+++ b/src/cmd/internal/objabi/path.go
@@ -0,0 +1,63 @@
+// Copyright 2017 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 objabi
+
+import "strings"
+
+// PathToPrefix converts raw string to the prefix that will be used in the
+// symbol table. All control characters, space, '%' and '"', as well as
+// non-7-bit clean bytes turn into %xx. The period needs escaping only in the
+// last segment of the path, and it makes for happier users if we escape that as
+// little as possible.
+func PathToPrefix(s string) string {
+ slash := strings.LastIndex(s, "/")
+ // check for chars that need escaping
+ n := 0
+ for r := 0; r < len(s); r++ {
+ if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
+ n++
+ }
+ }
+
+ // quick exit
+ if n == 0 {
+ return s
+ }
+
+ // escape
+ const hex = "0123456789abcdef"
+ p := make([]byte, 0, len(s)+2*n)
+ for r := 0; r < len(s); r++ {
+ if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
+ p = append(p, '%', hex[c>>4], hex[c&0xF])
+ } else {
+ p = append(p, c)
+ }
+ }
+
+ return string(p)
+}
+
+// IsRuntimePackagePath examines 'pkgpath' and returns TRUE if it
+// belongs to the collection of "runtime-related" packages, including
+// "runtime" itself, "reflect", "syscall", and the
+// "runtime/internal/*" packages. The compiler and/or assembler in
+// some cases need to be aware of when they are building such a
+// package, for example to enable features such as ABI selectors in
+// assembly sources.
+func IsRuntimePackagePath(pkgpath string) bool {
+ rval := false
+ switch pkgpath {
+ case "runtime":
+ rval = true
+ case "reflect":
+ rval = true
+ case "syscall":
+ rval = true
+ default:
+ rval = strings.HasPrefix(pkgpath, "runtime/internal")
+ }
+ return rval
+}
diff --git a/src/cmd/internal/objabi/path_test.go b/src/cmd/internal/objabi/path_test.go
new file mode 100644
index 0000000..05d7fb4
--- /dev/null
+++ b/src/cmd/internal/objabi/path_test.go
@@ -0,0 +1,33 @@
+// Copyright 2017 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 objabi
+
+import "testing"
+
+func TestPathToPrefix(t *testing.T) {
+ tests := []struct {
+ Path string
+ Expected string
+ }{{"foo/bar/v1", "foo/bar/v1"},
+ {"foo/bar/v.1", "foo/bar/v%2e1"},
+ {"f.o.o/b.a.r/v1", "f.o.o/b.a.r/v1"},
+ {"f.o.o/b.a.r/v.1", "f.o.o/b.a.r/v%2e1"},
+ {"f.o.o/b.a.r/v..1", "f.o.o/b.a.r/v%2e%2e1"},
+ {"f.o.o/b.a.r/v..1.", "f.o.o/b.a.r/v%2e%2e1%2e"},
+ {"f.o.o/b.a.r/v%1", "f.o.o/b.a.r/v%251"},
+ {"runtime", "runtime"},
+ {"sync/atomic", "sync/atomic"},
+ {"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
+ {"foo.bar/baz.quux", "foo.bar/baz%2equux"},
+ {"", ""},
+ {"%foo%bar", "%25foo%25bar"},
+ {"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
+ }
+ for _, tc := range tests {
+ if got := PathToPrefix(tc.Path); got != tc.Expected {
+ t.Errorf("expected PathToPrefix(%s) = %s, got %s", tc.Path, tc.Expected, got)
+ }
+ }
+}
diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go
new file mode 100644
index 0000000..649f690
--- /dev/null
+++ b/src/cmd/internal/objabi/reloctype.go
@@ -0,0 +1,291 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+type RelocType int16
+
+//go:generate stringer -type=RelocType
+const (
+ R_ADDR RelocType = 1 + iota
+ // R_ADDRPOWER relocates a pair of "D-form" instructions (instructions with 16-bit
+ // immediates in the low half of the instruction word), usually addis followed by
+ // another add or a load, inserting the "high adjusted" 16 bits of the address of
+ // the referenced symbol into the immediate field of the first instruction and the
+ // low 16 bits into that of the second instruction.
+ R_ADDRPOWER
+ // R_ADDRARM64 relocates an adrp, add pair to compute the address of the
+ // referenced symbol.
+ R_ADDRARM64
+ // R_ADDRMIPS (only used on mips/mips64) resolves to the low 16 bits of an external
+ // address, by encoding it into the instruction.
+ R_ADDRMIPS
+ // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
+ // holding the data being relocated to the referenced symbol.
+ R_ADDROFF
+ // R_WEAKADDROFF resolves just like R_ADDROFF but is a weak relocation.
+ // A weak relocation does not make the symbol it refers to reachable,
+ // and is only honored by the linker if the symbol is in some other way
+ // reachable.
+ R_WEAKADDROFF
+ R_SIZE
+ R_CALL
+ R_CALLARM
+ R_CALLARM64
+ R_CALLIND
+ R_CALLPOWER
+ // R_CALLMIPS (only used on mips64) resolves to non-PC-relative target address
+ // of a CALL (JAL) instruction, by encoding the address into the instruction.
+ R_CALLMIPS
+ // R_CALLRISCV marks RISC-V CALLs for stack checking.
+ R_CALLRISCV
+ R_CONST
+ R_PCREL
+ // R_TLS_LE, used on 386, amd64, and ARM, resolves to the offset of the
+ // thread-local symbol from the thread local base and is used to implement the
+ // "local exec" model for tls access (r.Sym is not set on intel platforms but is
+ // set to a TLS symbol -- runtime.tlsg -- in the linker when externally linking).
+ R_TLS_LE
+ // R_TLS_IE, used 386, amd64, and ARM resolves to the PC-relative offset to a GOT
+ // slot containing the offset from the thread-local symbol from the thread local
+ // base and is used to implemented the "initial exec" model for tls access (r.Sym
+ // is not set on intel platforms but is set to a TLS symbol -- runtime.tlsg -- in
+ // the linker when externally linking).
+ R_TLS_IE
+ R_GOTOFF
+ R_PLT0
+ R_PLT1
+ R_PLT2
+ R_USEFIELD
+ // R_USETYPE resolves to an *rtype, but no relocation is created. The
+ // linker uses this as a signal that the pointed-to type information
+ // should be linked into the final binary, even if there are no other
+ // direct references. (This is used for types reachable by reflection.)
+ R_USETYPE
+ // R_USEIFACE marks a type is converted to an interface in the function this
+ // relocation is applied to. The target is a type descriptor.
+ // This is a marker relocation (0-sized), for the linker's reachabililty
+ // analysis.
+ R_USEIFACE
+ // R_USEIFACEMETHOD marks an interface method that is used in the function
+ // this relocation is applied to. The target is an interface type descriptor.
+ // The addend is the offset of the method in the type descriptor.
+ // This is a marker relocation (0-sized), for the linker's reachabililty
+ // analysis.
+ R_USEIFACEMETHOD
+ // R_METHODOFF resolves to a 32-bit offset from the beginning of the section
+ // holding the data being relocated to the referenced symbol.
+ // It is a variant of R_ADDROFF used when linking from the uncommonType of a
+ // *rtype, and may be set to zero by the linker if it determines the method
+ // text is unreachable by the linked program.
+ R_METHODOFF
+ R_POWER_TOC
+ R_GOTPCREL
+ // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address
+ // of a JMP instruction, by encoding the address into the instruction.
+ // The stack nosplit check ignores this since it is not a function call.
+ R_JMPMIPS
+
+ // R_DWARFSECREF resolves to the offset of the symbol from its section.
+ // Target of relocation must be size 4 (in current implementation).
+ R_DWARFSECREF
+
+ // R_DWARFFILEREF resolves to an index into the DWARF .debug_line
+ // file table for the specified file symbol. Must be applied to an
+ // attribute of form DW_FORM_data4.
+ R_DWARFFILEREF
+
+ // Platform dependent relocations. Architectures with fixed width instructions
+ // have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
+ // stuffed into a 32-bit instruction, so an address needs to be spread across
+ // several instructions, and in turn this requires a sequence of relocations, each
+ // updating a part of an instruction. This leads to relocation codes that are
+ // inherently processor specific.
+
+ // Arm64.
+
+ // Set a MOV[NZ] immediate field to bits [15:0] of the offset from the thread
+ // local base to the thread local variable defined by the referenced (thread
+ // local) symbol. Error if the offset does not fit into 16 bits.
+ R_ARM64_TLS_LE
+
+ // Relocates an ADRP; LD64 instruction sequence to load the offset between
+ // the thread local base and the thread local variable defined by the
+ // referenced (thread local) symbol from the GOT.
+ R_ARM64_TLS_IE
+
+ // R_ARM64_GOTPCREL relocates an adrp, ld64 pair to compute the address of the GOT
+ // slot of the referenced symbol.
+ R_ARM64_GOTPCREL
+
+ // R_ARM64_GOT resolves a GOT-relative instruction sequence, usually an adrp
+ // followed by another ld instruction.
+ R_ARM64_GOT
+
+ // R_ARM64_PCREL resolves a PC-relative addresses instruction sequence, usually an
+ // adrp followed by another add instruction.
+ R_ARM64_PCREL
+
+ // R_ARM64_LDST8 sets a LD/ST immediate value to bits [11:0] of a local address.
+ R_ARM64_LDST8
+
+ // R_ARM64_LDST16 sets a LD/ST immediate value to bits [11:1] of a local address.
+ R_ARM64_LDST16
+
+ // R_ARM64_LDST32 sets a LD/ST immediate value to bits [11:2] of a local address.
+ R_ARM64_LDST32
+
+ // R_ARM64_LDST64 sets a LD/ST immediate value to bits [11:3] of a local address.
+ R_ARM64_LDST64
+
+ // R_ARM64_LDST128 sets a LD/ST immediate value to bits [11:4] of a local address.
+ R_ARM64_LDST128
+
+ // PPC64.
+
+ // R_POWER_TLS_LE is used to implement the "local exec" model for tls
+ // access. It resolves to the offset of the thread-local symbol from the
+ // thread pointer (R13) and inserts this value into the low 16 bits of an
+ // instruction word.
+ R_POWER_TLS_LE
+
+ // R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It
+ // relocates a D-form, DS-form instruction sequence like R_ADDRPOWER_DS. It
+ // inserts to the offset of GOT slot for the thread-local symbol from the TOC (the
+ // GOT slot is filled by the dynamic linker with the offset of the thread-local
+ // symbol from the thread pointer (R13)).
+ R_POWER_TLS_IE
+
+ // R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as
+ // accessing a particular thread-local symbol. It does not affect code generation
+ // but is used by the system linker when relaxing "initial exec" model code to
+ // "local exec" model code.
+ R_POWER_TLS
+
+ // R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
+ // instruction is a "DS-form" instruction, which has an immediate field occupying
+ // bits [15:2] of the instruction word. Bits [15:2] of the address of the
+ // relocated symbol are inserted into this field; it is an error if the last two
+ // bits of the address are not 0.
+ R_ADDRPOWER_DS
+
+ // R_ADDRPOWER_PCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset of the GOT slot for the referenced symbol
+ // from the TOC rather than the symbol's address.
+ R_ADDRPOWER_GOT
+
+ // R_ADDRPOWER_PCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the displacement from the place being relocated to the address of the
+ // relocated symbol instead of just its address.
+ R_ADDRPOWER_PCREL
+
+ // R_ADDRPOWER_TOCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the offset from the TOC to the address of the relocated symbol
+ // rather than the symbol's address.
+ R_ADDRPOWER_TOCREL
+
+ // R_ADDRPOWER_TOCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the
+ // relocated symbol rather than the symbol's address.
+ R_ADDRPOWER_TOCREL_DS
+
+ // RISC-V.
+
+ // R_RISCV_PCREL_ITYPE resolves a 32-bit PC-relative address using an
+ // AUIPC + I-type instruction pair.
+ R_RISCV_PCREL_ITYPE
+
+ // R_RISCV_PCREL_STYPE resolves a 32-bit PC-relative address using an
+ // AUIPC + S-type instruction pair.
+ R_RISCV_PCREL_STYPE
+
+ // R_RISCV_TLS_IE_ITYPE resolves a 32-bit TLS initial-exec TOC offset
+ // address using an AUIPC + I-type instruction pair.
+ R_RISCV_TLS_IE_ITYPE
+
+ // R_RISCV_TLS_IE_STYPE resolves a 32-bit TLS initial-exec TOC offset
+ // address using an AUIPC + S-type instruction pair.
+ R_RISCV_TLS_IE_STYPE
+
+ // R_PCRELDBL relocates s390x 2-byte aligned PC-relative addresses.
+ // TODO(mundaym): remove once variants can be serialized - see issue 14218.
+ R_PCRELDBL
+
+ // R_ADDRMIPSU (only used on mips/mips64) resolves to the sign-adjusted "upper" 16
+ // bits (bit 16-31) of an external address, by encoding it into the instruction.
+ R_ADDRMIPSU
+ // R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
+ // address (offset from thread pointer), by encoding it into the instruction.
+ R_ADDRMIPSTLS
+
+ // R_ADDRCUOFF resolves to a pointer-sized offset from the start of the
+ // symbol's DWARF compile unit.
+ R_ADDRCUOFF
+
+ // R_WASMIMPORT resolves to the index of the WebAssembly function import.
+ R_WASMIMPORT
+
+ // R_XCOFFREF (only used on aix/ppc64) prevents garbage collection by ld
+ // of a symbol. This isn't a real relocation, it can be placed in anywhere
+ // in a symbol and target any symbols.
+ R_XCOFFREF
+)
+
+// IsDirectCall reports whether r is a relocation for a direct call.
+// A direct call is a CALL instruction that takes the target address
+// as an immediate. The address is embedded into the instruction, possibly
+// with limited width. An indirect call is a CALL instruction that takes
+// the target address in register or memory.
+func (r RelocType) IsDirectCall() bool {
+ switch r {
+ case R_CALL, R_CALLARM, R_CALLARM64, R_CALLMIPS, R_CALLPOWER, R_CALLRISCV:
+ return true
+ }
+ return false
+}
+
+// IsDirectJump reports whether r is a relocation for a direct jump.
+// A direct jump is a JMP instruction that takes the target address
+// as an immediate. The address is embedded into the instruction, possibly
+// with limited width. An indirect jump is a JMP instruction that takes
+// the target address in register or memory.
+func (r RelocType) IsDirectJump() bool {
+ switch r {
+ case R_JMPMIPS:
+ return true
+ }
+ return false
+}
+
+// IsDirectCallOrJump reports whether r is a relocation for a direct
+// call or a direct jump.
+func (r RelocType) IsDirectCallOrJump() bool {
+ return r.IsDirectCall() || r.IsDirectJump()
+}
diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go
new file mode 100644
index 0000000..658a44f
--- /dev/null
+++ b/src/cmd/internal/objabi/reloctype_string.go
@@ -0,0 +1,83 @@
+// Code generated by "stringer -type=RelocType"; DO NOT EDIT.
+
+package objabi
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[R_ADDR-1]
+ _ = x[R_ADDRPOWER-2]
+ _ = x[R_ADDRARM64-3]
+ _ = x[R_ADDRMIPS-4]
+ _ = x[R_ADDROFF-5]
+ _ = x[R_WEAKADDROFF-6]
+ _ = x[R_SIZE-7]
+ _ = x[R_CALL-8]
+ _ = x[R_CALLARM-9]
+ _ = x[R_CALLARM64-10]
+ _ = x[R_CALLIND-11]
+ _ = x[R_CALLPOWER-12]
+ _ = x[R_CALLMIPS-13]
+ _ = x[R_CALLRISCV-14]
+ _ = x[R_CONST-15]
+ _ = x[R_PCREL-16]
+ _ = x[R_TLS_LE-17]
+ _ = x[R_TLS_IE-18]
+ _ = x[R_GOTOFF-19]
+ _ = x[R_PLT0-20]
+ _ = x[R_PLT1-21]
+ _ = x[R_PLT2-22]
+ _ = x[R_USEFIELD-23]
+ _ = x[R_USETYPE-24]
+ _ = x[R_USEIFACE-25]
+ _ = x[R_USEIFACEMETHOD-26]
+ _ = x[R_METHODOFF-27]
+ _ = x[R_POWER_TOC-28]
+ _ = x[R_GOTPCREL-29]
+ _ = x[R_JMPMIPS-30]
+ _ = x[R_DWARFSECREF-31]
+ _ = x[R_DWARFFILEREF-32]
+ _ = x[R_ARM64_TLS_LE-33]
+ _ = x[R_ARM64_TLS_IE-34]
+ _ = x[R_ARM64_GOTPCREL-35]
+ _ = x[R_ARM64_GOT-36]
+ _ = x[R_ARM64_PCREL-37]
+ _ = x[R_ARM64_LDST8-38]
+ _ = x[R_ARM64_LDST16-39]
+ _ = x[R_ARM64_LDST32-40]
+ _ = x[R_ARM64_LDST64-41]
+ _ = x[R_ARM64_LDST128-42]
+ _ = x[R_POWER_TLS_LE-43]
+ _ = x[R_POWER_TLS_IE-44]
+ _ = x[R_POWER_TLS-45]
+ _ = x[R_ADDRPOWER_DS-46]
+ _ = x[R_ADDRPOWER_GOT-47]
+ _ = x[R_ADDRPOWER_PCREL-48]
+ _ = x[R_ADDRPOWER_TOCREL-49]
+ _ = x[R_ADDRPOWER_TOCREL_DS-50]
+ _ = x[R_RISCV_PCREL_ITYPE-51]
+ _ = x[R_RISCV_PCREL_STYPE-52]
+ _ = x[R_RISCV_TLS_IE_ITYPE-53]
+ _ = x[R_RISCV_TLS_IE_STYPE-54]
+ _ = x[R_PCRELDBL-55]
+ _ = x[R_ADDRMIPSU-56]
+ _ = x[R_ADDRMIPSTLS-57]
+ _ = x[R_ADDRCUOFF-58]
+ _ = x[R_WASMIMPORT-59]
+ _ = x[R_XCOFFREF-60]
+}
+
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
+
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 133, 140, 147, 155, 163, 171, 177, 183, 189, 199, 208, 218, 234, 245, 256, 266, 275, 288, 302, 316, 330, 346, 357, 370, 383, 397, 411, 425, 440, 454, 468, 479, 493, 508, 525, 543, 564, 583, 602, 622, 642, 652, 663, 676, 687, 699, 709}
+
+func (i RelocType) String() string {
+ i -= 1
+ if i < 0 || i >= RelocType(len(_RelocType_index)-1) {
+ return "RelocType(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ }
+ return _RelocType_name[_RelocType_index[i]:_RelocType_index[i+1]]
+}
diff --git a/src/cmd/internal/objabi/stack.go b/src/cmd/internal/objabi/stack.go
new file mode 100644
index 0000000..05a1d4a
--- /dev/null
+++ b/src/cmd/internal/objabi/stack.go
@@ -0,0 +1,33 @@
+// Copyright 2011 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 objabi
+
+// For the linkers. Must match Go definitions.
+
+const (
+ STACKSYSTEM = 0
+ StackSystem = STACKSYSTEM
+ StackBig = 4096
+ StackSmall = 128
+)
+
+const (
+ StackPreempt = -1314 // 0xfff...fade
+)
+
+// Initialize StackGuard and StackLimit according to target system.
+var StackGuard = 928*stackGuardMultiplier() + StackSystem
+var StackLimit = StackGuard - StackSystem - StackSmall
+
+// stackGuardMultiplier returns a multiplier to apply to the default
+// stack guard size. Larger multipliers are used for non-optimized
+// builds that have larger stack frames or for specific targets.
+func stackGuardMultiplier() int {
+ // On AIX, a larger stack is needed for syscalls.
+ if GOOS == "aix" {
+ return 2
+ }
+ return stackGuardMultiplierDefault
+}
diff --git a/src/cmd/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go
new file mode 100644
index 0000000..6c99112
--- /dev/null
+++ b/src/cmd/internal/objabi/symkind.go
@@ -0,0 +1,79 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+// A SymKind describes the kind of memory represented by a symbol.
+type SymKind uint8
+
+// Defined SymKind values.
+// These are used to index into cmd/link/internal/sym/AbiSymKindToSymKind
+//
+// TODO(rsc): Give idiomatic Go names.
+//go:generate stringer -type=SymKind
+const (
+ // An otherwise invalid zero value for the type
+ Sxxx SymKind = iota
+ // Executable instructions
+ STEXT
+ // Read only static data
+ SRODATA
+ // Static data that does not contain any pointers
+ SNOPTRDATA
+ // Static data
+ SDATA
+ // Statically data that is initially all 0s
+ SBSS
+ // Statically data that is initially all 0s and does not contain pointers
+ SNOPTRBSS
+ // Thread-local data that is initially all 0s
+ STLSBSS
+ // Debugging data
+ SDWARFCUINFO
+ SDWARFCONST
+ SDWARFFCN
+ SDWARFABSFCN
+ SDWARFTYPE
+ SDWARFVAR
+ SDWARFRANGE
+ SDWARFLOC
+ SDWARFLINES
+ // ABI alias. An ABI alias symbol is an empty symbol with a
+ // single relocation with 0 size that references the native
+ // function implementation symbol.
+ //
+ // TODO(austin): Remove this and all uses once the compiler
+ // generates real ABI wrappers rather than symbol aliases.
+ SABIALIAS
+ // Coverage instrumentation counter for libfuzzer.
+ SLIBFUZZER_EXTRA_COUNTER
+ // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values.
+
+)
diff --git a/src/cmd/internal/objabi/symkind_string.go b/src/cmd/internal/objabi/symkind_string.go
new file mode 100644
index 0000000..1b1c394
--- /dev/null
+++ b/src/cmd/internal/objabi/symkind_string.go
@@ -0,0 +1,41 @@
+// Code generated by "stringer -type=SymKind"; DO NOT EDIT.
+
+package objabi
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[Sxxx-0]
+ _ = x[STEXT-1]
+ _ = x[SRODATA-2]
+ _ = x[SNOPTRDATA-3]
+ _ = x[SDATA-4]
+ _ = x[SBSS-5]
+ _ = x[SNOPTRBSS-6]
+ _ = x[STLSBSS-7]
+ _ = x[SDWARFCUINFO-8]
+ _ = x[SDWARFCONST-9]
+ _ = x[SDWARFFCN-10]
+ _ = x[SDWARFABSFCN-11]
+ _ = x[SDWARFTYPE-12]
+ _ = x[SDWARFVAR-13]
+ _ = x[SDWARFRANGE-14]
+ _ = x[SDWARFLOC-15]
+ _ = x[SDWARFLINES-16]
+ _ = x[SABIALIAS-17]
+ _ = x[SLIBFUZZER_EXTRA_COUNTER-18]
+}
+
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER"
+
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 154, 178}
+
+func (i SymKind) String() string {
+ if i >= SymKind(len(_SymKind_index)-1) {
+ return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]]
+}
diff --git a/src/cmd/internal/objabi/typekind.go b/src/cmd/internal/objabi/typekind.go
new file mode 100644
index 0000000..990ff18
--- /dev/null
+++ b/src/cmd/internal/objabi/typekind.go
@@ -0,0 +1,40 @@
+// Copyright 2012 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 objabi
+
+// Must match runtime and reflect.
+// Included by cmd/gc.
+
+const (
+ KindBool = 1 + iota
+ KindInt
+ KindInt8
+ KindInt16
+ KindInt32
+ KindInt64
+ KindUint
+ KindUint8
+ KindUint16
+ KindUint32
+ KindUint64
+ KindUintptr
+ KindFloat32
+ KindFloat64
+ KindComplex64
+ KindComplex128
+ KindArray
+ KindChan
+ KindFunc
+ KindInterface
+ KindMap
+ KindPtr
+ KindSlice
+ KindString
+ KindStruct
+ KindUnsafePointer
+ KindDirectIface = 1 << 5
+ KindGCProg = 1 << 6
+ KindMask = (1 << 5) - 1
+)
diff --git a/src/cmd/internal/objabi/util.go b/src/cmd/internal/objabi/util.go
new file mode 100644
index 0000000..a73ab47
--- /dev/null
+++ b/src/cmd/internal/objabi/util.go
@@ -0,0 +1,201 @@
+// Copyright 2015 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 objabi
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strings"
+)
+
+func envOr(key, value string) string {
+ if x := os.Getenv(key); x != "" {
+ return x
+ }
+ return value
+}
+
+var (
+ defaultGOROOT string // set by linker
+
+ GOROOT = envOr("GOROOT", defaultGOROOT)
+ GOARCH = envOr("GOARCH", defaultGOARCH)
+ GOOS = envOr("GOOS", defaultGOOS)
+ GO386 = envOr("GO386", defaultGO386)
+ GOARM = goarm()
+ GOMIPS = gomips()
+ GOMIPS64 = gomips64()
+ GOPPC64 = goppc64()
+ GOWASM = gowasm()
+ GO_LDSO = defaultGO_LDSO
+ Version = version
+)
+
+const (
+ ElfRelocOffset = 256
+ MachoRelocOffset = 2048 // reserve enough space for ELF relocations
+)
+
+func goarm() int {
+ def := defaultGOARM
+ if GOOS == "android" && GOARCH == "arm" {
+ // Android arm devices always support GOARM=7.
+ def = "7"
+ }
+ switch v := envOr("GOARM", def); v {
+ case "5":
+ return 5
+ case "6":
+ return 6
+ case "7":
+ return 7
+ }
+ // Fail here, rather than validate at multiple call sites.
+ log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.")
+ panic("unreachable")
+}
+
+func gomips() string {
+ switch v := envOr("GOMIPS", defaultGOMIPS); v {
+ case "hardfloat", "softfloat":
+ return v
+ }
+ log.Fatalf("Invalid GOMIPS value. Must be hardfloat or softfloat.")
+ panic("unreachable")
+}
+
+func gomips64() string {
+ switch v := envOr("GOMIPS64", defaultGOMIPS64); v {
+ case "hardfloat", "softfloat":
+ return v
+ }
+ log.Fatalf("Invalid GOMIPS64 value. Must be hardfloat or softfloat.")
+ panic("unreachable")
+}
+
+func goppc64() int {
+ switch v := envOr("GOPPC64", defaultGOPPC64); v {
+ case "power8":
+ return 8
+ case "power9":
+ return 9
+ }
+ log.Fatalf("Invalid GOPPC64 value. Must be power8 or power9.")
+ panic("unreachable")
+}
+
+type gowasmFeatures struct {
+ SignExt bool
+ SatConv bool
+}
+
+func (f gowasmFeatures) String() string {
+ var flags []string
+ if f.SatConv {
+ flags = append(flags, "satconv")
+ }
+ if f.SignExt {
+ flags = append(flags, "signext")
+ }
+ return strings.Join(flags, ",")
+}
+
+func gowasm() (f gowasmFeatures) {
+ for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
+ switch opt {
+ case "satconv":
+ f.SatConv = true
+ case "signext":
+ f.SignExt = true
+ case "":
+ // ignore
+ default:
+ log.Fatalf("Invalid GOWASM value. No such feature: " + opt)
+ }
+ }
+ return
+}
+
+func Getgoextlinkenabled() string {
+ return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED)
+}
+
+func init() {
+ for _, f := range strings.Split(goexperiment, ",") {
+ if f != "" {
+ addexp(f)
+ }
+ }
+
+ // regabi is only supported on amd64.
+ if GOARCH != "amd64" {
+ Regabi_enabled = 0
+ }
+}
+
+// Note: must agree with runtime.framepointer_enabled.
+var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin" || GOOS == "ios")
+
+func addexp(s string) {
+ // Could do general integer parsing here, but the runtime copy doesn't yet.
+ v := 1
+ name := s
+ if len(name) > 2 && name[:2] == "no" {
+ v = 0
+ name = name[2:]
+ }
+ for i := 0; i < len(exper); i++ {
+ if exper[i].name == name {
+ if exper[i].val != nil {
+ *exper[i].val = v
+ }
+ return
+ }
+ }
+
+ fmt.Printf("unknown experiment %s\n", s)
+ os.Exit(2)
+}
+
+var (
+ Fieldtrack_enabled int
+ Preemptibleloops_enabled int
+ Staticlockranking_enabled int
+ Regabi_enabled int
+)
+
+// Toolchain experiments.
+// These are controlled by the GOEXPERIMENT environment
+// variable recorded when the toolchain is built.
+// This list is also known to cmd/gc.
+var exper = []struct {
+ name string
+ val *int
+}{
+ {"fieldtrack", &Fieldtrack_enabled},
+ {"preemptibleloops", &Preemptibleloops_enabled},
+ {"staticlockranking", &Staticlockranking_enabled},
+ {"regabi", &Regabi_enabled},
+}
+
+var defaultExpstring = Expstring()
+
+func DefaultExpstring() string {
+ return defaultExpstring
+}
+
+func Expstring() string {
+ buf := "X"
+ for i := range exper {
+ if *exper[i].val != 0 {
+ buf += "," + exper[i].name
+ }
+ }
+ if buf == "X" {
+ buf += ",none"
+ }
+ return "X:" + buf[2:]
+}