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.go373
-rw-r--r--src/cmd/internal/objabi/flag_test.go26
-rw-r--r--src/cmd/internal/objabi/funcdata.go51
-rw-r--r--src/cmd/internal/objabi/funcid.go91
-rw-r--r--src/cmd/internal/objabi/head.go109
-rw-r--r--src/cmd/internal/objabi/line.go126
-rw-r--r--src/cmd/internal/objabi/line_test.go50
-rw-r--r--src/cmd/internal/objabi/path.go67
-rw-r--r--src/cmd/internal/objabi/path_test.go33
-rw-r--r--src/cmd/internal/objabi/reloctype.go378
-rw-r--r--src/cmd/internal/objabi/reloctype_string.go100
-rw-r--r--src/cmd/internal/objabi/stack.go40
-rw-r--r--src/cmd/internal/objabi/symkind.go76
-rw-r--r--src/cmd/internal/objabi/symkind_string.go42
-rw-r--r--src/cmd/internal/objabi/typekind.go40
-rw-r--r--src/cmd/internal/objabi/util.go33
17 files changed, 1673 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..847ed48
--- /dev/null
+++ b/src/cmd/internal/objabi/flag.go
@@ -0,0 +1,373 @@
+// 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 (
+ "flag"
+ "fmt"
+ "internal/buildcfg"
+ "io"
+ "log"
+ "os"
+ "reflect"
+ "sort"
+ "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 := os.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")
+
+ p := ""
+
+ if s == "goexperiment" {
+ // test/run.go uses this to discover the full set of
+ // experiment tags. Report everything.
+ p = " X:" + strings.Join(buildcfg.Experiment.All(), ",")
+ } else {
+ // If the enabled experiments differ from the baseline,
+ // include that difference.
+ if goexperiment := buildcfg.Experiment.String(); goexperiment != "" {
+ p = " X:" + goexperiment
+ }
+ }
+
+ // 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(buildcfg.Version, "devel") {
+ p += " buildID=" + buildID
+ }
+ }
+
+ fmt.Printf("%s version %s%s\n", name, buildcfg.Version, 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
+ }
+
+ var b strings.Builder
+ 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()
+}
+
+type debugField struct {
+ name string
+ help string
+ concurrentOk bool // true if this field/flag is compatible with concurrent compilation
+ val interface{} // *int or *string
+}
+
+type DebugFlag struct {
+ tab map[string]debugField
+ concurrentOk *bool // this is non-nil only for compiler's DebugFlags, but only compiler has concurrent:ok fields
+ debugSSA DebugSSA // this is non-nil only for compiler's DebugFlags.
+}
+
+// A DebugSSA function is called to set a -d ssa/... option.
+// If nil, those options are reported as invalid options.
+// If DebugSSA returns a non-empty string, that text is reported as a compiler error.
+// If phase is "help", it should print usage information and terminate the process.
+type DebugSSA func(phase, flag string, val int, valString string) string
+
+// NewDebugFlag constructs a DebugFlag for the fields of debug, which
+// must be a pointer to a struct.
+//
+// Each field of *debug is a different value, named for the lower-case of the field name.
+// Each field must be an int or string and must have a `help` struct tag.
+// There may be an "Any bool" field, which will be set if any debug flags are set.
+//
+// The returned flag takes a comma-separated list of settings.
+// Each setting is name=value; for ints, name is short for name=1.
+//
+// If debugSSA is non-nil, any debug flags of the form ssa/... will be
+// passed to debugSSA for processing.
+func NewDebugFlag(debug interface{}, debugSSA DebugSSA) *DebugFlag {
+ flag := &DebugFlag{
+ tab: make(map[string]debugField),
+ debugSSA: debugSSA,
+ }
+
+ v := reflect.ValueOf(debug).Elem()
+ t := v.Type()
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ ptr := v.Field(i).Addr().Interface()
+ if f.Name == "ConcurrentOk" {
+ switch ptr := ptr.(type) {
+ default:
+ panic("debug.ConcurrentOk must have type bool")
+ case *bool:
+ flag.concurrentOk = ptr
+ }
+ continue
+ }
+ name := strings.ToLower(f.Name)
+ help := f.Tag.Get("help")
+ if help == "" {
+ panic(fmt.Sprintf("debug.%s is missing help text", f.Name))
+ }
+ concurrent := f.Tag.Get("concurrent")
+
+ switch ptr.(type) {
+ default:
+ panic(fmt.Sprintf("debug.%s has invalid type %v (must be int or string)", f.Name, f.Type))
+ case *int, *string:
+ // ok
+ }
+ flag.tab[name] = debugField{name, help, concurrent == "ok", ptr}
+ }
+
+ return flag
+}
+
+func (f *DebugFlag) Set(debugstr string) error {
+ if debugstr == "" {
+ return nil
+ }
+ for _, name := range strings.Split(debugstr, ",") {
+ if name == "" {
+ continue
+ }
+ // display help about the debug option itself and quit
+ if name == "help" {
+ fmt.Print(debugHelpHeader)
+ maxLen, names := 0, []string{}
+ if f.debugSSA != nil {
+ maxLen = len("ssa/help")
+ }
+ for name := range f.tab {
+ if len(name) > maxLen {
+ maxLen = len(name)
+ }
+ names = append(names, name)
+ }
+ sort.Strings(names)
+ // Indent multi-line help messages.
+ nl := fmt.Sprintf("\n\t%-*s\t", maxLen, "")
+ for _, name := range names {
+ help := f.tab[name].help
+ fmt.Printf("\t%-*s\t%s\n", maxLen, name, strings.Replace(help, "\n", nl, -1))
+ }
+ if f.debugSSA != nil {
+ // ssa options have their own help
+ fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
+ }
+ os.Exit(0)
+ }
+
+ val, valstring, haveInt := 1, "", true
+ if i := strings.IndexAny(name, "=:"); i >= 0 {
+ var err error
+ name, valstring = name[:i], name[i+1:]
+ val, err = strconv.Atoi(valstring)
+ if err != nil {
+ val, haveInt = 1, false
+ }
+ }
+
+ if t, ok := f.tab[name]; ok {
+ switch vp := t.val.(type) {
+ case nil:
+ // Ignore
+ case *string:
+ *vp = valstring
+ case *int:
+ if !haveInt {
+ log.Fatalf("invalid debug value %v", name)
+ }
+ *vp = val
+ default:
+ panic("bad debugtab type")
+ }
+ // assembler DebugFlags don't have a ConcurrentOk field to reset, so check against that.
+ if !t.concurrentOk && f.concurrentOk != nil {
+ *f.concurrentOk = false
+ }
+ } else if f.debugSSA != nil && strings.HasPrefix(name, "ssa/") {
+ // expect form ssa/phase/flag
+ // e.g. -d=ssa/generic_cse/time
+ // _ in phase name also matches space
+ phase := name[4:]
+ flag := "debug" // default flag is debug
+ if i := strings.Index(phase, "/"); i >= 0 {
+ flag = phase[i+1:]
+ phase = phase[:i]
+ }
+ err := f.debugSSA(phase, flag, val, valstring)
+ if err != "" {
+ log.Fatalf(err)
+ }
+ // Setting this false for -d=ssa/... preserves old behavior
+ // of turning off concurrency for any debug flags.
+ // It's not known for sure if this is necessary, but it is safe.
+ *f.concurrentOk = false
+
+ } else {
+ return fmt.Errorf("unknown debug key %s\n", name)
+ }
+ }
+
+ return nil
+}
+
+const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]
+
+<key> is one of:
+
+`
+
+func (f *DebugFlag) String() string {
+ return ""
+}
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..05a1d49
--- /dev/null
+++ b/src/cmd/internal/objabi/funcdata.go
@@ -0,0 +1,51 @@
+// 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
+ PCDATA_ArgLiveIndex = 3
+
+ FUNCDATA_ArgsPointerMaps = 0
+ FUNCDATA_LocalsPointerMaps = 1
+ FUNCDATA_StackObjects = 2
+ FUNCDATA_InlTree = 3
+ FUNCDATA_OpenCodedDeferInfo = 4
+ FUNCDATA_ArgInfo = 5
+ FUNCDATA_ArgLiveInfo = 6
+ FUNCDATA_WrapInfo = 7
+
+ // 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..c2eb4d5
--- /dev/null
+++ b/src/cmd/internal/objabi/funcid.go
@@ -0,0 +1,91 @@
+// 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
+
+import "strings"
+
+// A FuncFlag records bits about a function, passed to the runtime.
+type FuncFlag uint8
+
+// Note: This list must match the list in runtime/symtab.go.
+const (
+ FuncFlag_TOPFRAME = 1 << iota
+ FuncFlag_SPWRITE
+ FuncFlag_ASM
+)
+
+// 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.
+type FuncID uint8
+
+// Note: this list must match the list in runtime/symtab.go.
+const (
+ FuncID_normal FuncID = iota // not a special function
+ FuncID_abort
+ FuncID_asmcgocall
+ FuncID_asyncPreempt
+ FuncID_cgocallback
+ FuncID_debugCallV2
+ FuncID_gcBgMarkWorker
+ FuncID_goexit
+ FuncID_gogo
+ FuncID_gopanic
+ FuncID_handleAsyncEvent
+ FuncID_mcall
+ FuncID_morestack
+ FuncID_mstart
+ FuncID_panicwrap
+ FuncID_rt0_go
+ FuncID_runfinq
+ FuncID_runtime_main
+ FuncID_sigpanic
+ FuncID_systemstack
+ FuncID_systemstack_switch
+ FuncID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
+)
+
+var funcIDs = map[string]FuncID{
+ "abort": FuncID_abort,
+ "asmcgocall": FuncID_asmcgocall,
+ "asyncPreempt": FuncID_asyncPreempt,
+ "cgocallback": FuncID_cgocallback,
+ "debugCallV2": FuncID_debugCallV2,
+ "gcBgMarkWorker": FuncID_gcBgMarkWorker,
+ "rt0_go": FuncID_rt0_go,
+ "goexit": FuncID_goexit,
+ "gogo": FuncID_gogo,
+ "gopanic": FuncID_gopanic,
+ "handleAsyncEvent": FuncID_handleAsyncEvent,
+ "main": FuncID_runtime_main,
+ "mcall": FuncID_mcall,
+ "morestack": FuncID_morestack,
+ "mstart": FuncID_mstart,
+ "panicwrap": FuncID_panicwrap,
+ "runfinq": FuncID_runfinq,
+ "sigpanic": FuncID_sigpanic,
+ "systemstack_switch": FuncID_systemstack_switch,
+ "systemstack": FuncID_systemstack,
+
+ // Don't show in call stack but otherwise not special.
+ "deferreturn": FuncID_wrapper,
+ "runOpenDeferFrame": FuncID_wrapper,
+ "deferCallSave": FuncID_wrapper,
+}
+
+// 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
+ }
+ if strings.HasPrefix(name, "runtime.") {
+ if id, ok := funcIDs[name[len("runtime."):]]; ok {
+ return id
+ }
+ }
+ 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..763910f
--- /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..beee129
--- /dev/null
+++ b/src/cmd/internal/objabi/line.go
@@ -0,0 +1,126 @@
+// 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 (
+ "internal/buildcfg"
+ "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 && buildcfg.GOROOT != "" && hasPathPrefix(abs, buildcfg.GOROOT) {
+ abs = "$GOROOT" + abs[len(buildcfg.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..aacab9a
--- /dev/null
+++ b/src/cmd/internal/objabi/path.go
@@ -0,0 +1,67 @@
+// 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.
+//
+// Keep in sync with cmd/dist/build.go:IsRuntimePackagePath.
+func IsRuntimePackagePath(pkgpath string) bool {
+ rval := false
+ switch pkgpath {
+ case "runtime":
+ rval = true
+ case "reflect":
+ rval = true
+ case "syscall":
+ rval = true
+ case "internal/bytealg":
+ 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..2bc7b2d
--- /dev/null
+++ b/src/cmd/internal/objabi/reloctype.go
@@ -0,0 +1,378 @@
+// 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_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_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
+ // Similar to R_USEIFACEMETHOD, except instead of indicating a type +
+ // method offset with Sym+Add, Sym points to a symbol containing the name
+ // of the method being called. See the description in
+ // cmd/compile/internal/reflectdata/reflect.go:MarkUsedIfaceMethod for details.
+ R_USEGENERICIFACEMETHOD
+ // 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_KEEP tells the linker to keep the referred-to symbol in the final binary
+ // if the symbol containing the R_KEEP relocation is in the final binary.
+ R_KEEP
+ 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_PCREL_LDST8 resolves a PC-relative addresses instruction sequence, usually an
+ // adrp followed by a LD8 or ST8 instruction.
+ R_ARM64_PCREL_LDST8
+
+ // R_ARM64_PCREL_LDST16 resolves a PC-relative addresses instruction sequence, usually an
+ // adrp followed by a LD16 or ST16 instruction.
+ R_ARM64_PCREL_LDST16
+
+ // R_ARM64_PCREL_LDST32 resolves a PC-relative addresses instruction sequence, usually an
+ // adrp followed by a LD32 or ST32 instruction.
+ R_ARM64_PCREL_LDST32
+
+ // R_ARM64_PCREL_LDST64 resolves a PC-relative addresses instruction sequence, usually an
+ // adrp followed by a LD64 or ST64 instruction.
+ R_ARM64_PCREL_LDST64
+
+ // 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 is split against a pair of instructions to
+ // support a 32 bit displacement.
+ 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 "ADD R3,R13,R4" as completing
+ // a sequence of GOT-relative relocations to compute a TLS address. This can be
+ // used by the system linker to to rewrite the GOT-relative TLS relocation into a
+ // simpler thread-pointer relative relocation. See table 3.26 and 3.28 in the
+ // ppc64 elfv2 1.4 ABI on this transformation. Likewise, the second argument
+ // (usually called RB in X-form instructions) is assumed to be R13.
+ R_POWER_TLS
+
+ // R_POWER_TLS_IE_PCREL34 is similar to R_POWER_TLS_IE, but marks a single MOVD
+ // which has been assembled as a single prefixed load doubleword without using the
+ // TOC.
+ R_POWER_TLS_IE_PCREL34
+
+ // R_POWER_TLS_LE_TPREL34 is similar to R_POWER_TLS_LE, but computes an offset from
+ // the thread pointer in one prefixed instruction.
+ R_POWER_TLS_LE_TPREL34
+
+ // 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_GOT relocates a D-form + DS-form instruction sequence by inserting
+ // a relative displacement of referenced symbol's GOT entry to the TOC pointer.
+ R_ADDRPOWER_GOT
+
+ // R_ADDRPOWER_GOT_PCREL34 is identical to R_ADDRPOWER_GOT, but uses a PC relative
+ // sequence to generate a GOT symbol addresss.
+ R_ADDRPOWER_GOT_PCREL34
+
+ // 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_DS 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
+
+ // R_ADDRPOWER_D34 relocates a single prefixed D-form load/store operation. All
+ // prefixed forms are D form. The high 18 bits are stored in the prefix,
+ // and the low 16 are stored in the suffix. The address is absolute.
+ R_ADDRPOWER_D34
+
+ // R_ADDRPOWER_PCREL34 relates a single prefixed D-form load/store/add operation.
+ // All prefixed forms are D form. The resulting address is relative to the
+ // PC. It is a signed 34 bit offset.
+ R_ADDRPOWER_PCREL34
+
+ // RISC-V.
+
+ // R_RISCV_CALL relocates a J-type instruction with a 21 bit PC-relative
+ // address.
+ R_RISCV_CALL
+
+ // R_RISCV_CALL_TRAMP is the same as R_RISCV_CALL but denotes the use of a
+ // trampoline, which we may be able to avoid during relocation. These are
+ // only used by the linker and are not emitted by the compiler or assembler.
+ R_RISCV_CALL_TRAMP
+
+ // 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
+
+ // Loong64.
+
+ // R_ADDRLOONG64 resolves to the low 12 bits of an external address, by encoding
+ // it into the instruction.
+ R_ADDRLOONG64
+
+ // R_ADDRLOONG64U resolves to the sign-adjusted "upper" 20 bits (bit 5-24) of an
+ // external address, by encoding it into the instruction.
+ R_ADDRLOONG64U
+
+ // R_ADDRLOONG64TLS resolves to the low 12 bits of a TLS address (offset from
+ // thread pointer), by encoding it into the instruction.
+ R_ADDRLOONG64TLS
+
+ // R_ADDRLOONG64TLSU resolves to the high 20 bits of a TLS address (offset from
+ // thread pointer), by encoding it into the instruction.
+ R_ADDRLOONG64TLSU
+
+ // R_CALLLOONG64 resolves to non-PC-relative target address of a CALL (BL/JIRL)
+ // instruction, by encoding the address into the instruction.
+ R_CALLLOONG64
+
+ // R_JMPLOONG64 resolves to non-PC-relative target address of a JMP instruction,
+ // by encoding the address into the instruction.
+ R_JMPLOONG64
+
+ // 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
+
+ // R_WEAK marks the relocation as a weak reference.
+ // 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_WEAK = -1 << 15
+
+ R_WEAKADDR = R_WEAK | R_ADDR
+ R_WEAKADDROFF = R_WEAK | R_ADDROFF
+)
+
+// 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_CALLLOONG64, R_CALLMIPS, R_CALLPOWER, R_RISCV_CALL, R_RISCV_CALL_TRAMP:
+ 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
+ case R_JMPLOONG64:
+ 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..9ce37d0
--- /dev/null
+++ b/src/cmd/internal/objabi/reloctype_string.go
@@ -0,0 +1,100 @@
+// 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_SIZE-6]
+ _ = x[R_CALL-7]
+ _ = x[R_CALLARM-8]
+ _ = x[R_CALLARM64-9]
+ _ = x[R_CALLIND-10]
+ _ = x[R_CALLPOWER-11]
+ _ = x[R_CALLMIPS-12]
+ _ = x[R_CONST-13]
+ _ = x[R_PCREL-14]
+ _ = x[R_TLS_LE-15]
+ _ = x[R_TLS_IE-16]
+ _ = x[R_GOTOFF-17]
+ _ = x[R_PLT0-18]
+ _ = x[R_PLT1-19]
+ _ = x[R_PLT2-20]
+ _ = x[R_USEFIELD-21]
+ _ = x[R_USETYPE-22]
+ _ = x[R_USEIFACE-23]
+ _ = x[R_USEIFACEMETHOD-24]
+ _ = x[R_USEGENERICIFACEMETHOD-25]
+ _ = x[R_METHODOFF-26]
+ _ = x[R_KEEP-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_PCREL_LDST8-38]
+ _ = x[R_ARM64_PCREL_LDST16-39]
+ _ = x[R_ARM64_PCREL_LDST32-40]
+ _ = x[R_ARM64_PCREL_LDST64-41]
+ _ = x[R_ARM64_LDST8-42]
+ _ = x[R_ARM64_LDST16-43]
+ _ = x[R_ARM64_LDST32-44]
+ _ = x[R_ARM64_LDST64-45]
+ _ = x[R_ARM64_LDST128-46]
+ _ = x[R_POWER_TLS_LE-47]
+ _ = x[R_POWER_TLS_IE-48]
+ _ = x[R_POWER_TLS-49]
+ _ = x[R_POWER_TLS_IE_PCREL34-50]
+ _ = x[R_POWER_TLS_LE_TPREL34-51]
+ _ = x[R_ADDRPOWER_DS-52]
+ _ = x[R_ADDRPOWER_GOT-53]
+ _ = x[R_ADDRPOWER_GOT_PCREL34-54]
+ _ = x[R_ADDRPOWER_PCREL-55]
+ _ = x[R_ADDRPOWER_TOCREL-56]
+ _ = x[R_ADDRPOWER_TOCREL_DS-57]
+ _ = x[R_ADDRPOWER_D34-58]
+ _ = x[R_ADDRPOWER_PCREL34-59]
+ _ = x[R_RISCV_CALL-60]
+ _ = x[R_RISCV_CALL_TRAMP-61]
+ _ = x[R_RISCV_PCREL_ITYPE-62]
+ _ = x[R_RISCV_PCREL_STYPE-63]
+ _ = x[R_RISCV_TLS_IE_ITYPE-64]
+ _ = x[R_RISCV_TLS_IE_STYPE-65]
+ _ = x[R_PCRELDBL-66]
+ _ = x[R_ADDRLOONG64-67]
+ _ = x[R_ADDRLOONG64U-68]
+ _ = x[R_ADDRLOONG64TLS-69]
+ _ = x[R_ADDRLOONG64TLSU-70]
+ _ = x[R_CALLLOONG64-71]
+ _ = x[R_JMPLOONG64-72]
+ _ = x[R_ADDRMIPSU-73]
+ _ = x[R_ADDRMIPSTLS-74]
+ _ = x[R_ADDRCUOFF-75]
+ _ = x[R_WASMIMPORT-76]
+ _ = x[R_XCOFFREF-77]
+}
+
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USEGENERICIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
+
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 585, 607, 621, 636, 659, 676, 694, 715, 730, 749, 761, 779, 798, 817, 837, 857, 867, 880, 894, 910, 927, 940, 952, 963, 976, 987, 999, 1009}
+
+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..88b4990
--- /dev/null
+++ b/src/cmd/internal/objabi/stack.go
@@ -0,0 +1,40 @@
+// 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
+
+import "internal/buildcfg"
+
+// For the linkers. Must match Go definitions.
+
+const (
+ STACKSYSTEM = 0
+ StackSystem = STACKSYSTEM
+ StackBig = 4096
+ StackSmall = 128
+)
+
+func StackLimit(race bool) int {
+ // This arithmetic must match that in runtime/stack.go:{_StackGuard,_StackLimit}.
+ stackGuard := 928*stackGuardMultiplier(race) + StackSystem
+ stackLimit := stackGuard - StackSystem - StackSmall
+ return stackLimit
+}
+
+// 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(race bool) int {
+ // This arithmetic must match that in runtime/internal/sys/consts.go:StackGuardMultiplier.
+ n := 1
+ // On AIX, a larger stack is needed for syscalls.
+ if buildcfg.GOOS == "aix" {
+ n += 1
+ }
+ // The race build also needs more stack.
+ if race {
+ n += 1
+ }
+ return n
+}
diff --git a/src/cmd/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go
new file mode 100644
index 0000000..a58816e
--- /dev/null
+++ b/src/cmd/internal/objabi/symkind.go
@@ -0,0 +1,76 @@
+// 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
+ // Coverage instrumentation counter for libfuzzer.
+ SLIBFUZZER_8BIT_COUNTER
+ // Coverage instrumentation counter, aux variable for cmd/cover
+ SCOVERAGE_COUNTER
+ SCOVERAGE_AUXVAR
+
+ // 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..be4e91f
--- /dev/null
+++ b/src/cmd/internal/objabi/symkind_string.go
@@ -0,0 +1,42 @@
+// 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[SLIBFUZZER_8BIT_COUNTER-17]
+ _ = x[SCOVERAGE_COUNTER-18]
+ _ = x[SCOVERAGE_AUXVAR-19]
+}
+
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVAR"
+
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 168, 185, 201}
+
+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..a3e1242
--- /dev/null
+++ b/src/cmd/internal/objabi/util.go
@@ -0,0 +1,33 @@
+// 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"
+ "strings"
+
+ "internal/buildcfg"
+)
+
+const (
+ ElfRelocOffset = 256
+ MachoRelocOffset = 2048 // reserve enough space for ELF relocations
+ GlobalDictPrefix = ".dict" // prefix for names of global dictionaries
+)
+
+// HeaderString returns the toolchain configuration string written in
+// Go object headers. This string ensures we don't attempt to import
+// or link object files that are incompatible with each other. This
+// string always starts with "go object ".
+func HeaderString() string {
+ archExtra := ""
+ if k, v := buildcfg.GOGOARCH(); k != "" && v != "" {
+ archExtra = " " + k + "=" + v
+ }
+ return fmt.Sprintf("go object %s %s %s%s X:%s\n",
+ buildcfg.GOOS, buildcfg.GOARCH,
+ buildcfg.Version, archExtra,
+ strings.Join(buildcfg.Experiment.Enabled(), ","))
+}