mirror of
https://github.com/Binject/debug
synced 2026-06-08 10:28:33 +00:00
1249 lines
34 KiB
Go
1249 lines
34 KiB
Go
// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
|
|
//go:generate bundle -o objabi.go -pkg objabi -prefix= cmd/internal/objabi
|
|
|
|
// Originally, Go object files were Plan 9 object files, but no longer.
|
|
// Now they are more like standard object files, in that each symbol is defined
|
|
// by an associated memory image (bytes) and a list of relocations to apply
|
|
// during linking. We do not (yet?) use a standard file format, however.
|
|
// For now, the format is chosen to be as simple as possible to read and write.
|
|
// It may change for reasons of efficiency, or we may even switch to a
|
|
// standard file format if there are compelling benefits to doing so.
|
|
// See golang.org/s/go13linker for more background.
|
|
//
|
|
// The file format is:
|
|
//
|
|
// - magic header: "\x00go114ld"
|
|
// - byte 1 - version number
|
|
// - sequence of strings giving dependencies (imported packages)
|
|
// - empty string (marks end of sequence)
|
|
// - number of entries in the following sequence
|
|
// - sequence of filename strings to generate debug information
|
|
// - sequence of symbol references used by the defined symbols
|
|
// - byte 0xff (marks end of sequence)
|
|
// - sequence of integer lengths:
|
|
// - total data length
|
|
// - total number of relocations
|
|
// - total number of pcdata
|
|
// - total number of automatics
|
|
// - total number of funcdata
|
|
// - total number of files
|
|
// - data, the content of the defined symbols
|
|
// - sequence of defined symbols
|
|
// - byte 0xff (marks end of sequence)
|
|
// - magic footer: "\xffgo114ld"
|
|
//
|
|
// All integers are stored in a zigzag varint format.
|
|
// See golang.org/s/go12symtab for a definition.
|
|
//
|
|
// Data blocks and strings are both stored as an integer
|
|
// followed by that many bytes.
|
|
//
|
|
// A symbol reference is a string name followed by an ABI or -1 for static.
|
|
//
|
|
// A symbol points to other symbols using an index into the symbol
|
|
// reference sequence. Index 0 corresponds to a nil symbol pointer.
|
|
// In the symbol layout described below "symref index" stands for this
|
|
// index.
|
|
//
|
|
// Each symbol is laid out as the following fields:
|
|
//
|
|
// - byte 0xfe (sanity check for synchronization)
|
|
// - type [byte]
|
|
// - name & ABI [symref index]
|
|
// - flags [int]
|
|
// 1<<0 dupok
|
|
// 1<<1 local
|
|
// 1<<2 add to typelink table
|
|
// - size [int]
|
|
// - gotype [symref index]
|
|
// - p [data block]
|
|
// - nr [int]
|
|
// - r [nr relocations, sorted by off]
|
|
//
|
|
// If type == STEXT, there are a few more fields:
|
|
//
|
|
// - args [int]
|
|
// - locals [int]
|
|
// - nosplit [int]
|
|
// - flags [int]
|
|
// 1<<0 leaf
|
|
// 1<<1 C function
|
|
// 1<<2 function may call reflect.Type.Method
|
|
// 1<<3 function compiled with -shared
|
|
// - nlocal [int]
|
|
// - local [nlocal automatics]
|
|
// - pcln [pcln table]
|
|
//
|
|
// Each relocation has the encoding:
|
|
//
|
|
// - off [int]
|
|
// - siz [int]
|
|
// - type [int]
|
|
// - add [int]
|
|
// - sym [symref index]
|
|
//
|
|
// Each local has the encoding:
|
|
//
|
|
// - asym [symref index]
|
|
// - offset [int]
|
|
// - type [int]
|
|
// - gotype [symref index]
|
|
//
|
|
// The pcln table has the encoding:
|
|
//
|
|
// - pcsp [data block]
|
|
// - pcfile [data block]
|
|
// - pcline [data block]
|
|
// - pcinline [data block]
|
|
// - npcdata [int]
|
|
// - pcdata [npcdata data blocks]
|
|
// - nfuncdata [int]
|
|
// - funcdata [nfuncdata symref index]
|
|
// - funcdatasym [nfuncdata ints]
|
|
// - nfile [int]
|
|
// - file [nfile symref index]
|
|
// - ninlinedcall [int]
|
|
// - inlinedcall [ninlinedcall int symref int symref]
|
|
//
|
|
// The file layout and meaning of type integers are architecture-independent.
|
|
//
|
|
// TODO(rsc): The file format is good for a first pass but needs work.
|
|
// - There are SymID in the object file that should really just be strings.
|
|
//
|
|
|
|
package objabi
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Auto.name
|
|
const (
|
|
A_AUTO = 1 + iota
|
|
A_PARAM
|
|
A_DELETED_AUTO
|
|
)
|
|
|
|
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")
|
|
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 "" }
|
|
|
|
// 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_RegMapIndex = 0 // if !go115ReduceLiveness
|
|
PCDATA_UnsafePoint = 0 // if go115ReduceLiveness
|
|
PCDATA_StackMapIndex = 1
|
|
PCDATA_InlTreeIndex = 2
|
|
|
|
FUNCDATA_ArgsPointerMaps = 0
|
|
FUNCDATA_LocalsPointerMaps = 1
|
|
FUNCDATA_RegPointerMaps = 2 // if !go115ReduceLiveness
|
|
FUNCDATA_StackObjects = 3
|
|
FUNCDATA_InlTree = 4
|
|
FUNCDATA_OpenCodedDeferInfo = 5
|
|
|
|
// 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_RegMapIndex values.
|
|
//
|
|
// Only if !go115ReduceLiveness.
|
|
PCDATA_RegMapUnsafe = -2 // Unsafe for async preemption
|
|
|
|
// 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
|
|
)
|
|
|
|
// 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_gofunc
|
|
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, file string) FuncID {
|
|
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_gofunc":
|
|
return FuncID_cgocallback_gofunc
|
|
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
|
|
}
|
|
if file == "<autogenerated>" {
|
|
return FuncID_wrapper
|
|
}
|
|
if strings.HasPrefix(name, "runtime.call") {
|
|
if _, err := strconv.Atoi(name[12:]); err == nil {
|
|
// runtime.callXX reflect call wrappers.
|
|
return FuncID_wrapper
|
|
}
|
|
}
|
|
if strings.HasSuffix(name, "-fm") {
|
|
return FuncID_wrapper
|
|
}
|
|
return FuncID_normal
|
|
}
|
|
|
|
// 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":
|
|
*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)
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
start := 0
|
|
for i := 0; i <= len(rewrites); i++ {
|
|
if i == len(rewrites) || rewrites[i] == ';' {
|
|
if new, ok := applyRewrite(abs, rewrites[start:i]); ok {
|
|
abs = new
|
|
goto Rewritten
|
|
}
|
|
start = i + 1
|
|
}
|
|
}
|
|
if hasPathPrefix(abs, GOROOT) {
|
|
abs = "$GOROOT" + abs[len(GOROOT):]
|
|
}
|
|
|
|
Rewritten:
|
|
if abs == "" {
|
|
abs = "??"
|
|
}
|
|
return abs
|
|
}
|
|
|
|
// 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] == '\\'
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
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_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_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_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()
|
|
}
|
|
|
|
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_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_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_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, 219, 230, 240, 249, 262, 276, 290, 304, 320, 331, 344, 357, 371, 385, 400, 414, 428, 439, 453, 468, 485, 503, 524, 543, 562, 572, 583, 596, 607, 619, 629}
|
|
|
|
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]]
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
SDWARFINFO
|
|
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.
|
|
|
|
)
|
|
|
|
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[SDWARFINFO-8]
|
|
_ = x[SDWARFRANGE-9]
|
|
_ = x[SDWARFLOC-10]
|
|
_ = x[SDWARFLINES-11]
|
|
_ = x[SABIALIAS-12]
|
|
_ = x[SLIBFUZZER_EXTRA_COUNTER-13]
|
|
}
|
|
|
|
const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER"
|
|
|
|
var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 92, 101, 125}
|
|
|
|
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]]
|
|
}
|
|
|
|
// 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
|
|
)
|
|
|
|
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)
|
|
GOAMD64 = goamd64()
|
|
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
|
|
Go115AMD64 = "alignedjumps" // Should be "alignedjumps" or "normaljumps"; this replaces environment variable introduced in CL 219357.
|
|
)
|
|
|
|
// TODO(1.16): assuming no issues in 1.15 release, remove this and related constant.
|
|
func goamd64() string {
|
|
return Go115AMD64
|
|
}
|
|
|
|
func goarm() int {
|
|
switch v := envOr("GOARM", defaultGOARM); 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)
|
|
}
|
|
}
|
|
}
|
|
|
|
func Framepointer_enabled(goos, goarch string) bool {
|
|
return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin"))
|
|
}
|
|
|
|
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 (
|
|
framepointer_enabled int = 1
|
|
Fieldtrack_enabled int
|
|
Preemptibleloops_enabled int
|
|
Staticlockranking_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},
|
|
{"framepointer", &framepointer_enabled},
|
|
{"preemptibleloops", &Preemptibleloops_enabled},
|
|
{"staticlockranking", &Staticlockranking_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:]
|
|
}
|
|
|
|
const defaultGO386 = `sse2`
|
|
|
|
const defaultGOARM = `5`
|
|
|
|
const defaultGOMIPS = `hardfloat`
|
|
|
|
const defaultGOMIPS64 = `hardfloat`
|
|
|
|
const defaultGOPPC64 = `power8`
|
|
|
|
const defaultGOOS = runtime.GOOS
|
|
|
|
const defaultGOARCH = runtime.GOARCH
|
|
|
|
const defaultGO_EXTLINK_ENABLED = ``
|
|
|
|
const defaultGO_LDSO = ``
|
|
|
|
const version = `devel +11f92e9 Mon Jul 20 18:18:56 2020 +0000`
|
|
|
|
const stackGuardMultiplierDefault = 1
|
|
|
|
const goexperiment = ``
|