// 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 == "" { 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 = ``