diff --git a/README.md b/README.md index b264ffb..14bb5da 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + bee === @@ -34,17 +35,20 @@ go get -u github.com/beego/bee Bee provides a variety of commands which can be helpful at various stages of development. The top level commands include: ``` - new Creates a Beego application - run Run the application by starting a local development server - pack Compresses a Beego application into a single file - api Creates a Beego API application - hprose Creates an RPC application based on Hprose and Beego frameworks - bale Transforms non-Go files to Go source files version Prints the current Bee version - generate Source code generator migrate Runs database migrations + api Creates a Beego API application + bale Transforms non-Go files to Go source files fix Fixes your application by making it compatible with newer versions of Beego + dlv Start a debugging session using Delve dockerize Generates a Dockerfile for your Beego application + generate Source code generator + hprose Creates an RPC application based on Hprose and Beego frameworks + new Creates a Beego application + pack Compresses a Beego application into a single file + rs Run customized scripts + run Run the application by starting a local development server + ``` ### bee version @@ -298,6 +302,37 @@ ______ For more information on the usage, run `bee help dockerize`. +### bee dlv + +Bee can also help with debugging your application. To start a debugging session: + +```bash +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.8.0 +2017/03/22 11:17:05 INFO ▶ 0001 Starting Delve Debugger... +Type 'help' for list of commands. +(dlv) break main.main +Breakpoint 1 set at 0x40100f for main.main() ./main.go:8 + +(dlv) continue +> main.main() ./main.go:8 (hits goroutine(1):1 total:1) (PC: 0x40100f) + 3: import ( + 4: _ "github.com/user/myapp/routers" + 5: "github.com/astaxie/beego" + 6: ) + 7: +=> 8: func main() { + 9: beego.Run() + 10: } + 11: +``` + +For more information on the usage, run `bee help dlv`. + ## Shortcuts Because you'll likely type these generator commands over and over, it makes sense to create aliases: diff --git a/cmd/bee.go b/cmd/bee.go index 702340e..8cf15aa 100644 --- a/cmd/bee.go +++ b/cmd/bee.go @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations // under the License. -// Bee is a tool for developing applications based on beego framework. +// Package cmd ... package cmd import ( @@ -20,6 +20,7 @@ import ( _ "github.com/beego/bee/cmd/commands/api" _ "github.com/beego/bee/cmd/commands/bale" _ "github.com/beego/bee/cmd/commands/beefix" + _ "github.com/beego/bee/cmd/commands/dlv" _ "github.com/beego/bee/cmd/commands/dockerize" _ "github.com/beego/bee/cmd/commands/generate" _ "github.com/beego/bee/cmd/commands/hprose" diff --git a/cmd/commands/dlv/dlv.go b/cmd/commands/dlv/dlv.go new file mode 100644 index 0000000..ec0dafa --- /dev/null +++ b/cmd/commands/dlv/dlv.go @@ -0,0 +1,135 @@ +// Copyright 2017 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// Package dlv ... +package dlv + +import ( + "flag" + "fmt" + "net" + "os" + "path/filepath" + + "github.com/beego/bee/cmd/commands" + "github.com/beego/bee/cmd/commands/version" + beeLogger "github.com/beego/bee/logger" + "github.com/beego/bee/utils" + "github.com/derekparker/delve/pkg/terminal" + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/rpc2" + "github.com/derekparker/delve/service/rpccommon" +) + +var cmdDlv = &commands.Command{ + CustomFlags: true, + UsageLine: "dlv [-package=\"\"] [-port=8181]", + Short: "Start a debugging session using Delve", + Long: `dlv command start a debugging session using debugging tool Delve. + + To debug your application using Delve, use: {{"$ bee dlv" | bold}} + + For more information on Delve: https://github.com/derekparker/delve +`, + PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() }, + Run: runDlv, +} + +var ( + packageName string + port int +) + +func init() { + fs := flag.NewFlagSet("dlv", flag.ContinueOnError) + fs.IntVar(&port, "port", 8181, "Port to listen to for clients") + fs.StringVar(&packageName, "package", "", "The package to debug (Must have a main package)") + cmdDlv.Flag = *fs + commands.AvailableCommands = append(commands.AvailableCommands, cmdDlv) +} + +func runDlv(cmd *commands.Command, args []string) int { + if err := cmd.Flag.Parse(args); err != nil { + beeLogger.Log.Fatalf("Error parsing flags: %v", err.Error()) + } + + debugname := "debug" + addr := fmt.Sprintf("127.0.0.1:%d", port) + return runDelve(addr, debugname) +} + +// runDelve runs the Delve debugger server +func runDelve(addr, debugname string) int { + beeLogger.Log.Info("Starting Delve Debugger...") + + err := gobuild(debugname, packageName) + if err != nil { + beeLogger.Log.Fatalf("%v", err) + } + + fp, err := filepath.Abs("./" + debugname) + if err != nil { + beeLogger.Log.Fatalf("%v", err) + } + defer os.Remove(fp) + + abs, err := filepath.Abs(debugname) + if err != nil { + beeLogger.Log.Fatalf("%v", err) + } + + // Create and start the debugger server + listener, err := net.Listen("tcp", addr) + if err != nil { + beeLogger.Log.Fatalf("Could not start listener: %s", err) + } + defer listener.Close() + + server := rpccommon.NewServer(&service.Config{ + Listener: listener, + AcceptMulti: true, + AttachPid: 0, + APIVersion: 2, + WorkingDir: "./", + ProcessArgs: []string{abs}, + }, false) + if err := server.Run(); err != nil { + beeLogger.Log.Fatalf("Could not start debugger server: %v", err) + } + + // Start the Delve client REPL + client := rpc2.NewClient(addr) + term := terminal.New(client, nil) + + status, err := term.Run() + if err != nil { + beeLogger.Log.Fatalf("Could not start Delve REPL: %v", err) + } + defer term.Close() + + // Stop and kill the debugger server once + // user quits the REPL + if err := server.Stop(true); err != nil { + beeLogger.Log.Fatalf("Could not stop Delve server: %v", err) + } + return status +} + +// gobuild runs the "go build" command on the specified package +func gobuild(debugname, pkg string) error { + args := []string{"-gcflags", "-N -l", "-o", debugname} + args = append(args, utils.SplitQuotedFields("-ldflags='-linkmode internal'")...) + args = append(args, pkg) + return utils.GoCommand("build", args...) +} diff --git a/utils/utils.go b/utils/utils.go index 8ee7198..a7da051 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -26,6 +26,7 @@ import ( "runtime" "strings" "text/template" + "unicode" beeLogger "github.com/beego/bee/logger" "github.com/beego/bee/logger/colors" @@ -332,3 +333,69 @@ func PrintErrorAndExit(message, errorTemplate string) { Tmpl(fmt.Sprintf(errorTemplate, message), nil) os.Exit(2) } + +// GoCommand executes the passed command using Go tool +func GoCommand(command string, args ...string) error { + allargs := []string{command} + allargs = append(allargs, args...) + goBuild := exec.Command("go", allargs...) + goBuild.Stderr = os.Stderr + return goBuild.Run() +} + +// SplitQuotedFields is like strings.Fields but ignores spaces +// inside areas surrounded by single quotes. +// To specify a single quote use backslash to escape it: '\'' +func SplitQuotedFields(in string) []string { + type stateEnum int + const ( + inSpace stateEnum = iota + inField + inQuote + inQuoteEscaped + ) + state := inSpace + r := []string{} + var buf bytes.Buffer + + for _, ch := range in { + switch state { + case inSpace: + if ch == '\'' { + state = inQuote + } else if !unicode.IsSpace(ch) { + buf.WriteRune(ch) + state = inField + } + + case inField: + if ch == '\'' { + state = inQuote + } else if unicode.IsSpace(ch) { + r = append(r, buf.String()) + buf.Reset() + } else { + buf.WriteRune(ch) + } + + case inQuote: + if ch == '\'' { + state = inField + } else if ch == '\\' { + state = inQuoteEscaped + } else { + buf.WriteRune(ch) + } + + case inQuoteEscaped: + buf.WriteRune(ch) + state = inQuote + } + } + + if buf.Len() != 0 { + r = append(r, buf.String()) + } + + return r +} diff --git a/vendor/github.com/derekparker/delve/LICENSE b/vendor/github.com/derekparker/delve/LICENSE new file mode 100644 index 0000000..5ee9d2f --- /dev/null +++ b/vendor/github.com/derekparker/delve/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Derek Parker + +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. diff --git a/vendor/github.com/derekparker/delve/pkg/config/config.go b/vendor/github.com/derekparker/delve/pkg/config/config.go new file mode 100644 index 0000000..3abb485 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/config/config.go @@ -0,0 +1,134 @@ +package config + +import ( + "fmt" + "io/ioutil" + "os" + "os/user" + "path" + + yaml "gopkg.in/yaml.v2" +) + +const ( + configDir string = ".dlv" + configFile string = "config.yml" +) + +// Describes a rule for substitution of path to source code file. +type SubstitutePathRule struct { + // Directory path will be substituted if it matches `From`. + From string + // Path to which substitution is performed. + To string +} + +// Slice of source code path substitution rules. +type SubstitutePathRules []SubstitutePathRule + +// Config defines all configuration options available to be set through the config file. +type Config struct { + // Commands aliases. + Aliases map[string][]string + // Source code path substitution rules. + SubstitutePath SubstitutePathRules `yaml:"substitute-path"` +} + +// LoadConfig attempts to populate a Config object from the config.yml file. +func LoadConfig() *Config { + err := createConfigPath() + if err != nil { + fmt.Printf("Could not create config directory: %v.", err) + return nil + } + fullConfigFile, err := GetConfigFilePath(configFile) + if err != nil { + fmt.Printf("Unable to get config file path: %v.", err) + return nil + } + + f, err := os.Open(fullConfigFile) + if err != nil { + createDefaultConfig(fullConfigFile) + return nil + } + defer func() { + err := f.Close() + if err != nil { + fmt.Printf("Closing config file failed: %v.", err) + } + }() + + data, err := ioutil.ReadAll(f) + if err != nil { + fmt.Printf("Unable to read config data: %v.", err) + return nil + } + + var c Config + err = yaml.Unmarshal(data, &c) + if err != nil { + fmt.Printf("Unable to decode config file: %v.", err) + return nil + } + + return &c +} + +func createDefaultConfig(path string) { + f, err := os.Create(path) + if err != nil { + fmt.Printf("Unable to create config file: %v.", err) + return + } + defer func() { + err := f.Close() + if err != nil { + fmt.Printf("Closing config file failed: %v.", err) + } + }() + err = writeDefaultConfig(f) + if err != nil { + fmt.Printf("Unable to write default configuration: %v.", err) + } +} + +func writeDefaultConfig(f *os.File) error { + _, err := f.WriteString( + `# Configuration file for the delve debugger. + +# This is the default configuration file. Available options are provided, but disabled. +# Delete the leading hash mark to enable an item. + +# Provided aliases will be added to the default aliases for a given command. +aliases: + # command: ["alias1", "alias2"] + +# Define sources path substitution rules. Can be used to rewrite a source path stored +# in program's debug information, if the sources were moved to a different place +# between compilation and debugging. +# Note that substitution rules will not be used for paths passed to "break" and "trace" +# commands. +substitute-path: + # - {from: path, to: path} +`) + return err +} + +// createConfigPath creates the directory structure at which all config files are saved. +func createConfigPath() error { + path, err := GetConfigFilePath("") + if err != nil { + return err + } + return os.MkdirAll(path, 0700) +} + +// GetConfigFilePath gets the full path to the given config file name. +func GetConfigFilePath(file string) (string, error) { + usr, err := user.Current() + if err != nil { + return "", err + } + return path.Join(usr.HomeDir, configDir, file), nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go new file mode 100644 index 0000000..caca2ce --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go @@ -0,0 +1,95 @@ +package frame + +import ( + "encoding/binary" + "fmt" + "sort" +) + +// Represents a Common Information Entry in +// the Dwarf .debug_frame section. +type CommonInformationEntry struct { + Length uint32 + CIE_id uint32 + Version uint8 + Augmentation string + CodeAlignmentFactor uint64 + DataAlignmentFactor int64 + ReturnAddressRegister uint64 + InitialInstructions []byte +} + +// Represents a Frame Descriptor Entry in the +// Dwarf .debug_frame section. +type FrameDescriptionEntry struct { + Length uint32 + CIE *CommonInformationEntry + Instructions []byte + begin, end uint64 + order binary.ByteOrder +} + +// Returns whether or not the given address is within the +// bounds of this frame. +func (fde *FrameDescriptionEntry) Cover(addr uint64) bool { + if (addr - fde.begin) < fde.end { + return true + } + return false +} + +// Address of first location for this frame. +func (fde *FrameDescriptionEntry) Begin() uint64 { + return fde.begin +} + +// Address of last location for this frame. +func (fde *FrameDescriptionEntry) End() uint64 { + return fde.begin + fde.end +} + +// Set up frame for the given PC. +func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext { + return executeDwarfProgramUntilPC(fde, pc) +} + +// Return the offset from the current SP that the return address is stored at. +func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) (frameOffset, returnAddressOffset int64) { + frame := fde.EstablishFrame(pc) + return frame.cfa.offset, frame.regs[fde.CIE.ReturnAddressRegister].offset +} + +type FrameDescriptionEntries []*FrameDescriptionEntry + +func NewFrameIndex() FrameDescriptionEntries { + return make(FrameDescriptionEntries, 0, 1000) +} + +type NoFDEForPCError struct { + PC uint64 +} + +func (err *NoFDEForPCError) Error() string { + return fmt.Sprintf("could not find FDE for PC %#v", err.PC) +} + +// Returns the Frame Description Entry for the given PC. +func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) { + idx := sort.Search(len(fdes), func(i int) bool { + if fdes[i].Cover(pc) { + return true + } + if fdes[i].LessThan(pc) { + return false + } + return true + }) + if idx == len(fdes) { + return nil, &NoFDEForPCError{pc} + } + return fdes[idx], nil +} + +func (frame *FrameDescriptionEntry) LessThan(pc uint64) bool { + return frame.End() <= pc +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go new file mode 100644 index 0000000..95240cf --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go @@ -0,0 +1,164 @@ +package frame + +// Operation opcodes +const ( + DW_OP_addr = 0x03 + DW_OP_const1s = 0x09 +) + +const ( + DW_OP_const2u = 0x0a + DW_OP_const2s = 0x0b + DW_OP_const4u = iota + DW_OP_const4s + DW_OP_const8u + DW_OP_const8s + DW_OP_constu + DW_OP_consts + DW_OP_dup + DW_OP_drop + DW_OP_over + DW_OP_pick + DW_OP_swap + DW_OP_rot + DW_OP_xderef + DW_OP_abs + DW_OP_and + DW_OP_div + DW_OP_minus + DW_OP_mod + DW_OP_mul + DW_OP_neg + DW_OP_not + DW_OP_or + DW_OP_plus + DW_OP_plus_uconst + DW_OP_shl + DW_OP_shr + DW_OP_shra + DW_OP_xor + DW_OP_skip + DW_OP_bra + DW_OP_eq + DW_OP_ge + DW_OP_gt + DW_OP_le + DW_OP_lt + DW_OP_ne +) + +const ( + DW_OP_lit0 = 0x30 + DW_OP_lit1 = 0x31 + DW_OP_lit2 = iota + DW_OP_lit3 + DW_OP_lit4 + DW_OP_lit5 + DW_OP_lit6 + DW_OP_lit7 + DW_OP_lit8 + DW_OP_lit9 + DW_OP_lit10 + DW_OP_lit11 + DW_OP_lit12 + DW_OP_lit13 + DW_OP_lit14 + DW_OP_lit15 + DW_OP_lit16 + DW_OP_lit17 + DW_OP_lit18 + DW_OP_lit19 + DW_OP_lit20 + DW_OP_lit21 + DW_OP_lit22 + DW_OP_lit23 + DW_OP_lit24 + DW_OP_lit25 + DW_OP_lit26 + DW_OP_lit27 + DW_OP_lit28 + DW_OP_lit29 + DW_OP_lit30 + DW_OP_lit31 + DW_OP_reg0 + DW_OP_reg1 + DW_OP_reg2 + DW_OP_reg3 + DW_OP_reg4 + DW_OP_reg5 + DW_OP_reg6 + DW_OP_reg7 + DW_OP_reg8 + DW_OP_reg9 + DW_OP_reg10 + DW_OP_reg11 + DW_OP_reg12 + DW_OP_reg13 + DW_OP_reg14 + DW_OP_reg15 + DW_OP_reg16 + DW_OP_reg17 + DW_OP_reg18 + DW_OP_reg19 + DW_OP_reg20 + DW_OP_reg21 + DW_OP_reg22 + DW_OP_reg23 + DW_OP_reg24 + DW_OP_reg25 + DW_OP_reg26 + DW_OP_reg27 + DW_OP_reg28 + DW_OP_reg29 + DW_OP_reg30 + DW_OP_reg31 + DW_OP_breg0 + DW_OP_breg1 + DW_OP_breg2 + DW_OP_breg3 + DW_OP_breg4 + DW_OP_breg5 + DW_OP_breg6 + DW_OP_breg7 + DW_OP_breg8 + DW_OP_breg9 + DW_OP_breg10 + DW_OP_breg11 + DW_OP_breg12 + DW_OP_breg13 + DW_OP_breg14 + DW_OP_breg15 + DW_OP_breg16 + DW_OP_breg17 + DW_OP_breg18 + DW_OP_breg19 + DW_OP_breg20 + DW_OP_breg21 + DW_OP_breg22 + DW_OP_breg23 + DW_OP_breg24 + DW_OP_breg25 + DW_OP_breg26 + DW_OP_breg27 + DW_OP_breg28 + DW_OP_breg29 + DW_OP_breg30 + DW_OP_breg31 + DW_OP_regx + DW_OP_fbreg + DW_OP_bregx + DW_OP_piece + DW_OP_deref_size + DW_OP_xderef_size + DW_OP_nop + DW_OP_push_object_address + DW_OP_call2 + DW_OP_call4 + DW_OP_call_ref + DW_OP_form_tls_address + DW_OP_call_frame_cfa + DW_OP_bit_piece + + DW_OP_lo_user = 0xe0 + DW_OP_hi_user = 0xff +) diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go new file mode 100644 index 0000000..9afa5a2 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go @@ -0,0 +1,125 @@ +// Package frame contains data structures and +// related functions for parsing and searching +// through Dwarf .debug_frame data. +package frame + +import ( + "bytes" + "encoding/binary" + + "github.com/derekparker/delve/pkg/dwarf/util" +) + +type parsefunc func(*parseContext) parsefunc + +type parseContext struct { + buf *bytes.Buffer + entries FrameDescriptionEntries + common *CommonInformationEntry + frame *FrameDescriptionEntry + length uint32 +} + +// Parse takes in data (a byte slice) and returns a slice of +// commonInformationEntry structures. Each commonInformationEntry +// has a slice of frameDescriptionEntry structures. +func Parse(data []byte, order binary.ByteOrder) FrameDescriptionEntries { + var ( + buf = bytes.NewBuffer(data) + pctx = &parseContext{buf: buf, entries: NewFrameIndex()} + ) + + for fn := parselength; buf.Len() != 0; { + fn = fn(pctx) + } + + for i := range pctx.entries { + pctx.entries[i].order = order + } + + return pctx.entries +} + +func cieEntry(data []byte) bool { + return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff}) +} + +func parselength(ctx *parseContext) parsefunc { + var data = ctx.buf.Next(8) + + ctx.length = binary.LittleEndian.Uint32(data[:4]) - 4 // take off the length of the CIE id / CIE pointer. + + if cieEntry(data[4:]) { + ctx.common = &CommonInformationEntry{Length: ctx.length} + return parseCIE + } + + ctx.frame = &FrameDescriptionEntry{Length: ctx.length, CIE: ctx.common} + return parseFDE +} + +func parseFDE(ctx *parseContext) parsefunc { + r := ctx.buf.Next(int(ctx.length)) + + ctx.frame.begin = binary.LittleEndian.Uint64(r[:8]) + ctx.frame.end = binary.LittleEndian.Uint64(r[8:16]) + + // Insert into the tree after setting address range begin + // otherwise compares won't work. + ctx.entries = append(ctx.entries, ctx.frame) + + // The rest of this entry consists of the instructions + // so we can just grab all of the data from the buffer + // cursor to length. + ctx.frame.Instructions = r[16:] + ctx.length = 0 + + return parselength +} + +func parseCIE(ctx *parseContext) parsefunc { + data := ctx.buf.Next(int(ctx.length)) + buf := bytes.NewBuffer(data) + // parse version + ctx.common.Version = data[0] + + // parse augmentation + ctx.common.Augmentation, _ = util.ParseString(buf) + + // parse code alignment factor + ctx.common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf) + + // parse data alignment factor + ctx.common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf) + + // parse return address register + ctx.common.ReturnAddressRegister, _ = util.DecodeULEB128(buf) + + // parse initial instructions + // The rest of this entry consists of the instructions + // so we can just grab all of the data from the buffer + // cursor to length. + ctx.common.InitialInstructions = buf.Bytes() //ctx.buf.Next(int(ctx.length)) + ctx.length = 0 + + return parselength +} + +// DwarfEndian determines the endianness of the DWARF by using the version number field in the debug_info section +// Trick borrowed from "debug/dwarf".New() +func DwarfEndian(infoSec []byte) binary.ByteOrder { + if len(infoSec) < 6 { + return binary.BigEndian + } + x, y := infoSec[4], infoSec[5] + switch { + case x == 0 && y == 0: + return binary.BigEndian + case x == 0: + return binary.BigEndian + case y == 0: + return binary.LittleEndian + default: + return binary.BigEndian + } +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go new file mode 100644 index 0000000..03788f7 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go @@ -0,0 +1,429 @@ +package frame + +import ( + "bytes" + "encoding/binary" + "fmt" + + "github.com/derekparker/delve/pkg/dwarf/util" +) + +type CurrentFrameAddress struct { + register uint64 + offset int64 + expression []byte + rule byte +} + +type DWRule struct { + rule byte + offset int64 + newreg uint64 + expression []byte +} + +type FrameContext struct { + loc uint64 + order binary.ByteOrder + address uint64 + cfa CurrentFrameAddress + regs map[uint64]DWRule + initialRegs map[uint64]DWRule + prevRegs map[uint64]DWRule + buf *bytes.Buffer + cie *CommonInformationEntry + codeAlignment uint64 + dataAlignment int64 +} + +func (fctx *FrameContext) CFAOffset() int64 { + return fctx.cfa.offset +} + +// Instructions used to recreate the table from the .debug_frame data. +const ( + DW_CFA_nop = 0x0 // No ops + DW_CFA_set_loc = 0x01 // op1: address + DW_CFA_advance_loc1 = iota // op1: 1-bytes delta + DW_CFA_advance_loc2 // op1: 2-byte delta + DW_CFA_advance_loc4 // op1: 4-byte delta + DW_CFA_offset_extended // op1: ULEB128 register, op2: ULEB128 offset + DW_CFA_restore_extended // op1: ULEB128 register + DW_CFA_undefined // op1: ULEB128 register + DW_CFA_same_value // op1: ULEB128 register + DW_CFA_register // op1: ULEB128 register, op2: ULEB128 register + DW_CFA_remember_state // No ops + DW_CFA_restore_state // No ops + DW_CFA_def_cfa // op1: ULEB128 register, op2: ULEB128 offset + DW_CFA_def_cfa_register // op1: ULEB128 register + DW_CFA_def_cfa_offset // op1: ULEB128 offset + DW_CFA_def_cfa_expression // op1: BLOCK + DW_CFA_expression // op1: ULEB128 register, op2: BLOCK + DW_CFA_offset_extended_sf // op1: ULEB128 register, op2: SLEB128 BLOCK + DW_CFA_def_cfa_sf // op1: ULEB128 register, op2: SLEB128 offset + DW_CFA_def_cfa_offset_sf // op1: SLEB128 offset + DW_CFA_val_offset // op1: ULEB128, op2: ULEB128 + DW_CFA_val_offset_sf // op1: ULEB128, op2: SLEB128 + DW_CFA_val_expression // op1: ULEB128, op2: BLOCK + DW_CFA_lo_user = 0x1c // op1: BLOCK + DW_CFA_hi_user = 0x3f // op1: ULEB128 register, op2: BLOCK + DW_CFA_advance_loc = (0x1 << 6) // High 2 bits: 0x1, low 6: delta + DW_CFA_offset = (0x2 << 6) // High 2 bits: 0x2, low 6: register + DW_CFA_restore = (0x3 << 6) // High 2 bits: 0x3, low 6: register +) + +// Rules defined for register values. +const ( + rule_undefined = iota + rule_sameval + rule_offset + rule_valoffset + rule_register + rule_expression + rule_valexpression + rule_architectural +) + +const low_6_offset = 0x3f + +type instruction func(frame *FrameContext) + +// // Mapping from DWARF opcode to function. +var fnlookup = map[byte]instruction{ + DW_CFA_advance_loc: advanceloc, + DW_CFA_offset: offset, + DW_CFA_restore: restore, + DW_CFA_set_loc: setloc, + DW_CFA_advance_loc1: advanceloc1, + DW_CFA_advance_loc2: advanceloc2, + DW_CFA_advance_loc4: advanceloc4, + DW_CFA_offset_extended: offsetextended, + DW_CFA_restore_extended: restoreextended, + DW_CFA_undefined: undefined, + DW_CFA_same_value: samevalue, + DW_CFA_register: register, + DW_CFA_remember_state: rememberstate, + DW_CFA_restore_state: restorestate, + DW_CFA_def_cfa: defcfa, + DW_CFA_def_cfa_register: defcfaregister, + DW_CFA_def_cfa_offset: defcfaoffset, + DW_CFA_def_cfa_expression: defcfaexpression, + DW_CFA_expression: expression, + DW_CFA_offset_extended_sf: offsetextendedsf, + DW_CFA_def_cfa_sf: defcfasf, + DW_CFA_def_cfa_offset_sf: defcfaoffsetsf, + DW_CFA_val_offset: valoffset, + DW_CFA_val_offset_sf: valoffsetsf, + DW_CFA_val_expression: valexpression, + DW_CFA_lo_user: louser, + DW_CFA_hi_user: hiuser, +} + +func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext { + initialInstructions := make([]byte, len(cie.InitialInstructions)) + copy(initialInstructions, cie.InitialInstructions) + frame := &FrameContext{ + cie: cie, + regs: make(map[uint64]DWRule), + initialRegs: make(map[uint64]DWRule), + prevRegs: make(map[uint64]DWRule), + codeAlignment: cie.CodeAlignmentFactor, + dataAlignment: cie.DataAlignmentFactor, + buf: bytes.NewBuffer(initialInstructions), + } + + frame.ExecuteDwarfProgram() + return frame +} + +// Unwind the stack to find the return address register. +func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext { + frame := executeCIEInstructions(fde.CIE) + frame.order = fde.order + frame.loc = fde.Begin() + frame.address = pc + fdeInstructions := make([]byte, len(fde.Instructions)) + copy(fdeInstructions, fde.Instructions) + frame.ExecuteUntilPC(fdeInstructions) + + return frame +} + +func (frame *FrameContext) ExecuteDwarfProgram() { + for frame.buf.Len() > 0 { + executeDwarfInstruction(frame) + } +} + +// Execute dwarf instructions. +func (frame *FrameContext) ExecuteUntilPC(instructions []byte) { + frame.buf.Truncate(0) + frame.buf.Write(instructions) + + // We only need to execute the instructions until + // ctx.loc > ctx.addess (which is the address we + // are currently at in the traced process). + for frame.address >= frame.loc && frame.buf.Len() > 0 { + executeDwarfInstruction(frame) + } +} + +func executeDwarfInstruction(frame *FrameContext) { + instruction, err := frame.buf.ReadByte() + if err != nil { + panic("Could not read from instruction buffer") + } + + if instruction == DW_CFA_nop { + return + } + + fn := lookupFunc(instruction, frame.buf) + + fn(frame) +} + +func lookupFunc(instruction byte, buf *bytes.Buffer) instruction { + const high_2_bits = 0xc0 + var restore bool + + // Special case the 3 opcodes that have their argument encoded in the opcode itself. + switch instruction & high_2_bits { + case DW_CFA_advance_loc: + instruction = DW_CFA_advance_loc + restore = true + + case DW_CFA_offset: + instruction = DW_CFA_offset + restore = true + + case DW_CFA_restore: + instruction = DW_CFA_restore + restore = true + } + + if restore { + // Restore the last byte as it actually contains the argument for the opcode. + err := buf.UnreadByte() + if err != nil { + panic("Could not unread byte") + } + } + + fn, ok := fnlookup[instruction] + if !ok { + panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction)) + } + + return fn +} + +func advanceloc(frame *FrameContext) { + b, err := frame.buf.ReadByte() + if err != nil { + panic("Could not read byte") + } + + delta := b & low_6_offset + frame.loc += uint64(delta) * frame.codeAlignment +} + +func advanceloc1(frame *FrameContext) { + delta, err := frame.buf.ReadByte() + if err != nil { + panic("Could not read byte") + } + + frame.loc += uint64(delta) * frame.codeAlignment +} + +func advanceloc2(frame *FrameContext) { + var delta uint16 + binary.Read(frame.buf, frame.order, &delta) + + frame.loc += uint64(delta) * frame.codeAlignment +} + +func advanceloc4(frame *FrameContext) { + var delta uint32 + binary.Read(frame.buf, frame.order, &delta) + + frame.loc += uint64(delta) * frame.codeAlignment +} + +func offset(frame *FrameContext) { + b, err := frame.buf.ReadByte() + if err != nil { + panic(err) + } + + var ( + reg = b & low_6_offset + offset, _ = util.DecodeULEB128(frame.buf) + ) + + frame.regs[uint64(reg)] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset} +} + +func restore(frame *FrameContext) { + b, err := frame.buf.ReadByte() + if err != nil { + panic(err) + } + + reg := uint64(b & low_6_offset) + oldrule, ok := frame.initialRegs[reg] + if ok { + frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset} + } else { + frame.regs[reg] = DWRule{rule: rule_undefined} + } +} + +func setloc(frame *FrameContext) { + var loc uint64 + binary.Read(frame.buf, frame.order, &loc) + + frame.loc = loc +} + +func offsetextended(frame *FrameContext) { + var ( + reg, _ = util.DecodeULEB128(frame.buf) + offset, _ = util.DecodeULEB128(frame.buf) + ) + + frame.regs[reg] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset} +} + +func undefined(frame *FrameContext) { + reg, _ := util.DecodeULEB128(frame.buf) + frame.regs[reg] = DWRule{rule: rule_undefined} +} + +func samevalue(frame *FrameContext) { + reg, _ := util.DecodeULEB128(frame.buf) + frame.regs[reg] = DWRule{rule: rule_sameval} +} + +func register(frame *FrameContext) { + reg1, _ := util.DecodeULEB128(frame.buf) + reg2, _ := util.DecodeULEB128(frame.buf) + frame.regs[reg1] = DWRule{newreg: reg2, rule: rule_register} +} + +func rememberstate(frame *FrameContext) { + frame.prevRegs = frame.regs +} + +func restorestate(frame *FrameContext) { + frame.regs = frame.prevRegs +} + +func restoreextended(frame *FrameContext) { + reg, _ := util.DecodeULEB128(frame.buf) + + oldrule, ok := frame.initialRegs[reg] + if ok { + frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset} + } else { + frame.regs[reg] = DWRule{rule: rule_undefined} + } +} + +func defcfa(frame *FrameContext) { + reg, _ := util.DecodeULEB128(frame.buf) + offset, _ := util.DecodeULEB128(frame.buf) + + frame.cfa.register = reg + frame.cfa.offset = int64(offset) +} + +func defcfaregister(frame *FrameContext) { + reg, _ := util.DecodeULEB128(frame.buf) + frame.cfa.register = reg +} + +func defcfaoffset(frame *FrameContext) { + offset, _ := util.DecodeULEB128(frame.buf) + frame.cfa.offset = int64(offset) +} + +func defcfasf(frame *FrameContext) { + reg, _ := util.DecodeULEB128(frame.buf) + offset, _ := util.DecodeSLEB128(frame.buf) + + frame.cfa.register = reg + frame.cfa.offset = offset * frame.dataAlignment +} + +func defcfaoffsetsf(frame *FrameContext) { + offset, _ := util.DecodeSLEB128(frame.buf) + offset *= frame.dataAlignment + frame.cfa.offset = offset +} + +func defcfaexpression(frame *FrameContext) { + var ( + l, _ = util.DecodeULEB128(frame.buf) + expr = frame.buf.Next(int(l)) + ) + + frame.cfa.expression = expr + frame.cfa.rule = rule_expression +} + +func expression(frame *FrameContext) { + var ( + reg, _ = util.DecodeULEB128(frame.buf) + l, _ = util.DecodeULEB128(frame.buf) + expr = frame.buf.Next(int(l)) + ) + + frame.regs[reg] = DWRule{rule: rule_expression, expression: expr} +} + +func offsetextendedsf(frame *FrameContext) { + var ( + reg, _ = util.DecodeULEB128(frame.buf) + offset, _ = util.DecodeSLEB128(frame.buf) + ) + + frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_offset} +} + +func valoffset(frame *FrameContext) { + var ( + reg, _ = util.DecodeULEB128(frame.buf) + offset, _ = util.DecodeULEB128(frame.buf) + ) + + frame.regs[reg] = DWRule{offset: int64(offset), rule: rule_valoffset} +} + +func valoffsetsf(frame *FrameContext) { + var ( + reg, _ = util.DecodeULEB128(frame.buf) + offset, _ = util.DecodeSLEB128(frame.buf) + ) + + frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_valoffset} +} + +func valexpression(frame *FrameContext) { + var ( + reg, _ = util.DecodeULEB128(frame.buf) + l, _ = util.DecodeULEB128(frame.buf) + expr = frame.buf.Next(int(l)) + ) + + frame.regs[reg] = DWRule{rule: rule_valexpression, expression: expr} +} + +func louser(frame *FrameContext) { + frame.buf.Next(1) +} + +func hiuser(frame *FrameContext) { + frame.buf.Next(1) +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go b/vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go new file mode 100644 index 0000000..0d3677f --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go @@ -0,0 +1,122 @@ +package line + +import ( + "bytes" + "encoding/binary" + + "github.com/derekparker/delve/pkg/dwarf/util" +) + +type DebugLinePrologue struct { + UnitLength uint32 + Version uint16 + Length uint32 + MinInstrLength uint8 + InitialIsStmt uint8 + LineBase int8 + LineRange uint8 + OpcodeBase uint8 + StdOpLengths []uint8 +} + +type DebugLineInfo struct { + Prologue *DebugLinePrologue + IncludeDirs []string + FileNames []*FileEntry + Instructions []byte + Lookup map[string]*FileEntry +} + +type FileEntry struct { + Name string + DirIdx uint64 + LastModTime uint64 + Length uint64 +} + +type DebugLines []*DebugLineInfo + +func (d *DebugLines) GetLineInfo(name string) *DebugLineInfo { + // Find in which table file exists and return it. + for _, l := range *d { + if _, ok := l.Lookup[name]; ok { + return l + } + } + return nil +} + +func Parse(data []byte) DebugLines { + var ( + lines = make(DebugLines, 0) + buf = bytes.NewBuffer(data) + ) + + // We have to parse multiple file name tables here. + for buf.Len() > 0 { + dbl := new(DebugLineInfo) + dbl.Lookup = make(map[string]*FileEntry) + + parseDebugLinePrologue(dbl, buf) + parseIncludeDirs(dbl, buf) + parseFileEntries(dbl, buf) + + // Instructions size calculation breakdown: + // - dbl.Prologue.UnitLength is the length of the entire unit, not including the 4 bytes to represent that length. + // - dbl.Prologue.Length is the length of the prologue not including unit length, version or prologue length itself. + // - So you have UnitLength - PrologueLength - (version_length_bytes(2) + prologue_length_bytes(4)). + dbl.Instructions = buf.Next(int(dbl.Prologue.UnitLength - dbl.Prologue.Length - 6)) + + lines = append(lines, dbl) + } + + return lines +} + +func parseDebugLinePrologue(dbl *DebugLineInfo, buf *bytes.Buffer) { + p := new(DebugLinePrologue) + + p.UnitLength = binary.LittleEndian.Uint32(buf.Next(4)) + p.Version = binary.LittleEndian.Uint16(buf.Next(2)) + p.Length = binary.LittleEndian.Uint32(buf.Next(4)) + p.MinInstrLength = uint8(buf.Next(1)[0]) + p.InitialIsStmt = uint8(buf.Next(1)[0]) + p.LineBase = int8(buf.Next(1)[0]) + p.LineRange = uint8(buf.Next(1)[0]) + p.OpcodeBase = uint8(buf.Next(1)[0]) + + p.StdOpLengths = make([]uint8, p.OpcodeBase-1) + binary.Read(buf, binary.LittleEndian, &p.StdOpLengths) + + dbl.Prologue = p +} + +func parseIncludeDirs(info *DebugLineInfo, buf *bytes.Buffer) { + for { + str, _ := util.ParseString(buf) + if str == "" { + break + } + + info.IncludeDirs = append(info.IncludeDirs, str) + } +} + +func parseFileEntries(info *DebugLineInfo, buf *bytes.Buffer) { + for { + entry := new(FileEntry) + + name, _ := util.ParseString(buf) + if name == "" { + break + } + + entry.Name = name + entry.DirIdx, _ = util.DecodeULEB128(buf) + entry.LastModTime, _ = util.DecodeULEB128(buf) + entry.Length, _ = util.DecodeULEB128(buf) + + info.FileNames = append(info.FileNames, entry) + info.Lookup[name] = entry + } +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go b/vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go new file mode 100644 index 0000000..feedd4e --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go @@ -0,0 +1,267 @@ +package line + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + + "github.com/derekparker/delve/pkg/dwarf/util" +) + +type Location struct { + File string + Line int + Address uint64 + Delta int +} + +type StateMachine struct { + dbl *DebugLineInfo + file string + line int + address uint64 + column uint + isStmt bool + basicBlock bool + endSeq bool + lastWasStandard bool + lastDelta int + // valid is true if the current value of the state machine is the address of + // an instruction (using the terminology used by DWARF spec the current + // value of the state machine should be appended to the matrix representing + // the compilation unit) + valid bool +} + +type opcodefn func(*StateMachine, *bytes.Buffer) + +// Special opcodes +const ( + DW_LNS_copy = 1 + DW_LNS_advance_pc = 2 + DW_LNS_advance_line = 3 + DW_LNS_set_file = 4 + DW_LNS_set_column = 5 + DW_LNS_negate_stmt = 6 + DW_LNS_set_basic_block = 7 + DW_LNS_const_add_pc = 8 + DW_LNS_fixed_advance_pc = 9 +) + +// Extended opcodes +const ( + DW_LINE_end_sequence = 1 + DW_LINE_set_address = 2 + DW_LINE_define_file = 3 +) + +var standardopcodes = map[byte]opcodefn{ + DW_LNS_copy: copyfn, + DW_LNS_advance_pc: advancepc, + DW_LNS_advance_line: advanceline, + DW_LNS_set_file: setfile, + DW_LNS_set_column: setcolumn, + DW_LNS_negate_stmt: negatestmt, + DW_LNS_set_basic_block: setbasicblock, + DW_LNS_const_add_pc: constaddpc, + DW_LNS_fixed_advance_pc: fixedadvancepc, +} + +var extendedopcodes = map[byte]opcodefn{ + DW_LINE_end_sequence: endsequence, + DW_LINE_set_address: setaddress, + DW_LINE_define_file: definefile, +} + +func newStateMachine(dbl *DebugLineInfo) *StateMachine { + return &StateMachine{dbl: dbl, file: dbl.FileNames[0].Name, line: 1} +} + +// Returns all PCs for a given file/line. Useful for loops where the 'for' line +// could be split amongst 2 PCs. +func (dbl *DebugLines) AllPCsForFileLine(f string, l int) (pcs []uint64) { + var ( + foundFile bool + lastAddr uint64 + lineInfo = dbl.GetLineInfo(f) + sm = newStateMachine(lineInfo) + buf = bytes.NewBuffer(lineInfo.Instructions) + ) + + for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() { + findAndExecOpcode(sm, buf, b) + if foundFile && sm.file != f { + return + } + if sm.line == l && sm.file == f && sm.address != lastAddr { + foundFile = true + if sm.valid { + pcs = append(pcs, sm.address) + } + line := sm.line + // Keep going until we're on a different line. We only care about + // when a line comes back around (i.e. for loop) so get to next line, + // and try to find the line we care about again. + for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() { + findAndExecOpcode(sm, buf, b) + if line < sm.line { + break + } + } + } + } + return +} + +var NoSourceError = errors.New("no source available") + +func (dbl *DebugLines) AllPCsBetween(begin, end uint64, filename string) ([]uint64, error) { + lineInfo := dbl.GetLineInfo(filename) + if lineInfo == nil { + return nil, NoSourceError + } + var ( + pcs []uint64 + lastaddr uint64 + sm = newStateMachine(lineInfo) + buf = bytes.NewBuffer(lineInfo.Instructions) + ) + + for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() { + findAndExecOpcode(sm, buf, b) + if !sm.valid { + continue + } + if sm.address > end { + break + } + if sm.address >= begin && sm.address > lastaddr { + lastaddr = sm.address + pcs = append(pcs, sm.address) + } + } + return pcs, nil +} + +func findAndExecOpcode(sm *StateMachine, buf *bytes.Buffer, b byte) { + switch { + case b == 0: + execExtendedOpcode(sm, b, buf) + case b < sm.dbl.Prologue.OpcodeBase: + execStandardOpcode(sm, b, buf) + default: + execSpecialOpcode(sm, b) + } +} + +func execSpecialOpcode(sm *StateMachine, instr byte) { + var ( + opcode = uint8(instr) + decoded = opcode - sm.dbl.Prologue.OpcodeBase + ) + + if sm.dbl.Prologue.InitialIsStmt == uint8(1) { + sm.isStmt = true + } + + sm.lastDelta = int(sm.dbl.Prologue.LineBase + int8(decoded%sm.dbl.Prologue.LineRange)) + sm.line += sm.lastDelta + sm.address += uint64(decoded/sm.dbl.Prologue.LineRange) * uint64(sm.dbl.Prologue.MinInstrLength) + sm.basicBlock = false + sm.lastWasStandard = false + sm.valid = true +} + +func execExtendedOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) { + _, _ = util.DecodeULEB128(buf) + b, _ := buf.ReadByte() + fn, ok := extendedopcodes[b] + if !ok { + panic(fmt.Sprintf("Encountered unknown extended opcode %#v\n", b)) + } + sm.lastWasStandard = false + sm.valid = false + + fn(sm, buf) +} + +func execStandardOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) { + fn, ok := standardopcodes[instr] + if !ok { + panic(fmt.Sprintf("Encountered unknown standard opcode %#v\n", instr)) + } + sm.lastWasStandard = true + sm.valid = false + + fn(sm, buf) +} + +func copyfn(sm *StateMachine, buf *bytes.Buffer) { + sm.basicBlock = false + sm.valid = true +} + +func advancepc(sm *StateMachine, buf *bytes.Buffer) { + addr, _ := util.DecodeULEB128(buf) + sm.address += addr * uint64(sm.dbl.Prologue.MinInstrLength) +} + +func advanceline(sm *StateMachine, buf *bytes.Buffer) { + line, _ := util.DecodeSLEB128(buf) + sm.line += int(line) + sm.lastDelta = int(line) +} + +func setfile(sm *StateMachine, buf *bytes.Buffer) { + i, _ := util.DecodeULEB128(buf) + sm.file = sm.dbl.FileNames[i-1].Name +} + +func setcolumn(sm *StateMachine, buf *bytes.Buffer) { + c, _ := util.DecodeULEB128(buf) + sm.column = uint(c) +} + +func negatestmt(sm *StateMachine, buf *bytes.Buffer) { + sm.isStmt = !sm.isStmt +} + +func setbasicblock(sm *StateMachine, buf *bytes.Buffer) { + sm.basicBlock = true +} + +func constaddpc(sm *StateMachine, buf *bytes.Buffer) { + sm.address += uint64((255-sm.dbl.Prologue.OpcodeBase)/sm.dbl.Prologue.LineRange) * uint64(sm.dbl.Prologue.MinInstrLength) +} + +func fixedadvancepc(sm *StateMachine, buf *bytes.Buffer) { + var operand uint16 + binary.Read(buf, binary.LittleEndian, &operand) + + sm.address += uint64(operand) +} + +func endsequence(sm *StateMachine, buf *bytes.Buffer) { + sm.endSeq = true + sm.valid = true +} + +func setaddress(sm *StateMachine, buf *bytes.Buffer) { + var addr uint64 + + binary.Read(buf, binary.LittleEndian, &addr) + + sm.address = addr +} + +func definefile(sm *StateMachine, buf *bytes.Buffer) { + var ( + _, _ = util.ParseString(buf) + _, _ = util.DecodeULEB128(buf) + _, _ = util.DecodeULEB128(buf) + _, _ = util.DecodeULEB128(buf) + ) + + // Don't do anything here yet. +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go b/vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go new file mode 100644 index 0000000..158b073 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go @@ -0,0 +1,84 @@ +package op + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + + "github.com/derekparker/delve/pkg/dwarf/util" +) + +const ( + DW_OP_addr = 0x3 + DW_OP_call_frame_cfa = 0x9c + DW_OP_plus = 0x22 + DW_OP_consts = 0x11 + DW_OP_plus_uconsts = 0x23 +) + +type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error) + +var oplut = map[byte]stackfn{ + DW_OP_call_frame_cfa: callframecfa, + DW_OP_plus: plus, + DW_OP_consts: consts, + DW_OP_addr: addr, + DW_OP_plus_uconsts: plusuconsts, +} + +func ExecuteStackProgram(cfa int64, instructions []byte) (int64, error) { + stack := make([]int64, 0, 3) + buf := bytes.NewBuffer(instructions) + + for opcode, err := buf.ReadByte(); err == nil; opcode, err = buf.ReadByte() { + fn, ok := oplut[opcode] + if !ok { + return 0, fmt.Errorf("invalid instruction %#v", opcode) + } + + stack, err = fn(buf, stack, cfa) + if err != nil { + return 0, err + } + } + + if len(stack) == 0 { + return 0, errors.New("empty OP stack") + } + + return stack[len(stack)-1], nil +} + +func callframecfa(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) { + if cfa == 0 { + return stack, fmt.Errorf("Could not retrieve CFA for current PC") + } + return append(stack, int64(cfa)), nil +} + +func addr(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) { + return append(stack, int64(binary.LittleEndian.Uint64(buf.Next(8)))), nil +} + +func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) { + var ( + slen = len(stack) + digits = stack[slen-2 : slen] + st = stack[:slen-2] + ) + + return append(st, digits[0]+digits[1]), nil +} + +func plusuconsts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) { + slen := len(stack) + num, _ := util.DecodeULEB128(buf) + stack[slen-1] = stack[slen-1] + int64(num) + return stack, nil +} + +func consts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) { + num, _ := util.DecodeSLEB128(buf) + return append(stack, num), nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go b/vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go new file mode 100755 index 0000000..ecd61f5 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go @@ -0,0 +1,345 @@ +package reader + +import ( + "errors" + "fmt" + + "github.com/derekparker/delve/pkg/dwarf/op" + "golang.org/x/debug/dwarf" +) + +type Reader struct { + *dwarf.Reader + depth int +} + +// New returns a reader for the specified dwarf data. +func New(data *dwarf.Data) *Reader { + return &Reader{data.Reader(), 0} +} + +// Seek moves the reader to an arbitrary offset. +func (reader *Reader) Seek(off dwarf.Offset) { + reader.depth = 0 + reader.Reader.Seek(off) +} + +// SeekToEntry moves the reader to an arbitrary entry. +func (reader *Reader) SeekToEntry(entry *dwarf.Entry) error { + reader.Seek(entry.Offset) + // Consume the current entry so .Next works as intended + _, err := reader.Next() + return err +} + +// SeekToFunctionEntry moves the reader to the function that includes the +// specified program counter. +func (reader *Reader) SeekToFunction(pc uint64) (*dwarf.Entry, error) { + reader.Seek(0) + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + if entry.Tag != dwarf.TagSubprogram { + continue + } + + lowpc, ok := entry.Val(dwarf.AttrLowpc).(uint64) + if !ok { + continue + } + + highpc, ok := entry.Val(dwarf.AttrHighpc).(uint64) + if !ok { + continue + } + + if lowpc <= pc && highpc > pc { + return entry, nil + } + } + + return nil, fmt.Errorf("unable to find function context") +} + +// Returns the address for the named entry. +func (reader *Reader) AddrFor(name string) (uint64, error) { + entry, err := reader.FindEntryNamed(name, false) + if err != nil { + return 0, err + } + instructions, ok := entry.Val(dwarf.AttrLocation).([]byte) + if !ok { + return 0, fmt.Errorf("type assertion failed") + } + addr, err := op.ExecuteStackProgram(0, instructions) + if err != nil { + return 0, err + } + return uint64(addr), nil +} + +// Returns the address for the named struct member. Expects the reader to be at the parent entry +// or one of the parents children, thus does not seek to parent by itself. +func (reader *Reader) AddrForMember(member string, initialInstructions []byte) (uint64, error) { + for { + entry, err := reader.NextMemberVariable() + if err != nil { + return 0, err + } + if entry == nil { + return 0, fmt.Errorf("nil entry for member named %s", member) + } + name, ok := entry.Val(dwarf.AttrName).(string) + if !ok || name != member { + continue + } + instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte) + if !ok { + continue + } + addr, err := op.ExecuteStackProgram(0, append(initialInstructions, instructions...)) + return uint64(addr), err + } +} + +var TypeNotFoundErr = errors.New("no type entry found, use 'types' for a list of valid types") + +// SeekToType moves the reader to the type specified by the entry, +// optionally resolving typedefs and pointer types. If the reader is set +// to a struct type the NextMemberVariable call can be used to walk all member data. +func (reader *Reader) SeekToType(entry *dwarf.Entry, resolveTypedefs bool, resolvePointerTypes bool) (*dwarf.Entry, error) { + offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset) + if !ok { + return nil, fmt.Errorf("entry does not have a type attribute") + } + + // Seek to the first type offset + reader.Seek(offset) + + // Walk the types to the base + for typeEntry, err := reader.Next(); typeEntry != nil; typeEntry, err = reader.Next() { + if err != nil { + return nil, err + } + + if typeEntry.Tag == dwarf.TagTypedef && !resolveTypedefs { + return typeEntry, nil + } + + if typeEntry.Tag == dwarf.TagPointerType && !resolvePointerTypes { + return typeEntry, nil + } + + offset, ok = typeEntry.Val(dwarf.AttrType).(dwarf.Offset) + if !ok { + return typeEntry, nil + } + + reader.Seek(offset) + } + + return nil, TypeNotFoundErr +} + +func (reader *Reader) NextType() (*dwarf.Entry, error) { + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + switch entry.Tag { + case dwarf.TagArrayType, dwarf.TagBaseType, dwarf.TagClassType, dwarf.TagStructType, dwarf.TagUnionType, dwarf.TagConstType, dwarf.TagVolatileType, dwarf.TagRestrictType, dwarf.TagEnumerationType, dwarf.TagPointerType, dwarf.TagSubroutineType, dwarf.TagTypedef, dwarf.TagUnspecifiedType: + return entry, nil + } + } + + return nil, nil +} + +// SeekToTypeNamed moves the reader to the type specified by the name. +// If the reader is set to a struct type the NextMemberVariable call +// can be used to walk all member data. +func (reader *Reader) SeekToTypeNamed(name string) (*dwarf.Entry, error) { + // Walk the types to the base + for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() { + if err != nil { + return nil, err + } + + n, ok := entry.Val(dwarf.AttrName).(string) + if !ok { + continue + } + + if n == name { + return entry, nil + } + } + + return nil, TypeNotFoundErr +} + +// Finds the entry for 'name'. +func (reader *Reader) FindEntryNamed(name string, member bool) (*dwarf.Entry, error) { + depth := 1 + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + if entry.Children { + depth++ + } + + if entry.Tag == 0 { + depth-- + if depth <= 0 { + return nil, fmt.Errorf("could not find symbol value for %s", name) + } + } + + if member { + if entry.Tag != dwarf.TagMember { + continue + } + } else { + if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagStructType { + continue + } + } + + n, ok := entry.Val(dwarf.AttrName).(string) + if !ok || n != name { + continue + } + return entry, nil + } + return nil, fmt.Errorf("could not find symbol value for %s", name) +} + +func (reader *Reader) InstructionsForEntryNamed(name string, member bool) ([]byte, error) { + entry, err := reader.FindEntryNamed(name, member) + if err != nil { + return nil, err + } + var attr dwarf.Attr + if member { + attr = dwarf.AttrDataMemberLoc + } else { + attr = dwarf.AttrLocation + } + instr, ok := entry.Val(attr).([]byte) + if !ok { + return nil, errors.New("invalid typecast for Dwarf instructions") + } + return instr, nil +} + +func (reader *Reader) InstructionsForEntry(entry *dwarf.Entry) ([]byte, error) { + if entry.Tag == dwarf.TagMember { + instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte) + if !ok { + return nil, fmt.Errorf("member data has no data member location attribute") + } + // clone slice to prevent stomping on the dwarf data + return append([]byte{}, instructions...), nil + } + + // non-member + instructions, ok := entry.Val(dwarf.AttrLocation).([]byte) + if !ok { + return nil, fmt.Errorf("entry has no location attribute") + } + + // clone slice to prevent stomping on the dwarf data + return append([]byte{}, instructions...), nil +} + +// NextScopeVariable moves the reader to the next debug entry that describes a local variable and returns the entry. +func (reader *Reader) NextScopeVariable() (*dwarf.Entry, error) { + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + // All scope variables will be at the same depth + reader.SkipChildren() + + // End of the current depth + if entry.Tag == 0 { + break + } + + if entry.Tag == dwarf.TagVariable || entry.Tag == dwarf.TagFormalParameter { + return entry, nil + } + } + + // No more items + return nil, nil +} + +// NextMememberVariable moves the reader to the next debug entry that describes a member variable and returns the entry. +func (reader *Reader) NextMemberVariable() (*dwarf.Entry, error) { + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + // All member variables will be at the same depth + reader.SkipChildren() + + // End of the current depth + if entry.Tag == 0 { + break + } + + if entry.Tag == dwarf.TagMember { + return entry, nil + } + } + + // No more items + return nil, nil +} + +// NextPackageVariable moves the reader to the next debug entry that describes a package variable. +// Any TagVariable entry that is not inside a sub prgram entry and is marked external is considered a package variable. +func (reader *Reader) NextPackageVariable() (*dwarf.Entry, error) { + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + if entry.Tag == dwarf.TagVariable { + ext, ok := entry.Val(dwarf.AttrExternal).(bool) + if ok && ext { + return entry, nil + } + } + + // Ignore everything inside sub programs + if entry.Tag == dwarf.TagSubprogram { + reader.SkipChildren() + } + } + + // No more items + return nil, nil +} + +func (reader *Reader) NextCompileUnit() (*dwarf.Entry, error) { + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return nil, err + } + + if entry.Tag == dwarf.TagCompileUnit { + return entry, nil + } + } + + return nil, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/util/util.go b/vendor/github.com/derekparker/delve/pkg/dwarf/util/util.go new file mode 100644 index 0000000..f60c203 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/dwarf/util/util.go @@ -0,0 +1,81 @@ +package util + +import "bytes" + +// DecodeULEB128 decodes an unsigned Little Endian Base 128 +// represented number. +func DecodeULEB128(buf *bytes.Buffer) (uint64, uint32) { + var ( + result uint64 + shift uint64 + length uint32 + ) + + if buf.Len() == 0 { + return 0, 0 + } + + for { + b, err := buf.ReadByte() + if err != nil { + panic("Could not parse ULEB128 value") + } + length++ + + result |= uint64((uint(b) & 0x7f) << shift) + + // If high order bit is 1. + if b&0x80 == 0 { + break + } + + shift += 7 + } + + return result, length +} + +// DecodeSLEB128 decodes a signed Little Endian Base 128 +// represented number. +func DecodeSLEB128(buf *bytes.Buffer) (int64, uint32) { + var ( + b byte + err error + result int64 + shift uint64 + length uint32 + ) + + if buf.Len() == 0 { + return 0, 0 + } + + for { + b, err = buf.ReadByte() + if err != nil { + panic("Could not parse SLEB128 value") + } + length++ + + result |= int64((int64(b) & 0x7f) << shift) + shift += 7 + if b&0x80 == 0 { + break + } + } + + if (shift < 8*uint64(length)) && (b&0x40 > 0) { + result |= -(1 << shift) + } + + return result, length +} + +func ParseString(data *bytes.Buffer) (string, uint32) { + str, err := data.ReadString(0x0) + if err != nil { + panic("Could not parse string") + } + + return str[:len(str)-1], uint32(len(str)) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/arch.go b/vendor/github.com/derekparker/delve/pkg/proc/arch.go new file mode 100644 index 0000000..4031fd8 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/arch.go @@ -0,0 +1,79 @@ +package proc + +import "runtime" + +// Arch defines an interface for representing a +// CPU architecture. +type Arch interface { + SetGStructOffset(ver GoVersion, iscgo bool) + PtrSize() int + BreakpointInstruction() []byte + BreakpointSize() int + GStructOffset() uint64 +} + +// AMD64 represents the AMD64 CPU architecture. +type AMD64 struct { + ptrSize int + breakInstruction []byte + breakInstructionLen int + gStructOffset uint64 + hardwareBreakpointUsage []bool +} + +// AMD64Arch returns an initialized AMD64 +// struct. +func AMD64Arch() *AMD64 { + var breakInstr = []byte{0xCC} + + return &AMD64{ + ptrSize: 8, + breakInstruction: breakInstr, + breakInstructionLen: len(breakInstr), + hardwareBreakpointUsage: make([]bool, 4), + } +} + +// SetGStructOffset sets the offset of the G struct on the AMD64 +// arch struct. The offset is dependent on the Go compiler Version +// and whether or not the target program was externally linked. +func (a *AMD64) SetGStructOffset(ver GoVersion, isextld bool) { + switch runtime.GOOS { + case "darwin": + a.gStructOffset = 0x8a0 + case "linux": + a.gStructOffset = 0xfffffffffffffff0 + if isextld || ver.AfterOrEqual(GoVersion{1, 5, -1, 2, 0}) || ver.IsDevel() { + a.gStructOffset += 8 + } + case "windows": + // Use ArbitraryUserPointer (0x28) as pointer to pointer + // to G struct per: + // https://golang.org/src/runtime/cgo/gcc_windows_amd64.c + a.gStructOffset = 0x28 + } +} + +// PtrSize returns the size of a pointer +// on this architecture. +func (a *AMD64) PtrSize() int { + return a.ptrSize +} + +// BreakpointInstruction returns the Breakpoint +// instruction for this architecture. +func (a *AMD64) BreakpointInstruction() []byte { + return a.breakInstruction +} + +// BreakpointSize returns the size of the +// breakpoint instruction on this architecture. +func (a *AMD64) BreakpointSize() int { + return a.breakInstructionLen +} + +// GStructOffset returns the offset of the G +// struct in thread local storage. +func (a *AMD64) GStructOffset() uint64 { + return a.gStructOffset +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go b/vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go new file mode 100644 index 0000000..8f13d47 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go @@ -0,0 +1,163 @@ +package proc + +import ( + "errors" + "fmt" + "go/ast" + "go/constant" + "reflect" +) + +// Breakpoint represents a breakpoint. Stores information on the break +// point including the byte of data that originally was stored at that +// address. +type Breakpoint struct { + // File & line information for printing. + FunctionName string + File string + Line int + + Addr uint64 // Address breakpoint is set for. + OriginalData []byte // If software breakpoint, the data we replace with breakpoint instruction. + Name string // User defined name of the breakpoint + ID int // Monotonically increasing ID. + Kind BreakpointKind // Whether this is an internal breakpoint (for next'ing or stepping). + + // Breakpoint information + Tracepoint bool // Tracepoint flag + Goroutine bool // Retrieve goroutine information + Stacktrace int // Number of stack frames to retrieve + Variables []string // Variables to evaluate + LoadArgs *LoadConfig + LoadLocals *LoadConfig + HitCount map[int]uint64 // Number of times a breakpoint has been reached in a certain goroutine + TotalHitCount uint64 // Number of times a breakpoint has been reached + + // DeferReturns: when kind == NextDeferBreakpoint this breakpoint + // will also check if the caller is runtime.gopanic or if the return + // address is in the DeferReturns array. + // Next uses NextDeferBreakpoints for the breakpoint it sets on the + // deferred function, DeferReturns is populated with the + // addresses of calls to runtime.deferreturn in the current + // function. This insures that the breakpoint on the deferred + // function only triggers on panic or on the defer call to + // the function, not when the function is called directly + DeferReturns []uint64 + // Cond: if not nil the breakpoint will be triggered only if evaluating Cond returns true + Cond ast.Expr +} + +// Breakpoint Kind determines the behavior of delve when the +// breakpoint is reached. +type BreakpointKind int + +const ( + // UserBreakpoint is a user set breakpoint + UserBreakpoint BreakpointKind = iota + // NextBreakpoint is a breakpoint set by Next, Continue + // will stop on it and delete it + NextBreakpoint + // NextDeferBreakpoint is a breakpoint set by Next on the + // first deferred function. In addition to checking their condition + // breakpoints of this kind will also check that the function has been + // called by runtime.gopanic or through runtime.deferreturn. + NextDeferBreakpoint + // StepBreakpoint is a breakpoint set by Step on a CALL instruction, + // Continue will set a new breakpoint (of NextBreakpoint kind) on the + // destination of CALL, delete this breakpoint and then continue again + StepBreakpoint +) + +func (bp *Breakpoint) String() string { + return fmt.Sprintf("Breakpoint %d at %#v %s:%d (%d)", bp.ID, bp.Addr, bp.File, bp.Line, bp.TotalHitCount) +} + +// Clear this breakpoint appropriately depending on whether it is a +// hardware or software breakpoint. +func (bp *Breakpoint) Clear(thread *Thread) (*Breakpoint, error) { + if _, err := thread.writeMemory(uintptr(bp.Addr), bp.OriginalData); err != nil { + return nil, fmt.Errorf("could not clear breakpoint %s", err) + } + return bp, nil +} + +// BreakpointExistsError is returned when trying to set a breakpoint at +// an address that already has a breakpoint set for it. +type BreakpointExistsError struct { + file string + line int + addr uint64 +} + +func (bpe BreakpointExistsError) Error() string { + return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr) +} + +// InvalidAddressError represents the result of +// attempting to set a breakpoint at an invalid address. +type InvalidAddressError struct { + address uint64 +} + +func (iae InvalidAddressError) Error() string { + return fmt.Sprintf("Invalid address %#v\n", iae.address) +} + +func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error { + _, err := thread.writeMemory(uintptr(addr), dbp.arch.BreakpointInstruction()) + return err +} + +func (bp *Breakpoint) checkCondition(thread *Thread) (bool, error) { + if bp.Cond == nil { + return true, nil + } + if bp.Kind == NextDeferBreakpoint { + frames, err := thread.Stacktrace(2) + if err == nil { + ispanic := len(frames) >= 3 && frames[2].Current.Fn != nil && frames[2].Current.Fn.Name == "runtime.gopanic" + isdeferreturn := false + if len(frames) >= 1 { + for _, pc := range bp.DeferReturns { + if frames[0].Ret == pc { + isdeferreturn = true + break + } + } + } + if !ispanic && !isdeferreturn { + return false, nil + } + } + } + scope, err := thread.Scope() + if err != nil { + return true, err + } + v, err := scope.evalAST(bp.Cond) + if err != nil { + return true, fmt.Errorf("error evaluating expression: %v", err) + } + if v.Unreadable != nil { + return true, fmt.Errorf("condition expression unreadable: %v", v.Unreadable) + } + if v.Kind != reflect.Bool { + return true, errors.New("condition expression not boolean") + } + return constant.BoolVal(v.Value), nil +} + +// Internal returns true for breakpoints not set directly by the user. +func (bp *Breakpoint) Internal() bool { + return bp.Kind != UserBreakpoint +} + +// NoBreakpointError is returned when trying to +// clear a breakpoint that does not exist. +type NoBreakpointError struct { + addr uint64 +} + +func (nbp NoBreakpointError) Error() string { + return fmt.Sprintf("no breakpoint at %#v", nbp.addr) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/disasm.go b/vendor/github.com/derekparker/delve/pkg/proc/disasm.go new file mode 100644 index 0000000..731336e --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/disasm.go @@ -0,0 +1,67 @@ +package proc + +type AsmInstruction struct { + Loc Location + DestLoc *Location + Bytes []byte + Breakpoint bool + AtPC bool + Inst *ArchInst +} + +type AssemblyFlavour int + +const ( + GNUFlavour = AssemblyFlavour(iota) + IntelFlavour +) + +// Disassemble disassembles target memory between startPC and endPC +// If currentGoroutine is set and thread is stopped at a CALL instruction Disassemble will evaluate the argument of the CALL instruction using the thread's registers +// Be aware that the Bytes field of each returned instruction is a slice of a larger array of size endPC - startPC +func (thread *Thread) Disassemble(startPC, endPC uint64, currentGoroutine bool) ([]AsmInstruction, error) { + if thread.dbp.exited { + return nil, &ProcessExitedError{} + } + mem, err := thread.readMemory(uintptr(startPC), int(endPC-startPC)) + if err != nil { + return nil, err + } + + r := make([]AsmInstruction, 0, len(mem)/15) + pc := startPC + + var curpc uint64 + var regs Registers + if currentGoroutine { + regs, _ = thread.Registers(false) + if regs != nil { + curpc = regs.PC() + } + } + + for len(mem) > 0 { + bp, atbp := thread.dbp.breakpoints[pc] + if atbp { + for i := range bp.OriginalData { + mem[i] = bp.OriginalData[i] + } + } + file, line, fn := thread.dbp.PCToLine(pc) + loc := Location{PC: pc, File: file, Line: line, Fn: fn} + inst, err := asmDecode(mem, pc) + if err == nil { + atpc := currentGoroutine && (curpc == pc) + destloc := thread.resolveCallArg(inst, atpc, regs) + r = append(r, AsmInstruction{Loc: loc, DestLoc: destloc, Bytes: mem[:inst.Len], Breakpoint: atbp, AtPC: atpc, Inst: inst}) + + pc += uint64(inst.Size()) + mem = mem[inst.Size():] + } else { + r = append(r, AsmInstruction{Loc: loc, Bytes: mem[:1], Breakpoint: atbp, Inst: nil}) + pc++ + mem = mem[1:] + } + } + return r, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go new file mode 100644 index 0000000..ebe085b --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go @@ -0,0 +1,184 @@ +package proc + +import ( + "debug/gosym" + "encoding/binary" + + "rsc.io/x86/x86asm" +) + +var maxInstructionLength uint64 = 15 + +type ArchInst x86asm.Inst + +func asmDecode(mem []byte, pc uint64) (*ArchInst, error) { + inst, err := x86asm.Decode(mem, 64) + if err != nil { + return nil, err + } + patchPCRel(pc, &inst) + r := ArchInst(inst) + return &r, nil +} + +func (inst *ArchInst) Size() int { + return inst.Len +} + +// converts PC relative arguments to absolute addresses +func patchPCRel(pc uint64, inst *x86asm.Inst) { + for i := range inst.Args { + rel, isrel := inst.Args[i].(x86asm.Rel) + if isrel { + inst.Args[i] = x86asm.Imm(int64(pc) + int64(rel) + int64(inst.Len)) + } + } + return +} + +func (inst *AsmInstruction) Text(flavour AssemblyFlavour) string { + if inst.Inst == nil { + return "?" + } + + var text string + + switch flavour { + case GNUFlavour: + text = x86asm.GNUSyntax(x86asm.Inst(*inst.Inst)) + case IntelFlavour: + fallthrough + default: + text = x86asm.IntelSyntax(x86asm.Inst(*inst.Inst)) + } + + if inst.IsCall() && inst.DestLoc != nil && inst.DestLoc.Fn != nil { + text += " " + inst.DestLoc.Fn.Name + } + + return text +} + +func (inst *AsmInstruction) IsCall() bool { + return inst.Inst.Op == x86asm.CALL || inst.Inst.Op == x86asm.LCALL +} + +func (thread *Thread) resolveCallArg(inst *ArchInst, currentGoroutine bool, regs Registers) *Location { + if inst.Op != x86asm.CALL && inst.Op != x86asm.LCALL { + return nil + } + + var pc uint64 + var err error + + switch arg := inst.Args[0].(type) { + case x86asm.Imm: + pc = uint64(arg) + case x86asm.Reg: + if !currentGoroutine || regs == nil { + return nil + } + pc, err = regs.Get(int(arg)) + if err != nil { + return nil + } + case x86asm.Mem: + if !currentGoroutine || regs == nil { + return nil + } + if arg.Segment != 0 { + return nil + } + regs, err := thread.Registers(false) + if err != nil { + return nil + } + base, err1 := regs.Get(int(arg.Base)) + index, err2 := regs.Get(int(arg.Index)) + if err1 != nil || err2 != nil { + return nil + } + addr := uintptr(int64(base) + int64(index*uint64(arg.Scale)) + arg.Disp) + //TODO: should this always be 64 bits instead of inst.MemBytes? + pcbytes, err := thread.readMemory(addr, inst.MemBytes) + if err != nil { + return nil + } + pc = binary.LittleEndian.Uint64(pcbytes) + default: + return nil + } + + file, line, fn := thread.dbp.PCToLine(pc) + if fn == nil { + return nil + } + return &Location{PC: pc, File: file, Line: line, Fn: fn} +} + +type instrseq []x86asm.Op + +// Possible stacksplit prologues are inserted by stacksplit in +// $GOROOT/src/cmd/internal/obj/x86/obj6.go. +// The stacksplit prologue will always begin with loading curg in CX, this +// instruction is added by load_g_cx in the same file and is either 1 or 2 +// MOVs. +var prologues []instrseq + +func init() { + var tinyStacksplit = instrseq{x86asm.CMP, x86asm.JBE} + var smallStacksplit = instrseq{x86asm.LEA, x86asm.CMP, x86asm.JBE} + var bigStacksplit = instrseq{x86asm.MOV, x86asm.CMP, x86asm.JE, x86asm.LEA, x86asm.SUB, x86asm.CMP, x86asm.JBE} + var unixGetG = instrseq{x86asm.MOV} + var windowsGetG = instrseq{x86asm.MOV, x86asm.MOV} + + prologues = make([]instrseq, 0, 2*3) + for _, getG := range []instrseq{unixGetG, windowsGetG} { + for _, stacksplit := range []instrseq{tinyStacksplit, smallStacksplit, bigStacksplit} { + prologue := make(instrseq, 0, len(getG)+len(stacksplit)) + prologue = append(prologue, getG...) + prologue = append(prologue, stacksplit...) + prologues = append(prologues, prologue) + } + } +} + +// FirstPCAfterPrologue returns the address of the first instruction after the prologue for function fn +// If sameline is set FirstPCAfterPrologue will always return an address associated with the same line as fn.Entry +func (dbp *Process) FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error) { + text, err := dbp.CurrentThread().Disassemble(fn.Entry, fn.End, false) + if err != nil { + return fn.Entry, err + } + + if len(text) <= 0 { + return fn.Entry, nil + } + + for _, prologue := range prologues { + if len(prologue) >= len(text) { + continue + } + if checkPrologue(text, prologue) { + r := &text[len(prologue)] + if sameline { + if r.Loc.Line != text[0].Loc.Line { + return fn.Entry, nil + } + } + return r.Loc.PC, nil + } + } + + return fn.Entry, nil +} + +func checkPrologue(s []AsmInstruction, prologuePattern instrseq) bool { + line := s[0].Loc.Line + for i, op := range prologuePattern { + if s[i].Inst.Op != op || s[i].Loc.Line != line { + return false + } + } + return true +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/doc.go b/vendor/github.com/derekparker/delve/pkg/proc/doc.go new file mode 100644 index 0000000..6079887 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/doc.go @@ -0,0 +1,9 @@ +// Package proc is a low-level package that provides methods to manipulate +// the process we are debugging. +// +// proc implements all core functionality including: +// * creating / attaching to a process +// * process manipulation (step, next, continue, halt) +// * methods to explore the memory of the process +// +package proc diff --git a/vendor/github.com/derekparker/delve/pkg/proc/eval.go b/vendor/github.com/derekparker/delve/pkg/proc/eval.go new file mode 100644 index 0000000..0b50cb8 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/eval.go @@ -0,0 +1,1131 @@ +package proc + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "go/ast" + "go/constant" + "go/parser" + "go/printer" + "go/token" + "reflect" + + "github.com/derekparker/delve/pkg/dwarf/reader" + "golang.org/x/debug/dwarf" +) + +var OperationOnSpecialFloatError = errors.New("operations on non-finite floats not implemented") + +// EvalExpression returns the value of the given expression. +func (scope *EvalScope) EvalExpression(expr string, cfg LoadConfig) (*Variable, error) { + t, err := parser.ParseExpr(expr) + if err != nil { + return nil, err + } + + ev, err := scope.evalAST(t) + if err != nil { + return nil, err + } + ev.loadValue(cfg) + if ev.Name == "" { + ev.Name = expr + } + return ev, nil +} + +func (scope *EvalScope) evalAST(t ast.Expr) (*Variable, error) { + switch node := t.(type) { + case *ast.CallExpr: + if len(node.Args) == 1 { + v, err := scope.evalTypeCast(node) + if err == nil { + return v, nil + } + _, isident := node.Fun.(*ast.Ident) + // we don't support function calls at the moment except for a few + // builtin functions so just return the type error here if the function + // isn't an identifier. + // More sophisticated logic will be required when function calls + // are implemented. + if err != reader.TypeNotFoundErr || !isident { + return v, err + } + } + return scope.evalBuiltinCall(node) + + case *ast.Ident: + return scope.evalIdent(node) + + case *ast.ParenExpr: + // otherwise just eval recursively + return scope.evalAST(node.X) + + case *ast.SelectorExpr: // . + // try to interpret the selector as a package variable + if maybePkg, ok := node.X.(*ast.Ident); ok { + if maybePkg.Name == "runtime" && node.Sel.Name == "curg" { + return scope.Thread.getGVariable() + } else if v, err := scope.packageVarAddr(maybePkg.Name + "." + node.Sel.Name); err == nil { + return v, nil + } + } + // if it's not a package variable then it must be a struct member access + return scope.evalStructSelector(node) + + case *ast.TypeAssertExpr: // .() + return scope.evalTypeAssert(node) + + case *ast.IndexExpr: + return scope.evalIndex(node) + + case *ast.SliceExpr: + if node.Slice3 { + return nil, fmt.Errorf("3-index slice expressions not supported") + } + return scope.evalReslice(node) + + case *ast.StarExpr: + // pointer dereferencing * + return scope.evalPointerDeref(node) + + case *ast.UnaryExpr: + // The unary operators we support are +, - and & (note that unary * is parsed as ast.StarExpr) + switch node.Op { + case token.AND: + return scope.evalAddrOf(node) + + default: + return scope.evalUnary(node) + } + + case *ast.BinaryExpr: + return scope.evalBinary(node) + + case *ast.BasicLit: + return newConstant(constant.MakeFromLiteral(node.Value, node.Kind, 0), scope.Thread), nil + + default: + return nil, fmt.Errorf("expression %T not implemented", t) + + } +} + +func exprToString(t ast.Expr) string { + var buf bytes.Buffer + printer.Fprint(&buf, token.NewFileSet(), t) + return buf.String() +} + +// Eval type cast expressions +func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) { + argv, err := scope.evalAST(node.Args[0]) + if err != nil { + return nil, err + } + argv.loadValue(loadSingleValue) + if argv.Unreadable != nil { + return nil, argv.Unreadable + } + + fnnode := node.Fun + + // remove all enclosing parenthesis from the type name + for { + p, ok := fnnode.(*ast.ParenExpr) + if !ok { + break + } + fnnode = p.X + } + + styp, err := scope.Thread.dbp.findTypeExpr(fnnode) + if err != nil { + return nil, err + } + typ := resolveTypedef(styp) + + converr := fmt.Errorf("can not convert %q to %s", exprToString(node.Args[0]), typ.String()) + + v := newVariable("", 0, styp, scope.Thread.dbp, scope.Thread) + v.loaded = true + + switch ttyp := typ.(type) { + case *dwarf.PtrType: + switch argv.Kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + // ok + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + // ok + default: + return nil, converr + } + + n, _ := constant.Int64Val(argv.Value) + + v.Children = []Variable{*(scope.newVariable("", uintptr(n), ttyp.Type))} + return v, nil + + case *dwarf.UintType: + switch argv.Kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, _ := constant.Int64Val(argv.Value) + v.Value = constant.MakeUint64(convertInt(uint64(n), false, ttyp.Size())) + return v, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + n, _ := constant.Uint64Val(argv.Value) + v.Value = constant.MakeUint64(convertInt(n, false, ttyp.Size())) + return v, nil + case reflect.Float32, reflect.Float64: + x, _ := constant.Float64Val(argv.Value) + v.Value = constant.MakeUint64(uint64(x)) + return v, nil + } + case *dwarf.IntType: + switch argv.Kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, _ := constant.Int64Val(argv.Value) + v.Value = constant.MakeInt64(int64(convertInt(uint64(n), true, ttyp.Size()))) + return v, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + n, _ := constant.Uint64Val(argv.Value) + v.Value = constant.MakeInt64(int64(convertInt(n, true, ttyp.Size()))) + return v, nil + case reflect.Float32, reflect.Float64: + x, _ := constant.Float64Val(argv.Value) + v.Value = constant.MakeInt64(int64(x)) + return v, nil + } + case *dwarf.FloatType: + switch argv.Kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + fallthrough + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + fallthrough + case reflect.Float32, reflect.Float64: + v.Value = argv.Value + return v, nil + } + case *dwarf.ComplexType: + switch argv.Kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + fallthrough + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + fallthrough + case reflect.Float32, reflect.Float64: + v.Value = argv.Value + return v, nil + } + } + + return nil, converr +} + +func convertInt(n uint64, signed bool, size int64) uint64 { + buf := make([]byte, 64/8) + binary.BigEndian.PutUint64(buf, n) + m := 64/8 - int(size) + s := byte(0) + if signed && (buf[m]&0x80 > 0) { + s = 0xff + } + for i := 0; i < m; i++ { + buf[i] = s + } + return uint64(binary.BigEndian.Uint64(buf)) +} + +func (scope *EvalScope) evalBuiltinCall(node *ast.CallExpr) (*Variable, error) { + fnnode, ok := node.Fun.(*ast.Ident) + if !ok { + return nil, fmt.Errorf("function calls are not supported") + } + + args := make([]*Variable, len(node.Args)) + + for i := range node.Args { + v, err := scope.evalAST(node.Args[i]) + if err != nil { + return nil, err + } + args[i] = v + } + + switch fnnode.Name { + case "cap": + return capBuiltin(args, node.Args) + case "len": + return lenBuiltin(args, node.Args) + case "complex": + return complexBuiltin(args, node.Args) + case "imag": + return imagBuiltin(args, node.Args) + case "real": + return realBuiltin(args, node.Args) + } + + return nil, fmt.Errorf("function calls are not supported") +} + +func capBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) { + if len(args) != 1 { + return nil, fmt.Errorf("wrong number of arguments to cap: %d", len(args)) + } + + arg := args[0] + invalidArgErr := fmt.Errorf("invalid argument %s (type %s) for cap", exprToString(nodeargs[0]), arg.TypeString()) + + switch arg.Kind { + case reflect.Ptr: + arg = arg.maybeDereference() + if arg.Kind != reflect.Array { + return nil, invalidArgErr + } + fallthrough + case reflect.Array: + return newConstant(constant.MakeInt64(arg.Len), arg.mem), nil + case reflect.Slice: + return newConstant(constant.MakeInt64(arg.Cap), arg.mem), nil + case reflect.Chan: + arg.loadValue(loadFullValue) + if arg.Unreadable != nil { + return nil, arg.Unreadable + } + if arg.Base == 0 { + return newConstant(constant.MakeInt64(0), arg.mem), nil + } + return newConstant(arg.Children[1].Value, arg.mem), nil + default: + return nil, invalidArgErr + } +} + +func lenBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) { + if len(args) != 1 { + return nil, fmt.Errorf("wrong number of arguments to len: %d", len(args)) + } + arg := args[0] + invalidArgErr := fmt.Errorf("invalid argument %s (type %s) for len", exprToString(nodeargs[0]), arg.TypeString()) + + switch arg.Kind { + case reflect.Ptr: + arg = arg.maybeDereference() + if arg.Kind != reflect.Array { + return nil, invalidArgErr + } + fallthrough + case reflect.Array, reflect.Slice, reflect.String: + if arg.Unreadable != nil { + return nil, arg.Unreadable + } + return newConstant(constant.MakeInt64(arg.Len), arg.mem), nil + case reflect.Chan: + arg.loadValue(loadFullValue) + if arg.Unreadable != nil { + return nil, arg.Unreadable + } + if arg.Base == 0 { + return newConstant(constant.MakeInt64(0), arg.mem), nil + } + return newConstant(arg.Children[0].Value, arg.mem), nil + case reflect.Map: + it := arg.mapIterator() + if arg.Unreadable != nil { + return nil, arg.Unreadable + } + if it == nil { + return newConstant(constant.MakeInt64(0), arg.mem), nil + } + return newConstant(constant.MakeInt64(arg.Len), arg.mem), nil + default: + return nil, invalidArgErr + } +} + +func complexBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) { + if len(args) != 2 { + return nil, fmt.Errorf("wrong number of arguments to complex: %d", len(args)) + } + + realev := args[0] + imagev := args[1] + + realev.loadValue(loadSingleValue) + imagev.loadValue(loadSingleValue) + + if realev.Unreadable != nil { + return nil, realev.Unreadable + } + + if imagev.Unreadable != nil { + return nil, imagev.Unreadable + } + + if realev.Value == nil || ((realev.Value.Kind() != constant.Int) && (realev.Value.Kind() != constant.Float)) { + return nil, fmt.Errorf("invalid argument 1 %s (type %s) to complex", exprToString(nodeargs[0]), realev.TypeString()) + } + + if imagev.Value == nil || ((imagev.Value.Kind() != constant.Int) && (imagev.Value.Kind() != constant.Float)) { + return nil, fmt.Errorf("invalid argument 2 %s (type %s) to complex", exprToString(nodeargs[1]), imagev.TypeString()) + } + + sz := int64(0) + if realev.RealType != nil { + sz = realev.RealType.(*dwarf.FloatType).Size() + } + if imagev.RealType != nil { + isz := imagev.RealType.(*dwarf.FloatType).Size() + if isz > sz { + sz = isz + } + } + + if sz == 0 { + sz = 128 + } + + typ := &dwarf.ComplexType{BasicType: dwarf.BasicType{CommonType: dwarf.CommonType{ByteSize: int64(sz / 8), Name: fmt.Sprintf("complex%d", sz)}, BitSize: sz, BitOffset: 0}} + + r := realev.newVariable("", 0, typ) + r.Value = constant.BinaryOp(realev.Value, token.ADD, constant.MakeImag(imagev.Value)) + return r, nil +} + +func imagBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) { + if len(args) != 1 { + return nil, fmt.Errorf("wrong number of arguments to imag: %d", len(args)) + } + + arg := args[0] + arg.loadValue(loadSingleValue) + + if arg.Unreadable != nil { + return nil, arg.Unreadable + } + + if arg.Kind != reflect.Complex64 && arg.Kind != reflect.Complex128 { + return nil, fmt.Errorf("invalid argument %s (type %s) to imag", exprToString(nodeargs[0]), arg.TypeString()) + } + + return newConstant(constant.Imag(arg.Value), arg.mem), nil +} + +func realBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) { + if len(args) != 1 { + return nil, fmt.Errorf("wrong number of arguments to real: %d", len(args)) + } + + arg := args[0] + arg.loadValue(loadSingleValue) + + if arg.Unreadable != nil { + return nil, arg.Unreadable + } + + if arg.Value == nil || ((arg.Value.Kind() != constant.Int) && (arg.Value.Kind() != constant.Float) && (arg.Value.Kind() != constant.Complex)) { + return nil, fmt.Errorf("invalid argument %s (type %s) to real", exprToString(nodeargs[0]), arg.TypeString()) + } + + return newConstant(constant.Real(arg.Value), arg.mem), nil +} + +// Evaluates identifier expressions +func (scope *EvalScope) evalIdent(node *ast.Ident) (*Variable, error) { + switch node.Name { + case "true", "false": + return newConstant(constant.MakeBool(node.Name == "true"), scope.Thread), nil + case "nil": + return nilVariable, nil + } + + // try to interpret this as a local variable + v, err := scope.extractVarInfo(node.Name) + if err == nil { + return v, nil + } + origErr := err + // workaround: sometimes go inserts an entry for '&varname' instead of varname + v, err = scope.extractVarInfo("&" + node.Name) + if err == nil { + v = v.maybeDereference() + v.Name = node.Name + return v, nil + } + // if it's not a local variable then it could be a package variable w/o explicit package name + _, _, fn := scope.Thread.dbp.PCToLine(scope.PC) + if fn != nil { + if v, err = scope.packageVarAddr(fn.PackageName() + "." + node.Name); err == nil { + v.Name = node.Name + return v, nil + } + } + return nil, origErr +} + +// Evaluates expressions . where subexpr is not a package name +func (scope *EvalScope) evalStructSelector(node *ast.SelectorExpr) (*Variable, error) { + xv, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + return xv.structMember(node.Sel.Name) +} + +// Evaluates expressions .() +func (scope *EvalScope) evalTypeAssert(node *ast.TypeAssertExpr) (*Variable, error) { + xv, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + if xv.Kind != reflect.Interface { + return nil, fmt.Errorf("expression \"%s\" not an interface", exprToString(node.X)) + } + xv.loadInterface(0, false, loadFullValue) + if xv.Unreadable != nil { + return nil, xv.Unreadable + } + if xv.Children[0].Unreadable != nil { + return nil, xv.Children[0].Unreadable + } + if xv.Children[0].Addr == 0 { + return nil, fmt.Errorf("interface conversion: %s is nil, not %s", xv.DwarfType.String(), exprToString(node.Type)) + } + typ, err := scope.Thread.dbp.findTypeExpr(node.Type) + if err != nil { + return nil, err + } + if xv.Children[0].DwarfType.Common().Name != typ.Common().Name { + return nil, fmt.Errorf("interface conversion: %s is %s, not %s", xv.DwarfType.Common().Name, xv.Children[0].TypeString(), typ.Common().Name) + } + return &xv.Children[0], nil +} + +// Evaluates expressions [] (subscript access to arrays, slices and maps) +func (scope *EvalScope) evalIndex(node *ast.IndexExpr) (*Variable, error) { + xev, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + if xev.Unreadable != nil { + return nil, xev.Unreadable + } + + idxev, err := scope.evalAST(node.Index) + if err != nil { + return nil, err + } + + switch xev.Kind { + case reflect.Slice, reflect.Array, reflect.String: + if xev.Base == 0 { + return nil, fmt.Errorf("can not index \"%s\"", exprToString(node.X)) + } + n, err := idxev.asInt() + if err != nil { + return nil, err + } + return xev.sliceAccess(int(n)) + + case reflect.Map: + idxev.loadValue(loadFullValue) + if idxev.Unreadable != nil { + return nil, idxev.Unreadable + } + return xev.mapAccess(idxev) + default: + return nil, fmt.Errorf("expression \"%s\" (%s) does not support indexing", exprToString(node.X), xev.TypeString()) + + } +} + +// Evaluates expressions [:] +// HACK: slicing a map expression with [0:0] will return the whole map +func (scope *EvalScope) evalReslice(node *ast.SliceExpr) (*Variable, error) { + xev, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + if xev.Unreadable != nil { + return nil, xev.Unreadable + } + + var low, high int64 + + if node.Low != nil { + lowv, err := scope.evalAST(node.Low) + if err != nil { + return nil, err + } + low, err = lowv.asInt() + if err != nil { + return nil, fmt.Errorf("can not convert \"%s\" to int: %v", exprToString(node.Low), err) + } + } + + if node.High == nil { + high = xev.Len + } else { + highv, err := scope.evalAST(node.High) + if err != nil { + return nil, err + } + high, err = highv.asInt() + if err != nil { + return nil, fmt.Errorf("can not convert \"%s\" to int: %v", exprToString(node.High), err) + } + } + + switch xev.Kind { + case reflect.Slice, reflect.Array, reflect.String: + if xev.Base == 0 { + return nil, fmt.Errorf("can not slice \"%s\"", exprToString(node.X)) + } + return xev.reslice(low, high) + case reflect.Map: + if node.High != nil { + return nil, fmt.Errorf("second slice argument must be empty for maps") + } + xev.mapSkip += int(low) + xev.loadValue(loadFullValue) + if xev.Unreadable != nil { + return nil, xev.Unreadable + } + return xev, nil + default: + return nil, fmt.Errorf("can not slice \"%s\" (type %s)", exprToString(node.X), xev.TypeString()) + } +} + +// Evaluates a pointer dereference expression: * +func (scope *EvalScope) evalPointerDeref(node *ast.StarExpr) (*Variable, error) { + xev, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + + if xev.Kind != reflect.Ptr { + return nil, fmt.Errorf("expression \"%s\" (%s) can not be dereferenced", exprToString(node.X), xev.TypeString()) + } + + if xev == nilVariable { + return nil, fmt.Errorf("nil can not be dereferenced") + } + + if len(xev.Children) == 1 { + // this branch is here to support pointers constructed with typecasts from ints + return &(xev.Children[0]), nil + } + rv := xev.maybeDereference() + if rv.Addr == 0 { + return nil, fmt.Errorf("nil pointer dereference") + } + return rv, nil +} + +// Evaluates expressions & +func (scope *EvalScope) evalAddrOf(node *ast.UnaryExpr) (*Variable, error) { + xev, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + if xev.Addr == 0 || xev.DwarfType == nil { + return nil, fmt.Errorf("can not take address of \"%s\"", exprToString(node.X)) + } + + xev.OnlyAddr = true + + typename := "*" + xev.DwarfType.Common().Name + rv := scope.newVariable("", 0, &dwarf.PtrType{CommonType: dwarf.CommonType{ByteSize: int64(scope.Thread.dbp.arch.PtrSize()), Name: typename}, Type: xev.DwarfType}) + rv.Children = []Variable{*xev} + rv.loaded = true + + return rv, nil +} + +func constantUnaryOp(op token.Token, y constant.Value) (r constant.Value, err error) { + defer func() { + if ierr := recover(); ierr != nil { + err = fmt.Errorf("%v", ierr) + } + }() + r = constant.UnaryOp(op, y, 0) + return +} + +func constantBinaryOp(op token.Token, x, y constant.Value) (r constant.Value, err error) { + defer func() { + if ierr := recover(); ierr != nil { + err = fmt.Errorf("%v", ierr) + } + }() + switch op { + case token.SHL, token.SHR: + n, _ := constant.Uint64Val(y) + r = constant.Shift(x, op, uint(n)) + default: + r = constant.BinaryOp(x, op, y) + } + return +} + +func constantCompare(op token.Token, x, y constant.Value) (r bool, err error) { + defer func() { + if ierr := recover(); ierr != nil { + err = fmt.Errorf("%v", ierr) + } + }() + r = constant.Compare(x, op, y) + return +} + +// Evaluates expressions: - and + +func (scope *EvalScope) evalUnary(node *ast.UnaryExpr) (*Variable, error) { + xv, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + + xv.loadValue(loadSingleValue) + if xv.Unreadable != nil { + return nil, xv.Unreadable + } + if xv.FloatSpecial != 0 { + return nil, OperationOnSpecialFloatError + } + if xv.Value == nil { + return nil, fmt.Errorf("operator %s can not be applied to \"%s\"", node.Op.String(), exprToString(node.X)) + } + rc, err := constantUnaryOp(node.Op, xv.Value) + if err != nil { + return nil, err + } + if xv.DwarfType != nil { + r := xv.newVariable("", 0, xv.DwarfType) + r.Value = rc + return r, nil + } + return newConstant(rc, xv.mem), nil +} + +func negotiateType(op token.Token, xv, yv *Variable) (dwarf.Type, error) { + if xv == nilVariable { + return nil, negotiateTypeNil(op, yv) + } + + if yv == nilVariable { + return nil, negotiateTypeNil(op, xv) + } + + if op == token.SHR || op == token.SHL { + if xv.Value == nil || xv.Value.Kind() != constant.Int { + return nil, fmt.Errorf("shift of type %s", xv.Kind) + } + + switch yv.Kind { + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + // ok + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if yv.DwarfType != nil || constant.Sign(yv.Value) < 0 { + return nil, fmt.Errorf("shift count type %s, must be unsigned integer", yv.Kind.String()) + } + default: + return nil, fmt.Errorf("shift count type %s, must be unsigned integer", yv.Kind.String()) + } + + return xv.DwarfType, nil + } + + if xv.DwarfType == nil && yv.DwarfType == nil { + return nil, nil + } + + if xv.DwarfType != nil && yv.DwarfType != nil { + if xv.DwarfType.String() != yv.DwarfType.String() { + return nil, fmt.Errorf("mismatched types \"%s\" and \"%s\"", xv.DwarfType.String(), yv.DwarfType.String()) + } + return xv.DwarfType, nil + } else if xv.DwarfType != nil && yv.DwarfType == nil { + if err := yv.isType(xv.DwarfType, xv.Kind); err != nil { + return nil, err + } + return xv.DwarfType, nil + } else if xv.DwarfType == nil && yv.DwarfType != nil { + if err := xv.isType(yv.DwarfType, yv.Kind); err != nil { + return nil, err + } + return yv.DwarfType, nil + } + + panic("unreachable") +} + +func negotiateTypeNil(op token.Token, v *Variable) error { + if op != token.EQL && op != token.NEQ { + return fmt.Errorf("operator %s can not be applied to \"nil\"", op.String()) + } + switch v.Kind { + case reflect.Ptr, reflect.UnsafePointer, reflect.Chan, reflect.Map, reflect.Interface, reflect.Slice, reflect.Func: + return nil + default: + return fmt.Errorf("can not compare %s to nil", v.Kind.String()) + } +} + +func (scope *EvalScope) evalBinary(node *ast.BinaryExpr) (*Variable, error) { + switch node.Op { + case token.INC, token.DEC, token.ARROW: + return nil, fmt.Errorf("operator %s not supported", node.Op.String()) + } + + xv, err := scope.evalAST(node.X) + if err != nil { + return nil, err + } + + yv, err := scope.evalAST(node.Y) + if err != nil { + return nil, err + } + + xv.loadValue(loadFullValue) + yv.loadValue(loadFullValue) + + if xv.Unreadable != nil { + return nil, xv.Unreadable + } + + if yv.Unreadable != nil { + return nil, yv.Unreadable + } + + if xv.FloatSpecial != 0 || yv.FloatSpecial != 0 { + return nil, OperationOnSpecialFloatError + } + + typ, err := negotiateType(node.Op, xv, yv) + if err != nil { + return nil, err + } + + op := node.Op + if typ != nil && (op == token.QUO) { + _, isint := typ.(*dwarf.IntType) + _, isuint := typ.(*dwarf.UintType) + if isint || isuint { + // forces integer division if the result type is integer + op = token.QUO_ASSIGN + } + } + + switch op { + case token.EQL, token.LSS, token.GTR, token.NEQ, token.LEQ, token.GEQ: + v, err := compareOp(op, xv, yv) + if err != nil { + return nil, err + } + return newConstant(constant.MakeBool(v), xv.mem), nil + + default: + if xv.Value == nil { + return nil, fmt.Errorf("operator %s can not be applied to \"%s\"", node.Op.String(), exprToString(node.X)) + } + + if yv.Value == nil { + return nil, fmt.Errorf("operator %s can not be applied to \"%s\"", node.Op.String(), exprToString(node.Y)) + } + + rc, err := constantBinaryOp(op, xv.Value, yv.Value) + if err != nil { + return nil, err + } + + if typ == nil { + return newConstant(rc, xv.mem), nil + } + + r := xv.newVariable("", 0, typ) + r.Value = rc + return r, nil + } +} + +// Comapres xv to yv using operator op +// Both xv and yv must be loaded and have a compatible type (as determined by negotiateType) +func compareOp(op token.Token, xv *Variable, yv *Variable) (bool, error) { + switch xv.Kind { + case reflect.Bool: + fallthrough + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + fallthrough + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + fallthrough + case reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: + return constantCompare(op, xv.Value, yv.Value) + case reflect.String: + if int64(len(constant.StringVal(xv.Value))) != xv.Len || int64(len(constant.StringVal(yv.Value))) != yv.Len { + return false, fmt.Errorf("string too long for comparison") + } + return constantCompare(op, xv.Value, yv.Value) + } + + if op != token.EQL && op != token.NEQ { + return false, fmt.Errorf("operator %s not defined on %s", op.String(), xv.Kind.String()) + } + + var eql bool + var err error + + if xv == nilVariable { + switch op { + case token.EQL: + return yv.isNil(), nil + case token.NEQ: + return !yv.isNil(), nil + } + } + + if yv == nilVariable { + switch op { + case token.EQL: + return xv.isNil(), nil + case token.NEQ: + return !xv.isNil(), nil + } + } + + switch xv.Kind { + case reflect.Ptr: + eql = xv.Children[0].Addr == yv.Children[0].Addr + case reflect.Array: + if int64(len(xv.Children)) != xv.Len || int64(len(yv.Children)) != yv.Len { + return false, fmt.Errorf("array too long for comparison") + } + eql, err = equalChildren(xv, yv, true) + case reflect.Struct: + if len(xv.Children) != len(yv.Children) { + return false, nil + } + if int64(len(xv.Children)) != xv.Len || int64(len(yv.Children)) != yv.Len { + return false, fmt.Errorf("sturcture too deep for comparison") + } + eql, err = equalChildren(xv, yv, false) + case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan: + return false, fmt.Errorf("can not compare %s variables", xv.Kind.String()) + case reflect.Interface: + if xv.Children[0].RealType.String() != yv.Children[0].RealType.String() { + eql = false + } else { + eql, err = compareOp(token.EQL, &xv.Children[0], &yv.Children[0]) + } + default: + return false, fmt.Errorf("unimplemented comparison of %s variables", xv.Kind.String()) + } + + if op == token.NEQ { + return !eql, err + } + return eql, err +} + +func (v *Variable) isNil() bool { + switch v.Kind { + case reflect.Ptr: + return v.Children[0].Addr == 0 + case reflect.Interface: + return false + case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan: + return v.Base == 0 + } + return false +} + +func equalChildren(xv, yv *Variable, shortcircuit bool) (bool, error) { + r := true + for i := range xv.Children { + eql, err := compareOp(token.EQL, &xv.Children[i], &yv.Children[i]) + if err != nil { + return false, err + } + r = r && eql + if !r && shortcircuit { + return false, nil + } + } + return r, nil +} + +func (v *Variable) asInt() (int64, error) { + if v.DwarfType == nil { + if v.Value.Kind() != constant.Int { + return 0, fmt.Errorf("can not convert constant %s to int", v.Value) + } + } else { + v.loadValue(loadSingleValue) + if v.Unreadable != nil { + return 0, v.Unreadable + } + if _, ok := v.DwarfType.(*dwarf.IntType); !ok { + return 0, fmt.Errorf("can not convert value of type %s to int", v.DwarfType.String()) + } + } + n, _ := constant.Int64Val(v.Value) + return n, nil +} + +func (v *Variable) asUint() (uint64, error) { + if v.DwarfType == nil { + if v.Value.Kind() != constant.Int { + return 0, fmt.Errorf("can not convert constant %s to uint", v.Value) + } + } else { + v.loadValue(loadSingleValue) + if v.Unreadable != nil { + return 0, v.Unreadable + } + if _, ok := v.DwarfType.(*dwarf.UintType); !ok { + return 0, fmt.Errorf("can not convert value of type %s to uint", v.DwarfType.String()) + } + } + n, _ := constant.Uint64Val(v.Value) + return n, nil +} + +func (v *Variable) isType(typ dwarf.Type, kind reflect.Kind) error { + if v.DwarfType != nil { + if typ != nil && typ.String() != v.RealType.String() { + return fmt.Errorf("can not convert value of type %s to %s", v.DwarfType.String(), typ.String()) + } + return nil + } + + if typ == nil { + return nil + } + + if v == nilVariable { + switch kind { + case reflect.Slice, reflect.Map, reflect.Func, reflect.Ptr, reflect.Chan, reflect.Interface: + return nil + default: + return fmt.Errorf("mismatched types nil and %s", typ.String()) + } + } + + converr := fmt.Errorf("can not convert %s constant to %s", v.Value, typ.String()) + + if v.Value == nil { + return converr + } + + switch typ.(type) { + case *dwarf.IntType: + if v.Value.Kind() != constant.Int { + return converr + } + case *dwarf.UintType: + if v.Value.Kind() != constant.Int { + return converr + } + case *dwarf.FloatType: + if (v.Value.Kind() != constant.Int) && (v.Value.Kind() != constant.Float) { + return converr + } + case *dwarf.BoolType: + if v.Value.Kind() != constant.Bool { + return converr + } + case *dwarf.StringType: + if v.Value.Kind() != constant.String { + return converr + } + case *dwarf.ComplexType: + if v.Value.Kind() != constant.Complex && v.Value.Kind() != constant.Float && v.Value.Kind() != constant.Int { + return converr + } + default: + return converr + } + + return nil +} + +func (v *Variable) sliceAccess(idx int) (*Variable, error) { + if idx < 0 || int64(idx) >= v.Len { + return nil, fmt.Errorf("index out of bounds") + } + return v.newVariable("", v.Base+uintptr(int64(idx)*v.stride), v.fieldType), nil +} + +func (v *Variable) mapAccess(idx *Variable) (*Variable, error) { + it := v.mapIterator() + if it == nil { + return nil, fmt.Errorf("can not access unreadable map: %v", v.Unreadable) + } + + first := true + for it.next() { + key := it.key() + key.loadValue(loadFullValue) + if key.Unreadable != nil { + return nil, fmt.Errorf("can not access unreadable map: %v", key.Unreadable) + } + if first { + first = false + if err := idx.isType(key.DwarfType, key.Kind); err != nil { + return nil, err + } + } + eql, err := compareOp(token.EQL, key, idx) + if err != nil { + return nil, err + } + if eql { + return it.value(), nil + } + } + if v.Unreadable != nil { + return nil, v.Unreadable + } + // go would return zero for the map value type here, we do not have the ability to create zeroes + return nil, fmt.Errorf("key not found") +} + +func (v *Variable) reslice(low int64, high int64) (*Variable, error) { + if low < 0 || low >= v.Len || high < 0 || high > v.Len { + return nil, fmt.Errorf("index out of bounds") + } + + base := v.Base + uintptr(int64(low)*v.stride) + len := high - low + + if high-low < 0 { + return nil, fmt.Errorf("index out of bounds") + } + + typ := v.DwarfType + if _, isarr := v.DwarfType.(*dwarf.ArrayType); isarr { + typ = &dwarf.SliceType{ + StructType: dwarf.StructType{ + CommonType: dwarf.CommonType{ + ByteSize: 24, + Name: "", + }, + StructName: fmt.Sprintf("[]%s", v.fieldType.Common().Name), + Kind: "struct", + Field: nil, + }, + ElemType: v.fieldType, + } + } + + r := v.newVariable("", 0, typ) + r.Cap = len + r.Len = len + r.Base = base + r.stride = v.stride + r.fieldType = v.fieldType + + return r, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/exc.h b/vendor/github.com/derekparker/delve/pkg/proc/exc.h new file mode 100644 index 0000000..c5c4386 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/exc.h @@ -0,0 +1,283 @@ +#ifndef _exc_user_ +#define _exc_user_ + +/* Module exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef exc_MSG_COUNT +#define exc_MSG_COUNT 3 +#endif /* exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include +__BEGIN_DECLS + + +/* Routine exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +__END_DECLS + +/********************** Caution **************************/ +/* The following data types should be used to calculate */ +/* maximum message sizes only. The actual message may be */ +/* smaller, and the position of the arguments within the */ +/* message layout may vary from what is presented here. */ +/* For example, if any of the arguments are variable- */ +/* sized, and less than the maximum is sent, the data */ +/* will be packed tight in the actual message to reduce */ +/* the presence of holes. */ +/********************** Caution **************************/ + +/* typedefs for all requests */ + +#ifndef __Request__exc_subsystem__defined +#define __Request__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + } __Request__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__exc_subsystem__defined */ + +/* union of all requests */ + +#ifndef __RequestUnion__exc_subsystem__defined +#define __RequestUnion__exc_subsystem__defined +union __RequestUnion__exc_subsystem { + __Request__exception_raise_t Request_exception_raise; + __Request__exception_raise_state_t Request_exception_raise_state; + __Request__exception_raise_state_identity_t Request_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__exc_subsystem__defined +#define __Reply__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__exc_subsystem__defined */ + +/* union of all replies */ + +#ifndef __ReplyUnion__exc_subsystem__defined +#define __ReplyUnion__exc_subsystem__defined +union __ReplyUnion__exc_subsystem { + __Reply__exception_raise_t Reply_exception_raise; + __Reply__exception_raise_state_t Reply_exception_raise_state; + __Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_exc +#define subsystem_to_name_map_exc \ + { "exception_raise", 2401 },\ + { "exception_raise_state", 2402 },\ + { "exception_raise_state_identity", 2403 } +#endif + +#ifdef __AfterMigUserHeader +__AfterMigUserHeader +#endif /* __AfterMigUserHeader */ + +#endif /* _exc_user_ */ diff --git a/vendor/github.com/derekparker/delve/pkg/proc/exc_user_darwin.c b/vendor/github.com/derekparker/delve/pkg/proc/exc_user_darwin.c new file mode 100644 index 0000000..bd2e689 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/exc_user_darwin.c @@ -0,0 +1,768 @@ +/* + * IDENTIFICATION: + * stub generated Sun Feb 22 20:54:31 2015 + * with a MiG generated by bootstrap_cmds-91 + * OPTIONS: + */ +#define __MIG_check__Reply__exc_subsystem__ 1 + +#include "exc.h" + + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __MachMsgErrorWithTimeout +#define __MachMsgErrorWithTimeout(_R_) { \ + switch (_R_) { \ + case MACH_SEND_INVALID_DATA: \ + case MACH_SEND_INVALID_DEST: \ + case MACH_SEND_INVALID_HEADER: \ + mig_put_reply_port(InP->Head.msgh_reply_port); \ + break; \ + case MACH_SEND_TIMED_OUT: \ + case MACH_RCV_TIMED_OUT: \ + default: \ + mig_dealloc_reply_port(InP->Head.msgh_reply_port); \ + } \ +} +#endif /* __MachMsgErrorWithTimeout */ + +#ifndef __MachMsgErrorWithoutTimeout +#define __MachMsgErrorWithoutTimeout(_R_) { \ + switch (_R_) { \ + case MACH_SEND_INVALID_DATA: \ + case MACH_SEND_INVALID_DEST: \ + case MACH_SEND_INVALID_HEADER: \ + mig_put_reply_port(InP->Head.msgh_reply_port); \ + break; \ + default: \ + mig_dealloc_reply_port(InP->Head.msgh_reply_port); \ + } \ +} +#endif /* __MachMsgErrorWithoutTimeout */ + +#ifndef __DeclareSendRpc +#define __DeclareSendRpc(_NUM_, _NAME_) +#endif /* __DeclareSendRpc */ + +#ifndef __BeforeSendRpc +#define __BeforeSendRpc(_NUM_, _NAME_) +#endif /* __BeforeSendRpc */ + +#ifndef __AfterSendRpc +#define __AfterSendRpc(_NUM_, _NAME_) +#endif /* __AfterSendRpc */ + +#ifndef __DeclareSendSimple +#define __DeclareSendSimple(_NUM_, _NAME_) +#endif /* __DeclareSendSimple */ + +#ifndef __BeforeSendSimple +#define __BeforeSendSimple(_NUM_, _NAME_) +#endif /* __BeforeSendSimple */ + +#ifndef __AfterSendSimple +#define __AfterSendSimple(_NUM_, _NAME_) +#endif /* __AfterSendSimple */ + +#define msgh_request_port msgh_remote_port +#define msgh_reply_port msgh_local_port + + + +#if ( __MigTypeCheck ) +#if __MIG_check__Reply__exc_subsystem__ +#if !defined(__MIG_check__Reply__exception_raise_t__defined) +#define __MIG_check__Reply__exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Reply__exception_raise_t(__Reply__exception_raise_t *Out0P) +{ + + typedef __Reply__exception_raise_t __Reply; + if (Out0P->Head.msgh_id != 2501) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + +#if __MigTypeCheck + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply))) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + { + return Out0P->RetCode; + } +} +#endif /* !defined(__MIG_check__Reply__exception_raise_t__defined) */ +#endif /* __MIG_check__Reply__exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine exception_raise */ +mig_external kern_return_t exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt +) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_msg_trailer_t trailer; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + +#ifdef __MIG_check__Reply__exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Reply__exception_raise_t__defined */ + + __DeclareSendRpc(2401, "exception_raise") + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t threadTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t taskTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + + InP->msgh_body.msgh_descriptor_count = 2; +#if UseStaticTemplates + InP->thread = threadTemplate; + InP->thread.name = thread; +#else /* UseStaticTemplates */ + InP->thread.name = thread; + InP->thread.disposition = 19; + InP->thread.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + InP->task = taskTemplate; + InP->task.name = task; +#else /* UseStaticTemplates */ + InP->task.name = task; + InP->task.disposition = 19; + InP->task.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size = (mach_msg_size_t)(sizeof(Request) - 8) + ((4 * codeCnt)); + InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX| + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2401; + +/* BEGIN VOUCHER CODE */ + +#ifdef USING_VOUCHERS + if (voucher_mach_msg_set != NULL) { + voucher_mach_msg_set(&InP->Head); + } +#endif // USING_VOUCHERS + +/* END VOUCHER CODE */ + + __BeforeSendRpc(2401, "exception_raise") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2401, "exception_raise") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + +#if defined(__MIG_check__Reply__exception_raise_t__defined) + check_result = __MIG_check__Reply__exception_raise_t((__Reply__exception_raise_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } +#endif /* defined(__MIG_check__Reply__exception_raise_t__defined) */ + + return KERN_SUCCESS; +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Reply__exc_subsystem__ +#if !defined(__MIG_check__Reply__exception_raise_state_t__defined) +#define __MIG_check__Reply__exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_t(__Reply__exception_raise_state_t *Out0P) +{ + + typedef __Reply__exception_raise_state_t __Reply; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + + if (Out0P->Head.msgh_id != 2502) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + +#if __MigTypeCheck + msgh_size = Out0P->Head.msgh_size; + + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) && + (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) || + Out0P->RetCode == KERN_SUCCESS))) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + if (Out0P->RetCode != KERN_SUCCESS) { + return ((mig_reply_error_t *)Out0P)->RetCode; + } + +#if __MigTypeCheck + if ( Out0P->new_stateCnt > 224 ) + return MIG_TYPE_ERROR; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4)) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Reply__exception_raise_state_t__defined) */ +#endif /* __MIG_check__Reply__exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine exception_raise_state */ +mig_external kern_return_t exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + mach_msg_trailer_t trailer; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + unsigned int msgh_size_delta; + + +#ifdef __MIG_check__Reply__exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Reply__exception_raise_state_t__defined */ + + __DeclareSendRpc(2402, "exception_raise_state") + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size_delta = (4 * codeCnt); + msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta; + InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8); + + InP->flavor = *flavor; + + if (old_stateCnt > 224) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt); + + InP->old_stateCnt = old_stateCnt; + + msgh_size += (4 * old_stateCnt); + InP = &Mess.In; + InP->Head.msgh_bits = + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2402; + +/* BEGIN VOUCHER CODE */ + +#ifdef USING_VOUCHERS + if (voucher_mach_msg_set != NULL) { + voucher_mach_msg_set(&InP->Head); + } +#endif // USING_VOUCHERS + +/* END VOUCHER CODE */ + + __BeforeSendRpc(2402, "exception_raise_state") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2402, "exception_raise_state") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + +#if defined(__MIG_check__Reply__exception_raise_state_t__defined) + check_result = __MIG_check__Reply__exception_raise_state_t((__Reply__exception_raise_state_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } +#endif /* defined(__MIG_check__Reply__exception_raise_state_t__defined) */ + + *flavor = Out0P->flavor; + + if (Out0P->new_stateCnt > 224) { + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224); + *new_stateCnt = Out0P->new_stateCnt; + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt); + + *new_stateCnt = Out0P->new_stateCnt; + + return KERN_SUCCESS; +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Reply__exc_subsystem__ +#if !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) +#define __MIG_check__Reply__exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_identity_t(__Reply__exception_raise_state_identity_t *Out0P) +{ + + typedef __Reply__exception_raise_state_identity_t __Reply; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + + if (Out0P->Head.msgh_id != 2503) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + +#if __MigTypeCheck + msgh_size = Out0P->Head.msgh_size; + + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) && + (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) || + Out0P->RetCode == KERN_SUCCESS))) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + if (Out0P->RetCode != KERN_SUCCESS) { + return ((mig_reply_error_t *)Out0P)->RetCode; + } + +#if __MigTypeCheck + if ( Out0P->new_stateCnt > 224 ) + return MIG_TYPE_ERROR; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4)) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Reply__exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine exception_raise_state_identity */ +mig_external kern_return_t exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + mach_msg_trailer_t trailer; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + unsigned int msgh_size_delta; + + +#ifdef __MIG_check__Reply__exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Reply__exception_raise_state_identity_t__defined */ + + __DeclareSendRpc(2403, "exception_raise_state_identity") + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t threadTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t taskTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + + InP->msgh_body.msgh_descriptor_count = 2; +#if UseStaticTemplates + InP->thread = threadTemplate; + InP->thread.name = thread; +#else /* UseStaticTemplates */ + InP->thread.name = thread; + InP->thread.disposition = 19; + InP->thread.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + InP->task = taskTemplate; + InP->task.name = task; +#else /* UseStaticTemplates */ + InP->task.name = task; + InP->task.disposition = 19; + InP->task.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size_delta = (4 * codeCnt); + msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta; + InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8); + + InP->flavor = *flavor; + + if (old_stateCnt > 224) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt); + + InP->old_stateCnt = old_stateCnt; + + msgh_size += (4 * old_stateCnt); + InP = &Mess.In; + InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX| + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2403; + +/* BEGIN VOUCHER CODE */ + +#ifdef USING_VOUCHERS + if (voucher_mach_msg_set != NULL) { + voucher_mach_msg_set(&InP->Head); + } +#endif // USING_VOUCHERS + +/* END VOUCHER CODE */ + + __BeforeSendRpc(2403, "exception_raise_state_identity") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2403, "exception_raise_state_identity") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + +#if defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) + check_result = __MIG_check__Reply__exception_raise_state_identity_t((__Reply__exception_raise_state_identity_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } +#endif /* defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */ + + *flavor = Out0P->flavor; + + if (Out0P->new_stateCnt > 224) { + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224); + *new_stateCnt = Out0P->new_stateCnt; + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt); + + *new_stateCnt = Out0P->new_stateCnt; + + return KERN_SUCCESS; +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/exec_darwin.c b/vendor/github.com/derekparker/delve/pkg/proc/exec_darwin.c new file mode 100644 index 0000000..67409e3 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/exec_darwin.c @@ -0,0 +1,112 @@ +#include "exec_darwin.h" +#include "stdio.h" + +extern char** environ; + +int +close_exec_pipe(int fd[2]) { + if (pipe(fd) < 0) return -1; + if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0) return -1; + if (fcntl(fd[1], F_SETFD, FD_CLOEXEC) < 0) return -1; + return 0; +} + +int +fork_exec(char *argv0, char **argv, int size, + char *wd, + task_t *task, + mach_port_t *port_set, + mach_port_t *exception_port, + mach_port_t *notification_port) +{ + // Since we're using mach exceptions instead of signals, + // we need to coordinate between parent and child via pipes + // to ensure that the parent has set the exception ports on + // the child task before it execs. + int fd[2]; + if (close_exec_pipe(fd) < 0) return -1; + + // Create another pipe to signal the parent on exec. + int efd[2]; + if (close_exec_pipe(efd) < 0) return -1; + + kern_return_t kret; + pid_t pid = fork(); + if (pid > 0) { + // In parent. + close(fd[0]); + close(efd[1]); + kret = acquire_mach_task(pid, task, port_set, exception_port, notification_port); + if (kret != KERN_SUCCESS) return -1; + + char msg = 'c'; + write(fd[1], &msg, 1); + close(fd[1]); + + char w; + size_t n = read(efd[0], &w, 1); + close(efd[0]); + if (n != 0) { + // Child died, reap it. + waitpid(pid, NULL, 0); + return -1; + } + return pid; + } + + // Fork succeeded, we are in the child. + int pret, cret; + char sig; + + close(fd[1]); + read(fd[0], &sig, 1); + close(fd[0]); + + // Create a new process group. + if (setpgid(0, 0) < 0) { + perror("setpgid"); + exit(1); + } + + // Set errno to zero before a call to ptrace. + // It is documented that ptrace can return -1 even + // for successful calls. + errno = 0; + pret = ptrace(PT_TRACE_ME, 0, 0, 0); + if (pret != 0 && errno != 0) { + perror("ptrace"); + exit(1); + } + + // Change working directory if wd is not empty. + if (wd && wd[0]) { + errno = 0; + cret = chdir(wd); + if (cret != 0 && errno != 0) { + char *error_msg; + asprintf(&error_msg, "%s '%s'", "chdir", wd); + perror(error_msg); + exit(1); + } + } + + errno = 0; + pret = ptrace(PT_SIGEXC, 0, 0, 0); + if (pret != 0 && errno != 0) { + perror("ptrace"); + exit(1); + } + + sleep(1); + + // Create the child process. + execve(argv0, argv, environ); + + // We should never reach here, but if we did something went wrong. + // Write a message to parent to alert that exec failed. + char msg = 'd'; + write(efd[1], &msg, 1); + close(efd[1]); + + exit(1); +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/exec_darwin.h b/vendor/github.com/derekparker/delve/pkg/proc/exec_darwin.h new file mode 100644 index 0000000..995e7e8 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/exec_darwin.h @@ -0,0 +1,10 @@ +#include "proc_darwin.h" + +#include +#include +#include +#include +#include + +int +fork_exec(char *, char **, int, char *, task_t*, mach_port_t*, mach_port_t*, mach_port_t*); diff --git a/vendor/github.com/derekparker/delve/pkg/proc/go_version.go b/vendor/github.com/derekparker/delve/pkg/proc/go_version.go new file mode 100644 index 0000000..87d5dec --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/go_version.go @@ -0,0 +1,117 @@ +package proc + +import ( + "strconv" + "strings" +) + +// GoVersion represents the Go version of +// the Go compiler version used to compile +// the target binary. +type GoVersion struct { + Major int + Minor int + Rev int + Beta int + RC int +} + +var ( + GoVer18Beta = GoVersion{1, 8, -1, 0, 0} +) + +func ParseVersionString(ver string) (GoVersion, bool) { + var r GoVersion + var err1, err2, err3 error + + if strings.HasPrefix(ver, "devel") { + return GoVersion{-1, 0, 0, 0, 0}, true + } + + if strings.HasPrefix(ver, "go") { + ver := strings.Split(ver, " ")[0] + v := strings.SplitN(ver[2:], ".", 3) + switch len(v) { + case 2: + r.Major, err1 = strconv.Atoi(v[0]) + vr := strings.SplitN(v[1], "beta", 2) + if len(vr) == 2 { + r.Beta, err3 = strconv.Atoi(vr[1]) + } else { + vr = strings.SplitN(v[1], "rc", 2) + if len(vr) == 2 { + r.RC, err3 = strconv.Atoi(vr[1]) + } else { + r.Minor, err2 = strconv.Atoi(v[1]) + if err2 != nil { + return GoVersion{}, false + } + return r, true + } + } + + r.Minor, err2 = strconv.Atoi(vr[0]) + r.Rev = -1 + + if err1 != nil || err2 != nil || err3 != nil { + return GoVersion{}, false + } + + return r, true + + case 3: + + r.Major, err1 = strconv.Atoi(v[0]) + r.Minor, err2 = strconv.Atoi(v[1]) + r.Rev, err3 = strconv.Atoi(v[2]) + if err1 != nil || err2 != nil || err3 != nil { + return GoVersion{}, false + } + + return r, true + + default: + return GoVersion{}, false + } + } + + return GoVersion{}, false +} + +// AfterOrEqual returns whether one GoVersion is after or +// equal to the other. +func (v *GoVersion) AfterOrEqual(b GoVersion) bool { + if v.Major < b.Major { + return false + } else if v.Major > b.Major { + return true + } + + if v.Minor < b.Minor { + return false + } else if v.Minor > b.Minor { + return true + } + + if v.Rev < b.Rev { + return false + } else if v.Rev > b.Rev { + return true + } + + if v.Beta < b.Beta { + return false + } + + if v.RC < b.RC { + return false + } + + return true +} + +// IsDevel returns whether the GoVersion +// is a development version. +func (v *GoVersion) IsDevel() bool { + return v.Major < 0 +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/mach_exc.defs b/vendor/github.com/derekparker/delve/pkg/proc/mach_exc.defs new file mode 100644 index 0000000..00fae28 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/mach_exc.defs @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * @OSF_COPYRIGHT@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + */ +/* + * Abstract: + * MiG definitions file for Mach exception interface. + */ + +subsystem +#if KERNEL_USER + KernelUser +#endif + mach_exc 2405; + +#include +#include + +ServerPrefix catch_; + +type mach_exception_data_t = array[*:2] of int64_t; +type exception_type_t = int; + +routine mach_exception_raise( +#if KERNEL_USER + exception_port : mach_port_move_send_t; + thread : mach_port_move_send_t; + task : mach_port_move_send_t; +#else /* KERNEL_USER */ + exception_port : mach_port_t; + thread : mach_port_t; + task : mach_port_t; +#endif /* KERNEL_USER */ + exception : exception_type_t; + code : mach_exception_data_t + ); + +routine mach_exception_raise_state( +#if KERNEL_USER + exception_port : mach_port_move_send_t; +#else /* KERNEL_USER */ + exception_port : mach_port_t; +#endif /* KERNEL_USER */ + exception : exception_type_t; + code : mach_exception_data_t, const; + inout flavor : int; + old_state : thread_state_t, const; + out new_state : thread_state_t); + +routine mach_exception_raise_state_identity( +#if KERNEL_USER + exception_port : mach_port_move_send_t; + thread : mach_port_move_send_t; + task : mach_port_move_send_t; +#else /* KERNEL_USER */ + exception_port : mach_port_t; + thread : mach_port_t; + task : mach_port_t; +#endif /* KERNEL_USER */ + exception : exception_type_t; + code : mach_exception_data_t; + inout flavor : int; + old_state : thread_state_t; + out new_state : thread_state_t); + +/* vim: set ft=c : */ diff --git a/vendor/github.com/derekparker/delve/pkg/proc/mach_exc.h b/vendor/github.com/derekparker/delve/pkg/proc/mach_exc.h new file mode 100644 index 0000000..b5f6dfc --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/mach_exc.h @@ -0,0 +1,283 @@ +#ifndef _mach_exc_user_ +#define _mach_exc_user_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include +__BEGIN_DECLS + + +/* Routine mach_exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t mach_exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine mach_exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t mach_exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine mach_exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t mach_exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +__END_DECLS + +/********************** Caution **************************/ +/* The following data types should be used to calculate */ +/* maximum message sizes only. The actual message may be */ +/* smaller, and the position of the arguments within the */ +/* message layout may vary from what is presented here. */ +/* For example, if any of the arguments are variable- */ +/* sized, and less than the maximum is sent, the data */ +/* will be packed tight in the actual message to reduce */ +/* the presence of holes. */ +/********************** Caution **************************/ + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + +/* union of all requests */ + +#ifndef __RequestUnion__mach_exc_subsystem__defined +#define __RequestUnion__mach_exc_subsystem__defined +union __RequestUnion__mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + +/* union of all replies */ + +#ifndef __ReplyUnion__mach_exc_subsystem__defined +#define __ReplyUnion__mach_exc_subsystem__defined +union __ReplyUnion__mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise", 2401 },\ + { "mach_exception_raise_state", 2402 },\ + { "mach_exception_raise_state_identity", 2403 } +#endif + +#ifdef __AfterMigUserHeader +__AfterMigUserHeader +#endif /* __AfterMigUserHeader */ + +#endif /* _mach_exc_user_ */ diff --git a/vendor/github.com/derekparker/delve/pkg/proc/mach_exc_user_darwin.c b/vendor/github.com/derekparker/delve/pkg/proc/mach_exc_user_darwin.c new file mode 100644 index 0000000..e475808 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/mach_exc_user_darwin.c @@ -0,0 +1,768 @@ +/* + * IDENTIFICATION: + * stub generated Sat Feb 21 18:10:52 2015 + * with a MiG generated by bootstrap_cmds-91 + * OPTIONS: + */ +#define __MIG_check__Reply__mach_exc_subsystem__ 1 + +#include "mach_exc.h" + + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __MachMsgErrorWithTimeout +#define __MachMsgErrorWithTimeout(_R_) { \ + switch (_R_) { \ + case MACH_SEND_INVALID_DATA: \ + case MACH_SEND_INVALID_DEST: \ + case MACH_SEND_INVALID_HEADER: \ + mig_put_reply_port(InP->Head.msgh_reply_port); \ + break; \ + case MACH_SEND_TIMED_OUT: \ + case MACH_RCV_TIMED_OUT: \ + default: \ + mig_dealloc_reply_port(InP->Head.msgh_reply_port); \ + } \ +} +#endif /* __MachMsgErrorWithTimeout */ + +#ifndef __MachMsgErrorWithoutTimeout +#define __MachMsgErrorWithoutTimeout(_R_) { \ + switch (_R_) { \ + case MACH_SEND_INVALID_DATA: \ + case MACH_SEND_INVALID_DEST: \ + case MACH_SEND_INVALID_HEADER: \ + mig_put_reply_port(InP->Head.msgh_reply_port); \ + break; \ + default: \ + mig_dealloc_reply_port(InP->Head.msgh_reply_port); \ + } \ +} +#endif /* __MachMsgErrorWithoutTimeout */ + +#ifndef __DeclareSendRpc +#define __DeclareSendRpc(_NUM_, _NAME_) +#endif /* __DeclareSendRpc */ + +#ifndef __BeforeSendRpc +#define __BeforeSendRpc(_NUM_, _NAME_) +#endif /* __BeforeSendRpc */ + +#ifndef __AfterSendRpc +#define __AfterSendRpc(_NUM_, _NAME_) +#endif /* __AfterSendRpc */ + +#ifndef __DeclareSendSimple +#define __DeclareSendSimple(_NUM_, _NAME_) +#endif /* __DeclareSendSimple */ + +#ifndef __BeforeSendSimple +#define __BeforeSendSimple(_NUM_, _NAME_) +#endif /* __BeforeSendSimple */ + +#ifndef __AfterSendSimple +#define __AfterSendSimple(_NUM_, _NAME_) +#endif /* __AfterSendSimple */ + +#define msgh_request_port msgh_remote_port +#define msgh_reply_port msgh_local_port + + + +#if ( __MigTypeCheck ) +#if __MIG_check__Reply__mach_exc_subsystem__ +#if !defined(__MIG_check__Reply__mach_exception_raise_t__defined) +#define __MIG_check__Reply__mach_exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_t(__Reply__mach_exception_raise_t *Out0P) +{ + + typedef __Reply__mach_exception_raise_t __Reply; + if (Out0P->Head.msgh_id != 2505) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + +#if __MigTypeCheck + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply))) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + { + return Out0P->RetCode; + } +} +#endif /* !defined(__MIG_check__Reply__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Reply__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise */ +mig_external kern_return_t mach_exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt +) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_msg_trailer_t trailer; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + +#ifdef __MIG_check__Reply__mach_exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Reply__mach_exception_raise_t__defined */ + + __DeclareSendRpc(2405, "mach_exception_raise") + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t threadTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t taskTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + + InP->msgh_body.msgh_descriptor_count = 2; +#if UseStaticTemplates + InP->thread = threadTemplate; + InP->thread.name = thread; +#else /* UseStaticTemplates */ + InP->thread.name = thread; + InP->thread.disposition = 19; + InP->thread.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + InP->task = taskTemplate; + InP->task.name = task; +#else /* UseStaticTemplates */ + InP->task.name = task; + InP->task.disposition = 19; + InP->task.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt)); + InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX| + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2405; + +/* BEGIN VOUCHER CODE */ + +#ifdef USING_VOUCHERS + if (voucher_mach_msg_set != NULL) { + voucher_mach_msg_set(&InP->Head); + } +#endif // USING_VOUCHERS + +/* END VOUCHER CODE */ + + __BeforeSendRpc(2405, "mach_exception_raise") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2405, "mach_exception_raise") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + +#if defined(__MIG_check__Reply__mach_exception_raise_t__defined) + check_result = __MIG_check__Reply__mach_exception_raise_t((__Reply__mach_exception_raise_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } +#endif /* defined(__MIG_check__Reply__mach_exception_raise_t__defined) */ + + return KERN_SUCCESS; +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Reply__mach_exc_subsystem__ +#if !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) +#define __MIG_check__Reply__mach_exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_t(__Reply__mach_exception_raise_state_t *Out0P) +{ + + typedef __Reply__mach_exception_raise_state_t __Reply; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + + if (Out0P->Head.msgh_id != 2506) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + +#if __MigTypeCheck + msgh_size = Out0P->Head.msgh_size; + + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) && + (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) || + Out0P->RetCode == KERN_SUCCESS))) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + if (Out0P->RetCode != KERN_SUCCESS) { + return ((mig_reply_error_t *)Out0P)->RetCode; + } + +#if __MigTypeCheck + if ( Out0P->new_stateCnt > 224 ) + return MIG_TYPE_ERROR; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4)) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Reply__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state */ +mig_external kern_return_t mach_exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + mach_msg_trailer_t trailer; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + unsigned int msgh_size_delta; + + +#ifdef __MIG_check__Reply__mach_exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Reply__mach_exception_raise_state_t__defined */ + + __DeclareSendRpc(2406, "mach_exception_raise_state") + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size_delta = (8 * codeCnt); + msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta; + InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16); + + InP->flavor = *flavor; + + if (old_stateCnt > 224) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt); + + InP->old_stateCnt = old_stateCnt; + + msgh_size += (4 * old_stateCnt); + InP = &Mess.In; + InP->Head.msgh_bits = + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2406; + +/* BEGIN VOUCHER CODE */ + +#ifdef USING_VOUCHERS + if (voucher_mach_msg_set != NULL) { + voucher_mach_msg_set(&InP->Head); + } +#endif // USING_VOUCHERS + +/* END VOUCHER CODE */ + + __BeforeSendRpc(2406, "mach_exception_raise_state") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2406, "mach_exception_raise_state") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + +#if defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Reply__mach_exception_raise_state_t((__Reply__mach_exception_raise_state_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } +#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */ + + *flavor = Out0P->flavor; + + if (Out0P->new_stateCnt > 224) { + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224); + *new_stateCnt = Out0P->new_stateCnt; + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt); + + *new_stateCnt = Out0P->new_stateCnt; + + return KERN_SUCCESS; +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Reply__mach_exc_subsystem__ +#if !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Reply__mach_exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_identity_t(__Reply__mach_exception_raise_state_identity_t *Out0P) +{ + + typedef __Reply__mach_exception_raise_state_identity_t __Reply; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + + if (Out0P->Head.msgh_id != 2507) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + +#if __MigTypeCheck + msgh_size = Out0P->Head.msgh_size; + + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) && + (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) || + Out0P->RetCode == KERN_SUCCESS))) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + if (Out0P->RetCode != KERN_SUCCESS) { + return ((mig_reply_error_t *)Out0P)->RetCode; + } + +#if __MigTypeCheck + if ( Out0P->new_stateCnt > 224 ) + return MIG_TYPE_ERROR; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4)) + { return MIG_TYPE_ERROR ; } +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Reply__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state_identity */ +mig_external kern_return_t mach_exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + mach_msg_trailer_t trailer; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + unsigned int msgh_size_delta; + + +#ifdef __MIG_check__Reply__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Reply__mach_exception_raise_state_identity_t__defined */ + + __DeclareSendRpc(2407, "mach_exception_raise_state_identity") + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t threadTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + const static mach_msg_port_descriptor_t taskTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; +#endif /* UseStaticTemplates */ + + InP->msgh_body.msgh_descriptor_count = 2; +#if UseStaticTemplates + InP->thread = threadTemplate; + InP->thread.name = thread; +#else /* UseStaticTemplates */ + InP->thread.name = thread; + InP->thread.disposition = 19; + InP->thread.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + +#if UseStaticTemplates + InP->task = taskTemplate; + InP->task.name = task; +#else /* UseStaticTemplates */ + InP->task.name = task; + InP->task.disposition = 19; + InP->task.type = MACH_MSG_PORT_DESCRIPTOR; +#endif /* UseStaticTemplates */ + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size_delta = (8 * codeCnt); + msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta; + InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16); + + InP->flavor = *flavor; + + if (old_stateCnt > 224) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt); + + InP->old_stateCnt = old_stateCnt; + + msgh_size += (4 * old_stateCnt); + InP = &Mess.In; + InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX| + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2407; + +/* BEGIN VOUCHER CODE */ + +#ifdef USING_VOUCHERS + if (voucher_mach_msg_set != NULL) { + voucher_mach_msg_set(&InP->Head); + } +#endif // USING_VOUCHERS + +/* END VOUCHER CODE */ + + __BeforeSendRpc(2407, "mach_exception_raise_state_identity") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2407, "mach_exception_raise_state_identity") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + +#if defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Reply__mach_exception_raise_state_identity_t((__Reply__mach_exception_raise_state_identity_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } +#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */ + + *flavor = Out0P->flavor; + + if (Out0P->new_stateCnt > 224) { + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224); + *new_stateCnt = Out0P->new_stateCnt; + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt); + + *new_stateCnt = Out0P->new_stateCnt; + + return KERN_SUCCESS; +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/mem.go b/vendor/github.com/derekparker/delve/pkg/proc/mem.go new file mode 100644 index 0000000..ea45360 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/mem.go @@ -0,0 +1,57 @@ +package proc + +const cacheEnabled = true + +type memoryReadWriter interface { + readMemory(addr uintptr, size int) (data []byte, err error) + writeMemory(addr uintptr, data []byte) (written int, err error) +} + +type memCache struct { + cacheAddr uintptr + cache []byte + mem memoryReadWriter +} + +func (m *memCache) contains(addr uintptr, size int) bool { + return addr >= m.cacheAddr && addr <= (m.cacheAddr+uintptr(len(m.cache)-size)) +} + +func (m *memCache) readMemory(addr uintptr, size int) (data []byte, err error) { + if m.contains(addr, size) { + d := make([]byte, size) + copy(d, m.cache[addr-m.cacheAddr:]) + return d, nil + } + + return m.mem.readMemory(addr, size) +} + +func (m *memCache) writeMemory(addr uintptr, data []byte) (written int, err error) { + return m.mem.writeMemory(addr, data) +} + +func cacheMemory(mem memoryReadWriter, addr uintptr, size int) memoryReadWriter { + if !cacheEnabled { + return mem + } + if size <= 0 { + return mem + } + if cacheMem, isCache := mem.(*memCache); isCache { + if cacheMem.contains(addr, size) { + return mem + } else { + cache, err := cacheMem.mem.readMemory(addr, size) + if err != nil { + return mem + } + return &memCache{addr, cache, mem} + } + } + cache, err := mem.readMemory(addr, size) + if err != nil { + return mem + } + return &memCache{addr, cache, mem} +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/moduledata.go b/vendor/github.com/derekparker/delve/pkg/proc/moduledata.go new file mode 100644 index 0000000..ae9d840 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/moduledata.go @@ -0,0 +1,189 @@ +package proc + +import ( + "go/constant" + "unsafe" +) + +// delve counterpart to runtime.moduledata +type moduleData struct { + types, etypes uintptr + typemapVar *Variable +} + +func (dbp *Process) loadModuleData() (err error) { + dbp.loadModuleDataOnce.Do(func() { + scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0} + var md *Variable + md, err = scope.packageVarAddr("runtime.firstmoduledata") + if err != nil { + return + } + + for md.Addr != 0 { + var typesVar, etypesVar, nextVar, typemapVar *Variable + var types, etypes uint64 + + if typesVar, err = md.structMember("types"); err != nil { + return + } + if etypesVar, err = md.structMember("etypes"); err != nil { + return + } + if nextVar, err = md.structMember("next"); err != nil { + return + } + if typemapVar, err = md.structMember("typemap"); err != nil { + return + } + if types, err = typesVar.asUint(); err != nil { + return + } + if etypes, err = etypesVar.asUint(); err != nil { + return + } + + dbp.moduleData = append(dbp.moduleData, moduleData{uintptr(types), uintptr(etypes), typemapVar}) + + md = nextVar.maybeDereference() + if md.Unreadable != nil { + err = md.Unreadable + return + } + } + }) + + return +} + +func (dbp *Process) resolveTypeOff(typeAddr uintptr, off uintptr) (*Variable, error) { + // See runtime.(*_type).typeOff in $GOROOT/src/runtime/type.go + if err := dbp.loadModuleData(); err != nil { + return nil, err + } + + var md *moduleData + for i := range dbp.moduleData { + if typeAddr >= dbp.moduleData[i].types && typeAddr < dbp.moduleData[i].etypes { + md = &dbp.moduleData[i] + } + } + + rtyp, err := dbp.findType("runtime._type") + if err != nil { + return nil, err + } + + if md == nil { + v, err := dbp.reflectOffsMapAccess(off) + if err != nil { + return nil, err + } + v.loadValue(LoadConfig{false, 1, 0, 0, -1}) + addr, _ := constant.Int64Val(v.Value) + return v.newVariable(v.Name, uintptr(addr), rtyp), nil + } + + if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.currentThread)); t != nil { + return t, nil + } + + res := md.types + uintptr(off) + + return dbp.currentThread.newVariable("", res, rtyp), nil +} + +func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag string, pkgpathoff int32, err error) { + // See runtime.resolveNameOff in $GOROOT/src/runtime/type.go + if err = dbp.loadModuleData(); err != nil { + return "", "", 0, err + } + + for _, md := range dbp.moduleData { + if typeAddr >= md.types && typeAddr < md.etypes { + return dbp.loadName(md.types + off) + } + } + + v, err := dbp.reflectOffsMapAccess(off) + if err != nil { + return "", "", 0, err + } + + resv := v.maybeDereference() + if resv.Unreadable != nil { + return "", "", 0, resv.Unreadable + } + + return dbp.loadName(resv.Addr) +} + +func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) { + scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0} + reflectOffs, err := scope.packageVarAddr("runtime.reflectOffs") + if err != nil { + return nil, err + } + + reflectOffsm, err := reflectOffs.structMember("m") + if err != nil { + return nil, err + } + + return reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.currentThread)) +} + +const ( + // flags for the name struct (see 'type name struct' in $GOROOT/src/reflect/type.go) + nameflagExported = 1 << 0 + nameflagHasTag = 1 << 1 + nameflagHasPkg = 1 << 2 +) + +func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, err error) { + off := addr + namedata, err := dbp.currentThread.readMemory(off, 3) + off += 3 + if err != nil { + return "", "", 0, err + } + + namelen := uint16(namedata[1]<<8) | uint16(namedata[2]) + + rawstr, err := dbp.currentThread.readMemory(off, int(namelen)) + off += uintptr(namelen) + if err != nil { + return "", "", 0, err + } + + name = string(rawstr) + + if namedata[0]&nameflagHasTag != 0 { + taglendata, err := dbp.currentThread.readMemory(off, 2) + off += 2 + if err != nil { + return "", "", 0, err + } + taglen := uint16(taglendata[0]<<8) | uint16(taglendata[1]) + + rawstr, err := dbp.currentThread.readMemory(off, int(taglen)) + off += uintptr(taglen) + if err != nil { + return "", "", 0, err + } + + tag = string(rawstr) + } + + if namedata[0]&nameflagHasPkg != 0 { + pkgdata, err := dbp.currentThread.readMemory(off, 4) + if err != nil { + return "", "", 0, err + } + + // see func pkgPath in $GOROOT/src/reflect/type.go + copy((*[4]byte)(unsafe.Pointer(&pkgpathoff))[:], pkgdata) + } + + return name, tag, pkgpathoff, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc.go b/vendor/github.com/derekparker/delve/pkg/proc/proc.go new file mode 100644 index 0000000..de9aa63 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/proc.go @@ -0,0 +1,986 @@ +package proc + +import ( + "debug/gosym" + "encoding/binary" + "errors" + "fmt" + "go/ast" + "go/constant" + "go/token" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" + "time" + + "github.com/derekparker/delve/pkg/dwarf/frame" + "github.com/derekparker/delve/pkg/dwarf/line" + "github.com/derekparker/delve/pkg/dwarf/reader" + "golang.org/x/debug/dwarf" +) + +// Process represents all of the information the debugger +// is holding onto regarding the process we are debugging. +type Process struct { + pid int // Process Pid + Process *os.Process // Pointer to process struct for the actual process we are debugging + lastModified time.Time // Time the executable of this process was last modified + + // Breakpoint table, holds information on breakpoints. + // Maps instruction address to Breakpoint struct. + breakpoints map[uint64]*Breakpoint + + // List of threads mapped as such: pid -> *Thread + threads map[int]*Thread + + // Active thread + currentThread *Thread + + // Goroutine that will be used by default to set breakpoint, eval variables, etc... + // Normally selectedGoroutine is currentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread + selectedGoroutine *G + + // Maps package names to package paths, needed to lookup types inside DWARF info + packageMap map[string]string + + allGCache []*G + dwarf *dwarf.Data + goSymTable *gosym.Table + frameEntries frame.FrameDescriptionEntries + lineInfo line.DebugLines + os *OSProcessDetails + arch Arch + breakpointIDCounter int + internalBreakpointIDCounter int + firstStart bool + halt bool + exited bool + ptraceChan chan func() + ptraceDoneChan chan interface{} + types map[string]dwarf.Offset + functions []functionDebugInfo + + loadModuleDataOnce sync.Once + moduleData []moduleData + nameOfRuntimeType map[uintptr]nameOfRuntimeTypeEntry +} + +type functionDebugInfo struct { + lowpc, highpc uint64 + offset dwarf.Offset +} + +var NotExecutableErr = errors.New("not an executable file") + +// New returns an initialized Process struct. Before returning, +// it will also launch a goroutine in order to handle ptrace(2) +// functions. For more information, see the documentation on +// `handlePtraceFuncs`. +func New(pid int) *Process { + dbp := &Process{ + pid: pid, + threads: make(map[int]*Thread), + breakpoints: make(map[uint64]*Breakpoint), + firstStart: true, + os: new(OSProcessDetails), + ptraceChan: make(chan func()), + ptraceDoneChan: make(chan interface{}), + nameOfRuntimeType: make(map[uintptr]nameOfRuntimeTypeEntry), + } + // TODO: find better way to determine proc arch (perhaps use executable file info) + switch runtime.GOARCH { + case "amd64": + dbp.arch = AMD64Arch() + } + go dbp.handlePtraceFuncs() + return dbp +} + +// ProcessExitedError indicates that the process has exited and contains both +// process id and exit status. +type ProcessExitedError struct { + Pid int + Status int +} + +func (pe ProcessExitedError) Error() string { + return fmt.Sprintf("Process %d has exited with status %d", pe.Pid, pe.Status) +} + +// Detach from the process being debugged, optionally killing it. +func (dbp *Process) Detach(kill bool) (err error) { + if dbp.exited { + return nil + } + if dbp.Running() { + if err = dbp.Halt(); err != nil { + return + } + } + if !kill { + // Clean up any breakpoints we've set. + for _, bp := range dbp.breakpoints { + if bp != nil { + _, err := dbp.ClearBreakpoint(bp.Addr) + if err != nil { + return err + } + } + } + } + dbp.execPtraceFunc(func() { + err = PtraceDetach(dbp.pid, 0) + if err != nil { + return + } + if kill { + err = killProcess(dbp.pid) + } + }) + return +} + +// Exited returns whether the debugged +// process has exited. +func (dbp *Process) Exited() bool { + return dbp.exited +} + +// Running returns whether the debugged +// process is currently executing. +func (dbp *Process) Running() bool { + for _, th := range dbp.threads { + if th.running { + return true + } + } + return false +} + +func (dbp *Process) LastModified() time.Time { + return dbp.lastModified +} + +func (dbp *Process) Pid() int { + return dbp.pid +} + +func (dbp *Process) SelectedGoroutine() *G { + return dbp.selectedGoroutine +} + +func (dbp *Process) Threads() map[int]*Thread { + return dbp.threads +} + +func (dbp *Process) CurrentThread() *Thread { + return dbp.currentThread +} + +func (dbp *Process) Breakpoints() map[uint64]*Breakpoint { + return dbp.breakpoints +} + +// LoadInformation finds the executable and then uses it +// to parse the following information: +// * Dwarf .debug_frame section +// * Dwarf .debug_line section +// * Go symbol table. +func (dbp *Process) LoadInformation(path string) error { + var wg sync.WaitGroup + + exe, path, err := dbp.findExecutable(path) + if err != nil { + return err + } + fi, err := os.Stat(path) + if err == nil { + dbp.lastModified = fi.ModTime() + } + + wg.Add(5) + go dbp.loadProcessInformation(&wg) + go dbp.parseDebugFrame(exe, &wg) + go dbp.obtainGoSymbols(exe, &wg) + go dbp.parseDebugLineInfo(exe, &wg) + go dbp.loadDebugInfoMaps(&wg) + wg.Wait() + + return nil +} + +// FindFileLocation returns the PC for a given file:line. +// Assumes that `file` is normailzed to lower case and '/' on Windows. +func (dbp *Process) FindFileLocation(fileName string, lineno int) (uint64, error) { + pc, fn, err := dbp.goSymTable.LineToPC(fileName, lineno) + if err != nil { + return 0, err + } + if fn.Entry == pc { + pc, _ = dbp.FirstPCAfterPrologue(fn, true) + } + return pc, nil +} + +// FindFunctionLocation finds address of a function's line +// If firstLine == true is passed FindFunctionLocation will attempt to find the first line of the function +// If lineOffset is passed FindFunctionLocation will return the address of that line +// Pass lineOffset == 0 and firstLine == false if you want the address for the function's entry point +// Note that setting breakpoints at that address will cause surprising behavior: +// https://github.com/derekparker/delve/issues/170 +func (dbp *Process) FindFunctionLocation(funcName string, firstLine bool, lineOffset int) (uint64, error) { + origfn := dbp.goSymTable.LookupFunc(funcName) + if origfn == nil { + return 0, fmt.Errorf("Could not find function %s\n", funcName) + } + + if firstLine { + return dbp.FirstPCAfterPrologue(origfn, false) + } else if lineOffset > 0 { + filename, lineno, _ := dbp.goSymTable.PCToLine(origfn.Entry) + breakAddr, _, err := dbp.goSymTable.LineToPC(filename, lineno+lineOffset) + return breakAddr, err + } + + return origfn.Entry, nil +} + +// CurrentLocation returns the location of the current thread. +func (dbp *Process) CurrentLocation() (*Location, error) { + return dbp.currentThread.Location() +} + +// RequestManualStop sets the `halt` flag and +// sends SIGSTOP to all threads. +func (dbp *Process) RequestManualStop() error { + if dbp.exited { + return &ProcessExitedError{} + } + dbp.halt = true + return dbp.requestManualStop() +} + +// SetBreakpoint sets a breakpoint at addr, and stores it in the process wide +// break point table. Setting a break point must be thread specific due to +// ptrace actions needing the thread to be in a signal-delivery-stop. +func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) { + tid := dbp.currentThread.ID + + if bp, ok := dbp.FindBreakpoint(addr); ok { + return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr} + } + + f, l, fn := dbp.goSymTable.PCToLine(uint64(addr)) + if fn == nil { + return nil, InvalidAddressError{address: addr} + } + + newBreakpoint := &Breakpoint{ + FunctionName: fn.Name, + File: f, + Line: l, + Addr: addr, + Kind: kind, + Cond: cond, + HitCount: map[int]uint64{}, + } + + if kind != UserBreakpoint { + dbp.internalBreakpointIDCounter++ + newBreakpoint.ID = dbp.internalBreakpointIDCounter + } else { + dbp.breakpointIDCounter++ + newBreakpoint.ID = dbp.breakpointIDCounter + } + + thread := dbp.threads[tid] + originalData, err := thread.readMemory(uintptr(addr), dbp.arch.BreakpointSize()) + if err != nil { + return nil, err + } + if err := dbp.writeSoftwareBreakpoint(thread, addr); err != nil { + return nil, err + } + newBreakpoint.OriginalData = originalData + dbp.breakpoints[addr] = newBreakpoint + + return newBreakpoint, nil +} + +// ClearBreakpoint clears the breakpoint at addr. +func (dbp *Process) ClearBreakpoint(addr uint64) (*Breakpoint, error) { + if dbp.exited { + return nil, &ProcessExitedError{} + } + bp, ok := dbp.FindBreakpoint(addr) + if !ok { + return nil, NoBreakpointError{addr: addr} + } + + if _, err := bp.Clear(dbp.currentThread); err != nil { + return nil, err + } + + delete(dbp.breakpoints, addr) + + return bp, nil +} + +// Status returns the status of the current main thread context. +func (dbp *Process) Status() *WaitStatus { + return dbp.currentThread.Status +} + +// Next continues execution until the next source line. +func (dbp *Process) Next() (err error) { + if dbp.exited { + return &ProcessExitedError{} + } + for i := range dbp.breakpoints { + if dbp.breakpoints[i].Internal() { + return fmt.Errorf("next while nexting") + } + } + + if err = dbp.next(false); err != nil { + switch err.(type) { + case ThreadBlockedError, NoReturnAddr: // Noop + default: + dbp.ClearInternalBreakpoints() + return + } + } + + return dbp.Continue() +} + +// Continue continues execution of the debugged +// process. It will continue until it hits a breakpoint +// or is otherwise stopped. +func (dbp *Process) Continue() error { + if dbp.exited { + return &ProcessExitedError{} + } + for { + if err := dbp.resume(); err != nil { + return err + } + + dbp.allGCache = nil + for _, th := range dbp.threads { + th.clearBreakpointState() + } + + trapthread, err := dbp.trapWait(-1) + if err != nil { + return err + } + if err := dbp.Halt(); err != nil { + return dbp.exitGuard(err) + } + if err := dbp.setCurrentBreakpoints(trapthread); err != nil { + return err + } + if err := dbp.pickCurrentThread(trapthread); err != nil { + return err + } + + switch { + case dbp.currentThread.CurrentBreakpoint == nil: + // runtime.Breakpoint or manual stop + if dbp.currentThread.onRuntimeBreakpoint() { + // Single-step current thread until we exit runtime.breakpoint and + // runtime.Breakpoint. + // On go < 1.8 it was sufficient to single-step twice on go1.8 a change + // to the compiler requires 4 steps. + for { + if err = dbp.currentThread.StepInstruction(); err != nil { + return err + } + loc, err := dbp.currentThread.Location() + if err != nil || loc.Fn == nil || (loc.Fn.Name != "runtime.breakpoint" && loc.Fn.Name != "runtime.Breakpoint") { + break + } + } + } + return dbp.conditionErrors() + case dbp.currentThread.onTriggeredInternalBreakpoint(): + if dbp.currentThread.CurrentBreakpoint.Kind == StepBreakpoint { + // See description of proc.(*Process).next for the meaning of StepBreakpoints + if err := dbp.conditionErrors(); err != nil { + return err + } + pc, err := dbp.currentThread.PC() + if err != nil { + return err + } + text, err := dbp.currentThread.Disassemble(pc, pc+maxInstructionLength, true) + if err != nil { + return err + } + // here we either set a breakpoint into the destination of the CALL + // instruction or we determined that the called function is hidden, + // either way we need to resume execution + if err = dbp.setStepIntoBreakpoint(text, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil { + return err + } + } else { + if err := dbp.ClearInternalBreakpoints(); err != nil { + return err + } + return dbp.conditionErrors() + } + case dbp.currentThread.onTriggeredBreakpoint(): + onNextGoroutine, err := dbp.currentThread.onNextGoroutine() + if err != nil { + return err + } + if onNextGoroutine { + err := dbp.ClearInternalBreakpoints() + if err != nil { + return err + } + } + return dbp.conditionErrors() + default: + // not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat + } + } +} + +func (dbp *Process) conditionErrors() error { + var condErr error + for _, th := range dbp.threads { + if th.CurrentBreakpoint != nil && th.BreakpointConditionError != nil { + if condErr == nil { + condErr = th.BreakpointConditionError + } else { + return fmt.Errorf("multiple errors evaluating conditions") + } + } + } + return condErr +} + +// pick a new dbp.currentThread, with the following priority: +// - a thread with onTriggeredInternalBreakpoint() == true +// - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread) +// - trapthread +func (dbp *Process) pickCurrentThread(trapthread *Thread) error { + for _, th := range dbp.threads { + if th.onTriggeredInternalBreakpoint() { + return dbp.SwitchThread(th.ID) + } + } + if trapthread.onTriggeredBreakpoint() { + return dbp.SwitchThread(trapthread.ID) + } + for _, th := range dbp.threads { + if th.onTriggeredBreakpoint() { + return dbp.SwitchThread(th.ID) + } + } + return dbp.SwitchThread(trapthread.ID) +} + +// Step will continue until another source line is reached. +// Will step into functions. +func (dbp *Process) Step() (err error) { + if dbp.exited { + return &ProcessExitedError{} + } + for i := range dbp.breakpoints { + if dbp.breakpoints[i].Internal() { + return fmt.Errorf("next while nexting") + } + } + + if err = dbp.next(true); err != nil { + switch err.(type) { + case ThreadBlockedError, NoReturnAddr: // Noop + default: + dbp.ClearInternalBreakpoints() + return + } + } + + return dbp.Continue() +} + +// Returns an expression that evaluates to true when the current goroutine is g +func sameGoroutineCondition(g *G) ast.Expr { + if g == nil { + return nil + } + return &ast.BinaryExpr{ + Op: token.EQL, + X: &ast.SelectorExpr{ + X: &ast.SelectorExpr{ + X: &ast.Ident{Name: "runtime"}, + Sel: &ast.Ident{Name: "curg"}, + }, + Sel: &ast.Ident{Name: "goid"}, + }, + Y: &ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(g.ID)}, + } +} + +// StepInstruction will continue the current thread for exactly +// one instruction. This method affects only the thread +// asssociated with the selected goroutine. All other +// threads will remain stopped. +func (dbp *Process) StepInstruction() (err error) { + if dbp.selectedGoroutine == nil { + return errors.New("cannot single step: no selected goroutine") + } + if dbp.selectedGoroutine.thread == nil { + // Step called on parked goroutine + if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil { + return err + } + return dbp.Continue() + } + dbp.allGCache = nil + if dbp.exited { + return &ProcessExitedError{} + } + dbp.selectedGoroutine.thread.clearBreakpointState() + err = dbp.selectedGoroutine.thread.StepInstruction() + if err != nil { + return err + } + return dbp.selectedGoroutine.thread.SetCurrentBreakpoint() +} + +// StepOut will continue until the current goroutine exits the +// function currently being executed or a deferred function is executed +func (dbp *Process) StepOut() error { + cond := sameGoroutineCondition(dbp.selectedGoroutine) + + topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread) + if err != nil { + return err + } + + pcs := []uint64{} + + var deferpc uint64 = 0 + if filepath.Ext(topframe.Current.File) == ".go" { + if dbp.selectedGoroutine != nil { + deferPCEntry := dbp.selectedGoroutine.DeferPC() + if deferPCEntry != 0 { + _, _, deferfn := dbp.goSymTable.PCToLine(deferPCEntry) + deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false) + if err != nil { + return err + } + pcs = append(pcs, deferpc) + } + } + } + + if topframe.Ret == 0 && deferpc == 0 { + return errors.New("nothing to stepout to") + } + + if deferpc != 0 && deferpc != topframe.Current.PC { + bp, err := dbp.SetBreakpoint(deferpc, NextDeferBreakpoint, cond) + if err != nil { + if _, ok := err.(BreakpointExistsError); !ok { + dbp.ClearInternalBreakpoints() + return err + } + } + if bp != nil { + // For StepOut we do not want to step into the deferred function + // when it's called by runtime.deferreturn so we do not populate + // DeferReturns. + bp.DeferReturns = []uint64{} + } + } + + if topframe.Ret != 0 { + if err := dbp.setInternalBreakpoints(topframe.Current.PC, []uint64{topframe.Ret}, NextBreakpoint, cond); err != nil { + return err + } + } + + return dbp.Continue() +} + +// SwitchThread changes from current thread to the thread specified by `tid`. +func (dbp *Process) SwitchThread(tid int) error { + if dbp.exited { + return &ProcessExitedError{} + } + if th, ok := dbp.threads[tid]; ok { + dbp.currentThread = th + dbp.selectedGoroutine, _ = dbp.currentThread.GetG() + return nil + } + return fmt.Errorf("thread %d does not exist", tid) +} + +// SwitchGoroutine changes from current thread to the thread +// running the specified goroutine. +func (dbp *Process) SwitchGoroutine(gid int) error { + if dbp.exited { + return &ProcessExitedError{} + } + g, err := dbp.FindGoroutine(gid) + if err != nil { + return err + } + if g == nil { + // user specified -1 and selectedGoroutine is nil + return nil + } + if g.thread != nil { + return dbp.SwitchThread(g.thread.ID) + } + dbp.selectedGoroutine = g + return nil +} + +// GoroutinesInfo returns an array of G structures representing the information +// Delve cares about from the internal runtime G structure. +func (dbp *Process) GoroutinesInfo() ([]*G, error) { + if dbp.exited { + return nil, &ProcessExitedError{} + } + if dbp.allGCache != nil { + return dbp.allGCache, nil + } + + var ( + threadg = map[int]*Thread{} + allg []*G + rdr = dbp.DwarfReader() + ) + + for i := range dbp.threads { + if dbp.threads[i].blocked() { + continue + } + g, _ := dbp.threads[i].GetG() + if g != nil { + threadg[g.ID] = dbp.threads[i] + } + } + + addr, err := rdr.AddrFor("runtime.allglen") + if err != nil { + return nil, err + } + allglenBytes, err := dbp.currentThread.readMemory(uintptr(addr), 8) + if err != nil { + return nil, err + } + allglen := binary.LittleEndian.Uint64(allglenBytes) + + rdr.Seek(0) + allgentryaddr, err := rdr.AddrFor("runtime.allgs") + if err != nil { + // try old name (pre Go 1.6) + allgentryaddr, err = rdr.AddrFor("runtime.allg") + if err != nil { + return nil, err + } + } + faddr, err := dbp.currentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize()) + allgptr := binary.LittleEndian.Uint64(faddr) + + for i := uint64(0); i < allglen; i++ { + gvar, err := dbp.currentThread.newGVariable(uintptr(allgptr+(i*uint64(dbp.arch.PtrSize()))), true) + if err != nil { + return nil, err + } + g, err := gvar.parseG() + if err != nil { + return nil, err + } + if thread, allocated := threadg[g.ID]; allocated { + loc, err := thread.Location() + if err != nil { + return nil, err + } + g.thread = thread + // Prefer actual thread location information. + g.CurrentLoc = *loc + } + if g.Status != Gdead { + allg = append(allg, g) + } + } + dbp.allGCache = allg + return allg, nil +} + +func (g *G) Thread() *Thread { + return g.thread +} + +// Halt stops all threads. +func (dbp *Process) Halt() (err error) { + if dbp.exited { + return &ProcessExitedError{} + } + for _, th := range dbp.threads { + if err := th.Halt(); err != nil { + return err + } + } + return nil +} + +// Registers obtains register values from the +// "current" thread of the traced process. +func (dbp *Process) Registers() (Registers, error) { + return dbp.currentThread.Registers(false) +} + +// PC returns the PC of the current thread. +func (dbp *Process) PC() (uint64, error) { + return dbp.currentThread.PC() +} + +// CurrentBreakpoint returns the breakpoint the current thread +// is stopped at. +func (dbp *Process) CurrentBreakpoint() *Breakpoint { + return dbp.currentThread.CurrentBreakpoint +} + +// DwarfReader returns a reader for the dwarf data +func (dbp *Process) DwarfReader() *reader.Reader { + return reader.New(dbp.dwarf) +} + +// Sources returns list of source files that comprise the debugged binary. +func (dbp *Process) Sources() map[string]*gosym.Obj { + return dbp.goSymTable.Files +} + +// Funcs returns list of functions present in the debugged program. +func (dbp *Process) Funcs() []gosym.Func { + return dbp.goSymTable.Funcs +} + +// Types returns list of types present in the debugged program. +func (dbp *Process) Types() ([]string, error) { + types := make([]string, 0, len(dbp.types)) + for k := range dbp.types { + types = append(types, k) + } + return types, nil +} + +// PCToLine converts an instruction address to a file/line/function. +func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) { + return dbp.goSymTable.PCToLine(pc) +} + +// FindBreakpointByID finds the breakpoint for the given ID. +func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) { + for _, bp := range dbp.breakpoints { + if bp.ID == id { + return bp, true + } + } + return nil, false +} + +// FindBreakpoint finds the breakpoint for the given pc. +func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) { + // Check to see if address is past the breakpoint, (i.e. breakpoint was hit). + if bp, ok := dbp.breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok { + return bp, true + } + // Directly use addr to lookup breakpoint. + if bp, ok := dbp.breakpoints[pc]; ok { + return bp, true + } + return nil, false +} + +// Returns a new Process struct. +func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, error) { + if attach { + var err error + dbp.execPtraceFunc(func() { err = PtraceAttach(dbp.pid) }) + if err != nil { + return nil, err + } + _, _, err = dbp.wait(dbp.pid, 0) + if err != nil { + return nil, err + } + } + + proc, err := os.FindProcess(dbp.pid) + if err != nil { + return nil, err + } + + dbp.Process = proc + err = dbp.LoadInformation(path) + if err != nil { + return nil, err + } + + if err := dbp.updateThreadList(); err != nil { + return nil, err + } + + ver, isextld, err := dbp.getGoInformation() + if err != nil { + return nil, err + } + + dbp.arch.SetGStructOffset(ver, isextld) + // selectedGoroutine can not be set correctly by the call to updateThreadList + // because without calling SetGStructOffset we can not read the G struct of currentThread + // but without calling updateThreadList we can not examine memory to determine + // the offset of g struct inside TLS + dbp.selectedGoroutine, _ = dbp.currentThread.GetG() + + panicpc, err := dbp.FindFunctionLocation("runtime.startpanic", true, 0) + if err == nil { + bp, err := dbp.SetBreakpoint(panicpc, UserBreakpoint, nil) + if err == nil { + bp.Name = "unrecovered-panic" + bp.ID = -1 + dbp.breakpointIDCounter-- + } + } + + return dbp, nil +} + +func (dbp *Process) ClearInternalBreakpoints() error { + for _, bp := range dbp.breakpoints { + if !bp.Internal() { + continue + } + if _, err := dbp.ClearBreakpoint(bp.Addr); err != nil { + return err + } + } + for i := range dbp.threads { + if dbp.threads[i].CurrentBreakpoint != nil && dbp.threads[i].CurrentBreakpoint.Internal() { + dbp.threads[i].CurrentBreakpoint = nil + } + } + return nil +} + +func (dbp *Process) handlePtraceFuncs() { + // We must ensure here that we are running on the same thread during + // while invoking the ptrace(2) syscall. This is due to the fact that ptrace(2) expects + // all commands after PTRACE_ATTACH to come from the same thread. + runtime.LockOSThread() + + for fn := range dbp.ptraceChan { + fn() + dbp.ptraceDoneChan <- nil + } +} + +func (dbp *Process) execPtraceFunc(fn func()) { + dbp.ptraceChan <- fn + <-dbp.ptraceDoneChan +} + +func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error) { + vv, err := dbp.EvalPackageVariable("runtime.buildVersion", LoadConfig{true, 0, 64, 0, 0}) + if err != nil { + err = fmt.Errorf("Could not determine version number: %v\n", err) + return + } + if vv.Unreadable != nil { + err = fmt.Errorf("Unreadable version number: %v\n", vv.Unreadable) + return + } + + ver, ok := ParseVersionString(constant.StringVal(vv.Value)) + if !ok { + err = fmt.Errorf("Could not parse version number: %v\n", vv.Value) + return + } + + rdr := dbp.DwarfReader() + rdr.Seek(0) + for entry, err := rdr.NextCompileUnit(); entry != nil; entry, err = rdr.NextCompileUnit() { + if err != nil { + return ver, isextld, err + } + if prod, ok := entry.Val(dwarf.AttrProducer).(string); ok && (strings.HasPrefix(prod, "GNU AS")) { + isextld = true + break + } + } + return +} + +// FindGoroutine returns a G struct representing the goroutine +// specified by `gid`. +func (dbp *Process) FindGoroutine(gid int) (*G, error) { + if gid == -1 { + return dbp.selectedGoroutine, nil + } + + gs, err := dbp.GoroutinesInfo() + if err != nil { + return nil, err + } + for i := range gs { + if gs[i].ID == gid { + return gs[i], nil + } + } + return nil, fmt.Errorf("Unknown goroutine %d", gid) +} + +// ConvertEvalScope returns a new EvalScope in the context of the +// specified goroutine ID and stack frame. +func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) { + if dbp.exited { + return nil, &ProcessExitedError{} + } + g, err := dbp.FindGoroutine(gid) + if err != nil { + return nil, err + } + if g == nil { + return dbp.currentThread.Scope() + } + + var out EvalScope + + if g.thread == nil { + out.Thread = dbp.currentThread + } else { + out.Thread = g.thread + } + + locs, err := g.Stacktrace(frame) + if err != nil { + return nil, err + } + + if frame >= len(locs) { + return nil, fmt.Errorf("Frame %d does not exist in goroutine %d", frame, gid) + } + + out.PC, out.CFA = locs[frame].Current.PC, locs[frame].CFA + + return &out, nil +} + +func (dbp *Process) postExit() { + dbp.exited = true + close(dbp.ptraceChan) + close(dbp.ptraceDoneChan) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.c b/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.c new file mode 100644 index 0000000..24a6084 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.c @@ -0,0 +1,231 @@ +#include "proc_darwin.h" + +static const unsigned char info_plist[] +__attribute__ ((section ("__TEXT,__info_plist"),used)) = +"\n" +"\n" +"\n" +"\n" +" CFBundleIdentifier\n" +" org.dlv\n" +" CFBundleName\n" +" delve\n" +" CFBundleVersion\n" +" 1.0\n" +" SecTaskAccess\n" +" \n" +" allowed\n" +" debug\n" +" \n" +"\n" +"\n"; + +kern_return_t +acquire_mach_task(int tid, + task_t *task, + mach_port_t *port_set, + mach_port_t *exception_port, + mach_port_t *notification_port) +{ + kern_return_t kret; + mach_port_t prev_not; + mach_port_t self = mach_task_self(); + + kret = task_for_pid(self, tid, task); + if (kret != KERN_SUCCESS) return kret; + + // Allocate exception port. + kret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, exception_port); + if (kret != KERN_SUCCESS) return kret; + + kret = mach_port_insert_right(self, *exception_port, *exception_port, MACH_MSG_TYPE_MAKE_SEND); + if (kret != KERN_SUCCESS) return kret; + + kret = task_set_exception_ports(*task, EXC_MASK_BREAKPOINT|EXC_MASK_SOFTWARE, *exception_port, + EXCEPTION_DEFAULT, THREAD_STATE_NONE); + if (kret != KERN_SUCCESS) return kret; + + // Allocate notification port to alert of when the process dies. + kret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, notification_port); + if (kret != KERN_SUCCESS) return kret; + + kret = mach_port_insert_right(self, *notification_port, *notification_port, MACH_MSG_TYPE_MAKE_SEND); + if (kret != KERN_SUCCESS) return kret; + + kret = mach_port_request_notification(self, *task, MACH_NOTIFY_DEAD_NAME, 0, *notification_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev_not); + if (kret != KERN_SUCCESS) return kret; + + // Create port set. + kret = mach_port_allocate(self, MACH_PORT_RIGHT_PORT_SET, port_set); + if (kret != KERN_SUCCESS) return kret; + + // Move exception and notification ports to port set. + kret = mach_port_move_member(self, *exception_port, *port_set); + if (kret != KERN_SUCCESS) return kret; + + return mach_port_move_member(self, *notification_port, *port_set); +} + +kern_return_t +reset_exception_ports(task_t task, mach_port_t *exception_port, mach_port_t *notification_port) { + kern_return_t kret; + mach_port_t prev_not; + mach_port_t self = mach_task_self(); + + kret = task_set_exception_ports(task, EXC_MASK_BREAKPOINT|EXC_MASK_SOFTWARE, *exception_port, + EXCEPTION_DEFAULT, THREAD_STATE_NONE); + if (kret != KERN_SUCCESS) return kret; + + kret = mach_port_request_notification(self, task, MACH_NOTIFY_DEAD_NAME, 0, *notification_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev_not); + if (kret != KERN_SUCCESS) return kret; + + return KERN_SUCCESS; +} + +char * +find_executable(int pid) { + static char pathbuf[PATH_MAX]; + proc_pidpath(pid, pathbuf, PATH_MAX); + return pathbuf; +} + +kern_return_t +get_threads(task_t task, void *slice, int limit) { + kern_return_t kret; + thread_act_array_t list; + mach_msg_type_number_t count; + + kret = task_threads(task, &list, &count); + if (kret != KERN_SUCCESS) { + return kret; + } + + if (count > limit) { + vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0])); + return -2; + } + + memcpy(slice, (void*)list, count*sizeof(list[0])); + + kret = vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0])); + if (kret != KERN_SUCCESS) return kret; + + return (kern_return_t)0; +} + +int +thread_count(task_t task) { + kern_return_t kret; + thread_act_array_t list; + mach_msg_type_number_t count; + + kret = task_threads(task, &list, &count); + if (kret != KERN_SUCCESS) return -1; + + kret = vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0])); + if (kret != KERN_SUCCESS) return -1; + + return count; +} + +mach_port_t +mach_port_wait(mach_port_t port_set, task_t *task, int nonblocking) { + kern_return_t kret; + thread_act_t thread; + NDR_record_t *ndr; + integer_t *data; + union + { + mach_msg_header_t hdr; + char data[256]; + } msg; + mach_msg_option_t opts = MACH_RCV_MSG|MACH_RCV_INTERRUPT; + if (nonblocking) { + opts |= MACH_RCV_TIMEOUT; + } + + // Wait for mach msg. + kret = mach_msg(&msg.hdr, opts, + 0, sizeof(msg.data), port_set, 10, MACH_PORT_NULL); + if (kret == MACH_RCV_INTERRUPTED) return kret; + if (kret != MACH_MSG_SUCCESS) return 0; + + + switch (msg.hdr.msgh_id) { + case 2401: { // Exception + // 2401 is the exception_raise event, defined in: + // http://opensource.apple.com/source/xnu/xnu-2422.1.72/osfmk/mach/exc.defs?txt + // compile this file with mig to get the C version of the description + + mach_msg_body_t *bod = (mach_msg_body_t*)(&msg.hdr + 1); + mach_msg_port_descriptor_t *desc = (mach_msg_port_descriptor_t *)(bod + 1); + thread = desc[0].name; + *task = desc[1].name; + ndr = (NDR_record_t *)(desc + 2); + data = (integer_t *)(ndr + 1); + + if (thread_suspend(thread) != KERN_SUCCESS) return 0; + // Send our reply back so the kernel knows this exception has been handled. + kret = mach_send_reply(msg.hdr); + if (kret != MACH_MSG_SUCCESS) return 0; + if (data[2] == EXC_SOFT_SIGNAL) { + if (data[3] != SIGTRAP) { + if (thread_resume(thread) != KERN_SUCCESS) return 0; + return mach_port_wait(port_set, task, nonblocking); + } + } + return thread; + } + + case 72: { // Death + // 72 is mach_notify_dead_name, defined in: + // https://opensource.apple.com/source/xnu/xnu-1228.7.58/osfmk/mach/notify.defs?txt + // compile this file with mig to get the C version of the description + ndr = (NDR_record_t *)(&msg.hdr + 1); + *task = *((mach_port_name_t *)(ndr + 1)); + return msg.hdr.msgh_local_port; + } + } + return 0; +} + +kern_return_t +mach_send_reply(mach_msg_header_t hdr) { + mig_reply_error_t reply; + mach_msg_header_t *rh = &reply.Head; + rh->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(hdr.msgh_bits), 0); + rh->msgh_remote_port = hdr.msgh_remote_port; + rh->msgh_size = (mach_msg_size_t) sizeof(mig_reply_error_t); + rh->msgh_local_port = MACH_PORT_NULL; + rh->msgh_id = hdr.msgh_id + 100; + + reply.NDR = NDR_record; + reply.RetCode = KERN_SUCCESS; + + return mach_msg(&reply.Head, MACH_SEND_MSG|MACH_SEND_INTERRUPT, rh->msgh_size, 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); +} + +kern_return_t +raise_exception(mach_port_t task, mach_port_t thread, mach_port_t exception_port, exception_type_t exception) { + return exception_raise(exception_port, thread, task, exception, 0, 0); +} + +task_t +get_task_for_pid(int pid) { + task_t task = 0; + mach_port_t self = mach_task_self(); + + task_for_pid(self, pid, &task); + return task; +} + +int +task_is_valid(task_t task) { + struct task_basic_info info; + mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; + return task_info(task, TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS; +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.go b/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.go new file mode 100644 index 0000000..2a71300 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.go @@ -0,0 +1,511 @@ +package proc + +// #include "proc_darwin.h" +// #include "threads_darwin.h" +// #include "exec_darwin.h" +// #include +import "C" +import ( + "debug/gosym" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "sync" + "unsafe" + + "golang.org/x/debug/macho" + + "github.com/derekparker/delve/pkg/dwarf/frame" + "github.com/derekparker/delve/pkg/dwarf/line" + sys "golang.org/x/sys/unix" +) + +// OSProcessDetails holds Darwin specific information. +type OSProcessDetails struct { + task C.task_t // mach task for the debugged process. + exceptionPort C.mach_port_t // mach port for receiving mach exceptions. + notificationPort C.mach_port_t // mach port for dead name notification (process exit). + initialized bool + + // the main port we use, will return messages from both the + // exception and notification ports. + portSet C.mach_port_t +} + +// Launch creates and begins debugging a new process. Uses a +// custom fork/exec process in order to take advantage of +// PT_SIGEXC on Darwin which will turn Unix signals into +// Mach exceptions. +func Launch(cmd []string, wd string) (*Process, error) { + // check that the argument to Launch is an executable file + if fi, staterr := os.Stat(cmd[0]); staterr == nil && (fi.Mode()&0111) == 0 { + return nil, NotExecutableErr + } + argv0Go, err := filepath.Abs(cmd[0]) + if err != nil { + return nil, err + } + // Make sure the binary exists. + if filepath.Base(cmd[0]) == cmd[0] { + if _, err := exec.LookPath(cmd[0]); err != nil { + return nil, err + } + } + if _, err := os.Stat(argv0Go); err != nil { + return nil, err + } + + argv0 := C.CString(argv0Go) + argvSlice := make([]*C.char, 0, len(cmd)+1) + for _, arg := range cmd { + argvSlice = append(argvSlice, C.CString(arg)) + } + // argv array must be null terminated. + argvSlice = append(argvSlice, nil) + + dbp := New(0) + var pid int + dbp.execPtraceFunc(func() { + ret := C.fork_exec(argv0, &argvSlice[0], C.int(len(argvSlice)), + C.CString(wd), + &dbp.os.task, &dbp.os.portSet, &dbp.os.exceptionPort, + &dbp.os.notificationPort) + pid = int(ret) + }) + if pid <= 0 { + return nil, fmt.Errorf("could not fork/exec") + } + dbp.pid = pid + for i := range argvSlice { + C.free(unsafe.Pointer(argvSlice[i])) + } + + // Initialize enough of the Process state so that we can use resume and + // trapWait to wait until the child process calls execve. + + for { + err = dbp.updateThreadListForTask(C.get_task_for_pid(C.int(dbp.pid))) + if err == nil { + break + } + if err != couldNotGetThreadCount && err != couldNotGetThreadList { + return nil, err + } + } + + if err := dbp.resume(); err != nil { + return nil, err + } + + dbp.allGCache = nil + for _, th := range dbp.threads { + th.clearBreakpointState() + } + + trapthread, err := dbp.trapWait(-1) + if err != nil { + return nil, err + } + if err := dbp.Halt(); err != nil { + return nil, dbp.exitGuard(err) + } + + _, err = dbp.waitForStop() + if err != nil { + return nil, err + } + + dbp.os.initialized = true + dbp, err = initializeDebugProcess(dbp, argv0Go, false) + if err != nil { + return nil, err + } + + if err := dbp.SwitchThread(trapthread.ID); err != nil { + return nil, err + } + + return dbp, err +} + +// Attach to an existing process with the given PID. +func Attach(pid int) (*Process, error) { + dbp := New(pid) + + kret := C.acquire_mach_task(C.int(pid), + &dbp.os.task, &dbp.os.portSet, &dbp.os.exceptionPort, + &dbp.os.notificationPort) + + if kret != C.KERN_SUCCESS { + return nil, fmt.Errorf("could not attach to %d", pid) + } + + dbp.os.initialized = true + + return initializeDebugProcess(dbp, "", true) +} + +// Kill kills the process. +func (dbp *Process) Kill() (err error) { + if dbp.exited { + return nil + } + err = sys.Kill(-dbp.pid, sys.SIGKILL) + if err != nil { + return errors.New("could not deliver signal: " + err.Error()) + } + for port := range dbp.threads { + if C.thread_resume(C.thread_act_t(port)) != C.KERN_SUCCESS { + return errors.New("could not resume task") + } + } + for { + var task C.task_t + port := C.mach_port_wait(dbp.os.portSet, &task, C.int(0)) + if port == dbp.os.notificationPort { + break + } + } + dbp.postExit() + return +} + +func (dbp *Process) requestManualStop() (err error) { + var ( + task = C.mach_port_t(dbp.os.task) + thread = C.mach_port_t(dbp.currentThread.os.threadAct) + exceptionPort = C.mach_port_t(dbp.os.exceptionPort) + ) + kret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT) + if kret != C.KERN_SUCCESS { + return fmt.Errorf("could not raise mach exception") + } + return nil +} + +var couldNotGetThreadCount = errors.New("could not get thread count") +var couldNotGetThreadList = errors.New("could not get thread list") + +func (dbp *Process) updateThreadList() error { + return dbp.updateThreadListForTask(dbp.os.task) +} + +func (dbp *Process) updateThreadListForTask(task C.task_t) error { + var ( + err error + kret C.kern_return_t + count C.int + list []uint32 + ) + + for { + count = C.thread_count(task) + if count == -1 { + return couldNotGetThreadCount + } + list = make([]uint32, count) + + // TODO(dp) might be better to malloc mem in C and then free it here + // instead of getting count above and passing in a slice + kret = C.get_threads(task, unsafe.Pointer(&list[0]), count) + if kret != -2 { + break + } + } + if kret != C.KERN_SUCCESS { + return couldNotGetThreadList + } + + for _, thread := range dbp.threads { + thread.os.exists = false + } + + for _, port := range list { + thread, ok := dbp.threads[int(port)] + if !ok { + thread, err = dbp.addThread(int(port), false) + if err != nil { + return err + } + } + thread.os.exists = true + } + + for threadID, thread := range dbp.threads { + if !thread.os.exists { + delete(dbp.threads, threadID) + } + } + + return nil +} + +func (dbp *Process) addThread(port int, attach bool) (*Thread, error) { + if thread, ok := dbp.threads[port]; ok { + return thread, nil + } + thread := &Thread{ + ID: port, + dbp: dbp, + os: new(OSSpecificDetails), + } + dbp.threads[port] = thread + thread.os.threadAct = C.thread_act_t(port) + if dbp.currentThread == nil { + dbp.SwitchThread(thread.ID) + } + return thread, nil +} + +func (dbp *Process) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup) { + defer wg.Done() + + debugFrameSec := exe.Section("__debug_frame") + debugInfoSec := exe.Section("__debug_info") + + if debugFrameSec != nil && debugInfoSec != nil { + debugFrame, err := exe.Section("__debug_frame").Data() + if err != nil { + fmt.Println("could not get __debug_frame section", err) + os.Exit(1) + } + dat, err := debugInfoSec.Data() + if err != nil { + fmt.Println("could not get .debug_info section", err) + os.Exit(1) + } + dbp.frameEntries = frame.Parse(debugFrame, frame.DwarfEndian(dat)) + } else { + fmt.Println("could not find __debug_frame section in binary") + os.Exit(1) + } +} + +func (dbp *Process) obtainGoSymbols(exe *macho.File, wg *sync.WaitGroup) { + defer wg.Done() + + var ( + symdat []byte + pclndat []byte + err error + ) + + if sec := exe.Section("__gosymtab"); sec != nil { + symdat, err = sec.Data() + if err != nil { + fmt.Println("could not get .gosymtab section", err) + os.Exit(1) + } + } + + if sec := exe.Section("__gopclntab"); sec != nil { + pclndat, err = sec.Data() + if err != nil { + fmt.Println("could not get .gopclntab section", err) + os.Exit(1) + } + } + + pcln := gosym.NewLineTable(pclndat, exe.Section("__text").Addr) + tab, err := gosym.NewTable(symdat, pcln) + if err != nil { + fmt.Println("could not get initialize line table", err) + os.Exit(1) + } + + dbp.goSymTable = tab +} + +func (dbp *Process) parseDebugLineInfo(exe *macho.File, wg *sync.WaitGroup) { + defer wg.Done() + + if sec := exe.Section("__debug_line"); sec != nil { + debugLine, err := exe.Section("__debug_line").Data() + if err != nil { + fmt.Println("could not get __debug_line section", err) + os.Exit(1) + } + dbp.lineInfo = line.Parse(debugLine) + } else { + fmt.Println("could not find __debug_line section in binary") + os.Exit(1) + } +} + +var UnsupportedArchErr = errors.New("unsupported architecture - only darwin/amd64 is supported") + +func (dbp *Process) findExecutable(path string) (*macho.File, string, error) { + if path == "" { + path = C.GoString(C.find_executable(C.int(dbp.pid))) + } + exe, err := macho.Open(path) + if err != nil { + return nil, path, err + } + if exe.Cpu != macho.CpuAmd64 { + return nil, path, UnsupportedArchErr + } + dbp.dwarf, err = exe.DWARF() + if err != nil { + return nil, path, err + } + return exe, path, nil +} + +func (dbp *Process) trapWait(pid int) (*Thread, error) { + for { + task := dbp.os.task + port := C.mach_port_wait(dbp.os.portSet, &task, C.int(0)) + + switch port { + case dbp.os.notificationPort: + // on macOS >= 10.12.1 the task_t changes after an execve, we could + // receive the notification for the death of the pre-execve task_t, + // this could also happen *before* we are notified that our task_t has + // changed. + if dbp.os.task != task { + continue + } + if !dbp.os.initialized { + if pidtask := C.get_task_for_pid(C.int(dbp.pid)); pidtask != 0 && dbp.os.task != pidtask { + continue + } + } + _, status, err := dbp.wait(dbp.pid, 0) + if err != nil { + return nil, err + } + dbp.postExit() + return nil, ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()} + + case C.MACH_RCV_INTERRUPTED: + if !dbp.halt { + // Call trapWait again, it seems + // MACH_RCV_INTERRUPTED is emitted before + // process natural death _sometimes_. + continue + } + return nil, nil + + case 0: + return nil, fmt.Errorf("error while waiting for task") + } + + // In macOS 10.12.1 if we received a notification for a task other than + // the inferior's task and the inferior's task is no longer valid, this + // means inferior called execve and its task_t changed. + if dbp.os.task != task && C.task_is_valid(dbp.os.task) == 0 { + dbp.os.task = task + kret := C.reset_exception_ports(dbp.os.task, &dbp.os.exceptionPort, &dbp.os.notificationPort) + if kret != C.KERN_SUCCESS { + return nil, fmt.Errorf("could not follow task across exec: %d\n", kret) + } + } + + // Since we cannot be notified of new threads on OS X + // this is as good a time as any to check for them. + dbp.updateThreadList() + th, ok := dbp.threads[int(port)] + if !ok { + if dbp.halt { + dbp.halt = false + return th, nil + } + if dbp.firstStart || th.singleStepping { + dbp.firstStart = false + return th, nil + } + if err := th.Continue(); err != nil { + return nil, err + } + continue + } + return th, nil + } +} + +func (dbp *Process) waitForStop() ([]int, error) { + ports := make([]int, 0, len(dbp.threads)) + count := 0 + for { + var task C.task_t + port := C.mach_port_wait(dbp.os.portSet, &task, C.int(1)) + if port != 0 && port != dbp.os.notificationPort && port != C.MACH_RCV_INTERRUPTED { + count = 0 + ports = append(ports, int(port)) + } else { + n := C.num_running_threads(dbp.os.task) + if n == 0 { + return ports, nil + } else if n < 0 { + return nil, fmt.Errorf("error waiting for thread stop %d", n) + } else if count > 16 { + return nil, fmt.Errorf("could not stop process %d", n) + } + } + } +} + +func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { + ports, err := dbp.waitForStop() + if err != nil { + return err + } + trapthread.SetCurrentBreakpoint() + for _, port := range ports { + if th, ok := dbp.threads[port]; ok { + err := th.SetCurrentBreakpoint() + if err != nil { + return err + } + } + } + return nil +} + +func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) { + wg.Done() +} + +func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) { + var status sys.WaitStatus + wpid, err := sys.Wait4(pid, &status, options, nil) + return wpid, &status, err +} + +func killProcess(pid int) error { + return sys.Kill(pid, sys.SIGINT) +} + +func (dbp *Process) exitGuard(err error) error { + if err != ErrContinueThread { + return err + } + _, status, werr := dbp.wait(dbp.pid, sys.WNOHANG) + if werr == nil && status.Exited() { + dbp.postExit() + return ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()} + } + return err +} + +func (dbp *Process) resume() error { + // all threads stopped over a breakpoint are made to step over it + for _, thread := range dbp.threads { + if thread.CurrentBreakpoint != nil { + if err := thread.StepInstruction(); err != nil { + return err + } + thread.CurrentBreakpoint = nil + } + } + // everything is resumed + for _, thread := range dbp.threads { + if err := thread.resume(); err != nil { + return dbp.exitGuard(err) + } + } + return nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.h b/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.h new file mode 100644 index 0000000..022ab14 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/proc_darwin.h @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include "mach_exc.h" +#include "exc.h" + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +kern_return_t +acquire_mach_task(int, task_t*, mach_port_t*, mach_port_t*, mach_port_t*); + +char * +find_executable(int pid); + +kern_return_t +get_threads(task_t task, void *data,int limit); + +int +thread_count(task_t task); + +mach_port_t +mach_port_wait(mach_port_t, task_t*, int); + +kern_return_t +mach_send_reply(mach_msg_header_t); + +kern_return_t +raise_exception(mach_port_t, mach_port_t, mach_port_t, exception_type_t); + +kern_return_t +reset_exception_ports(task_t task, mach_port_t *exception_port, mach_port_t *notification_port); + +task_t +get_task_for_pid(int pid); + +int +task_is_valid(task_t task); diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc_linux.go b/vendor/github.com/derekparker/delve/pkg/proc/proc_linux.go new file mode 100644 index 0000000..4969f0f --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/proc_linux.go @@ -0,0 +1,489 @@ +package proc + +import ( + "bytes" + "debug/gosym" + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "strconv" + "strings" + "sync" + "syscall" + "time" + + sys "golang.org/x/sys/unix" + + "github.com/derekparker/delve/pkg/dwarf/frame" + "github.com/derekparker/delve/pkg/dwarf/line" + "golang.org/x/debug/elf" +) + +// Process statuses +const ( + StatusSleeping = 'S' + StatusRunning = 'R' + StatusTraceStop = 't' + StatusZombie = 'Z' + + // Kernel 2.6 has TraceStop as T + // TODO(derekparker) Since this means something different based on the + // version of the kernel ('T' is job control stop on modern 3.x+ kernels) we + // may want to differentiate at some point. + StatusTraceStopT = 'T' +) + +// OSProcessDetails contains Linux specific +// process details. +type OSProcessDetails struct { + comm string +} + +// Launch creates and begins debugging a new process. First entry in +// `cmd` is the program to run, and then rest are the arguments +// to be supplied to that process. `wd` is working directory of the program. +func Launch(cmd []string, wd string) (*Process, error) { + var ( + proc *exec.Cmd + err error + ) + // check that the argument to Launch is an executable file + if fi, staterr := os.Stat(cmd[0]); staterr == nil && (fi.Mode()&0111) == 0 { + return nil, NotExecutableErr + } + dbp := New(0) + dbp.execPtraceFunc(func() { + proc = exec.Command(cmd[0]) + proc.Args = cmd + proc.Stdout = os.Stdout + proc.Stderr = os.Stderr + proc.SysProcAttr = &syscall.SysProcAttr{Ptrace: true, Setpgid: true} + if wd != "" { + proc.Dir = wd + } + err = proc.Start() + }) + if err != nil { + return nil, err + } + dbp.pid = proc.Process.Pid + _, _, err = dbp.wait(proc.Process.Pid, 0) + if err != nil { + return nil, fmt.Errorf("waiting for target execve failed: %s", err) + } + return initializeDebugProcess(dbp, proc.Path, false) +} + +// Attach to an existing process with the given PID. +func Attach(pid int) (*Process, error) { + return initializeDebugProcess(New(pid), "", true) +} + +// Kill kills the target process. +func (dbp *Process) Kill() (err error) { + if dbp.exited { + return nil + } + if !dbp.threads[dbp.pid].Stopped() { + return errors.New("process must be stopped in order to kill it") + } + if err = sys.Kill(-dbp.pid, sys.SIGKILL); err != nil { + return errors.New("could not deliver signal " + err.Error()) + } + if _, _, err = dbp.wait(dbp.pid, 0); err != nil { + return + } + dbp.postExit() + return +} + +func (dbp *Process) requestManualStop() (err error) { + return sys.Kill(dbp.pid, sys.SIGTRAP) +} + +// Attach to a newly created thread, and store that thread in our list of +// known threads. +func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) { + if thread, ok := dbp.threads[tid]; ok { + return thread, nil + } + + var err error + if attach { + dbp.execPtraceFunc(func() { err = sys.PtraceAttach(tid) }) + if err != nil && err != sys.EPERM { + // Do not return err if err == EPERM, + // we may already be tracing this thread due to + // PTRACE_O_TRACECLONE. We will surely blow up later + // if we truly don't have permissions. + return nil, fmt.Errorf("could not attach to new thread %d %s", tid, err) + } + pid, status, err := dbp.wait(tid, 0) + if err != nil { + return nil, err + } + if status.Exited() { + return nil, fmt.Errorf("thread already exited %d", pid) + } + } + + dbp.execPtraceFunc(func() { err = syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE) }) + if err == syscall.ESRCH { + if _, _, err = dbp.wait(tid, 0); err != nil { + return nil, fmt.Errorf("error while waiting after adding thread: %d %s", tid, err) + } + dbp.execPtraceFunc(func() { err = syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE) }) + if err == syscall.ESRCH { + return nil, err + } + if err != nil { + return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err) + } + } + + dbp.threads[tid] = &Thread{ + ID: tid, + dbp: dbp, + os: new(OSSpecificDetails), + } + if dbp.currentThread == nil { + dbp.SwitchThread(tid) + } + return dbp.threads[tid], nil +} + +func (dbp *Process) updateThreadList() error { + tids, _ := filepath.Glob(fmt.Sprintf("/proc/%d/task/*", dbp.pid)) + for _, tidpath := range tids { + tidstr := filepath.Base(tidpath) + tid, err := strconv.Atoi(tidstr) + if err != nil { + return err + } + if _, err := dbp.addThread(tid, tid != dbp.pid); err != nil { + return err + } + } + return nil +} + +var UnsupportedArchErr = errors.New("unsupported architecture - only linux/amd64 is supported") + +func (dbp *Process) findExecutable(path string) (*elf.File, string, error) { + if path == "" { + path = fmt.Sprintf("/proc/%d/exe", dbp.pid) + } + f, err := os.OpenFile(path, 0, os.ModePerm) + if err != nil { + return nil, path, err + } + elfFile, err := elf.NewFile(f) + if err != nil { + return nil, path, err + } + if elfFile.Machine != elf.EM_X86_64 { + return nil, path, UnsupportedArchErr + } + dbp.dwarf, err = elfFile.DWARF() + if err != nil { + return nil, path, err + } + return elfFile, path, nil +} + +func (dbp *Process) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) { + defer wg.Done() + + debugFrameSec := exe.Section(".debug_frame") + debugInfoSec := exe.Section(".debug_info") + + if debugFrameSec != nil && debugInfoSec != nil { + debugFrame, err := exe.Section(".debug_frame").Data() + if err != nil { + fmt.Println("could not get .debug_frame section", err) + os.Exit(1) + } + dat, err := debugInfoSec.Data() + if err != nil { + fmt.Println("could not get .debug_info section", err) + os.Exit(1) + } + dbp.frameEntries = frame.Parse(debugFrame, frame.DwarfEndian(dat)) + } else { + fmt.Println("could not find .debug_frame section in binary") + os.Exit(1) + } +} + +func (dbp *Process) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) { + defer wg.Done() + + var ( + symdat []byte + pclndat []byte + err error + ) + + if sec := exe.Section(".gosymtab"); sec != nil { + symdat, err = sec.Data() + if err != nil { + fmt.Println("could not get .gosymtab section", err) + os.Exit(1) + } + } + + if sec := exe.Section(".gopclntab"); sec != nil { + pclndat, err = sec.Data() + if err != nil { + fmt.Println("could not get .gopclntab section", err) + os.Exit(1) + } + } + + pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr) + tab, err := gosym.NewTable(symdat, pcln) + if err != nil { + fmt.Println("could not get initialize line table", err) + os.Exit(1) + } + + dbp.goSymTable = tab +} + +func (dbp *Process) parseDebugLineInfo(exe *elf.File, wg *sync.WaitGroup) { + defer wg.Done() + + if sec := exe.Section(".debug_line"); sec != nil { + debugLine, err := exe.Section(".debug_line").Data() + if err != nil { + fmt.Println("could not get .debug_line section", err) + os.Exit(1) + } + dbp.lineInfo = line.Parse(debugLine) + } else { + fmt.Println("could not find .debug_line section in binary") + os.Exit(1) + } +} + +func (dbp *Process) trapWait(pid int) (*Thread, error) { + for { + wpid, status, err := dbp.wait(pid, 0) + if err != nil { + return nil, fmt.Errorf("wait err %s %d", err, pid) + } + if wpid == 0 { + continue + } + th, ok := dbp.threads[wpid] + if ok { + th.Status = (*WaitStatus)(status) + } + if status.Exited() { + if wpid == dbp.pid { + dbp.postExit() + return nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()} + } + delete(dbp.threads, wpid) + continue + } + if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE { + // A traced thread has cloned a new thread, grab the pid and + // add it to our list of traced threads. + var cloned uint + dbp.execPtraceFunc(func() { cloned, err = sys.PtraceGetEventMsg(wpid) }) + if err != nil { + if err == sys.ESRCH { + // thread died while we were adding it + continue + } + return nil, fmt.Errorf("could not get event message: %s", err) + } + th, err = dbp.addThread(int(cloned), false) + if err != nil { + if err == sys.ESRCH { + // thread died while we were adding it + continue + } + return nil, err + } + if err = th.Continue(); err != nil { + if err == sys.ESRCH { + // thread died while we were adding it + delete(dbp.threads, th.ID) + continue + } + return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err) + } + if err = dbp.threads[int(wpid)].Continue(); err != nil { + if err != sys.ESRCH { + return nil, fmt.Errorf("could not continue existing thread %d %s", wpid, err) + } + } + continue + } + if th == nil { + // Sometimes we get an unknown thread, ignore it? + continue + } + if status.StopSignal() == sys.SIGTRAP && dbp.halt { + th.running = false + dbp.halt = false + return th, nil + } + if status.StopSignal() == sys.SIGTRAP { + th.running = false + return th, nil + } + if th != nil { + // TODO(dp) alert user about unexpected signals here. + if err := th.resumeWithSig(int(status.StopSignal())); err != nil { + if err == sys.ESRCH { + return nil, ProcessExitedError{Pid: dbp.pid} + } + return nil, err + } + } + } +} + +func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) { + defer wg.Done() + + comm, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/comm", dbp.pid)) + if err == nil { + // removes newline character + comm = bytes.TrimSuffix(comm, []byte("\n")) + } + + if comm == nil || len(comm) <= 0 { + stat, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", dbp.pid)) + if err != nil { + fmt.Printf("Could not read proc stat: %v\n", err) + os.Exit(1) + } + expr := fmt.Sprintf("%d\\s*\\((.*)\\)", dbp.pid) + rexp, err := regexp.Compile(expr) + if err != nil { + fmt.Printf("Regexp compile error: %v\n", err) + os.Exit(1) + } + match := rexp.FindSubmatch(stat) + if match == nil { + fmt.Printf("No match found using regexp '%s' in /proc/%d/stat\n", expr, dbp.pid) + os.Exit(1) + } + comm = match[1] + } + dbp.os.comm = strings.Replace(string(comm), "%", "%%", -1) +} + +func status(pid int, comm string) rune { + f, err := os.Open(fmt.Sprintf("/proc/%d/stat", pid)) + if err != nil { + return '\000' + } + defer f.Close() + + var ( + p int + state rune + ) + + // The second field of /proc/pid/stat is the name of the task in parenthesis. + // The name of the task is the base name of the executable for this process limited to TASK_COMM_LEN characters + // Since both parenthesis and spaces can appear inside the name of the task and no escaping happens we need to read the name of the executable first + // See: include/linux/sched.c:315 and include/linux/sched.c:1510 + fmt.Fscanf(f, "%d ("+comm+") %c", &p, &state) + return state +} + +// waitFast is like wait but does not handle process-exit correctly +func (dbp *Process) waitFast(pid int) (int, *sys.WaitStatus, error) { + var s sys.WaitStatus + wpid, err := sys.Wait4(pid, &s, sys.WALL, nil) + return wpid, &s, err +} + +func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) { + var s sys.WaitStatus + if (pid != dbp.pid) || (options != 0) { + wpid, err := sys.Wait4(pid, &s, sys.WALL|options, nil) + return wpid, &s, err + } + // If we call wait4/waitpid on a thread that is the leader of its group, + // with options == 0, while ptracing and the thread leader has exited leaving + // zombies of its own then waitpid hangs forever this is apparently intended + // behaviour in the linux kernel because it's just so convenient. + // Therefore we call wait4 in a loop with WNOHANG, sleeping a while between + // calls and exiting when either wait4 succeeds or we find out that the thread + // has become a zombie. + // References: + // https://sourceware.org/bugzilla/show_bug.cgi?id=12702 + // https://sourceware.org/bugzilla/show_bug.cgi?id=10095 + // https://sourceware.org/bugzilla/attachment.cgi?id=5685 + for { + wpid, err := sys.Wait4(pid, &s, sys.WNOHANG|sys.WALL|options, nil) + if err != nil { + return 0, nil, err + } + if wpid != 0 { + return wpid, &s, err + } + if status(pid, dbp.os.comm) == StatusZombie { + return pid, nil, nil + } + time.Sleep(200 * time.Millisecond) + } +} + +func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { + for _, th := range dbp.threads { + if th.CurrentBreakpoint == nil { + err := th.SetCurrentBreakpoint() + if err != nil { + return err + } + } + } + return nil +} + +func (dbp *Process) exitGuard(err error) error { + if err != sys.ESRCH { + return err + } + if status(dbp.pid, dbp.os.comm) == StatusZombie { + _, err := dbp.trapWait(-1) + return err + } + + return err +} + +func (dbp *Process) resume() error { + // all threads stopped over a breakpoint are made to step over it + for _, thread := range dbp.threads { + if thread.CurrentBreakpoint != nil { + if err := thread.StepInstruction(); err != nil { + return err + } + thread.CurrentBreakpoint = nil + } + } + // everything is resumed + for _, thread := range dbp.threads { + if err := thread.resume(); err != nil && err != sys.ESRCH { + return err + } + } + return nil +} + +func killProcess(pid int) error { + return sys.Kill(pid, sys.SIGINT) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc_windows.go b/vendor/github.com/derekparker/delve/pkg/proc/proc_windows.go new file mode 100644 index 0000000..d3b7773 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/proc_windows.go @@ -0,0 +1,672 @@ +package proc + +import ( + "debug/gosym" + "debug/pe" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "sync" + "syscall" + "unsafe" + + sys "golang.org/x/sys/windows" + + "github.com/derekparker/delve/pkg/dwarf/frame" + "github.com/derekparker/delve/pkg/dwarf/line" + "golang.org/x/debug/dwarf" +) + +// OSProcessDetails holds Windows specific information. +type OSProcessDetails struct { + hProcess syscall.Handle + breakThread int +} + +// Launch creates and begins debugging a new process. +func Launch(cmd []string, wd string) (*Process, error) { + argv0Go, err := filepath.Abs(cmd[0]) + if err != nil { + return nil, err + } + + // Make sure the binary exists and is an executable file + if filepath.Base(cmd[0]) == cmd[0] { + if _, err := exec.LookPath(cmd[0]); err != nil { + return nil, err + } + } + + peFile, err := openExecutablePath(argv0Go) + if err != nil { + return nil, NotExecutableErr + } + peFile.Close() + + // Duplicate the stdin/stdout/stderr handles + files := []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)} + p, _ := syscall.GetCurrentProcess() + fd := make([]syscall.Handle, len(files)) + for i := range files { + err := syscall.DuplicateHandle(p, syscall.Handle(files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) + if err != nil { + return nil, err + } + defer syscall.CloseHandle(syscall.Handle(fd[i])) + } + + argv0, err := syscall.UTF16PtrFromString(argv0Go) + if err != nil { + return nil, err + } + + // create suitable command line for CreateProcess + // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L326 + // adapted from standard library makeCmdLine + // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L86 + var cmdLineGo string + if len(cmd) >= 1 { + for _, v := range cmd { + if cmdLineGo != "" { + cmdLineGo += " " + } + cmdLineGo += syscall.EscapeArg(v) + } + } + + var cmdLine *uint16 + if cmdLineGo != "" { + if cmdLine, err = syscall.UTF16PtrFromString(cmdLineGo); err != nil { + return nil, err + } + } + + var workingDir *uint16 + if wd != "" { + if workingDir, err = syscall.UTF16PtrFromString(wd); err != nil { + return nil, err + } + } + + // Initialize the startup info and create process + si := new(sys.StartupInfo) + si.Cb = uint32(unsafe.Sizeof(*si)) + si.Flags = syscall.STARTF_USESTDHANDLES + si.StdInput = sys.Handle(fd[0]) + si.StdOutput = sys.Handle(fd[1]) + si.StdErr = sys.Handle(fd[2]) + pi := new(sys.ProcessInformation) + + dbp := New(0) + dbp.execPtraceFunc(func() { + if wd == "" { + err = sys.CreateProcess(argv0, cmdLine, nil, nil, true, _DEBUG_ONLY_THIS_PROCESS, nil, nil, si, pi) + } else { + err = sys.CreateProcess(argv0, cmdLine, nil, nil, true, _DEBUG_ONLY_THIS_PROCESS, nil, workingDir, si, pi) + } + }) + if err != nil { + return nil, err + } + sys.CloseHandle(sys.Handle(pi.Process)) + sys.CloseHandle(sys.Handle(pi.Thread)) + + dbp.pid = int(pi.ProcessId) + + return newDebugProcess(dbp, argv0Go) +} + +// newDebugProcess prepares process pid for debugging. +func newDebugProcess(dbp *Process, exepath string) (*Process, error) { + // It should not actually be possible for the + // call to waitForDebugEvent to fail, since Windows + // will always fire a CREATE_PROCESS_DEBUG_EVENT event + // immediately after launching under DEBUG_ONLY_THIS_PROCESS. + // Attaching with DebugActiveProcess has similar effect. + var err error + var tid, exitCode int + dbp.execPtraceFunc(func() { + tid, exitCode, err = dbp.waitForDebugEvent(waitBlocking) + }) + if err != nil { + return nil, err + } + if tid == 0 { + dbp.postExit() + return nil, ProcessExitedError{Pid: dbp.pid, Status: exitCode} + } + // Suspend all threads so that the call to _ContinueDebugEvent will + // not resume the target. + for _, thread := range dbp.threads { + _, err := _SuspendThread(thread.os.hThread) + if err != nil { + return nil, err + } + } + + dbp.execPtraceFunc(func() { + err = _ContinueDebugEvent(uint32(dbp.pid), uint32(dbp.os.breakThread), _DBG_CONTINUE) + }) + if err != nil { + return nil, err + } + + return initializeDebugProcess(dbp, exepath, false) +} + +// findExePath searches for process pid, and returns its executable path. +func findExePath(pid int) (string, error) { + // Original code suggested different approach (see below). + // Maybe it could be useful in the future. + // + // Find executable path from PID/handle on Windows: + // https://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx + + p, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) + if err != nil { + return "", err + } + defer syscall.CloseHandle(p) + + n := uint32(128) + for { + buf := make([]uint16, int(n)) + err = _QueryFullProcessImageName(p, 0, &buf[0], &n) + switch err { + case syscall.ERROR_INSUFFICIENT_BUFFER: + // try bigger buffer + n *= 2 + // but stop if it gets too big + if n > 10000 { + return "", err + } + case nil: + return syscall.UTF16ToString(buf[:n]), nil + default: + return "", err + } + } +} + +// Attach to an existing process with the given PID. +func Attach(pid int) (*Process, error) { + // TODO: Probably should have SeDebugPrivilege before starting here. + err := _DebugActiveProcess(uint32(pid)) + if err != nil { + return nil, err + } + exepath, err := findExePath(pid) + if err != nil { + return nil, err + } + return newDebugProcess(New(pid), exepath) +} + +// Kill kills the process. +func (dbp *Process) Kill() error { + if dbp.exited { + return nil + } + if !dbp.threads[dbp.pid].Stopped() { + return errors.New("process must be stopped in order to kill it") + } + // TODO: Should not have to ignore failures here, + // but some tests appear to Kill twice causing + // this to fail on second attempt. + _ = syscall.TerminateProcess(dbp.os.hProcess, 1) + dbp.exited = true + return nil +} + +func (dbp *Process) requestManualStop() error { + return _DebugBreakProcess(dbp.os.hProcess) +} + +func (dbp *Process) updateThreadList() error { + // We ignore this request since threads are being + // tracked as they are created/killed in waitForDebugEvent. + return nil +} + +func (dbp *Process) addThread(hThread syscall.Handle, threadID int, attach, suspendNewThreads bool) (*Thread, error) { + if thread, ok := dbp.threads[threadID]; ok { + return thread, nil + } + thread := &Thread{ + ID: threadID, + dbp: dbp, + os: new(OSSpecificDetails), + } + thread.os.hThread = hThread + dbp.threads[threadID] = thread + if dbp.currentThread == nil { + dbp.SwitchThread(thread.ID) + } + if suspendNewThreads { + _, err := _SuspendThread(thread.os.hThread) + if err != nil { + return nil, err + } + } + return thread, nil +} + +func (dbp *Process) parseDebugFrame(exe *pe.File, wg *sync.WaitGroup) { + defer wg.Done() + + debugFrameSec := exe.Section(".debug_frame") + debugInfoSec := exe.Section(".debug_info") + + if debugFrameSec != nil && debugInfoSec != nil { + debugFrame, err := debugFrameSec.Data() + if err != nil && uint32(len(debugFrame)) < debugFrameSec.Size { + fmt.Println("could not get .debug_frame section", err) + os.Exit(1) + } + if 0 < debugFrameSec.VirtualSize && debugFrameSec.VirtualSize < debugFrameSec.Size { + debugFrame = debugFrame[:debugFrameSec.VirtualSize] + } + dat, err := debugInfoSec.Data() + if err != nil { + fmt.Println("could not get .debug_info section", err) + os.Exit(1) + } + dbp.frameEntries = frame.Parse(debugFrame, frame.DwarfEndian(dat)) + } else { + fmt.Println("could not find .debug_frame section in binary") + os.Exit(1) + } +} + +// Borrowed from https://golang.org/src/cmd/internal/objfile/pe.go +func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) { + for _, s := range f.Symbols { + if s.Name != name { + continue + } + if s.SectionNumber <= 0 { + return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) + } + if len(f.Sections) < int(s.SectionNumber) { + return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) + } + return s, nil + } + return nil, fmt.Errorf("no %s symbol found", name) +} + +// Borrowed from https://golang.org/src/cmd/internal/objfile/pe.go +func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { + ssym, err := findPESymbol(f, sname) + if err != nil { + return nil, err + } + esym, err := findPESymbol(f, ename) + if err != nil { + return nil, err + } + if ssym.SectionNumber != esym.SectionNumber { + return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) + } + sect := f.Sections[ssym.SectionNumber-1] + data, err := sect.Data() + if err != nil { + return nil, err + } + return data[ssym.Value:esym.Value], nil +} + +// Borrowed from https://golang.org/src/cmd/internal/objfile/pe.go +func pcln(exe *pe.File) (textStart uint64, symtab, pclntab []byte, err error) { + var imageBase uint64 + switch oh := exe.OptionalHeader.(type) { + case *pe.OptionalHeader32: + imageBase = uint64(oh.ImageBase) + case *pe.OptionalHeader64: + imageBase = oh.ImageBase + default: + return 0, nil, nil, fmt.Errorf("pe file format not recognized") + } + if sect := exe.Section(".text"); sect != nil { + textStart = imageBase + uint64(sect.VirtualAddress) + } + if pclntab, err = loadPETable(exe, "runtime.pclntab", "runtime.epclntab"); err != nil { + // We didn't find the symbols, so look for the names used in 1.3 and earlier. + // TODO: Remove code looking for the old symbols when we no longer care about 1.3. + var err2 error + if pclntab, err2 = loadPETable(exe, "pclntab", "epclntab"); err2 != nil { + return 0, nil, nil, err + } + } + if symtab, err = loadPETable(exe, "runtime.symtab", "runtime.esymtab"); err != nil { + // Same as above. + var err2 error + if symtab, err2 = loadPETable(exe, "symtab", "esymtab"); err2 != nil { + return 0, nil, nil, err + } + } + return textStart, symtab, pclntab, nil +} + +func (dbp *Process) obtainGoSymbols(exe *pe.File, wg *sync.WaitGroup) { + defer wg.Done() + + _, symdat, pclndat, err := pcln(exe) + if err != nil { + fmt.Println("could not get Go symbols", err) + os.Exit(1) + } + + pcln := gosym.NewLineTable(pclndat, uint64(exe.Section(".text").Offset)) + tab, err := gosym.NewTable(symdat, pcln) + if err != nil { + fmt.Println("could not get initialize line table", err) + os.Exit(1) + } + + dbp.goSymTable = tab +} + +func (dbp *Process) parseDebugLineInfo(exe *pe.File, wg *sync.WaitGroup) { + defer wg.Done() + + if sec := exe.Section(".debug_line"); sec != nil { + debugLine, err := sec.Data() + if err != nil && uint32(len(debugLine)) < sec.Size { + fmt.Println("could not get .debug_line section", err) + os.Exit(1) + } + if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size { + debugLine = debugLine[:sec.VirtualSize] + } + dbp.lineInfo = line.Parse(debugLine) + } else { + fmt.Println("could not find .debug_line section in binary") + os.Exit(1) + } +} + +var UnsupportedArchErr = errors.New("unsupported architecture of windows/386 - only windows/amd64 is supported") + +func (dbp *Process) findExecutable(path string) (*pe.File, string, error) { + peFile, err := openExecutablePath(path) + if err != nil { + return nil, path, err + } + if peFile.Machine != pe.IMAGE_FILE_MACHINE_AMD64 { + return nil, path, UnsupportedArchErr + } + dbp.dwarf, err = dwarfFromPE(peFile) + if err != nil { + return nil, path, err + } + return peFile, path, nil +} + +func openExecutablePath(path string) (*pe.File, error) { + f, err := os.OpenFile(path, 0, os.ModePerm) + if err != nil { + return nil, err + } + return pe.NewFile(f) +} + +// Adapted from src/debug/pe/file.go: pe.(*File).DWARF() +func dwarfFromPE(f *pe.File) (*dwarf.Data, error) { + // There are many other DWARF sections, but these + // are the ones the debug/dwarf package uses. + // Don't bother loading others. + var names = [...]string{"abbrev", "info", "line", "str"} + var dat [len(names)][]byte + for i, name := range names { + name = ".debug_" + name + s := f.Section(name) + if s == nil { + continue + } + b, err := s.Data() + if err != nil && uint32(len(b)) < s.Size { + return nil, err + } + if 0 < s.VirtualSize && s.VirtualSize < s.Size { + b = b[:s.VirtualSize] + } + dat[i] = b + } + + abbrev, info, line, str := dat[0], dat[1], dat[2], dat[3] + return dwarf.New(abbrev, nil, nil, info, line, nil, nil, str) +} + +type waitForDebugEventFlags int + +const ( + waitBlocking waitForDebugEventFlags = 1 << iota + waitSuspendNewThreads +) + +func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, exitCode int, err error) { + var debugEvent _DEBUG_EVENT + shouldExit := false + for { + continueStatus := uint32(_DBG_CONTINUE) + var milliseconds uint32 = 0 + if flags&waitBlocking != 0 { + milliseconds = syscall.INFINITE + } + // Wait for a debug event... + err := _WaitForDebugEvent(&debugEvent, milliseconds) + if err != nil { + return 0, 0, err + } + + // ... handle each event kind ... + unionPtr := unsafe.Pointer(&debugEvent.U[0]) + switch debugEvent.DebugEventCode { + case _CREATE_PROCESS_DEBUG_EVENT: + debugInfo := (*_CREATE_PROCESS_DEBUG_INFO)(unionPtr) + hFile := debugInfo.File + if hFile != 0 && hFile != syscall.InvalidHandle { + err = syscall.CloseHandle(hFile) + if err != nil { + return 0, 0, err + } + } + dbp.os.hProcess = debugInfo.Process + _, err = dbp.addThread(debugInfo.Thread, int(debugEvent.ThreadId), false, flags&waitSuspendNewThreads != 0) + if err != nil { + return 0, 0, err + } + break + case _CREATE_THREAD_DEBUG_EVENT: + debugInfo := (*_CREATE_THREAD_DEBUG_INFO)(unionPtr) + _, err = dbp.addThread(debugInfo.Thread, int(debugEvent.ThreadId), false, flags&waitSuspendNewThreads != 0) + if err != nil { + return 0, 0, err + } + break + case _EXIT_THREAD_DEBUG_EVENT: + delete(dbp.threads, int(debugEvent.ThreadId)) + break + case _OUTPUT_DEBUG_STRING_EVENT: + //TODO: Handle debug output strings + break + case _LOAD_DLL_DEBUG_EVENT: + debugInfo := (*_LOAD_DLL_DEBUG_INFO)(unionPtr) + hFile := debugInfo.File + if hFile != 0 && hFile != syscall.InvalidHandle { + err = syscall.CloseHandle(hFile) + if err != nil { + return 0, 0, err + } + } + break + case _UNLOAD_DLL_DEBUG_EVENT: + break + case _RIP_EVENT: + break + case _EXCEPTION_DEBUG_EVENT: + exception := (*_EXCEPTION_DEBUG_INFO)(unionPtr) + tid := int(debugEvent.ThreadId) + + switch code := exception.ExceptionRecord.ExceptionCode; code { + case _EXCEPTION_BREAKPOINT: + + // check if the exception address really is a breakpoint instruction, if + // it isn't we already removed that breakpoint and we can't deal with + // this exception anymore. + atbp := true + if thread, found := dbp.threads[tid]; found { + if data, err := thread.readMemory(exception.ExceptionRecord.ExceptionAddress, dbp.arch.BreakpointSize()); err == nil { + instr := dbp.arch.BreakpointInstruction() + for i := range instr { + if data[i] != instr[i] { + atbp = false + break + } + } + } + if !atbp { + thread.SetPC(uint64(exception.ExceptionRecord.ExceptionAddress)) + } + } + + if atbp { + dbp.os.breakThread = tid + return tid, 0, nil + } else { + continueStatus = _DBG_CONTINUE + } + case _EXCEPTION_SINGLE_STEP: + dbp.os.breakThread = tid + return tid, 0, nil + default: + continueStatus = _DBG_EXCEPTION_NOT_HANDLED + } + case _EXIT_PROCESS_DEBUG_EVENT: + debugInfo := (*_EXIT_PROCESS_DEBUG_INFO)(unionPtr) + exitCode = int(debugInfo.ExitCode) + shouldExit = true + default: + return 0, 0, fmt.Errorf("unknown debug event code: %d", debugEvent.DebugEventCode) + } + + // .. and then continue unless we received an event that indicated we should break into debugger. + err = _ContinueDebugEvent(debugEvent.ProcessId, debugEvent.ThreadId, continueStatus) + if err != nil { + return 0, 0, err + } + + if shouldExit { + return 0, exitCode, nil + } + } +} + +func (dbp *Process) trapWait(pid int) (*Thread, error) { + var err error + var tid, exitCode int + dbp.execPtraceFunc(func() { + tid, exitCode, err = dbp.waitForDebugEvent(waitBlocking) + }) + if err != nil { + return nil, err + } + if tid == 0 { + dbp.postExit() + return nil, ProcessExitedError{Pid: dbp.pid, Status: exitCode} + } + th := dbp.threads[tid] + return th, nil +} + +func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) { + wg.Done() +} + +func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) { + return 0, nil, fmt.Errorf("not implemented: wait") +} + +func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { + // While the debug event that stopped the target was being propagated + // other target threads could generate other debug events. + // After this function we need to know about all the threads + // stopped on a breakpoint. To do that we first suspend all target + // threads and then repeatedly call _ContinueDebugEvent followed by + // waitForDebugEvent in non-blocking mode. + // We need to explicitly call SuspendThread because otherwise the + // call to _ContinueDebugEvent will resume execution of some of the + // target threads. + + err := trapthread.SetCurrentBreakpoint() + if err != nil { + return err + } + + for _, thread := range dbp.threads { + thread.running = false + _, err := _SuspendThread(thread.os.hThread) + if err != nil { + return err + } + } + + for { + var err error + var tid int + dbp.execPtraceFunc(func() { + err = _ContinueDebugEvent(uint32(dbp.pid), uint32(dbp.os.breakThread), _DBG_CONTINUE) + if err == nil { + tid, _, _ = dbp.waitForDebugEvent(waitSuspendNewThreads) + } + }) + if err != nil { + return err + } + if tid == 0 { + break + } + err = dbp.threads[tid].SetCurrentBreakpoint() + if err != nil { + return err + } + } + + return nil +} + +func (dbp *Process) exitGuard(err error) error { + return err +} + +func (dbp *Process) resume() error { + for _, thread := range dbp.threads { + if thread.CurrentBreakpoint != nil { + if err := thread.StepInstruction(); err != nil { + return err + } + thread.CurrentBreakpoint = nil + } + } + + for _, thread := range dbp.threads { + thread.running = true + _, err := _ResumeThread(thread.os.hThread) + if err != nil { + return err + } + } + + return nil +} + +func killProcess(pid int) error { + p, err := os.FindProcess(pid) + if err != nil { + return err + } + return p.Kill() +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/ptrace_darwin.go b/vendor/github.com/derekparker/delve/pkg/proc/ptrace_darwin.go new file mode 100644 index 0000000..c9ed435 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/ptrace_darwin.go @@ -0,0 +1,28 @@ +package proc + +import sys "golang.org/x/sys/unix" + +// PtraceAttach executes the sys.PtraceAttach call. +func PtraceAttach(pid int) error { + return sys.PtraceAttach(pid) +} + +// PtraceDetach executes the PT_DETACH ptrace call. +func PtraceDetach(tid, sig int) error { + return ptrace(sys.PT_DETACH, tid, 1, uintptr(sig)) +} + +// PtraceCont executes the PTRACE_CONT ptrace call. +func PtraceCont(tid, sig int) error { + return ptrace(sys.PTRACE_CONT, tid, 1, 0) +} + +// PtraceSingleStep returns PT_STEP ptrace call. +func PtraceSingleStep(tid int) error { + return ptrace(sys.PT_STEP, tid, 1, 0) +} + +func ptrace(request, pid int, addr uintptr, data uintptr) (err error) { + _, _, err = sys.Syscall6(sys.SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + return +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/ptrace_linux.go b/vendor/github.com/derekparker/delve/pkg/proc/ptrace_linux.go new file mode 100644 index 0000000..402dbb9 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/ptrace_linux.go @@ -0,0 +1,96 @@ +package proc + +import ( + "encoding/binary" + "syscall" + "unsafe" + + sys "golang.org/x/sys/unix" +) + +// PtraceAttach executes the sys.PtraceAttach call. +func PtraceAttach(pid int) error { + return sys.PtraceAttach(pid) +} + +// PtraceDetach calls ptrace(PTRACE_DETACH). +func PtraceDetach(tid, sig int) error { + _, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_DETACH, uintptr(tid), 1, uintptr(sig), 0, 0) + if err != syscall.Errno(0) { + return err + } + return nil +} + +// PtraceCont executes ptrace PTRACE_CONT +func PtraceCont(tid, sig int) error { + return sys.PtraceCont(tid, sig) +} + +// PtraceSingleStep executes ptrace PTRACE_SINGLE_STEP. +func PtraceSingleStep(tid int) error { + return sys.PtraceSingleStep(tid) +} + +// PtracePokeUser execute ptrace PTRACE_POKE_USER. +func PtracePokeUser(tid int, off, addr uintptr) error { + _, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_POKEUSR, uintptr(tid), uintptr(off), uintptr(addr), 0, 0) + if err != syscall.Errno(0) { + return err + } + return nil +} + +// PtracePeekUser execute ptrace PTRACE_PEEK_USER. +func PtracePeekUser(tid int, off uintptr) (uintptr, error) { + var val uintptr + _, _, err := syscall.Syscall6(syscall.SYS_PTRACE, syscall.PTRACE_PEEKUSR, uintptr(tid), uintptr(off), uintptr(unsafe.Pointer(&val)), 0, 0) + if err != syscall.Errno(0) { + return 0, err + } + return val, nil +} + +// PtraceGetRegset returns floating point registers of the specified thread +// using PTRACE. +// See amd64_linux_fetch_inferior_registers in gdb/amd64-linux-nat.c.html +// and amd64_supply_xsave in gdb/amd64-tdep.c.html +// and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture +func PtraceGetRegset(tid int) (regset PtraceXsave, err error) { + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(®set.PtraceFpRegs)), 0, 0) + if err == syscall.Errno(0) { + err = nil + } + + var xstateargs [_X86_XSTATE_MAX_SIZE]byte + iov := sys.Iovec{Base: &xstateargs[0], Len: _X86_XSTATE_MAX_SIZE} + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0) + if err != syscall.Errno(0) { + return + } else { + err = nil + } + + if _XSAVE_HEADER_START+_XSAVE_HEADER_LEN >= iov.Len { + return + } + xsaveheader := xstateargs[_XSAVE_HEADER_START : _XSAVE_HEADER_START+_XSAVE_HEADER_LEN] + xstate_bv := binary.LittleEndian.Uint64(xsaveheader[0:8]) + xcomp_bv := binary.LittleEndian.Uint64(xsaveheader[8:16]) + + if xcomp_bv&(1<<63) != 0 { + // compact format not supported + return + } + + if xstate_bv&(1<<2) == 0 { + // AVX state not present + return + } + + avxstate := xstateargs[_XSAVE_EXTENDED_REGION_START:iov.Len] + regset.AvxState = true + copy(regset.YmmSpace[:], avxstate[:len(regset.YmmSpace)]) + + return +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/ptrace_windows.go b/vendor/github.com/derekparker/delve/pkg/proc/ptrace_windows.go new file mode 100644 index 0000000..96e347b --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/ptrace_windows.go @@ -0,0 +1,13 @@ +package proc + +import ( + "fmt" +) + +func PtraceAttach(pid int) error { + return fmt.Errorf("not implemented: PtraceAttach") +} + +func PtraceDetach(tid, sig int) error { + return _DebugActiveProcessStop(uint32(tid)) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/registers.go b/vendor/github.com/derekparker/delve/pkg/proc/registers.go new file mode 100644 index 0000000..4818ed5 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/registers.go @@ -0,0 +1,231 @@ +package proc + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "math" + "os" + "strings" +) + +// Registers is an interface for a generic register type. The +// interface encapsulates the generic values / actions +// we need independent of arch. The concrete register types +// will be different depending on OS/Arch. +type Registers interface { + PC() uint64 + SP() uint64 + BP() uint64 + CX() uint64 + TLS() uint64 + Get(int) (uint64, error) + SetPC(*Thread, uint64) error + Slice() []Register +} + +type Register struct { + Name string + Value string +} + +func appendWordReg(regs []Register, name string, value uint16) []Register { + return append(regs, Register{name, fmt.Sprintf("%#04x", value)}) +} + +func appendDwordReg(regs []Register, name string, value uint32) []Register { + return append(regs, Register{name, fmt.Sprintf("%#08x", value)}) +} + +func appendQwordReg(regs []Register, name string, value uint64) []Register { + return append(regs, Register{name, fmt.Sprintf("%#016x", value)}) +} + +func appendFlagReg(regs []Register, name string, value uint64, descr flagRegisterDescr, size int) []Register { + return append(regs, Register{name, descr.Describe(value, size)}) +} + +func appendX87Reg(regs []Register, index int, exponent uint16, mantissa uint64) []Register { + var f float64 + fset := false + + const ( + _SIGNBIT = 1 << 15 + _EXP_BIAS = (1 << 14) - 1 // 2^(n-1) - 1 = 16383 + _SPECIALEXP = (1 << 15) - 1 // all bits set + _HIGHBIT = 1 << 63 + _QUIETBIT = 1 << 62 + ) + + sign := 1.0 + if exponent&_SIGNBIT != 0 { + sign = -1.0 + } + exponent &= ^uint16(_SIGNBIT) + + NaN := math.NaN() + Inf := math.Inf(+1) + + switch exponent { + case 0: + switch { + case mantissa == 0: + f = sign * 0.0 + fset = true + case mantissa&_HIGHBIT != 0: + f = NaN + fset = true + } + case _SPECIALEXP: + switch { + case mantissa&_HIGHBIT == 0: + f = sign * Inf + fset = true + default: + f = NaN // signaling NaN + fset = true + } + default: + if mantissa&_HIGHBIT == 0 { + f = NaN + fset = true + } + } + + if !fset { + significand := float64(mantissa) / (1 << 63) + f = sign * math.Ldexp(significand, int(exponent-_EXP_BIAS)) + } + + return append(regs, Register{fmt.Sprintf("ST(%d)", index), fmt.Sprintf("%#04x%016x\t%g", exponent, mantissa, f)}) +} + +func appendSSEReg(regs []Register, name string, xmm []byte) []Register { + buf := bytes.NewReader(xmm) + + var out bytes.Buffer + var vi [16]uint8 + for i := range vi { + binary.Read(buf, binary.LittleEndian, &vi[i]) + } + + fmt.Fprintf(&out, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8], vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0]) + + fmt.Fprintf(&out, "\tv2_int={ %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x }", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0], vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8]) + + fmt.Fprintf(&out, "\tv4_int={ %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x }", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4], vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12]) + + fmt.Fprintf(&out, "\tv8_int={ %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x }", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6], vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14]) + + fmt.Fprintf(&out, "\tv16_int={ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x }", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7], vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15]) + + buf.Seek(0, os.SEEK_SET) + var v2 [2]float64 + for i := range v2 { + binary.Read(buf, binary.LittleEndian, &v2[i]) + } + fmt.Fprintf(&out, "\tv2_float={ %g %g }", v2[0], v2[1]) + + buf.Seek(0, os.SEEK_SET) + var v4 [4]float32 + for i := range v4 { + binary.Read(buf, binary.LittleEndian, &v4[i]) + } + fmt.Fprintf(&out, "\tv4_float={ %g %g %g %g }", v4[0], v4[1], v4[2], v4[3]) + + return append(regs, Register{name, out.String()}) +} + +var UnknownRegisterError = errors.New("unknown register") + +// Registers obtains register values from the debugged process. +func (t *Thread) Registers(floatingPoint bool) (Registers, error) { + return registers(t, floatingPoint) +} + +// PC returns the current PC for this thread. +func (t *Thread) PC() (uint64, error) { + regs, err := t.Registers(false) + if err != nil { + return 0, err + } + return regs.PC(), nil +} + +type flagRegisterDescr []flagDescr +type flagDescr struct { + name string + mask uint64 +} + +var mxcsrDescription flagRegisterDescr = []flagDescr{ + {"FZ", 1 << 15}, + {"RZ/RN", 1<<14 | 1<<13}, + {"PM", 1 << 12}, + {"UM", 1 << 11}, + {"OM", 1 << 10}, + {"ZM", 1 << 9}, + {"DM", 1 << 8}, + {"IM", 1 << 7}, + {"DAZ", 1 << 6}, + {"PE", 1 << 5}, + {"UE", 1 << 4}, + {"OE", 1 << 3}, + {"ZE", 1 << 2}, + {"DE", 1 << 1}, + {"IE", 1 << 0}, +} + +var eflagsDescription flagRegisterDescr = []flagDescr{ + {"CF", 1 << 0}, + {"", 1 << 1}, + {"PF", 1 << 2}, + {"AF", 1 << 4}, + {"ZF", 1 << 6}, + {"SF", 1 << 7}, + {"TF", 1 << 8}, + {"IF", 1 << 9}, + {"DF", 1 << 10}, + {"OF", 1 << 11}, + {"IOPL", 1<<12 | 1<<13}, + {"NT", 1 << 14}, + {"RF", 1 << 16}, + {"VM", 1 << 17}, + {"AC", 1 << 18}, + {"VIF", 1 << 19}, + {"VIP", 1 << 20}, + {"ID", 1 << 21}, +} + +func (descr flagRegisterDescr) Mask() uint64 { + var r uint64 + for _, f := range descr { + r = r | f.mask + } + return r +} + +func (descr flagRegisterDescr) Describe(reg uint64, bitsize int) string { + var r []string + for _, f := range descr { + if f.name == "" { + continue + } + // rbm is f.mask with only the right-most bit set: + // 0001 1100 -> 0000 0100 + rbm := f.mask & -f.mask + if rbm == f.mask { + if reg&f.mask != 0 { + r = append(r, f.name) + } + } else { + x := (reg & f.mask) >> uint64(math.Log2(float64(rbm))) + r = append(r, fmt.Sprintf("%s=%x", f.name, x)) + } + } + if reg & ^descr.Mask() != 0 { + r = append(r, fmt.Sprintf("unknown_flags=%x", reg&^descr.Mask())) + } + return fmt.Sprintf("%#0*x\t[%s]", bitsize/4, reg, strings.Join(r, " ")) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/registers_darwin_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/registers_darwin_amd64.go new file mode 100644 index 0000000..4b3f8f1 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/registers_darwin_amd64.go @@ -0,0 +1,367 @@ +package proc + +// #include "threads_darwin.h" +import "C" +import ( + "encoding/binary" + "fmt" + "rsc.io/x86/x86asm" + "unsafe" +) + +// Regs represents CPU registers on an AMD64 processor. +type Regs struct { + rax uint64 + rbx uint64 + rcx uint64 + rdx uint64 + rdi uint64 + rsi uint64 + rbp uint64 + rsp uint64 + r8 uint64 + r9 uint64 + r10 uint64 + r11 uint64 + r12 uint64 + r13 uint64 + r14 uint64 + r15 uint64 + rip uint64 + rflags uint64 + cs uint64 + fs uint64 + gs uint64 + gsBase uint64 + fpregs []Register +} + +func (r *Regs) Slice() []Register { + var regs = []struct { + k string + v uint64 + }{ + {"Rip", r.rip}, + {"Rsp", r.rsp}, + {"Rax", r.rax}, + {"Rbx", r.rbx}, + {"Rcx", r.rcx}, + {"Rdx", r.rdx}, + {"Rdi", r.rdi}, + {"Rsi", r.rsi}, + {"Rbp", r.rbp}, + {"R8", r.r8}, + {"R9", r.r9}, + {"R10", r.r10}, + {"R11", r.r11}, + {"R12", r.r12}, + {"R13", r.r13}, + {"R14", r.r14}, + {"R15", r.r15}, + {"Rflags", r.rflags}, + {"Cs", r.cs}, + {"Fs", r.fs}, + {"Gs", r.gs}, + {"Gs_base", r.gsBase}, + } + out := make([]Register, 0, len(regs)+len(r.fpregs)) + for _, reg := range regs { + if reg.k == "Rflags" { + out = appendFlagReg(out, reg.k, reg.v, eflagsDescription, 64) + } else { + out = appendQwordReg(out, reg.k, reg.v) + } + } + out = append(out, r.fpregs...) + return out +} + +// PC returns the current program counter +// i.e. the RIP CPU register. +func (r *Regs) PC() uint64 { + return r.rip +} + +// SP returns the stack pointer location, +// i.e. the RSP register. +func (r *Regs) SP() uint64 { + return r.rsp +} + +func (r *Regs) BP() uint64 { + return r.rbp +} + +// CX returns the value of the RCX register. +func (r *Regs) CX() uint64 { + return r.rcx +} + +// TLS returns the value of the register +// that contains the location of the thread +// local storage segment. +func (r *Regs) TLS() uint64 { + return r.gsBase +} + +// SetPC sets the RIP register to the value specified by `pc`. +func (r *Regs) SetPC(thread *Thread, pc uint64) error { + kret := C.set_pc(thread.os.threadAct, C.uint64_t(pc)) + if kret != C.KERN_SUCCESS { + return fmt.Errorf("could not set pc") + } + return nil +} + +func (r *Regs) Get(n int) (uint64, error) { + reg := x86asm.Reg(n) + const ( + mask8 = 0x000f + mask16 = 0x00ff + mask32 = 0xffff + ) + + switch reg { + // 8-bit + case x86asm.AL: + return r.rax & mask8, nil + case x86asm.CL: + return r.rcx & mask8, nil + case x86asm.DL: + return r.rdx & mask8, nil + case x86asm.BL: + return r.rbx & mask8, nil + case x86asm.AH: + return (r.rax >> 8) & mask8, nil + case x86asm.CH: + return (r.rcx >> 8) & mask8, nil + case x86asm.DH: + return (r.rdx >> 8) & mask8, nil + case x86asm.BH: + return (r.rbx >> 8) & mask8, nil + case x86asm.SPB: + return r.rsp & mask8, nil + case x86asm.BPB: + return r.rbp & mask8, nil + case x86asm.SIB: + return r.rsi & mask8, nil + case x86asm.DIB: + return r.rdi & mask8, nil + case x86asm.R8B: + return r.r8 & mask8, nil + case x86asm.R9B: + return r.r9 & mask8, nil + case x86asm.R10B: + return r.r10 & mask8, nil + case x86asm.R11B: + return r.r11 & mask8, nil + case x86asm.R12B: + return r.r12 & mask8, nil + case x86asm.R13B: + return r.r13 & mask8, nil + case x86asm.R14B: + return r.r14 & mask8, nil + case x86asm.R15B: + return r.r15 & mask8, nil + + // 16-bit + case x86asm.AX: + return r.rax & mask16, nil + case x86asm.CX: + return r.rcx & mask16, nil + case x86asm.DX: + return r.rdx & mask16, nil + case x86asm.BX: + return r.rbx & mask16, nil + case x86asm.SP: + return r.rsp & mask16, nil + case x86asm.BP: + return r.rbp & mask16, nil + case x86asm.SI: + return r.rsi & mask16, nil + case x86asm.DI: + return r.rdi & mask16, nil + case x86asm.R8W: + return r.r8 & mask16, nil + case x86asm.R9W: + return r.r9 & mask16, nil + case x86asm.R10W: + return r.r10 & mask16, nil + case x86asm.R11W: + return r.r11 & mask16, nil + case x86asm.R12W: + return r.r12 & mask16, nil + case x86asm.R13W: + return r.r13 & mask16, nil + case x86asm.R14W: + return r.r14 & mask16, nil + case x86asm.R15W: + return r.r15 & mask16, nil + + // 32-bit + case x86asm.EAX: + return r.rax & mask32, nil + case x86asm.ECX: + return r.rcx & mask32, nil + case x86asm.EDX: + return r.rdx & mask32, nil + case x86asm.EBX: + return r.rbx & mask32, nil + case x86asm.ESP: + return r.rsp & mask32, nil + case x86asm.EBP: + return r.rbp & mask32, nil + case x86asm.ESI: + return r.rsi & mask32, nil + case x86asm.EDI: + return r.rdi & mask32, nil + case x86asm.R8L: + return r.r8 & mask32, nil + case x86asm.R9L: + return r.r9 & mask32, nil + case x86asm.R10L: + return r.r10 & mask32, nil + case x86asm.R11L: + return r.r11 & mask32, nil + case x86asm.R12L: + return r.r12 & mask32, nil + case x86asm.R13L: + return r.r13 & mask32, nil + case x86asm.R14L: + return r.r14 & mask32, nil + case x86asm.R15L: + return r.r15 & mask32, nil + + // 64-bit + case x86asm.RAX: + return r.rax, nil + case x86asm.RCX: + return r.rcx, nil + case x86asm.RDX: + return r.rdx, nil + case x86asm.RBX: + return r.rbx, nil + case x86asm.RSP: + return r.rsp, nil + case x86asm.RBP: + return r.rbp, nil + case x86asm.RSI: + return r.rsi, nil + case x86asm.RDI: + return r.rdi, nil + case x86asm.R8: + return r.r8, nil + case x86asm.R9: + return r.r9, nil + case x86asm.R10: + return r.r10, nil + case x86asm.R11: + return r.r11, nil + case x86asm.R12: + return r.r12, nil + case x86asm.R13: + return r.r13, nil + case x86asm.R14: + return r.r14, nil + case x86asm.R15: + return r.r15, nil + } + + return 0, UnknownRegisterError +} + +func registers(thread *Thread, floatingPoint bool) (Registers, error) { + var state C.x86_thread_state64_t + var identity C.thread_identifier_info_data_t + kret := C.get_registers(C.mach_port_name_t(thread.os.threadAct), &state) + if kret != C.KERN_SUCCESS { + return nil, fmt.Errorf("could not get registers") + } + kret = C.get_identity(C.mach_port_name_t(thread.os.threadAct), &identity) + if kret != C.KERN_SUCCESS { + return nil, fmt.Errorf("could not get thread identity informations") + } + /* + thread_identifier_info::thread_handle contains the base of the + thread-specific data area, which on x86 and x86_64 is the thread’s base + address of the %gs segment. 10.9.2 xnu-2422.90.20/osfmk/kern/thread.c + thread_info_internal() gets the value from + machine_thread::cthread_self, which is the same value used to set the + %gs base in xnu-2422.90.20/osfmk/i386/pcb_native.c + act_machine_switch_pcb(). + -- + comment copied from chromium's crashpad + https://chromium.googlesource.com/crashpad/crashpad/+/master/snapshot/mac/process_reader.cc + */ + regs := &Regs{ + rax: uint64(state.__rax), + rbx: uint64(state.__rbx), + rcx: uint64(state.__rcx), + rdx: uint64(state.__rdx), + rdi: uint64(state.__rdi), + rsi: uint64(state.__rsi), + rbp: uint64(state.__rbp), + rsp: uint64(state.__rsp), + r8: uint64(state.__r8), + r9: uint64(state.__r9), + r10: uint64(state.__r10), + r11: uint64(state.__r11), + r12: uint64(state.__r12), + r13: uint64(state.__r13), + r14: uint64(state.__r14), + r15: uint64(state.__r15), + rip: uint64(state.__rip), + rflags: uint64(state.__rflags), + cs: uint64(state.__cs), + fs: uint64(state.__fs), + gs: uint64(state.__gs), + gsBase: uint64(identity.thread_handle), + } + + if floatingPoint { + // https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/thread_status.h?txt + var fpstate C.x86_float_state64_t + kret = C.get_fpu_registers(C.mach_port_name_t(thread.os.threadAct), &fpstate) + if kret != C.KERN_SUCCESS { + return nil, fmt.Errorf("could not get floating point registers") + } + + regs.fpregs = appendWordReg(regs.fpregs, "CW", *((*uint16)(unsafe.Pointer(&fpstate.__fpu_fcw)))) + regs.fpregs = appendWordReg(regs.fpregs, "SW", *((*uint16)(unsafe.Pointer(&fpstate.__fpu_fsw)))) + regs.fpregs = appendWordReg(regs.fpregs, "TW", uint16(fpstate.__fpu_ftw)) + regs.fpregs = appendWordReg(regs.fpregs, "FOP", uint16(fpstate.__fpu_fop)) + regs.fpregs = appendQwordReg(regs.fpregs, "FIP", uint64(fpstate.__fpu_cs)<<32|uint64(fpstate.__fpu_ip)) + regs.fpregs = appendQwordReg(regs.fpregs, "FDP", uint64(fpstate.__fpu_ds)<<32|uint64(fpstate.__fpu_dp)) + + for i, st := range []*C.char{&fpstate.__fpu_stmm0.__mmst_reg[0], &fpstate.__fpu_stmm1.__mmst_reg[0], &fpstate.__fpu_stmm2.__mmst_reg[0], &fpstate.__fpu_stmm3.__mmst_reg[0], &fpstate.__fpu_stmm4.__mmst_reg[0], &fpstate.__fpu_stmm5.__mmst_reg[0], &fpstate.__fpu_stmm6.__mmst_reg[0], &fpstate.__fpu_stmm7.__mmst_reg[0]} { + stb := C.GoBytes(unsafe.Pointer(st), 10) + mantissa := binary.LittleEndian.Uint64(stb[:8]) + exponent := binary.LittleEndian.Uint16(stb[8:]) + regs.fpregs = appendX87Reg(regs.fpregs, i, exponent, mantissa) + } + + regs.fpregs = appendFlagReg(regs.fpregs, "MXCSR", uint64(fpstate.__fpu_mxcsr), mxcsrDescription, 32) + regs.fpregs = appendDwordReg(regs.fpregs, "MXCSR_MASK", uint32(fpstate.__fpu_mxcsrmask)) + + for i, xmm := range []*C.char{&fpstate.__fpu_xmm0.__xmm_reg[0], &fpstate.__fpu_xmm1.__xmm_reg[0], &fpstate.__fpu_xmm2.__xmm_reg[0], &fpstate.__fpu_xmm3.__xmm_reg[0], &fpstate.__fpu_xmm4.__xmm_reg[0], &fpstate.__fpu_xmm5.__xmm_reg[0], &fpstate.__fpu_xmm6.__xmm_reg[0], &fpstate.__fpu_xmm7.__xmm_reg[0], &fpstate.__fpu_xmm8.__xmm_reg[0], &fpstate.__fpu_xmm9.__xmm_reg[0], &fpstate.__fpu_xmm10.__xmm_reg[0], &fpstate.__fpu_xmm11.__xmm_reg[0], &fpstate.__fpu_xmm12.__xmm_reg[0], &fpstate.__fpu_xmm13.__xmm_reg[0], &fpstate.__fpu_xmm14.__xmm_reg[0], &fpstate.__fpu_xmm15.__xmm_reg[0]} { + regs.fpregs = appendSSEReg(regs.fpregs, fmt.Sprintf("XMM%d", i), C.GoBytes(unsafe.Pointer(xmm), 16)) + } + } + return regs, nil +} + +func (thread *Thread) saveRegisters() (Registers, error) { + kret := C.get_registers(C.mach_port_name_t(thread.os.threadAct), &thread.os.registers) + if kret != C.KERN_SUCCESS { + return nil, fmt.Errorf("could not save register contents") + } + return &Regs{rip: uint64(thread.os.registers.__rip), rsp: uint64(thread.os.registers.__rsp)}, nil +} + +func (thread *Thread) restoreRegisters() error { + kret := C.set_registers(C.mach_port_name_t(thread.os.threadAct), &thread.os.registers) + if kret != C.KERN_SUCCESS { + return fmt.Errorf("could not save register contents") + } + return nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/registers_linux_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/registers_linux_amd64.go new file mode 100644 index 0000000..4b7f6a7 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/registers_linux_amd64.go @@ -0,0 +1,329 @@ +package proc + +import ( + "fmt" + + "rsc.io/x86/x86asm" + + sys "golang.org/x/sys/unix" +) + +// Regs is a wrapper for sys.PtraceRegs. +type Regs struct { + regs *sys.PtraceRegs + fpregs []Register +} + +func (r *Regs) Slice() []Register { + var regs = []struct { + k string + v uint64 + }{ + {"Rip", r.regs.Rip}, + {"Rsp", r.regs.Rsp}, + {"Rax", r.regs.Rax}, + {"Rbx", r.regs.Rbx}, + {"Rcx", r.regs.Rcx}, + {"Rdx", r.regs.Rdx}, + {"Rdi", r.regs.Rdi}, + {"Rsi", r.regs.Rsi}, + {"Rbp", r.regs.Rbp}, + {"R8", r.regs.R8}, + {"R9", r.regs.R9}, + {"R10", r.regs.R10}, + {"R11", r.regs.R11}, + {"R12", r.regs.R12}, + {"R13", r.regs.R13}, + {"R14", r.regs.R14}, + {"R15", r.regs.R15}, + {"Orig_rax", r.regs.Orig_rax}, + {"Cs", r.regs.Cs}, + {"Eflags", r.regs.Eflags}, + {"Ss", r.regs.Ss}, + {"Fs_base", r.regs.Fs_base}, + {"Gs_base", r.regs.Gs_base}, + {"Ds", r.regs.Ds}, + {"Es", r.regs.Es}, + {"Fs", r.regs.Fs}, + {"Gs", r.regs.Gs}, + } + out := make([]Register, 0, len(regs)+len(r.fpregs)) + for _, reg := range regs { + if reg.k == "Eflags" { + out = appendFlagReg(out, reg.k, reg.v, eflagsDescription, 64) + } else { + out = appendQwordReg(out, reg.k, reg.v) + } + } + out = append(out, r.fpregs...) + return out +} + +// PC returns the value of RIP register. +func (r *Regs) PC() uint64 { + return r.regs.PC() +} + +// SP returns the value of RSP register. +func (r *Regs) SP() uint64 { + return r.regs.Rsp +} + +func (r *Regs) BP() uint64 { + return r.regs.Rbp +} + +// CX returns the value of RCX register. +func (r *Regs) CX() uint64 { + return r.regs.Rcx +} + +// TLS returns the address of the thread +// local storage memory segment. +func (r *Regs) TLS() uint64 { + return r.regs.Fs_base +} + +// SetPC sets RIP to the value specified by 'pc'. +func (r *Regs) SetPC(thread *Thread, pc uint64) (err error) { + r.regs.SetPC(pc) + thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, r.regs) }) + return +} + +func (r *Regs) Get(n int) (uint64, error) { + reg := x86asm.Reg(n) + const ( + mask8 = 0x000f + mask16 = 0x00ff + mask32 = 0xffff + ) + + switch reg { + // 8-bit + case x86asm.AL: + return r.regs.Rax & mask8, nil + case x86asm.CL: + return r.regs.Rcx & mask8, nil + case x86asm.DL: + return r.regs.Rdx & mask8, nil + case x86asm.BL: + return r.regs.Rbx & mask8, nil + case x86asm.AH: + return (r.regs.Rax >> 8) & mask8, nil + case x86asm.CH: + return (r.regs.Rcx >> 8) & mask8, nil + case x86asm.DH: + return (r.regs.Rdx >> 8) & mask8, nil + case x86asm.BH: + return (r.regs.Rbx >> 8) & mask8, nil + case x86asm.SPB: + return r.regs.Rsp & mask8, nil + case x86asm.BPB: + return r.regs.Rbp & mask8, nil + case x86asm.SIB: + return r.regs.Rsi & mask8, nil + case x86asm.DIB: + return r.regs.Rdi & mask8, nil + case x86asm.R8B: + return r.regs.R8 & mask8, nil + case x86asm.R9B: + return r.regs.R9 & mask8, nil + case x86asm.R10B: + return r.regs.R10 & mask8, nil + case x86asm.R11B: + return r.regs.R11 & mask8, nil + case x86asm.R12B: + return r.regs.R12 & mask8, nil + case x86asm.R13B: + return r.regs.R13 & mask8, nil + case x86asm.R14B: + return r.regs.R14 & mask8, nil + case x86asm.R15B: + return r.regs.R15 & mask8, nil + + // 16-bit + case x86asm.AX: + return r.regs.Rax & mask16, nil + case x86asm.CX: + return r.regs.Rcx & mask16, nil + case x86asm.DX: + return r.regs.Rdx & mask16, nil + case x86asm.BX: + return r.regs.Rbx & mask16, nil + case x86asm.SP: + return r.regs.Rsp & mask16, nil + case x86asm.BP: + return r.regs.Rbp & mask16, nil + case x86asm.SI: + return r.regs.Rsi & mask16, nil + case x86asm.DI: + return r.regs.Rdi & mask16, nil + case x86asm.R8W: + return r.regs.R8 & mask16, nil + case x86asm.R9W: + return r.regs.R9 & mask16, nil + case x86asm.R10W: + return r.regs.R10 & mask16, nil + case x86asm.R11W: + return r.regs.R11 & mask16, nil + case x86asm.R12W: + return r.regs.R12 & mask16, nil + case x86asm.R13W: + return r.regs.R13 & mask16, nil + case x86asm.R14W: + return r.regs.R14 & mask16, nil + case x86asm.R15W: + return r.regs.R15 & mask16, nil + + // 32-bit + case x86asm.EAX: + return r.regs.Rax & mask32, nil + case x86asm.ECX: + return r.regs.Rcx & mask32, nil + case x86asm.EDX: + return r.regs.Rdx & mask32, nil + case x86asm.EBX: + return r.regs.Rbx & mask32, nil + case x86asm.ESP: + return r.regs.Rsp & mask32, nil + case x86asm.EBP: + return r.regs.Rbp & mask32, nil + case x86asm.ESI: + return r.regs.Rsi & mask32, nil + case x86asm.EDI: + return r.regs.Rdi & mask32, nil + case x86asm.R8L: + return r.regs.R8 & mask32, nil + case x86asm.R9L: + return r.regs.R9 & mask32, nil + case x86asm.R10L: + return r.regs.R10 & mask32, nil + case x86asm.R11L: + return r.regs.R11 & mask32, nil + case x86asm.R12L: + return r.regs.R12 & mask32, nil + case x86asm.R13L: + return r.regs.R13 & mask32, nil + case x86asm.R14L: + return r.regs.R14 & mask32, nil + case x86asm.R15L: + return r.regs.R15 & mask32, nil + + // 64-bit + case x86asm.RAX: + return r.regs.Rax, nil + case x86asm.RCX: + return r.regs.Rcx, nil + case x86asm.RDX: + return r.regs.Rdx, nil + case x86asm.RBX: + return r.regs.Rbx, nil + case x86asm.RSP: + return r.regs.Rsp, nil + case x86asm.RBP: + return r.regs.Rbp, nil + case x86asm.RSI: + return r.regs.Rsi, nil + case x86asm.RDI: + return r.regs.Rdi, nil + case x86asm.R8: + return r.regs.R8, nil + case x86asm.R9: + return r.regs.R9, nil + case x86asm.R10: + return r.regs.R10, nil + case x86asm.R11: + return r.regs.R11, nil + case x86asm.R12: + return r.regs.R12, nil + case x86asm.R13: + return r.regs.R13, nil + case x86asm.R14: + return r.regs.R14, nil + case x86asm.R15: + return r.regs.R15, nil + } + + return 0, UnknownRegisterError +} + +func registers(thread *Thread, floatingPoint bool) (Registers, error) { + var ( + regs sys.PtraceRegs + err error + ) + thread.dbp.execPtraceFunc(func() { err = sys.PtraceGetRegs(thread.ID, ®s) }) + if err != nil { + return nil, err + } + r := &Regs{®s, nil} + if floatingPoint { + r.fpregs, err = thread.fpRegisters() + if err != nil { + return nil, err + } + } + return r, nil +} + +// tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h +type PtraceFpRegs struct { + Cwd uint16 + Swd uint16 + Ftw uint16 + Fop uint16 + Rip uint64 + Rdp uint64 + Mxcsr uint32 + MxcrMask uint32 + StSpace [32]uint32 + XmmSpace [256]byte + padding [24]uint32 +} + +type PtraceXsave struct { + PtraceFpRegs + AvxState bool // contains AVX state + YmmSpace [256]byte +} + +const ( + _X86_XSTATE_MAX_SIZE = 2688 + _NT_X86_XSTATE = 0x202 + + _XSAVE_HEADER_START = 512 + _XSAVE_HEADER_LEN = 64 + _XSAVE_EXTENDED_REGION_START = 576 + _XSAVE_SSE_REGION_LEN = 416 +) + +func (thread *Thread) fpRegisters() (regs []Register, err error) { + var fpregs PtraceXsave + thread.dbp.execPtraceFunc(func() { fpregs, err = PtraceGetRegset(thread.ID) }) + + // x87 registers + regs = appendWordReg(regs, "CW", fpregs.Cwd) + regs = appendWordReg(regs, "SW", fpregs.Swd) + regs = appendWordReg(regs, "TW", fpregs.Ftw) + regs = appendWordReg(regs, "FOP", fpregs.Fop) + regs = appendQwordReg(regs, "FIP", fpregs.Rip) + regs = appendQwordReg(regs, "FDP", fpregs.Rdp) + + for i := 0; i < len(fpregs.StSpace); i += 4 { + regs = appendX87Reg(regs, i/4, uint16(fpregs.StSpace[i+2]), uint64(fpregs.StSpace[i+1])<<32|uint64(fpregs.StSpace[i])) + } + + // SSE registers + regs = appendFlagReg(regs, "MXCSR", uint64(fpregs.Mxcsr), mxcsrDescription, 32) + regs = appendDwordReg(regs, "MXCSR_MASK", fpregs.MxcrMask) + + for i := 0; i < len(fpregs.XmmSpace); i += 16 { + regs = appendSSEReg(regs, fmt.Sprintf("XMM%d", i/16), fpregs.XmmSpace[i:i+16]) + if fpregs.AvxState { + regs = appendSSEReg(regs, fmt.Sprintf("YMM%d", i/16), fpregs.YmmSpace[i:i+16]) + } + } + + return +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/registers_windows_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/registers_windows_amd64.go new file mode 100644 index 0000000..23ff6e8 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/registers_windows_amd64.go @@ -0,0 +1,351 @@ +package proc + +import ( + "fmt" + "rsc.io/x86/x86asm" + "unsafe" +) + +// Regs represents CPU registers on an AMD64 processor. +type Regs struct { + rax uint64 + rbx uint64 + rcx uint64 + rdx uint64 + rdi uint64 + rsi uint64 + rbp uint64 + rsp uint64 + r8 uint64 + r9 uint64 + r10 uint64 + r11 uint64 + r12 uint64 + r13 uint64 + r14 uint64 + r15 uint64 + rip uint64 + eflags uint64 + cs uint64 + fs uint64 + gs uint64 + tls uint64 + fltSave *_XMM_SAVE_AREA32 +} + +func (r *Regs) Slice() []Register { + var regs = []struct { + k string + v uint64 + }{ + {"Rip", r.rip}, + {"Rsp", r.rsp}, + {"Rax", r.rax}, + {"Rbx", r.rbx}, + {"Rcx", r.rcx}, + {"Rdx", r.rdx}, + {"Rdi", r.rdi}, + {"Rsi", r.rsi}, + {"Rbp", r.rbp}, + {"R8", r.r8}, + {"R9", r.r9}, + {"R10", r.r10}, + {"R11", r.r11}, + {"R12", r.r12}, + {"R13", r.r13}, + {"R14", r.r14}, + {"R15", r.r15}, + {"Eflags", r.eflags}, + {"Cs", r.cs}, + {"Fs", r.fs}, + {"Gs", r.gs}, + {"TLS", r.tls}, + } + outlen := len(regs) + if r.fltSave != nil { + outlen += 6 + 8 + 2 + 16 + } + out := make([]Register, 0, outlen) + for _, reg := range regs { + if reg.k == "Eflags" { + out = append(out, Register{reg.k, eflagsDescription.Describe(reg.v, 64)}) + } else { + out = appendQwordReg(out, reg.k, reg.v) + } + } + if r.fltSave != nil { + out = appendWordReg(out, "CW", r.fltSave.ControlWord) + out = appendWordReg(out, "SW", r.fltSave.StatusWord) + out = appendWordReg(out, "TW", uint16(r.fltSave.TagWord)) + out = appendWordReg(out, "FOP", r.fltSave.ErrorOpcode) + out = appendQwordReg(out, "FIP", uint64(r.fltSave.ErrorSelector)<<32|uint64(r.fltSave.ErrorOffset)) + out = appendQwordReg(out, "FDP", uint64(r.fltSave.DataSelector)<<32|uint64(r.fltSave.DataOffset)) + + for i := range r.fltSave.FloatRegisters { + out = appendX87Reg(out, i, uint16(r.fltSave.FloatRegisters[i].High), r.fltSave.FloatRegisters[i].Low) + } + + out = appendFlagReg(out, "MXCSR", uint64(r.fltSave.MxCsr), mxcsrDescription, 32) + out = appendDwordReg(out, "MXCSR_MASK", r.fltSave.MxCsr_Mask) + + for i := 0; i < len(r.fltSave.XmmRegisters); i += 16 { + out = appendSSEReg(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16]) + } + } + return out +} + +// PC returns the current program counter +// i.e. the RIP CPU register. +func (r *Regs) PC() uint64 { + return r.rip +} + +// SP returns the stack pointer location, +// i.e. the RSP register. +func (r *Regs) SP() uint64 { + return r.rsp +} + +func (r *Regs) BP() uint64 { + return r.rbp +} + +// CX returns the value of the RCX register. +func (r *Regs) CX() uint64 { + return r.rcx +} + +// TLS returns the value of the register +// that contains the location of the thread +// local storage segment. +func (r *Regs) TLS() uint64 { + return r.tls +} + +// SetPC sets the RIP register to the value specified by `pc`. +func (r *Regs) SetPC(thread *Thread, pc uint64) error { + context := newCONTEXT() + context.ContextFlags = _CONTEXT_ALL + + err := _GetThreadContext(thread.os.hThread, context) + if err != nil { + return err + } + + context.Rip = pc + + return _SetThreadContext(thread.os.hThread, context) +} + +func (r *Regs) Get(n int) (uint64, error) { + reg := x86asm.Reg(n) + const ( + mask8 = 0x000f + mask16 = 0x00ff + mask32 = 0xffff + ) + + switch reg { + // 8-bit + case x86asm.AL: + return r.rax & mask8, nil + case x86asm.CL: + return r.rcx & mask8, nil + case x86asm.DL: + return r.rdx & mask8, nil + case x86asm.BL: + return r.rbx & mask8, nil + case x86asm.AH: + return (r.rax >> 8) & mask8, nil + case x86asm.CH: + return (r.rcx >> 8) & mask8, nil + case x86asm.DH: + return (r.rdx >> 8) & mask8, nil + case x86asm.BH: + return (r.rbx >> 8) & mask8, nil + case x86asm.SPB: + return r.rsp & mask8, nil + case x86asm.BPB: + return r.rbp & mask8, nil + case x86asm.SIB: + return r.rsi & mask8, nil + case x86asm.DIB: + return r.rdi & mask8, nil + case x86asm.R8B: + return r.r8 & mask8, nil + case x86asm.R9B: + return r.r9 & mask8, nil + case x86asm.R10B: + return r.r10 & mask8, nil + case x86asm.R11B: + return r.r11 & mask8, nil + case x86asm.R12B: + return r.r12 & mask8, nil + case x86asm.R13B: + return r.r13 & mask8, nil + case x86asm.R14B: + return r.r14 & mask8, nil + case x86asm.R15B: + return r.r15 & mask8, nil + + // 16-bit + case x86asm.AX: + return r.rax & mask16, nil + case x86asm.CX: + return r.rcx & mask16, nil + case x86asm.DX: + return r.rdx & mask16, nil + case x86asm.BX: + return r.rbx & mask16, nil + case x86asm.SP: + return r.rsp & mask16, nil + case x86asm.BP: + return r.rbp & mask16, nil + case x86asm.SI: + return r.rsi & mask16, nil + case x86asm.DI: + return r.rdi & mask16, nil + case x86asm.R8W: + return r.r8 & mask16, nil + case x86asm.R9W: + return r.r9 & mask16, nil + case x86asm.R10W: + return r.r10 & mask16, nil + case x86asm.R11W: + return r.r11 & mask16, nil + case x86asm.R12W: + return r.r12 & mask16, nil + case x86asm.R13W: + return r.r13 & mask16, nil + case x86asm.R14W: + return r.r14 & mask16, nil + case x86asm.R15W: + return r.r15 & mask16, nil + + // 32-bit + case x86asm.EAX: + return r.rax & mask32, nil + case x86asm.ECX: + return r.rcx & mask32, nil + case x86asm.EDX: + return r.rdx & mask32, nil + case x86asm.EBX: + return r.rbx & mask32, nil + case x86asm.ESP: + return r.rsp & mask32, nil + case x86asm.EBP: + return r.rbp & mask32, nil + case x86asm.ESI: + return r.rsi & mask32, nil + case x86asm.EDI: + return r.rdi & mask32, nil + case x86asm.R8L: + return r.r8 & mask32, nil + case x86asm.R9L: + return r.r9 & mask32, nil + case x86asm.R10L: + return r.r10 & mask32, nil + case x86asm.R11L: + return r.r11 & mask32, nil + case x86asm.R12L: + return r.r12 & mask32, nil + case x86asm.R13L: + return r.r13 & mask32, nil + case x86asm.R14L: + return r.r14 & mask32, nil + case x86asm.R15L: + return r.r15 & mask32, nil + + // 64-bit + case x86asm.RAX: + return r.rax, nil + case x86asm.RCX: + return r.rcx, nil + case x86asm.RDX: + return r.rdx, nil + case x86asm.RBX: + return r.rbx, nil + case x86asm.RSP: + return r.rsp, nil + case x86asm.RBP: + return r.rbp, nil + case x86asm.RSI: + return r.rsi, nil + case x86asm.RDI: + return r.rdi, nil + case x86asm.R8: + return r.r8, nil + case x86asm.R9: + return r.r9, nil + case x86asm.R10: + return r.r10, nil + case x86asm.R11: + return r.r11, nil + case x86asm.R12: + return r.r12, nil + case x86asm.R13: + return r.r13, nil + case x86asm.R14: + return r.r14, nil + case x86asm.R15: + return r.r15, nil + } + + return 0, UnknownRegisterError +} + +func registers(thread *Thread, floatingPoint bool) (Registers, error) { + context := newCONTEXT() + + context.ContextFlags = _CONTEXT_ALL + err := _GetThreadContext(thread.os.hThread, context) + if err != nil { + return nil, err + } + + var threadInfo _THREAD_BASIC_INFORMATION + status := _NtQueryInformationThread(thread.os.hThread, _ThreadBasicInformation, uintptr(unsafe.Pointer(&threadInfo)), uint32(unsafe.Sizeof(threadInfo)), nil) + if !_NT_SUCCESS(status) { + return nil, fmt.Errorf("NtQueryInformationThread failed: it returns 0x%x", status) + } + + regs := &Regs{ + rax: uint64(context.Rax), + rbx: uint64(context.Rbx), + rcx: uint64(context.Rcx), + rdx: uint64(context.Rdx), + rdi: uint64(context.Rdi), + rsi: uint64(context.Rsi), + rbp: uint64(context.Rbp), + rsp: uint64(context.Rsp), + r8: uint64(context.R8), + r9: uint64(context.R9), + r10: uint64(context.R10), + r11: uint64(context.R11), + r12: uint64(context.R12), + r13: uint64(context.R13), + r14: uint64(context.R14), + r15: uint64(context.R15), + rip: uint64(context.Rip), + eflags: uint64(context.EFlags), + cs: uint64(context.SegCs), + fs: uint64(context.SegFs), + gs: uint64(context.SegGs), + tls: uint64(threadInfo.TebBaseAddress), + } + + if floatingPoint { + regs.fltSave = &context.FltSave + } + + return regs, nil +} + +func (thread *Thread) saveRegisters() (Registers, error) { + return nil, fmt.Errorf("not implemented: saveRegisters") +} + +func (thread *Thread) restoreRegisters() error { + return fmt.Errorf("not implemented: restoreRegisters") +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/stack.go b/vendor/github.com/derekparker/delve/pkg/proc/stack.go new file mode 100644 index 0000000..df5cd67 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/stack.go @@ -0,0 +1,261 @@ +package proc + +import ( + "errors" + "fmt" + + "github.com/derekparker/delve/pkg/dwarf/frame" +) + +// This code is partly adaped from runtime.gentraceback in +// $GOROOT/src/runtime/traceback.go + +const runtimeStackBarrier = "runtime.stackBarrier" + +// NoReturnAddr is returned when return address +// could not be found during stack trace. +type NoReturnAddr struct { + fn string +} + +func (nra NoReturnAddr) Error() string { + return fmt.Sprintf("could not find return address for %s", nra.fn) +} + +// Stackframe represents a frame in a system stack. +type Stackframe struct { + // Address the function above this one on the call stack will return to. + Current Location + // Address of the call instruction for the function above on the call stack. + Call Location + // Start address of the stack frame. + CFA int64 + // Description of the stack frame. + FDE *frame.FrameDescriptionEntry + // Return address for this stack frame (as read from the stack frame itself). + Ret uint64 + // Address to the memory location containing the return address + addrret uint64 +} + +// Scope returns a new EvalScope using this frame. +func (frame *Stackframe) Scope(thread *Thread) *EvalScope { + return &EvalScope{Thread: thread, PC: frame.Current.PC, CFA: frame.CFA} +} + +// ReturnAddress returns the return address of the function +// this thread is executing. +func (t *Thread) ReturnAddress() (uint64, error) { + locations, err := t.Stacktrace(2) + if err != nil { + return 0, err + } + if len(locations) < 2 { + return 0, NoReturnAddr{locations[0].Current.Fn.BaseName()} + } + return locations[1].Current.PC, nil +} + +func (t *Thread) stackIterator(stkbar []savedLR, stkbarPos int) (*stackIterator, error) { + regs, err := t.Registers(false) + if err != nil { + return nil, err + } + return newStackIterator(t.dbp, regs.PC(), regs.SP(), regs.BP(), stkbar, stkbarPos), nil +} + +// Stacktrace returns the stack trace for thread. +// Note the locations in the array are return addresses not call addresses. +func (t *Thread) Stacktrace(depth int) ([]Stackframe, error) { + it, err := t.stackIterator(nil, -1) + if err != nil { + return nil, err + } + return it.stacktrace(depth) +} + +func (g *G) stackIterator() (*stackIterator, error) { + stkbar, err := g.stkbar() + if err != nil { + return nil, err + } + if g.thread != nil { + return g.thread.stackIterator(stkbar, g.stkbarPos) + } + return newStackIterator(g.dbp, g.PC, g.SP, 0, stkbar, g.stkbarPos), nil +} + +// Stacktrace returns the stack trace for a goroutine. +// Note the locations in the array are return addresses not call addresses. +func (g *G) Stacktrace(depth int) ([]Stackframe, error) { + it, err := g.stackIterator() + if err != nil { + return nil, err + } + return it.stacktrace(depth) +} + +// GoroutineLocation returns the location of the given +// goroutine. +func (dbp *Process) GoroutineLocation(g *G) *Location { + f, l, fn := dbp.PCToLine(g.PC) + return &Location{PC: g.PC, File: f, Line: l, Fn: fn} +} + +// NullAddrError is an error for a null address. +type NullAddrError struct{} + +func (n NullAddrError) Error() string { + return "NULL address" +} + +// stackIterator holds information +// required to iterate and walk the program +// stack. +type stackIterator struct { + pc, sp, bp uint64 + top bool + atend bool + frame Stackframe + dbp *Process + err error + + stackBarrierPC uint64 + stkbar []savedLR +} + +type savedLR struct { + ptr uint64 + val uint64 +} + +func newStackIterator(dbp *Process, pc, sp, bp uint64, stkbar []savedLR, stkbarPos int) *stackIterator { + stackBarrierFunc := dbp.goSymTable.LookupFunc(runtimeStackBarrier) // stack barriers were removed in Go 1.9 + var stackBarrierPC uint64 + if stackBarrierFunc != nil && stkbar != nil { + stackBarrierPC = stackBarrierFunc.Entry + fn := dbp.goSymTable.PCToFunc(pc) + if fn != nil && fn.Name == runtimeStackBarrier { + // We caught the goroutine as it's executing the stack barrier, we must + // determine whether or not g.stackPos has already been incremented or not. + if len(stkbar) > 0 && stkbar[stkbarPos].ptr < sp { + // runtime.stackBarrier has not incremented stkbarPos. + } else if stkbarPos > 0 && stkbar[stkbarPos-1].ptr < sp { + // runtime.stackBarrier has incremented stkbarPos. + stkbarPos-- + } else { + return &stackIterator{err: fmt.Errorf("failed to unwind through stackBarrier at SP %x", sp)} + } + } + stkbar = stkbar[stkbarPos:] + } + return &stackIterator{pc: pc, sp: sp, bp: bp, top: true, dbp: dbp, err: nil, atend: false, stackBarrierPC: stackBarrierPC, stkbar: stkbar} +} + +// Next points the iterator to the next stack frame. +func (it *stackIterator) Next() bool { + if it.err != nil || it.atend { + return false + } + it.frame, it.err = it.dbp.frameInfo(it.pc, it.sp, it.bp, it.top) + if it.err != nil { + if _, nofde := it.err.(*frame.NoFDEForPCError); nofde && !it.top { + it.frame = Stackframe{Current: Location{PC: it.pc, File: "?", Line: -1}, Call: Location{PC: it.pc, File: "?", Line: -1}, CFA: 0, Ret: 0} + it.atend = true + it.err = nil + return true + } + return false + } + + if it.frame.Ret <= 0 { + it.atend = true + return true + } + + if it.stkbar != nil && it.frame.Ret == it.stackBarrierPC && it.frame.addrret == it.stkbar[0].ptr { + // Skip stack barrier frames + it.frame.Ret = it.stkbar[0].val + it.stkbar = it.stkbar[1:] + } + + // Look for "top of stack" functions. + if it.frame.Current.Fn != nil && (it.frame.Current.Fn.Name == "runtime.goexit" || it.frame.Current.Fn.Name == "runtime.rt0_go" || it.frame.Current.Fn.Name == "runtime.mcall") { + it.atend = true + return true + } + + it.top = false + it.pc = it.frame.Ret + it.sp = uint64(it.frame.CFA) + it.bp, _ = readUintRaw(it.dbp.currentThread, uintptr(it.bp), int64(it.dbp.arch.PtrSize())) + return true +} + +// Frame returns the frame the iterator is pointing at. +func (it *stackIterator) Frame() Stackframe { + if it.err != nil { + panic(it.err) + } + return it.frame +} + +// Err returns the error encountered during stack iteration. +func (it *stackIterator) Err() error { + return it.err +} + +func (dbp *Process) frameInfo(pc, sp, bp uint64, top bool) (Stackframe, error) { + fde, err := dbp.frameEntries.FDEForPC(pc) + if _, nofde := err.(*frame.NoFDEForPCError); nofde { + if bp == 0 { + return Stackframe{}, err + } + // When no FDE is available attempt to use BP instead + retaddr := uintptr(int(bp) + dbp.arch.PtrSize()) + cfa := int64(retaddr) + int64(dbp.arch.PtrSize()) + return dbp.newStackframe(pc, cfa, retaddr, nil, top) + } + + spoffset, retoffset := fde.ReturnAddressOffset(pc) + cfa := int64(sp) + spoffset + + retaddr := uintptr(cfa + retoffset) + return dbp.newStackframe(pc, cfa, retaddr, fde, top) +} + +func (dbp *Process) newStackframe(pc uint64, cfa int64, retaddr uintptr, fde *frame.FrameDescriptionEntry, top bool) (Stackframe, error) { + if retaddr == 0 { + return Stackframe{}, NullAddrError{} + } + f, l, fn := dbp.PCToLine(pc) + ret, err := readUintRaw(dbp.currentThread, retaddr, int64(dbp.arch.PtrSize())) + if err != nil { + return Stackframe{}, err + } + r := Stackframe{Current: Location{PC: pc, File: f, Line: l, Fn: fn}, CFA: cfa, FDE: fde, Ret: ret, addrret: uint64(retaddr)} + if !top { + r.Call.File, r.Call.Line, r.Call.Fn = dbp.PCToLine(pc - 1) + r.Call.PC = r.Current.PC + } else { + r.Call = r.Current + } + return r, nil +} + +func (it *stackIterator) stacktrace(depth int) ([]Stackframe, error) { + if depth < 0 { + return nil, errors.New("negative maximum stack depth") + } + frames := make([]Stackframe, 0, depth+1) + for it.Next() { + frames = append(frames, it.Frame()) + if len(frames) >= depth+1 { + break + } + } + if err := it.Err(); err != nil { + return nil, err + } + return frames, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/syscall_windows.go b/vendor/github.com/derekparker/delve/pkg/proc/syscall_windows.go new file mode 100644 index 0000000..770a789 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/syscall_windows.go @@ -0,0 +1,112 @@ +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go + +package proc + +import ( + "syscall" +) + +type _NTSTATUS int32 + +type _CLIENT_ID struct { + UniqueProcess syscall.Handle + UniqueThread syscall.Handle +} + +type _THREAD_BASIC_INFORMATION struct { + ExitStatus _NTSTATUS + TebBaseAddress uintptr + ClientId _CLIENT_ID + AffinityMask uintptr + Priority int32 + BasePriority int32 +} + +type _CREATE_PROCESS_DEBUG_INFO struct { + File syscall.Handle + Process syscall.Handle + Thread syscall.Handle + BaseOfImage uintptr + DebugInfoFileOffset uint32 + DebugInfoSize uint32 + ThreadLocalBase uintptr + StartAddress uintptr + ImageName uintptr + Unicode uint16 +} + +type _CREATE_THREAD_DEBUG_INFO struct { + Thread syscall.Handle + ThreadLocalBase uintptr + StartAddress uintptr +} + +type _EXIT_PROCESS_DEBUG_INFO struct { + ExitCode uint32 +} + +type _LOAD_DLL_DEBUG_INFO struct { + File syscall.Handle + BaseOfDll uintptr + DebugInfoFileOffset uint32 + DebugInfoSize uint32 + ImageName uintptr + Unicode uint16 +} + +type _EXCEPTION_DEBUG_INFO struct { + ExceptionRecord _EXCEPTION_RECORD + FirstChance uint32 +} + +type _EXCEPTION_RECORD struct { + ExceptionCode uint32 + ExceptionFlags uint32 + ExceptionRecord *_EXCEPTION_RECORD + ExceptionAddress uintptr + NumberParameters uint32 + ExceptionInformation [_EXCEPTION_MAXIMUM_PARAMETERS]uintptr +} + +const ( + _ThreadBasicInformation = 0 + + _DBG_CONTINUE = 0x00010002 + _DBG_EXCEPTION_NOT_HANDLED = 0x80010001 + + _EXCEPTION_DEBUG_EVENT = 1 + _CREATE_THREAD_DEBUG_EVENT = 2 + _CREATE_PROCESS_DEBUG_EVENT = 3 + _EXIT_THREAD_DEBUG_EVENT = 4 + _EXIT_PROCESS_DEBUG_EVENT = 5 + _LOAD_DLL_DEBUG_EVENT = 6 + _UNLOAD_DLL_DEBUG_EVENT = 7 + _OUTPUT_DEBUG_STRING_EVENT = 8 + _RIP_EVENT = 9 + + // DEBUG_ONLY_THIS_PROCESS tracks https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx + _DEBUG_ONLY_THIS_PROCESS = 0x00000002 + + _EXCEPTION_BREAKPOINT = 0x80000003 + _EXCEPTION_SINGLE_STEP = 0x80000004 + + _EXCEPTION_MAXIMUM_PARAMETERS = 15 +) + +func _NT_SUCCESS(x _NTSTATUS) bool { + return x >= 0 +} + +//sys _NtQueryInformationThread(threadHandle syscall.Handle, infoclass int32, info uintptr, infolen uint32, retlen *uint32) (status _NTSTATUS) = ntdll.NtQueryInformationThread +//sys _GetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) = kernel32.GetThreadContext +//sys _SetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) = kernel32.SetThreadContext +//sys _SuspendThread(threadid syscall.Handle) (prevsuspcount uint32, err error) [failretval==0xffffffff] = kernel32.SuspendThread +//sys _ResumeThread(threadid syscall.Handle) (prevsuspcount uint32, err error) [failretval==0xffffffff] = kernel32.ResumeThread +//sys _ContinueDebugEvent(processid uint32, threadid uint32, continuestatus uint32) (err error) = kernel32.ContinueDebugEvent +//sys _WriteProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, byteswritten *uintptr) (err error) = kernel32.WriteProcessMemory +//sys _ReadProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, bytesread *uintptr) (err error) = kernel32.ReadProcessMemory +//sys _DebugBreakProcess(process syscall.Handle) (err error) = kernel32.DebugBreakProcess +//sys _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err error) = kernel32.WaitForDebugEvent +//sys _DebugActiveProcess(processid uint32) (err error) = kernel32.DebugActiveProcess +//sys _DebugActiveProcessStop(processid uint32) (err error) = kernel32.DebugActiveProcessStop +//sys _QueryFullProcessImageName(process syscall.Handle, flags uint32, exename *uint16, size *uint32) (err error) = kernel32.QueryFullProcessImageNameW diff --git a/vendor/github.com/derekparker/delve/pkg/proc/syscall_windows_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/syscall_windows_amd64.go new file mode 100644 index 0000000..1ce592e --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/syscall_windows_amd64.go @@ -0,0 +1,114 @@ +package proc + +import "unsafe" + +const ( + _CONTEXT_AMD64 = 0x100000 + _CONTEXT_CONTROL = (_CONTEXT_AMD64 | 0x1) + _CONTEXT_INTEGER = (_CONTEXT_AMD64 | 0x2) + _CONTEXT_SEGMENTS = (_CONTEXT_AMD64 | 0x4) + _CONTEXT_FLOATING_POINT = (_CONTEXT_AMD64 | 0x8) + _CONTEXT_DEBUG_REGISTERS = (_CONTEXT_AMD64 | 0x10) + _CONTEXT_FULL = (_CONTEXT_CONTROL | _CONTEXT_INTEGER | _CONTEXT_FLOATING_POINT) + _CONTEXT_ALL = (_CONTEXT_CONTROL | _CONTEXT_INTEGER | _CONTEXT_SEGMENTS | _CONTEXT_FLOATING_POINT | _CONTEXT_DEBUG_REGISTERS) + _CONTEXT_EXCEPTION_ACTIVE = 0x8000000 + _CONTEXT_SERVICE_ACTIVE = 0x10000000 + _CONTEXT_EXCEPTION_REQUEST = 0x40000000 + _CONTEXT_EXCEPTION_REPORTING = 0x80000000 +) + +type _M128A struct { + Low uint64 + High int64 +} + +type _XMM_SAVE_AREA32 struct { + ControlWord uint16 + StatusWord uint16 + TagWord byte + Reserved1 byte + ErrorOpcode uint16 + ErrorOffset uint32 + ErrorSelector uint16 + Reserved2 uint16 + DataOffset uint32 + DataSelector uint16 + Reserved3 uint16 + MxCsr uint32 + MxCsr_Mask uint32 + FloatRegisters [8]_M128A + XmmRegisters [256]byte + Reserved4 [96]byte +} + +type _CONTEXT struct { + P1Home uint64 + P2Home uint64 + P3Home uint64 + P4Home uint64 + P5Home uint64 + P6Home uint64 + + ContextFlags uint32 + MxCsr uint32 + + SegCs uint16 + SegDs uint16 + SegEs uint16 + SegFs uint16 + SegGs uint16 + SegSs uint16 + EFlags uint32 + + Dr0 uint64 + Dr1 uint64 + Dr2 uint64 + Dr3 uint64 + Dr6 uint64 + Dr7 uint64 + + Rax uint64 + Rcx uint64 + Rdx uint64 + Rbx uint64 + Rsp uint64 + Rbp uint64 + Rsi uint64 + Rdi uint64 + R8 uint64 + R9 uint64 + R10 uint64 + R11 uint64 + R12 uint64 + R13 uint64 + R14 uint64 + R15 uint64 + + Rip uint64 + + FltSave _XMM_SAVE_AREA32 + + VectorRegister [26]_M128A + VectorControl uint64 + + DebugControl uint64 + LastBranchToRip uint64 + LastBranchFromRip uint64 + LastExceptionToRip uint64 + LastExceptionFromRip uint64 +} + +// newCONTEXT allocates Windows CONTEXT structure aligned to 16 bytes. +func newCONTEXT() *_CONTEXT { + var c *_CONTEXT + buf := make([]byte, unsafe.Sizeof(*c)+15) + return (*_CONTEXT)(unsafe.Pointer((uintptr(unsafe.Pointer(&buf[15]))) &^ 15)) +} + +type _DEBUG_EVENT struct { + DebugEventCode uint32 + ProcessId uint32 + ThreadId uint32 + _ uint32 // to align Union properly + U [160]byte +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads.go b/vendor/github.com/derekparker/delve/pkg/proc/threads.go new file mode 100644 index 0000000..4e44efe --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/threads.go @@ -0,0 +1,510 @@ +package proc + +import ( + "debug/gosym" + "encoding/binary" + "errors" + "fmt" + "go/ast" + "path/filepath" + "reflect" + "runtime" + "strings" + + "golang.org/x/debug/dwarf" +) + +// Thread represents a single thread in the traced process +// ID represents the thread id or port, Process holds a reference to the +// Process struct that contains info on the process as +// a whole, and Status represents the last result of a `wait` call +// on this thread. +type Thread struct { + ID int // Thread ID or mach port + Status *WaitStatus // Status returned from last wait call + CurrentBreakpoint *Breakpoint // Breakpoint thread is currently stopped at + BreakpointConditionMet bool // Output of evaluating the breakpoint's condition + BreakpointConditionError error // Error evaluating the breakpoint's condition + + dbp *Process + singleStepping bool + running bool + os *OSSpecificDetails +} + +// Location represents the location of a thread. +// Holds information on the current instruction +// address, the source file:line, and the function. +type Location struct { + PC uint64 + File string + Line int + Fn *gosym.Func +} + +// Continue the execution of this thread. +// +// If we are currently at a breakpoint, we'll clear it +// first and then resume execution. Thread will continue until +// it hits a breakpoint or is signaled. +func (thread *Thread) Continue() error { + pc, err := thread.PC() + if err != nil { + return err + } + // Check whether we are stopped at a breakpoint, and + // if so, single step over it before continuing. + if _, ok := thread.dbp.FindBreakpoint(pc); ok { + if err := thread.StepInstruction(); err != nil { + return err + } + } + return thread.resume() +} + +// StepInstruction steps a single instruction. +// +// Executes exactly one instruction and then returns. +// If the thread is at a breakpoint, we first clear it, +// execute the instruction, and then replace the breakpoint. +// Otherwise we simply execute the next instruction. +func (thread *Thread) StepInstruction() (err error) { + thread.running = true + thread.singleStepping = true + defer func() { + thread.singleStepping = false + thread.running = false + }() + pc, err := thread.PC() + if err != nil { + return err + } + + bp, ok := thread.dbp.FindBreakpoint(pc) + if ok { + // Clear the breakpoint so that we can continue execution. + _, err = bp.Clear(thread) + if err != nil { + return err + } + + // Restore breakpoint now that we have passed it. + defer func() { + err = thread.dbp.writeSoftwareBreakpoint(thread, bp.Addr) + }() + } + + err = thread.singleStep() + if err != nil { + if _, exited := err.(ProcessExitedError); exited { + return err + } + return fmt.Errorf("step failed: %s", err.Error()) + } + return nil +} + +// Location returns the threads location, including the file:line +// of the corresponding source code, the function we're in +// and the current instruction address. +func (thread *Thread) Location() (*Location, error) { + pc, err := thread.PC() + if err != nil { + return nil, err + } + f, l, fn := thread.dbp.PCToLine(pc) + return &Location{PC: pc, File: f, Line: l, Fn: fn}, nil +} + +// ThreadBlockedError is returned when the thread +// is blocked in the scheduler. +type ThreadBlockedError struct{} + +func (tbe ThreadBlockedError) Error() string { + return "" +} + +// returns topmost frame of g or thread if g is nil +func topframe(g *G, thread *Thread) (Stackframe, error) { + var frames []Stackframe + var err error + + if g == nil { + if thread.blocked() { + return Stackframe{}, ThreadBlockedError{} + } + frames, err = thread.Stacktrace(0) + } else { + frames, err = g.Stacktrace(0) + } + if err != nil { + return Stackframe{}, err + } + if len(frames) < 1 { + return Stackframe{}, errors.New("empty stack trace") + } + return frames[0], nil +} + +// Set breakpoints at every line, and the return address. Also look for +// a deferred function and set a breakpoint there too. +// If stepInto is true it will also set breakpoints inside all +// functions called on the current source line, for non-absolute CALLs +// a breakpoint of kind StepBreakpoint is set on the CALL instruction, +// Continue will take care of setting a breakpoint to the destination +// once the CALL is reached. +func (dbp *Process) next(stepInto bool) error { + topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread) + if err != nil { + return err + } + + success := false + defer func() { + if !success { + dbp.ClearInternalBreakpoints() + } + }() + + csource := filepath.Ext(topframe.Current.File) != ".go" + thread := dbp.currentThread + currentGoroutine := false + if dbp.selectedGoroutine != nil && dbp.selectedGoroutine.thread != nil { + thread = dbp.selectedGoroutine.thread + currentGoroutine = true + } + + text, err := thread.Disassemble(topframe.FDE.Begin(), topframe.FDE.End(), currentGoroutine) + if err != nil && stepInto { + return err + } + + cond := sameGoroutineCondition(dbp.selectedGoroutine) + + if stepInto { + for _, instr := range text { + if instr.Loc.File != topframe.Current.File || instr.Loc.Line != topframe.Current.Line || !instr.IsCall() { + continue + } + + if instr.DestLoc != nil && instr.DestLoc.Fn != nil { + if err := dbp.setStepIntoBreakpoint([]AsmInstruction{instr}, cond); err != nil { + return err + } + } else { + // Non-absolute call instruction, set a StepBreakpoint here + if _, err := dbp.SetBreakpoint(instr.Loc.PC, StepBreakpoint, cond); err != nil { + if _, ok := err.(BreakpointExistsError); !ok { + return err + } + } + } + } + } + + if !csource { + deferreturns := []uint64{} + + // Find all runtime.deferreturn locations in the function + // See documentation of Breakpoint.DeferCond for why this is necessary + for _, instr := range text { + if instr.IsCall() && instr.DestLoc != nil && instr.DestLoc.Fn != nil && instr.DestLoc.Fn.Name == "runtime.deferreturn" { + deferreturns = append(deferreturns, instr.Loc.PC) + } + } + + // Set breakpoint on the most recently deferred function (if any) + var deferpc uint64 = 0 + if dbp.selectedGoroutine != nil { + deferPCEntry := dbp.selectedGoroutine.DeferPC() + if deferPCEntry != 0 { + _, _, deferfn := dbp.goSymTable.PCToLine(deferPCEntry) + var err error + deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false) + if err != nil { + return err + } + } + } + if deferpc != 0 && deferpc != topframe.Current.PC { + bp, err := dbp.SetBreakpoint(deferpc, NextDeferBreakpoint, cond) + if err != nil { + if _, ok := err.(BreakpointExistsError); !ok { + return err + } + } + if bp != nil { + bp.DeferReturns = deferreturns + } + } + } + + // Add breakpoints on all the lines in the current function + pcs, err := dbp.lineInfo.AllPCsBetween(topframe.FDE.Begin(), topframe.FDE.End()-1, topframe.Current.File) + if err != nil { + return err + } + + if !csource { + var covered bool + for i := range pcs { + if topframe.FDE.Cover(pcs[i]) { + covered = true + break + } + } + + if !covered { + fn := dbp.goSymTable.PCToFunc(topframe.Ret) + if dbp.selectedGoroutine != nil && fn != nil && fn.Name == "runtime.goexit" { + return nil + } + } + } + + // Add a breakpoint on the return address for the current frame + pcs = append(pcs, topframe.Ret) + success = true + return dbp.setInternalBreakpoints(topframe.Current.PC, pcs, NextBreakpoint, cond) +} + +func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr) error { + if len(text) <= 0 { + return nil + } + + instr := text[0] + + if instr.DestLoc == nil || instr.DestLoc.Fn == nil { + return nil + } + + fn := instr.DestLoc.Fn + + // Ensure PC and Entry match, otherwise StepInto is likely to set + // its breakpoint before DestLoc.PC and hence run too far ahead. + // Calls to runtime.duffzero and duffcopy have this problem. + if fn.Entry != instr.DestLoc.PC { + return nil + } + + // Skip unexported runtime functions + if strings.HasPrefix(fn.Name, "runtime.") && !isExportedRuntime(fn.Name) { + return nil + } + + //TODO(aarzilli): if we want to let users hide functions + // or entire packages from being stepped into with 'step' + // those extra checks should be done here. + + // Set a breakpoint after the function's prologue + pc, _ := dbp.FirstPCAfterPrologue(fn, false) + if _, err := dbp.SetBreakpoint(pc, NextBreakpoint, cond); err != nil { + if _, ok := err.(BreakpointExistsError); !ok { + return err + } + } + + return nil +} + +// setInternalBreakpoints sets a breakpoint to all addresses specified in pcs +// skipping over curpc and curpc-1 +func (dbp *Process) setInternalBreakpoints(curpc uint64, pcs []uint64, kind BreakpointKind, cond ast.Expr) error { + for i := range pcs { + if pcs[i] == curpc || pcs[i] == curpc-1 { + continue + } + if _, err := dbp.SetBreakpoint(pcs[i], kind, cond); err != nil { + if _, ok := err.(BreakpointExistsError); !ok { + dbp.ClearInternalBreakpoints() + return err + } + } + } + return nil +} + +// SetPC sets the PC for this thread. +func (thread *Thread) SetPC(pc uint64) error { + regs, err := thread.Registers(false) + if err != nil { + return err + } + return regs.SetPC(thread, pc) +} + +func (thread *Thread) getGVariable() (*Variable, error) { + regs, err := thread.Registers(false) + if err != nil { + return nil, err + } + + if thread.dbp.arch.GStructOffset() == 0 { + // GetG was called through SwitchThread / updateThreadList during initialization + // thread.dbp.arch isn't setup yet (it needs a current thread to read global variables from) + return nil, fmt.Errorf("g struct offset not initialized") + } + + gaddrbs, err := thread.readMemory(uintptr(regs.TLS()+thread.dbp.arch.GStructOffset()), thread.dbp.arch.PtrSize()) + if err != nil { + return nil, err + } + gaddr := uintptr(binary.LittleEndian.Uint64(gaddrbs)) + + // On Windows, the value at TLS()+GStructOffset() is a + // pointer to the G struct. + needsDeref := runtime.GOOS == "windows" + + return thread.newGVariable(gaddr, needsDeref) +} + +func (thread *Thread) newGVariable(gaddr uintptr, deref bool) (*Variable, error) { + typ, err := thread.dbp.findType("runtime.g") + if err != nil { + return nil, err + } + + name := "" + + if deref { + typ = &dwarf.PtrType{dwarf.CommonType{int64(thread.dbp.arch.PtrSize()), "", reflect.Ptr, 0}, typ} + } else { + name = "runtime.curg" + } + + return thread.newVariable(name, gaddr, typ), nil +} + +// GetG returns information on the G (goroutine) that is executing on this thread. +// +// The G structure for a thread is stored in thread local storage. Here we simply +// calculate the address and read and parse the G struct. +// +// We cannot simply use the allg linked list in order to find the M that represents +// the given OS thread and follow its G pointer because on Darwin mach ports are not +// universal, so our port for this thread would not map to the `id` attribute of the M +// structure. Also, when linked against libc, Go prefers the libc version of clone as +// opposed to the runtime version. This has the consequence of not setting M.id for +// any thread, regardless of OS. +// +// In order to get around all this craziness, we read the address of the G structure for +// the current thread from the thread local storage area. +func (thread *Thread) GetG() (g *G, err error) { + gaddr, err := thread.getGVariable() + if err != nil { + return nil, err + } + + g, err = gaddr.parseG() + if err == nil { + g.thread = thread + if loc, err := thread.Location(); err == nil { + g.CurrentLoc = *loc + } + } + return +} + +// Stopped returns whether the thread is stopped at +// the operating system level. Actual implementation +// is OS dependant, look in OS thread file. +func (thread *Thread) Stopped() bool { + return thread.stopped() +} + +// Halt stops this thread from executing. Actual +// implementation is OS dependant. Look in OS +// thread file. +func (thread *Thread) Halt() (err error) { + defer func() { + if err == nil { + thread.running = false + } + }() + if thread.Stopped() { + return + } + err = thread.halt() + return +} + +// Scope returns the current EvalScope for this thread. +func (thread *Thread) Scope() (*EvalScope, error) { + locations, err := thread.Stacktrace(0) + if err != nil { + return nil, err + } + if len(locations) < 1 { + return nil, errors.New("could not decode first frame") + } + return locations[0].Scope(thread), nil +} + +// SetCurrentBreakpoint sets the current breakpoint that this +// thread is stopped at as CurrentBreakpoint on the thread struct. +func (thread *Thread) SetCurrentBreakpoint() error { + thread.CurrentBreakpoint = nil + pc, err := thread.PC() + if err != nil { + return err + } + if bp, ok := thread.dbp.FindBreakpoint(pc); ok { + thread.CurrentBreakpoint = bp + if err = thread.SetPC(bp.Addr); err != nil { + return err + } + thread.BreakpointConditionMet, thread.BreakpointConditionError = bp.checkCondition(thread) + if thread.onTriggeredBreakpoint() { + if g, err := thread.GetG(); err == nil { + thread.CurrentBreakpoint.HitCount[g.ID]++ + } + thread.CurrentBreakpoint.TotalHitCount++ + } + } + return nil +} + +func (thread *Thread) clearBreakpointState() { + thread.CurrentBreakpoint = nil + thread.BreakpointConditionMet = false + thread.BreakpointConditionError = nil +} + +func (thread *Thread) onTriggeredBreakpoint() bool { + return (thread.CurrentBreakpoint != nil) && thread.BreakpointConditionMet +} + +func (thread *Thread) onTriggeredInternalBreakpoint() bool { + return thread.onTriggeredBreakpoint() && thread.CurrentBreakpoint.Internal() +} + +func (thread *Thread) onRuntimeBreakpoint() bool { + loc, err := thread.Location() + if err != nil { + return false + } + return loc.Fn != nil && loc.Fn.Name == "runtime.breakpoint" +} + +// onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command +func (thread *Thread) onNextGoroutine() (bool, error) { + var bp *Breakpoint + for i := range thread.dbp.breakpoints { + if thread.dbp.breakpoints[i].Internal() { + bp = thread.dbp.breakpoints[i] + break + } + } + if bp == nil { + return false, nil + } + if bp.Kind == NextDeferBreakpoint { + // we just want to check the condition on the goroutine id here + bp.Kind = NextBreakpoint + defer func() { + bp.Kind = NextDeferBreakpoint + }() + } + return bp.checkCondition(thread) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.c b/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.c new file mode 100644 index 0000000..88a92f4 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.c @@ -0,0 +1,177 @@ +#include "threads_darwin.h" + +int +write_memory(task_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) { + kern_return_t kret; + vm_region_submap_short_info_data_64_t info; + mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; + mach_vm_size_t l = len; + mach_port_t objname; + + if (len == 1) l = 2; + kret = mach_vm_region((vm_map_t)task, &(mach_vm_address_t){addr}, (mach_vm_size_t*)&l, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &count, &objname); + if (kret != KERN_SUCCESS) return -1; + + // Set permissions to enable writting to this memory location + kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_WRITE|VM_PROT_COPY|VM_PROT_READ); + if (kret != KERN_SUCCESS) return -1; + + kret = mach_vm_write((vm_map_t)task, addr, (vm_offset_t)d, len); + if (kret != KERN_SUCCESS) return -1; + + // Restore virtual memory permissions + kret = mach_vm_protect(task, addr, len, FALSE, info.protection); + if (kret != KERN_SUCCESS) return -1; + + return 0; +} + +int +read_memory(task_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) { + kern_return_t kret; + pointer_t data; + mach_msg_type_number_t count; + + kret = mach_vm_read((vm_map_t)task, addr, len, &data, &count); + if (kret != KERN_SUCCESS) return -1; + memcpy(d, (void *)data, len); + + kret = vm_deallocate(task, data, len); + if (kret != KERN_SUCCESS) return -1; + + return count; +} + +kern_return_t +get_registers(mach_port_name_t task, x86_thread_state64_t *state) { + kern_return_t kret; + mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT; + // TODO(dp) - possible memory leak - vm_deallocate state + return thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)state, &stateCount); +} + +kern_return_t +get_fpu_registers(mach_port_name_t task, x86_float_state64_t *state) { + kern_return_t kret; + mach_msg_type_number_t stateCount = x86_FLOAT_STATE64_COUNT; + return thread_get_state(task, x86_FLOAT_STATE64, (thread_state_t)state, &stateCount); +} + +kern_return_t +get_identity(mach_port_name_t task, thread_identifier_info_data_t *idinfo) { + mach_msg_type_number_t idinfoCount = THREAD_IDENTIFIER_INFO_COUNT; + return thread_info(task, THREAD_IDENTIFIER_INFO, (thread_info_t)idinfo, &idinfoCount); +} + +kern_return_t +set_registers(mach_port_name_t task, x86_thread_state64_t *state) { + mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT; + return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)state, stateCount); +} + +kern_return_t +set_pc(thread_act_t task, uint64_t pc) { + kern_return_t kret; + x86_thread_state64_t state; + mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT; + + kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount); + if (kret != KERN_SUCCESS) return kret; + state.__rip = pc; + + return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)&state, stateCount); +} + +kern_return_t +single_step(thread_act_t thread) { + kern_return_t kret; + x86_thread_state64_t regs; + mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; + + kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, &count); + if (kret != KERN_SUCCESS) return kret; + + // Set trap bit in rflags + regs.__rflags |= 0x100UL; + + kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, count); + if (kret != KERN_SUCCESS) return kret; + + return resume_thread(thread); +} + +kern_return_t +resume_thread(thread_act_t thread) { + kern_return_t kret; + struct thread_basic_info info; + unsigned int info_count = THREAD_BASIC_INFO_COUNT; + + kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count); + if (kret != KERN_SUCCESS) return kret; + + for (int i = 0; i < info.suspend_count; i++) { + kret = thread_resume(thread); + if (kret != KERN_SUCCESS) return kret; + } + return KERN_SUCCESS; +} + +kern_return_t +clear_trap_flag(thread_act_t thread) { + kern_return_t kret; + x86_thread_state64_t regs; + mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; + + kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, &count); + if (kret != KERN_SUCCESS) return kret; + + // Clear trap bit in rflags + regs.__rflags ^= 0x100UL; + + return thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, count); +} + +int +thread_blocked(thread_act_t thread) { + kern_return_t kret; + struct thread_basic_info info; + unsigned int info_count = THREAD_BASIC_INFO_COUNT; + + kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count); + if (kret != KERN_SUCCESS) return -1; + + return info.suspend_count; +} + +int +num_running_threads(task_t task) { + kern_return_t kret; + thread_act_array_t list; + mach_msg_type_number_t count; + int i, n = 0; + + kret = task_threads(task, &list, &count); + if (kret != KERN_SUCCESS) { + return -kret; + } + + for (i = 0; i < count; ++i) { + thread_act_t thread = list[i]; + struct thread_basic_info info; + unsigned int info_count = THREAD_BASIC_INFO_COUNT; + + kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count); + + if (kret == KERN_SUCCESS) { + if (info.suspend_count == 0) { + ++n; + } else { + } + } + } + + kret = vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0])); + if (kret != KERN_SUCCESS) return -kret; + + return n; +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.go b/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.go new file mode 100644 index 0000000..71c025b --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.go @@ -0,0 +1,137 @@ +package proc + +// #include "threads_darwin.h" +// #include "proc_darwin.h" +import "C" +import ( + "fmt" + "unsafe" + + sys "golang.org/x/sys/unix" +) + +// WaitStatus is a synonym for the platform-specific WaitStatus +type WaitStatus sys.WaitStatus + +// OSSpecificDetails holds information specific to the OSX/Darwin +// operating system / kernel. +type OSSpecificDetails struct { + threadAct C.thread_act_t + registers C.x86_thread_state64_t + exists bool +} + +// ErrContinueThread is the error returned when a thread could not +// be continued. +var ErrContinueThread = fmt.Errorf("could not continue thread") + +func (t *Thread) halt() (err error) { + kret := C.thread_suspend(t.os.threadAct) + if kret != C.KERN_SUCCESS { + errStr := C.GoString(C.mach_error_string(C.mach_error_t(kret))) + // check that the thread still exists before complaining + err2 := t.dbp.updateThreadList() + if err2 != nil { + err = fmt.Errorf("could not suspend thread %d %s (additionally could not update thread list: %v)", t.ID, errStr, err2) + return + } + + if _, ok := t.dbp.threads[t.ID]; ok { + err = fmt.Errorf("could not suspend thread %d %s", t.ID, errStr) + return + } + } + return +} + +func (t *Thread) singleStep() error { + kret := C.single_step(t.os.threadAct) + if kret != C.KERN_SUCCESS { + return fmt.Errorf("could not single step") + } + for { + twthread, err := t.dbp.trapWait(t.dbp.pid) + if err != nil { + return err + } + if twthread.ID == t.ID { + break + } + } + + kret = C.clear_trap_flag(t.os.threadAct) + if kret != C.KERN_SUCCESS { + return fmt.Errorf("could not clear CPU trap flag") + } + return nil +} + +func (t *Thread) resume() error { + t.running = true + // TODO(dp) set flag for ptrace stops + var err error + t.dbp.execPtraceFunc(func() { err = PtraceCont(t.dbp.pid, 0) }) + if err == nil { + return nil + } + kret := C.resume_thread(t.os.threadAct) + if kret != C.KERN_SUCCESS { + return ErrContinueThread + } + return nil +} + +func (t *Thread) blocked() bool { + // TODO(dp) cache the func pc to remove this lookup + pc, err := t.PC() + if err != nil { + return false + } + fn := t.dbp.goSymTable.PCToFunc(pc) + if fn == nil { + return false + } + switch fn.Name { + case "runtime.kevent", "runtime.mach_semaphore_wait", "runtime.usleep": + return true + default: + return false + } +} + +func (t *Thread) stopped() bool { + return C.thread_blocked(t.os.threadAct) > C.int(0) +} + +func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) { + if len(data) == 0 { + return 0, nil + } + var ( + vmData = unsafe.Pointer(&data[0]) + vmAddr = C.mach_vm_address_t(addr) + length = C.mach_msg_type_number_t(len(data)) + ) + if ret := C.write_memory(t.dbp.os.task, vmAddr, vmData, length); ret < 0 { + return 0, fmt.Errorf("could not write memory") + } + return len(data), nil +} + +func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) { + if size == 0 { + return nil, nil + } + var ( + buf = make([]byte, size) + vmData = unsafe.Pointer(&buf[0]) + vmAddr = C.mach_vm_address_t(addr) + length = C.mach_msg_type_number_t(size) + ) + + ret := C.read_memory(t.dbp.os.task, vmAddr, vmData, length) + if ret < 0 { + return nil, fmt.Errorf("could not read memory") + } + return buf, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.h b/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.h new file mode 100644 index 0000000..75a82b8 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/threads_darwin.h @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +int +write_memory(task_t, mach_vm_address_t, void *, mach_msg_type_number_t); + +int +read_memory(task_t, mach_vm_address_t, void *, mach_msg_type_number_t); + +kern_return_t +get_registers(mach_port_name_t, x86_thread_state64_t*); + +kern_return_t +get_fpu_registers(mach_port_name_t, x86_float_state64_t *); + +kern_return_t +set_pc(thread_act_t, uint64_t); + +kern_return_t +single_step(thread_act_t); + +kern_return_t +clear_trap_flag(thread_act_t); + +kern_return_t +resume_thread(thread_act_t); + +kern_return_t +set_registers(mach_port_name_t, x86_thread_state64_t*); + +kern_return_t +get_identity(mach_port_name_t, thread_identifier_info_data_t *); + +int +thread_blocked(thread_act_t thread); + +int +num_running_threads(task_t task); diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads_linux.go b/vendor/github.com/derekparker/delve/pkg/proc/threads_linux.go new file mode 100644 index 0000000..8592a2c --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/threads_linux.go @@ -0,0 +1,108 @@ +package proc + +import ( + "fmt" + + sys "golang.org/x/sys/unix" +) + +type WaitStatus sys.WaitStatus + +// OSSpecificDetails hold Linux specific +// process details. +type OSSpecificDetails struct { + registers sys.PtraceRegs +} + +func (t *Thread) halt() (err error) { + err = sys.Tgkill(t.dbp.pid, t.ID, sys.SIGSTOP) + if err != nil { + err = fmt.Errorf("halt err %s on thread %d", err, t.ID) + return + } + _, _, err = t.dbp.wait(t.ID, 0) + if err != nil { + err = fmt.Errorf("wait err %s on thread %d", err, t.ID) + return + } + return +} + +func (t *Thread) stopped() bool { + state := status(t.ID, t.dbp.os.comm) + return state == StatusTraceStop || state == StatusTraceStopT +} + +func (t *Thread) resume() error { + return t.resumeWithSig(0) +} + +func (t *Thread) resumeWithSig(sig int) (err error) { + t.running = true + t.dbp.execPtraceFunc(func() { err = PtraceCont(t.ID, sig) }) + return +} + +func (t *Thread) singleStep() (err error) { + for { + t.dbp.execPtraceFunc(func() { err = sys.PtraceSingleStep(t.ID) }) + if err != nil { + return err + } + wpid, status, err := t.dbp.waitFast(t.ID) + if err != nil { + return err + } + if (status == nil || status.Exited()) && wpid == t.dbp.pid { + t.dbp.postExit() + rs := 0 + if status != nil { + rs = status.ExitStatus() + } + return ProcessExitedError{Pid: t.dbp.pid, Status: rs} + } + if wpid == t.ID && status.StopSignal() == sys.SIGTRAP { + return nil + } + } +} + +func (t *Thread) blocked() bool { + pc, _ := t.PC() + fn := t.dbp.goSymTable.PCToFunc(pc) + if fn != nil && ((fn.Name == "runtime.futex") || (fn.Name == "runtime.usleep") || (fn.Name == "runtime.clone")) { + return true + } + return false +} + +func (t *Thread) saveRegisters() (Registers, error) { + var err error + t.dbp.execPtraceFunc(func() { err = sys.PtraceGetRegs(t.ID, &t.os.registers) }) + if err != nil { + return nil, fmt.Errorf("could not save register contents") + } + return &Regs{&t.os.registers, nil}, nil +} + +func (t *Thread) restoreRegisters() (err error) { + t.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(t.ID, &t.os.registers) }) + return +} + +func (t *Thread) writeMemory(addr uintptr, data []byte) (written int, err error) { + if len(data) == 0 { + return + } + t.dbp.execPtraceFunc(func() { written, err = sys.PtracePokeData(t.ID, addr, data) }) + return +} + +func (t *Thread) readMemory(addr uintptr, size int) (data []byte, err error) { + if size == 0 { + return + } + data = make([]byte, size) + t.dbp.execPtraceFunc(func() { _, err = sys.PtracePeekData(t.ID, addr, data) }) + return +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads_windows.go b/vendor/github.com/derekparker/delve/pkg/proc/threads_windows.go new file mode 100644 index 0000000..536a411 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/threads_windows.go @@ -0,0 +1,151 @@ +package proc + +import ( + "syscall" + + sys "golang.org/x/sys/windows" +) + +// WaitStatus is a synonym for the platform-specific WaitStatus +type WaitStatus sys.WaitStatus + +// OSSpecificDetails holds information specific to the Windows +// operating system / kernel. +type OSSpecificDetails struct { + hThread syscall.Handle +} + +func (t *Thread) halt() (err error) { + // Ignore the request to halt. On Windows, all threads are halted + // on return from WaitForDebugEvent. + return nil + + // TODO - This may not be correct in all usages of dbp.Halt. There + // are some callers who use dbp.Halt() to stop the process when it is not + // already broken on a debug event. +} + +func (t *Thread) singleStep() error { + context := newCONTEXT() + context.ContextFlags = _CONTEXT_ALL + + // Set the processor TRAP flag + err := _GetThreadContext(t.os.hThread, context) + if err != nil { + return err + } + + context.EFlags |= 0x100 + + err = _SetThreadContext(t.os.hThread, context) + if err != nil { + return err + } + + _, err = _ResumeThread(t.os.hThread) + if err != nil { + return err + } + + for { + var tid, exitCode int + t.dbp.execPtraceFunc(func() { + tid, exitCode, err = t.dbp.waitForDebugEvent(waitBlocking | waitSuspendNewThreads) + }) + if err != nil { + return err + } + if tid == 0 { + t.dbp.postExit() + return ProcessExitedError{Pid: t.dbp.pid, Status: exitCode} + } + + if t.dbp.os.breakThread == t.ID { + break + } + + t.dbp.execPtraceFunc(func() { + err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.dbp.os.breakThread), _DBG_CONTINUE) + }) + } + + _, err = _SuspendThread(t.os.hThread) + if err != nil { + return err + } + + t.dbp.execPtraceFunc(func() { + err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.ID), _DBG_CONTINUE) + }) + if err != nil { + return err + } + + // Unset the processor TRAP flag + err = _GetThreadContext(t.os.hThread, context) + if err != nil { + return err + } + + context.EFlags &= ^uint32(0x100) + + return _SetThreadContext(t.os.hThread, context) +} + +func (t *Thread) resume() error { + t.running = true + var err error + t.dbp.execPtraceFunc(func() { + //TODO: Note that we are ignoring the thread we were asked to continue and are continuing the + //thread that we last broke on. + err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.ID), _DBG_CONTINUE) + }) + return err +} + +func (t *Thread) blocked() bool { + // TODO: Probably incorrect - what are the runtime functions that + // indicate blocking on Windows? + pc, err := t.PC() + if err != nil { + return false + } + fn := t.dbp.goSymTable.PCToFunc(pc) + if fn == nil { + return false + } + switch fn.Name { + case "runtime.kevent", "runtime.usleep": + return true + default: + return false + } +} + +func (t *Thread) stopped() bool { + // TODO: We are assuming that threads are always stopped + // during command execution. + return true +} + +func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) { + var count uintptr + err := _WriteProcessMemory(t.dbp.os.hProcess, addr, &data[0], uintptr(len(data)), &count) + if err != nil { + return 0, err + } + return int(count), nil +} + +func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) { + if size == 0 { + return nil, nil + } + var count uintptr + buf := make([]byte, size) + err := _ReadProcessMemory(t.dbp.os.hProcess, addr, &buf[0], uintptr(size), &count) + if err != nil { + return nil, err + } + return buf[:count], nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/types.go b/vendor/github.com/derekparker/delve/pkg/proc/types.go new file mode 100644 index 0000000..65b8b38 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/types.go @@ -0,0 +1,755 @@ +package proc + +import ( + "bytes" + "errors" + "fmt" + "go/ast" + "go/constant" + "go/token" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "unsafe" + + "github.com/derekparker/delve/pkg/dwarf/reader" + + "golang.org/x/debug/dwarf" +) + +// The kind field in runtime._type is a reflect.Kind value plus +// some extra flags defined here. +// See equivalent declaration in $GOROOT/src/reflect/type.go +const ( + kindDirectIface = 1 << 5 + kindGCProg = 1 << 6 // Type.gc points to GC program + kindNoPointers = 1 << 7 + kindMask = (1 << 5) - 1 +) + +// Value of tflag field in runtime._type. +// See $GOROOT/reflect/type.go for a description of these flags. +const ( + tflagUncommon = 1 << 0 + tflagExtraStar = 1 << 1 + tflagNamed = 1 << 2 +) + +// Do not call this function directly it isn't able to deal correctly with package paths +func (dbp *Process) findType(name string) (dwarf.Type, error) { + off, found := dbp.types[name] + if !found { + return nil, reader.TypeNotFoundErr + } + return dbp.dwarf.Type(off) +} + +func (dbp *Process) pointerTo(typ dwarf.Type) dwarf.Type { + return &dwarf.PtrType{dwarf.CommonType{int64(dbp.arch.PtrSize()), "*" + typ.Common().Name, reflect.Ptr, 0}, typ} +} + +func (dbp *Process) findTypeExpr(expr ast.Expr) (dwarf.Type, error) { + dbp.loadPackageMap() + if lit, islit := expr.(*ast.BasicLit); islit && lit.Kind == token.STRING { + // Allow users to specify type names verbatim as quoted + // string. Useful as a catch-all workaround for cases where we don't + // parse/serialize types correctly or can not resolve package paths. + typn, _ := strconv.Unquote(lit.Value) + return dbp.findType(typn) + } + dbp.expandPackagesInType(expr) + if snode, ok := expr.(*ast.StarExpr); ok { + // Pointer types only appear in the dwarf informations when + // a pointer to the type is used in the target program, here + // we create a pointer type on the fly so that the user can + // specify a pointer to any variable used in the target program + ptyp, err := dbp.findTypeExpr(snode.X) + if err != nil { + return nil, err + } + return dbp.pointerTo(ptyp), nil + } + return dbp.findType(exprToString(expr)) +} + +func complexType(typename string) bool { + for _, ch := range typename { + switch ch { + case '*', '[', '<', '{', '(', ' ': + return true + } + } + return false +} + +func (dbp *Process) loadPackageMap() error { + if dbp.packageMap != nil { + return nil + } + dbp.packageMap = map[string]string{} + reader := dbp.DwarfReader() + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + return err + } + + if entry.Tag != dwarf.TagTypedef && entry.Tag != dwarf.TagBaseType && entry.Tag != dwarf.TagClassType && entry.Tag != dwarf.TagStructType { + continue + } + + typename, ok := entry.Val(dwarf.AttrName).(string) + if !ok || complexType(typename) { + continue + } + + dot := strings.LastIndex(typename, ".") + if dot < 0 { + continue + } + path := typename[:dot] + slash := strings.LastIndex(path, "/") + if slash < 0 || slash+1 >= len(path) { + continue + } + name := path[slash+1:] + dbp.packageMap[name] = path + } + return nil +} + +type sortFunctionsDebugInfoByLowpc []functionDebugInfo + +func (v sortFunctionsDebugInfoByLowpc) Len() int { return len(v) } +func (v sortFunctionsDebugInfoByLowpc) Less(i, j int) bool { return v[i].lowpc < v[j].lowpc } +func (v sortFunctionsDebugInfoByLowpc) Swap(i, j int) { + temp := v[i] + v[i] = v[j] + v[j] = temp +} + +func (dbp *Process) loadDebugInfoMaps(wg *sync.WaitGroup) { + defer wg.Done() + dbp.types = make(map[string]dwarf.Offset) + dbp.functions = []functionDebugInfo{} + reader := dbp.DwarfReader() + for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() { + if err != nil { + break + } + switch entry.Tag { + case dwarf.TagArrayType, dwarf.TagBaseType, dwarf.TagClassType, dwarf.TagStructType, dwarf.TagUnionType, dwarf.TagConstType, dwarf.TagVolatileType, dwarf.TagRestrictType, dwarf.TagEnumerationType, dwarf.TagPointerType, dwarf.TagSubroutineType, dwarf.TagTypedef, dwarf.TagUnspecifiedType: + name, ok := entry.Val(dwarf.AttrName).(string) + if !ok { + continue + } + if _, exists := dbp.types[name]; !exists { + dbp.types[name] = entry.Offset + } + case dwarf.TagSubprogram: + lowpc, ok := entry.Val(dwarf.AttrLowpc).(uint64) + if !ok { + continue + } + highpc, ok := entry.Val(dwarf.AttrHighpc).(uint64) + if !ok { + continue + } + dbp.functions = append(dbp.functions, functionDebugInfo{lowpc, highpc, entry.Offset}) + } + } + sort.Sort(sortFunctionsDebugInfoByLowpc(dbp.functions)) +} + +func (dbp *Process) findFunctionDebugInfo(pc uint64) (dwarf.Offset, error) { + i := sort.Search(len(dbp.functions), func(i int) bool { + fn := dbp.functions[i] + return pc <= fn.lowpc || (fn.lowpc <= pc && pc < fn.highpc) + }) + if i != len(dbp.functions) { + fn := dbp.functions[i] + if fn.lowpc <= pc && pc < fn.highpc { + return fn.offset, nil + } + } + return 0, errors.New("unable to find function context") +} + +func (dbp *Process) expandPackagesInType(expr ast.Expr) { + switch e := expr.(type) { + case *ast.ArrayType: + dbp.expandPackagesInType(e.Elt) + case *ast.ChanType: + dbp.expandPackagesInType(e.Value) + case *ast.FuncType: + for i := range e.Params.List { + dbp.expandPackagesInType(e.Params.List[i].Type) + } + if e.Results != nil { + for i := range e.Results.List { + dbp.expandPackagesInType(e.Results.List[i].Type) + } + } + case *ast.MapType: + dbp.expandPackagesInType(e.Key) + dbp.expandPackagesInType(e.Value) + case *ast.ParenExpr: + dbp.expandPackagesInType(e.X) + case *ast.SelectorExpr: + switch x := e.X.(type) { + case *ast.Ident: + if path, ok := dbp.packageMap[x.Name]; ok { + x.Name = path + } + default: + dbp.expandPackagesInType(e.X) + } + case *ast.StarExpr: + dbp.expandPackagesInType(e.X) + default: + // nothing to do + } +} + +type nameOfRuntimeTypeEntry struct { + typename string + kind int64 +} + +// Returns the type name of the type described in _type. +// _type is a non-loaded Variable pointing to runtime._type struct in the target. +// The returned string is in the format that's used in DWARF data +func nameOfRuntimeType(_type *Variable) (typename string, kind int64, err error) { + if e, ok := _type.dbp.nameOfRuntimeType[_type.Addr]; ok { + return e.typename, e.kind, nil + } + + var tflag int64 + + if tflagField := _type.loadFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil { + tflag, _ = constant.Int64Val(tflagField.Value) + } + if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil { + kind, _ = constant.Int64Val(kindField.Value) + } + + // Named types are defined by a 'type' expression, everything else + // (for example pointers to named types) are not considered named. + if tflag&tflagNamed != 0 { + typename, err = nameOfNamedRuntimeType(_type, kind, tflag) + return typename, kind, err + } else { + typename, err = nameOfUnnamedRuntimeType(_type, kind, tflag) + return typename, kind, err + } + + _type.dbp.nameOfRuntimeType[_type.Addr] = nameOfRuntimeTypeEntry{typename, kind} + + return typename, kind, nil +} + +// The layout of a runtime._type struct is as follows: +// +// +// +// with the 'uncommon type struct' being optional +// +// For named types first we extract the type name from the 'str' +// field in the runtime._type struct. +// Then we prepend the package path from the runtime.uncommontype +// struct, when it exists. +// +// To find out the memory address of the runtime.uncommontype struct +// we first cast the Variable pointing to the runtime._type struct +// to a struct specific to the type's kind (for example, if the type +// being described is a slice type the variable will be specialized +// to a runtime.slicetype). +func nameOfNamedRuntimeType(_type *Variable, kind, tflag int64) (typename string, err error) { + var strOff int64 + if strField := _type.loadFieldNamed("str"); strField != nil && strField.Value != nil { + strOff, _ = constant.Int64Val(strField.Value) + } else { + return "", errors.New("could not find str field") + } + + // The following code is adapted from reflect.(*rtype).Name. + // For a description of how memory is organized for type names read + // the comment to 'type name struct' in $GOROOT/src/reflect/type.go + + typename, _, _, err = _type.dbp.resolveNameOff(_type.Addr, uintptr(strOff)) + if err != nil { + return "", err + } + + if tflag&tflagExtraStar != 0 { + typename = typename[1:] + } + + if i := strings.Index(typename, "."); i >= 0 { + typename = typename[i+1:] + } else { + return typename, nil + } + + // The following code is adapted from reflect.(*rtype).PkgPath in + // $GOROOT/src/reflect/type.go + + _type, err = specificRuntimeType(_type, kind) + if err != nil { + return "", err + } + + if ut := uncommon(_type, tflag); ut != nil { + if pkgPathField := ut.loadFieldNamed("pkgpath"); pkgPathField != nil && pkgPathField.Value != nil { + pkgPathOff, _ := constant.Int64Val(pkgPathField.Value) + pkgPath, _, _, err := _type.dbp.resolveNameOff(_type.Addr, uintptr(pkgPathOff)) + if err != nil { + return "", err + } + typename = pkgPath + "." + typename + } + } + + return typename, nil +} + +func nameOfUnnamedRuntimeType(_type *Variable, kind, tflag int64) (string, error) { + _type, err := specificRuntimeType(_type, kind) + if err != nil { + return "", err + } + + // The types referred to here are defined in $GOROOT/src/runtime/type.go + switch reflect.Kind(kind & kindMask) { + case reflect.Array: + var len int64 + if lenField := _type.loadFieldNamed("len"); lenField != nil && lenField.Value != nil { + len, _ = constant.Int64Val(lenField.Value) + } + elemname, err := fieldToType(_type, "elem") + if err != nil { + return "", err + } + return fmt.Sprintf("[%d]%s", len, elemname), nil + case reflect.Chan: + elemname, err := fieldToType(_type, "elem") + if err != nil { + return "", err + } + return "chan " + elemname, nil + case reflect.Func: + return nameOfFuncRuntimeType(_type, tflag, true) + case reflect.Interface: + return nameOfInterfaceRuntimeType(_type, kind, tflag) + case reflect.Map: + keyname, err := fieldToType(_type, "key") + if err != nil { + return "", err + } + elemname, err := fieldToType(_type, "elem") + if err != nil { + return "", err + } + return "map[" + keyname + "]" + elemname, nil + case reflect.Ptr: + elemname, err := fieldToType(_type, "elem") + if err != nil { + return "", err + } + return "*" + elemname, nil + case reflect.Slice: + elemname, err := fieldToType(_type, "elem") + if err != nil { + return "", err + } + return "[]" + elemname, nil + case reflect.Struct: + return nameOfStructRuntimeType(_type, kind, tflag) + default: + return nameOfNamedRuntimeType(_type, kind, tflag) + } +} + +// Returns the expression describing an anonymous function type. +// A runtime.functype is followed by a runtime.uncommontype +// (optional) and then by an array of pointers to runtime._type, +// one for each input and output argument. +func nameOfFuncRuntimeType(_type *Variable, tflag int64, anonymous bool) (string, error) { + rtyp, err := _type.dbp.findType("runtime._type") + if err != nil { + return "", err + } + prtyp := _type.dbp.pointerTo(rtyp) + + uadd := _type.RealType.Common().ByteSize + if ut := uncommon(_type, tflag); ut != nil { + uadd += ut.RealType.Common().ByteSize + } + + var inCount, outCount int64 + if inCountField := _type.loadFieldNamed("inCount"); inCountField != nil && inCountField.Value != nil { + inCount, _ = constant.Int64Val(inCountField.Value) + } + if outCountField := _type.loadFieldNamed("outCount"); outCountField != nil && outCountField.Value != nil { + outCount, _ = constant.Int64Val(outCountField.Value) + // only the lowest 15 bits of outCount are used, rest are flags + outCount = outCount & (1<<15 - 1) + } + + cursortyp := _type.newVariable("", _type.Addr+uintptr(uadd), prtyp) + var buf bytes.Buffer + if anonymous { + buf.WriteString("func(") + } else { + buf.WriteString("(") + } + + for i := int64(0); i < inCount; i++ { + argtype := cursortyp.maybeDereference() + cursortyp.Addr += uintptr(_type.dbp.arch.PtrSize()) + argtypename, _, err := nameOfRuntimeType(argtype) + if err != nil { + return "", err + } + buf.WriteString(argtypename) + if i != inCount-1 { + buf.WriteString(", ") + } + } + buf.WriteString(")") + + switch outCount { + case 0: + // nothing to do + case 1: + buf.WriteString(" ") + argtype := cursortyp.maybeDereference() + argtypename, _, err := nameOfRuntimeType(argtype) + if err != nil { + return "", err + } + buf.WriteString(argtypename) + default: + buf.WriteString(" (") + for i := int64(0); i < outCount; i++ { + argtype := cursortyp.maybeDereference() + cursortyp.Addr += uintptr(_type.dbp.arch.PtrSize()) + argtypename, _, err := nameOfRuntimeType(argtype) + if err != nil { + return "", err + } + buf.WriteString(argtypename) + if i != inCount-1 { + buf.WriteString(", ") + } + } + buf.WriteString(")") + } + return buf.String(), nil +} + +func nameOfInterfaceRuntimeType(_type *Variable, kind, tflag int64) (string, error) { + var buf bytes.Buffer + buf.WriteString("interface {") + + methods, _ := _type.structMember("methods") + methods.loadArrayValues(0, LoadConfig{false, 1, 0, 4096, -1}) + if methods.Unreadable != nil { + return "", nil + } + + if len(methods.Children) == 0 { + buf.WriteString("}") + return buf.String(), nil + } else { + buf.WriteString(" ") + } + + for i, im := range methods.Children { + var methodname, methodtype string + for i := range im.Children { + switch im.Children[i].Name { + case "name": + nameoff, _ := constant.Int64Val(im.Children[i].Value) + var err error + methodname, _, _, err = _type.dbp.resolveNameOff(_type.Addr, uintptr(nameoff)) + if err != nil { + return "", err + } + + case "typ": + typeoff, _ := constant.Int64Val(im.Children[i].Value) + typ, err := _type.dbp.resolveTypeOff(_type.Addr, uintptr(typeoff)) + if err != nil { + return "", err + } + typ, err = specificRuntimeType(typ, int64(reflect.Func)) + if err != nil { + return "", err + } + var tflag int64 + if tflagField := typ.loadFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil { + tflag, _ = constant.Int64Val(tflagField.Value) + } + methodtype, err = nameOfFuncRuntimeType(typ, tflag, false) + if err != nil { + return "", err + } + } + } + + buf.WriteString(methodname) + buf.WriteString(methodtype) + + if i != len(methods.Children)-1 { + buf.WriteString("; ") + } else { + buf.WriteString(" }") + } + } + return buf.String(), nil +} + +func nameOfStructRuntimeType(_type *Variable, kind, tflag int64) (string, error) { + var buf bytes.Buffer + buf.WriteString("struct {") + + fields, _ := _type.structMember("fields") + fields.loadArrayValues(0, LoadConfig{false, 1, 0, 4096, -1}) + if fields.Unreadable != nil { + return "", fields.Unreadable + } + + if len(fields.Children) == 0 { + buf.WriteString("}") + return buf.String(), nil + } else { + buf.WriteString(" ") + } + + for i, field := range fields.Children { + var fieldname, fieldtypename string + var typeField *Variable + for i := range field.Children { + switch field.Children[i].Name { + case "name": + nameoff, _ := constant.Int64Val(field.Children[i].Value) + var err error + fieldname, _, _, err = _type.dbp.loadName(uintptr(nameoff)) + if err != nil { + return "", err + } + + case "typ": + typeField = field.Children[i].maybeDereference() + var err error + fieldtypename, _, err = nameOfRuntimeType(typeField) + if err != nil { + return "", err + } + } + } + + // fieldname will be the empty string for anonymous fields + if fieldname != "" { + buf.WriteString(fieldname) + buf.WriteString(" ") + } + buf.WriteString(fieldtypename) + if i != len(fields.Children)-1 { + buf.WriteString("; ") + } else { + buf.WriteString(" }") + } + } + + return buf.String(), nil +} + +func fieldToType(_type *Variable, fieldName string) (string, error) { + typeField, err := _type.structMember(fieldName) + if err != nil { + return "", err + } + typeField = typeField.maybeDereference() + typename, _, err := nameOfRuntimeType(typeField) + return typename, err +} + +func specificRuntimeType(_type *Variable, kind int64) (*Variable, error) { + rtyp, err := _type.dbp.findType("runtime._type") + if err != nil { + return nil, err + } + prtyp := _type.dbp.pointerTo(rtyp) + + uintptrtyp, err := _type.dbp.findType("uintptr") + if err != nil { + return nil, err + } + + uint32typ := &dwarf.UintType{dwarf.BasicType{CommonType: dwarf.CommonType{ByteSize: 4, Name: "uint32"}}} + uint16typ := &dwarf.UintType{dwarf.BasicType{CommonType: dwarf.CommonType{ByteSize: 2, Name: "uint16"}}} + + newStructType := func(name string, sz uintptr) *dwarf.StructType { + return &dwarf.StructType{dwarf.CommonType{Name: name, ByteSize: int64(sz)}, name, "struct", nil, false} + } + + appendField := func(typ *dwarf.StructType, name string, fieldtype dwarf.Type, off uintptr) { + typ.Field = append(typ.Field, &dwarf.StructField{Name: name, ByteOffset: int64(off), Type: fieldtype}) + } + + newSliceType := func(elemtype dwarf.Type) *dwarf.SliceType { + r := newStructType("[]"+elemtype.Common().Name, uintptr(3*uintptrtyp.Size())) + appendField(r, "array", _type.dbp.pointerTo(elemtype), 0) + appendField(r, "len", uintptrtyp, uintptr(uintptrtyp.Size())) + appendField(r, "cap", uintptrtyp, uintptr(2*uintptrtyp.Size())) + return &dwarf.SliceType{StructType: *r, ElemType: elemtype} + } + + var typ *dwarf.StructType + + type rtype struct { + size uintptr + ptrdata uintptr + hash uint32 // hash of type; avoids computation in hash tables + tflag uint8 // extra type information flags + align uint8 // alignment of variable with this type + fieldAlign uint8 // alignment of struct field with this type + kind uint8 // enumeration for C + alg *byte // algorithm table + gcdata *byte // garbage collection data + str int32 // string form + ptrToThis int32 // type for pointer to this type, may be zero + } + + switch reflect.Kind(kind & kindMask) { + case reflect.Array: + // runtime.arraytype + var a struct { + rtype + elem *rtype // array element type + slice *rtype // slice type + len uintptr + } + typ = newStructType("runtime.arraytype", unsafe.Sizeof(a)) + appendField(typ, "elem", prtyp, unsafe.Offsetof(a.elem)) + appendField(typ, "len", uintptrtyp, unsafe.Offsetof(a.len)) + case reflect.Chan: + // runtime.chantype + var a struct { + rtype + elem *rtype // channel element type + dir uintptr // channel direction (ChanDir) + } + typ = newStructType("runtime.chantype", unsafe.Sizeof(a)) + appendField(typ, "elem", prtyp, unsafe.Offsetof(a.elem)) + case reflect.Func: + // runtime.functype + var a struct { + rtype `reflect:"func"` + inCount uint16 + outCount uint16 // top bit is set if last input parameter is ... + } + typ = newStructType("runtime.functype", unsafe.Sizeof(a)) + appendField(typ, "inCount", uint16typ, unsafe.Offsetof(a.inCount)) + appendField(typ, "outCount", uint16typ, unsafe.Offsetof(a.outCount)) + case reflect.Interface: + // runtime.imethod + type imethod struct { + name uint32 // name of method + typ uint32 // .(*FuncType) underneath + } + + var im imethod + + // runtime.interfacetype + var a struct { + rtype `reflect:"interface"` + pkgPath *byte // import path + methods []imethod // sorted by hash + } + + imethodtype := newStructType("runtime.imethod", unsafe.Sizeof(im)) + appendField(imethodtype, "name", uint32typ, unsafe.Offsetof(im.name)) + appendField(imethodtype, "typ", uint32typ, unsafe.Offsetof(im.typ)) + typ = newStructType("runtime.interfacetype", unsafe.Sizeof(a)) + appendField(typ, "methods", newSliceType(imethodtype), unsafe.Offsetof(a.methods)) + case reflect.Map: + // runtime.maptype + var a struct { + rtype `reflect:"map"` + key *rtype // map key type + elem *rtype // map element (value) type + bucket *rtype // internal bucket structure + hmap *rtype // internal map header + keysize uint8 // size of key slot + indirectkey uint8 // store ptr to key instead of key itself + valuesize uint8 // size of value slot + indirectvalue uint8 // store ptr to value instead of value itself + bucketsize uint16 // size of bucket + reflexivekey bool // true if k==k for all keys + needkeyupdate bool // true if we need to update key on an overwrite + } + typ = newStructType("runtime.maptype", unsafe.Sizeof(a)) + appendField(typ, "key", prtyp, unsafe.Offsetof(a.key)) + appendField(typ, "elem", prtyp, unsafe.Offsetof(a.elem)) + case reflect.Ptr: + // runtime.ptrtype + var a struct { + rtype `reflect:"ptr"` + elem *rtype // pointer element (pointed at) type + } + typ = newStructType("runtime.ptrtype", unsafe.Sizeof(a)) + appendField(typ, "elem", prtyp, unsafe.Offsetof(a.elem)) + case reflect.Slice: + // runtime.slicetype + var a struct { + rtype `reflect:"slice"` + elem *rtype // slice element type + } + + typ = newStructType("runtime.slicetype", unsafe.Sizeof(a)) + appendField(typ, "elem", prtyp, unsafe.Offsetof(a.elem)) + case reflect.Struct: + // runtime.structtype + type structField struct { + name *byte // name is empty for embedded fields + typ *rtype // type of field + offset uintptr // byte offset of field within struct + } + + var sf structField + + var a struct { + rtype `reflect:"struct"` + pkgPath *byte + fields []structField // sorted by offset + } + + fieldtype := newStructType("runtime.structtype", unsafe.Sizeof(sf)) + appendField(fieldtype, "name", uintptrtyp, unsafe.Offsetof(sf.name)) + appendField(fieldtype, "typ", prtyp, unsafe.Offsetof(sf.typ)) + typ = newStructType("runtime.structtype", unsafe.Sizeof(a)) + appendField(typ, "fields", newSliceType(fieldtype), unsafe.Offsetof(a.fields)) + default: + return _type, nil + } + + return _type.newVariable(_type.Name, _type.Addr, typ), nil +} + +// See reflect.(*rtype).uncommon in $GOROOT/src/reflect/type.go +func uncommon(_type *Variable, tflag int64) *Variable { + if tflag&tflagUncommon == 0 { + return nil + } + + typ, err := _type.dbp.findType("runtime.uncommontype") + if err != nil { + return nil + } + + return _type.newVariable(_type.Name, _type.Addr+uintptr(_type.RealType.Size()), typ) +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/variables.go b/vendor/github.com/derekparker/delve/pkg/proc/variables.go new file mode 100644 index 0000000..f243d04 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/variables.go @@ -0,0 +1,1723 @@ +package proc + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "go/constant" + "go/parser" + "go/token" + "math" + "reflect" + "strings" + "unsafe" + + "github.com/derekparker/delve/pkg/dwarf/op" + "github.com/derekparker/delve/pkg/dwarf/reader" + "golang.org/x/debug/dwarf" +) + +const ( + maxErrCount = 3 // Max number of read errors to accept while evaluating slices, arrays and structs + + maxArrayStridePrefetch = 1024 // Maximum size of array stride for which we will prefetch the array contents + + chanRecv = "chan receive" + chanSend = "chan send" + + hashTophashEmpty = 0 // used by map reading code, indicates an empty bucket + hashMinTopHash = 4 // used by map reading code, indicates minimum value of tophash that isn't empty or evacuated +) + +type FloatSpecial uint8 + +const ( + FloatIsNormal FloatSpecial = iota + FloatIsNaN + FloatIsPosInf + FloatIsNegInf +) + +// Variable represents a variable. It contains the address, name, +// type and other information parsed from both the Dwarf information +// and the memory of the debugged process. +// If OnlyAddr is true, the variables value has not been loaded. +type Variable struct { + Addr uintptr + OnlyAddr bool + Name string + DwarfType dwarf.Type + RealType dwarf.Type + Kind reflect.Kind + mem memoryReadWriter + dbp *Process + + Value constant.Value + FloatSpecial FloatSpecial + + Len int64 + Cap int64 + + // Base address of arrays, Base address of the backing array for slices (0 for nil slices) + // Base address of the backing byte array for strings + // address of the struct backing chan and map variables + // address of the function entry point for function variables (0 for nil function pointers) + Base uintptr + stride int64 + fieldType dwarf.Type + + // number of elements to skip when loading a map + mapSkip int + + Children []Variable + + loaded bool + Unreadable error +} + +type LoadConfig struct { + // FollowPointers requests pointers to be automatically dereferenced. + FollowPointers bool + // MaxVariableRecurse is how far to recurse when evaluating nested types. + MaxVariableRecurse int + // MaxStringLen is the maximum number of bytes read from a string + MaxStringLen int + // MaxArrayValues is the maximum number of elements read from an array, a slice or a map. + MaxArrayValues int + // MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields. + MaxStructFields int +} + +var loadSingleValue = LoadConfig{false, 0, 64, 0, 0} +var loadFullValue = LoadConfig{true, 1, 64, 64, -1} + +// M represents a runtime M (OS thread) structure. +type M struct { + procid int // Thread ID or port. + spinning uint8 // Busy looping. + blocked uint8 // Waiting on futex / semaphore. + curg uintptr // Current G running on this thread. +} + +// G status, from: src/runtime/runtime2.go +const ( + Gidle uint64 = iota // 0 + Grunnable // 1 runnable and on a run queue + Grunning // 2 + Gsyscall // 3 + Gwaiting // 4 + GmoribundUnused // 5 currently unused, but hardcoded in gdb scripts + Gdead // 6 + Genqueue // 7 Only the Gscanenqueue is used. + Gcopystack // 8 in this state when newstack is moving the stack +) + +// G represents a runtime G (goroutine) structure (at least the +// fields that Delve is interested in). +type G struct { + ID int // Goroutine ID + PC uint64 // PC of goroutine when it was parked. + SP uint64 // SP of goroutine when it was parked. + GoPC uint64 // PC of 'go' statement that created this goroutine. + WaitReason string // Reason for goroutine being parked. + Status uint64 + stkbarVar *Variable // stkbar field of g struct + stkbarPos int // stkbarPos field of g struct + + // Information on goroutine location + CurrentLoc Location + + // Thread that this goroutine is currently allocated to + thread *Thread + + variable *Variable + dbp *Process +} + +// EvalScope is the scope for variable evaluation. Contains the thread, +// current location (PC), and canonical frame address. +type EvalScope struct { + Thread *Thread + PC uint64 + CFA int64 +} + +// IsNilErr is returned when a variable is nil. +type IsNilErr struct { + name string +} + +func (err *IsNilErr) Error() string { + return fmt.Sprintf("%s is nil", err.name) +} + +func (scope *EvalScope) newVariable(name string, addr uintptr, dwarfType dwarf.Type) *Variable { + return newVariable(name, addr, dwarfType, scope.Thread.dbp, scope.Thread) +} + +func (t *Thread) newVariable(name string, addr uintptr, dwarfType dwarf.Type) *Variable { + return newVariable(name, addr, dwarfType, t.dbp, t) +} + +func (v *Variable) newVariable(name string, addr uintptr, dwarfType dwarf.Type) *Variable { + return newVariable(name, addr, dwarfType, v.dbp, v.mem) +} + +func newVariable(name string, addr uintptr, dwarfType dwarf.Type, dbp *Process, mem memoryReadWriter) *Variable { + v := &Variable{ + Name: name, + Addr: addr, + DwarfType: dwarfType, + mem: mem, + dbp: dbp, + } + + v.RealType = resolveTypedef(v.DwarfType) + + switch t := v.RealType.(type) { + case *dwarf.PtrType: + v.Kind = reflect.Ptr + if _, isvoid := t.Type.(*dwarf.VoidType); isvoid { + v.Kind = reflect.UnsafePointer + } + case *dwarf.ChanType: + v.Kind = reflect.Chan + case *dwarf.MapType: + v.Kind = reflect.Map + case *dwarf.StringType: + v.Kind = reflect.String + v.stride = 1 + v.fieldType = &dwarf.UintType{BasicType: dwarf.BasicType{CommonType: dwarf.CommonType{ByteSize: 1, Name: "byte"}, BitSize: 8, BitOffset: 0}} + if v.Addr != 0 { + v.Base, v.Len, v.Unreadable = readStringInfo(v.mem, v.dbp.arch, v.Addr) + } + case *dwarf.SliceType: + v.Kind = reflect.Slice + if v.Addr != 0 { + v.loadSliceInfo(t) + } + case *dwarf.InterfaceType: + v.Kind = reflect.Interface + case *dwarf.StructType: + v.Kind = reflect.Struct + case *dwarf.ArrayType: + v.Kind = reflect.Array + v.Base = v.Addr + v.Len = t.Count + v.Cap = -1 + v.fieldType = t.Type + v.stride = 0 + + if t.Count > 0 { + v.stride = t.ByteSize / t.Count + } + case *dwarf.ComplexType: + switch t.ByteSize { + case 8: + v.Kind = reflect.Complex64 + case 16: + v.Kind = reflect.Complex128 + } + case *dwarf.IntType: + v.Kind = reflect.Int + case *dwarf.UintType: + v.Kind = reflect.Uint + case *dwarf.FloatType: + switch t.ByteSize { + case 4: + v.Kind = reflect.Float32 + case 8: + v.Kind = reflect.Float64 + } + case *dwarf.BoolType: + v.Kind = reflect.Bool + case *dwarf.FuncType: + v.Kind = reflect.Func + case *dwarf.VoidType: + v.Kind = reflect.Invalid + case *dwarf.UnspecifiedType: + v.Kind = reflect.Invalid + default: + v.Unreadable = fmt.Errorf("Unknown type: %T", t) + } + + return v +} + +func resolveTypedef(typ dwarf.Type) dwarf.Type { + for { + if tt, ok := typ.(*dwarf.TypedefType); ok { + typ = tt.Type + } else { + return typ + } + } +} + +func newConstant(val constant.Value, mem memoryReadWriter) *Variable { + v := &Variable{Value: val, mem: mem, loaded: true} + switch val.Kind() { + case constant.Int: + v.Kind = reflect.Int + case constant.Float: + v.Kind = reflect.Float64 + case constant.Bool: + v.Kind = reflect.Bool + case constant.Complex: + v.Kind = reflect.Complex128 + case constant.String: + v.Kind = reflect.String + v.Len = int64(len(constant.StringVal(val))) + } + return v +} + +var nilVariable = &Variable{ + Name: "nil", + Addr: 0, + Base: 0, + Kind: reflect.Ptr, + Children: []Variable{{Addr: 0, OnlyAddr: true}}, +} + +func (v *Variable) clone() *Variable { + r := *v + return &r +} + +// TypeString returns the string representation +// of the type of this variable. +func (v *Variable) TypeString() string { + if v == nilVariable { + return "nil" + } + if v.DwarfType != nil { + return v.DwarfType.Common().Name + } + return v.Kind.String() +} + +func (v *Variable) toField(field *dwarf.StructField) (*Variable, error) { + if v.Unreadable != nil { + return v.clone(), nil + } + if v.Addr == 0 { + return nil, &IsNilErr{v.Name} + } + + name := "" + if v.Name != "" { + parts := strings.Split(field.Name, ".") + if len(parts) > 1 { + name = fmt.Sprintf("%s.%s", v.Name, parts[1]) + } else { + name = fmt.Sprintf("%s.%s", v.Name, field.Name) + } + } + return v.newVariable(name, uintptr(int64(v.Addr)+field.ByteOffset), field.Type), nil +} + +// DwarfReader returns the DwarfReader containing the +// Dwarf information for the target process. +func (scope *EvalScope) DwarfReader() *reader.Reader { + return scope.Thread.dbp.DwarfReader() +} + +// Type returns the Dwarf type entry at `offset`. +func (scope *EvalScope) Type(offset dwarf.Offset) (dwarf.Type, error) { + return scope.Thread.dbp.dwarf.Type(offset) +} + +// PtrSize returns the size of a pointer. +func (scope *EvalScope) PtrSize() int { + return scope.Thread.dbp.arch.PtrSize() +} + +// ChanRecvBlocked returns whether the goroutine is blocked on +// a channel read operation. +func (g *G) ChanRecvBlocked() bool { + return (g.thread == nil) && (g.WaitReason == chanRecv) +} + +// chanRecvReturnAddr returns the address of the return from a channel read. +func (g *G) chanRecvReturnAddr(dbp *Process) (uint64, error) { + locs, err := g.Stacktrace(4) + if err != nil { + return 0, err + } + topLoc := locs[len(locs)-1] + return topLoc.Current.PC, nil +} + +// NoGError returned when a G could not be found +// for a specific thread. +type NoGError struct { + tid int +} + +func (ng NoGError) Error() string { + return fmt.Sprintf("no G executing on thread %d", ng.tid) +} + +func (gvar *Variable) parseG() (*G, error) { + mem := gvar.mem + dbp := gvar.dbp + gaddr := uint64(gvar.Addr) + _, deref := gvar.RealType.(*dwarf.PtrType) + + if deref { + gaddrbytes, err := mem.readMemory(uintptr(gaddr), dbp.arch.PtrSize()) + if err != nil { + return nil, fmt.Errorf("error derefing *G %s", err) + } + gaddr = binary.LittleEndian.Uint64(gaddrbytes) + } + if gaddr == 0 { + id := 0 + if thread, ok := mem.(*Thread); ok { + id = thread.ID + } + return nil, NoGError{tid: id} + } + for { + if _, isptr := gvar.RealType.(*dwarf.PtrType); !isptr { + break + } + gvar = gvar.maybeDereference() + } + gvar.loadValue(LoadConfig{false, 1, 64, 0, -1}) + if gvar.Unreadable != nil { + return nil, gvar.Unreadable + } + schedVar := gvar.fieldVariable("sched") + pc, _ := constant.Int64Val(schedVar.fieldVariable("pc").Value) + sp, _ := constant.Int64Val(schedVar.fieldVariable("sp").Value) + id, _ := constant.Int64Val(gvar.fieldVariable("goid").Value) + gopc, _ := constant.Int64Val(gvar.fieldVariable("gopc").Value) + waitReason := constant.StringVal(gvar.fieldVariable("waitreason").Value) + + stkbarVar, _ := gvar.structMember("stkbar") + stkbarVarPosFld := gvar.fieldVariable("stkbarPos") + var stkbarPos int64 + if stkbarVarPosFld != nil { // stack barriers were removed in Go 1.9 + stkbarPos, _ = constant.Int64Val(stkbarVarPosFld.Value) + } + + status, _ := constant.Int64Val(gvar.fieldVariable("atomicstatus").Value) + f, l, fn := gvar.dbp.goSymTable.PCToLine(uint64(pc)) + g := &G{ + ID: int(id), + GoPC: uint64(gopc), + PC: uint64(pc), + SP: uint64(sp), + WaitReason: waitReason, + Status: uint64(status), + CurrentLoc: Location{PC: uint64(pc), File: f, Line: l, Fn: fn}, + variable: gvar, + stkbarVar: stkbarVar, + stkbarPos: int(stkbarPos), + dbp: gvar.dbp, + } + return g, nil +} + +func (v *Variable) loadFieldNamed(name string) *Variable { + v, err := v.structMember(name) + if err != nil { + return nil + } + v.loadValue(loadFullValue) + if v.Unreadable != nil { + return nil + } + return v +} + +func (v *Variable) fieldVariable(name string) *Variable { + for i := range v.Children { + if child := &v.Children[i]; child.Name == name { + return child + } + } + return nil +} + +// PC of entry to top-most deferred function. +func (g *G) DeferPC() uint64 { + if g.variable.Unreadable != nil { + return 0 + } + d := g.variable.fieldVariable("_defer").maybeDereference() + if d.Addr == 0 { + return 0 + } + d.loadValue(LoadConfig{false, 1, 64, 0, -1}) + if d.Unreadable != nil { + return 0 + } + fnvar := d.fieldVariable("fn").maybeDereference() + if fnvar.Addr == 0 { + return 0 + } + fnvar.loadValue(LoadConfig{false, 1, 64, 0, -1}) + if fnvar.Unreadable != nil { + return 0 + } + deferPC, _ := constant.Int64Val(fnvar.fieldVariable("fn").Value) + return uint64(deferPC) +} + +// From $GOROOT/src/runtime/traceback.go:597 +// isExportedRuntime reports whether name is an exported runtime function. +// It is only for runtime functions, so ASCII A-Z is fine. +func isExportedRuntime(name string) bool { + const n = len("runtime.") + return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z' +} + +// UserCurrent returns the location the users code is at, +// or was at before entering a runtime function. +func (g *G) UserCurrent() Location { + it, err := g.stackIterator() + if err != nil { + return g.CurrentLoc + } + for it.Next() { + frame := it.Frame() + if frame.Call.Fn != nil { + name := frame.Call.Fn.Name + if (strings.Index(name, ".") >= 0) && (!strings.HasPrefix(name, "runtime.") || isExportedRuntime(name)) { + return frame.Call + } + } + } + return g.CurrentLoc +} + +// Go returns the location of the 'go' statement +// that spawned this goroutine. +func (g *G) Go() Location { + f, l, fn := g.dbp.goSymTable.PCToLine(g.GoPC) + return Location{PC: g.GoPC, File: f, Line: l, Fn: fn} +} + +// Returns the list of saved return addresses used by stack barriers +func (g *G) stkbar() ([]savedLR, error) { + if g.stkbarVar == nil { // stack barriers were removed in Go 1.9 + return nil, nil + } + g.stkbarVar.loadValue(LoadConfig{false, 1, 0, int(g.stkbarVar.Len), 3}) + if g.stkbarVar.Unreadable != nil { + return nil, fmt.Errorf("unreadable stkbar: %v\n", g.stkbarVar.Unreadable) + } + r := make([]savedLR, len(g.stkbarVar.Children)) + for i, child := range g.stkbarVar.Children { + for _, field := range child.Children { + switch field.Name { + case "savedLRPtr": + ptr, _ := constant.Int64Val(field.Value) + r[i].ptr = uint64(ptr) + case "savedLRVal": + val, _ := constant.Int64Val(field.Value) + r[i].val = uint64(val) + } + } + } + return r, nil +} + +// EvalVariable returns the value of the given expression (backwards compatibility). +func (scope *EvalScope) EvalVariable(name string, cfg LoadConfig) (*Variable, error) { + return scope.EvalExpression(name, cfg) +} + +// SetVariable sets the value of the named variable +func (scope *EvalScope) SetVariable(name, value string) error { + t, err := parser.ParseExpr(name) + if err != nil { + return err + } + + xv, err := scope.evalAST(t) + if err != nil { + return err + } + + if xv.Addr == 0 { + return fmt.Errorf("Can not assign to \"%s\"", name) + } + + if xv.Unreadable != nil { + return fmt.Errorf("Expression \"%s\" is unreadable: %v", name, xv.Unreadable) + } + + t, err = parser.ParseExpr(value) + if err != nil { + return err + } + + yv, err := scope.evalAST(t) + if err != nil { + return err + } + + yv.loadValue(loadSingleValue) + + if err := yv.isType(xv.RealType, xv.Kind); err != nil { + return err + } + + if yv.Unreadable != nil { + return fmt.Errorf("Expression \"%s\" is unreadable: %v", value, yv.Unreadable) + } + + return xv.setValue(yv) +} + +func (scope *EvalScope) extractVariableFromEntry(entry *dwarf.Entry, cfg LoadConfig) (*Variable, error) { + rdr := scope.DwarfReader() + v, err := scope.extractVarInfoFromEntry(entry, rdr) + if err != nil { + return nil, err + } + return v, nil +} + +func (scope *EvalScope) extractVarInfo(varName string) (*Variable, error) { + reader := scope.DwarfReader() + off, err := scope.Thread.dbp.findFunctionDebugInfo(scope.PC) + if err != nil { + return nil, err + } + reader.Seek(off) + reader.Next() + + for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() { + if err != nil { + return nil, err + } + if entry.Tag == 0 { + break + } + + n, ok := entry.Val(dwarf.AttrName).(string) + if !ok { + continue + } + + if n == varName { + return scope.extractVarInfoFromEntry(entry, reader) + } + } + return nil, fmt.Errorf("could not find symbol value for %s", varName) +} + +// LocalVariables returns all local variables from the current function scope. +func (scope *EvalScope) LocalVariables(cfg LoadConfig) ([]*Variable, error) { + return scope.variablesByTag(dwarf.TagVariable, cfg) +} + +// FunctionArguments returns the name, value, and type of all current function arguments. +func (scope *EvalScope) FunctionArguments(cfg LoadConfig) ([]*Variable, error) { + return scope.variablesByTag(dwarf.TagFormalParameter, cfg) +} + +// PackageVariables returns the name, value, and type of all package variables in the application. +func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) { + var vars []*Variable + reader := scope.DwarfReader() + + var utypoff dwarf.Offset + utypentry, err := reader.SeekToTypeNamed("") + if err == nil { + utypoff = utypentry.Offset + } + + for entry, err := reader.NextPackageVariable(); entry != nil; entry, err = reader.NextPackageVariable() { + if err != nil { + return nil, err + } + + if typoff, ok := entry.Val(dwarf.AttrType).(dwarf.Offset); !ok || typoff == utypoff { + continue + } + + // Ignore errors trying to extract values + val, err := scope.extractVariableFromEntry(entry, cfg) + if err != nil { + continue + } + val.loadValue(cfg) + vars = append(vars, val) + } + + return vars, nil +} + +// EvalPackageVariable will evaluate the package level variable +// specified by 'name'. +func (dbp *Process) EvalPackageVariable(name string, cfg LoadConfig) (*Variable, error) { + scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0} + + v, err := scope.packageVarAddr(name) + if err != nil { + return nil, err + } + v.loadValue(cfg) + return v, nil +} + +func (scope *EvalScope) packageVarAddr(name string) (*Variable, error) { + reader := scope.DwarfReader() + for entry, err := reader.NextPackageVariable(); entry != nil; entry, err = reader.NextPackageVariable() { + if err != nil { + return nil, err + } + + n, ok := entry.Val(dwarf.AttrName).(string) + if !ok { + continue + } + + if n == name { + return scope.extractVarInfoFromEntry(entry, reader) + } + } + return nil, fmt.Errorf("could not find symbol value for %s", name) +} + +func (v *Variable) structMember(memberName string) (*Variable, error) { + if v.Unreadable != nil { + return v.clone(), nil + } + structVar := v.maybeDereference() + structVar.Name = v.Name + if structVar.Unreadable != nil { + return structVar, nil + } + + switch t := structVar.RealType.(type) { + case *dwarf.StructType: + for _, field := range t.Field { + if field.Name != memberName { + continue + } + return structVar.toField(field) + } + // Check for embedded field only if field was + // not a regular struct member + for _, field := range t.Field { + isEmbeddedStructMember := + (field.Type.Common().Name == field.Name) || + (len(field.Name) > 1 && + field.Name[0] == '*' && + field.Type.Common().Name[1:] == field.Name[1:]) + if !isEmbeddedStructMember { + continue + } + // Check for embedded field referenced by type name + parts := strings.Split(field.Name, ".") + if len(parts) > 1 && parts[1] == memberName { + embeddedVar, err := structVar.toField(field) + if err != nil { + return nil, err + } + return embeddedVar, nil + } + // Recursively check for promoted fields on the embedded field + embeddedVar, err := structVar.toField(field) + if err != nil { + return nil, err + } + embeddedVar.Name = structVar.Name + embeddedField, err := embeddedVar.structMember(memberName) + if embeddedField != nil { + return embeddedField, nil + } + } + return nil, fmt.Errorf("%s has no member %s", v.Name, memberName) + default: + if v.Name == "" { + return nil, fmt.Errorf("type %s is not a struct", structVar.TypeString()) + } + return nil, fmt.Errorf("%s (type %s) is not a struct", v.Name, structVar.TypeString()) + } +} + +// Extracts the name and type of a variable from a dwarf entry +// then executes the instructions given in the DW_AT_location attribute to grab the variable's address +func (scope *EvalScope) extractVarInfoFromEntry(entry *dwarf.Entry, rdr *reader.Reader) (*Variable, error) { + if entry == nil { + return nil, fmt.Errorf("invalid entry") + } + + if entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagVariable { + return nil, fmt.Errorf("invalid entry tag, only supports FormalParameter and Variable, got %s", entry.Tag.String()) + } + + n, ok := entry.Val(dwarf.AttrName).(string) + if !ok { + return nil, fmt.Errorf("type assertion failed") + } + + offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset) + if !ok { + return nil, fmt.Errorf("type assertion failed") + } + + t, err := scope.Type(offset) + if err != nil { + return nil, err + } + + instructions, ok := entry.Val(dwarf.AttrLocation).([]byte) + if !ok { + return nil, fmt.Errorf("type assertion failed") + } + + addr, err := op.ExecuteStackProgram(scope.CFA, instructions) + if err != nil { + return nil, err + } + + return scope.newVariable(n, uintptr(addr), t), nil +} + +// If v is a pointer a new variable is returned containing the value pointed by v. +func (v *Variable) maybeDereference() *Variable { + if v.Unreadable != nil { + return v + } + + switch t := v.RealType.(type) { + case *dwarf.PtrType: + ptrval, err := readUintRaw(v.mem, uintptr(v.Addr), t.ByteSize) + r := v.newVariable("", uintptr(ptrval), t.Type) + if err != nil { + r.Unreadable = err + } + + return r + default: + return v + } +} + +// Extracts the value of the variable at the given address. +func (v *Variable) loadValue(cfg LoadConfig) { + v.loadValueInternal(0, cfg) +} + +func (v *Variable) loadValueInternal(recurseLevel int, cfg LoadConfig) { + if v.Unreadable != nil || v.loaded || (v.Addr == 0 && v.Base == 0) { + return + } + + v.loaded = true + switch v.Kind { + case reflect.Ptr, reflect.UnsafePointer: + v.Len = 1 + v.Children = []Variable{*v.maybeDereference()} + if cfg.FollowPointers { + // Don't increase the recursion level when dereferencing pointers + // unless this is a pointer to interface (which could cause an infinite loop) + nextLvl := recurseLevel + if v.Children[0].Kind == reflect.Interface { + nextLvl++ + } + v.Children[0].loadValueInternal(nextLvl, cfg) + } else { + v.Children[0].OnlyAddr = true + } + + case reflect.Chan: + sv := v.clone() + sv.RealType = resolveTypedef(&(sv.RealType.(*dwarf.ChanType).TypedefType)) + sv = sv.maybeDereference() + sv.loadValueInternal(0, loadFullValue) + v.Children = sv.Children + v.Len = sv.Len + v.Base = sv.Addr + + case reflect.Map: + if recurseLevel <= cfg.MaxVariableRecurse { + v.loadMap(recurseLevel, cfg) + } + + case reflect.String: + var val string + val, v.Unreadable = readStringValue(v.mem, v.Base, v.Len, cfg) + v.Value = constant.MakeString(val) + + case reflect.Slice, reflect.Array: + v.loadArrayValues(recurseLevel, cfg) + + case reflect.Struct: + v.mem = cacheMemory(v.mem, v.Addr, int(v.RealType.Size())) + t := v.RealType.(*dwarf.StructType) + v.Len = int64(len(t.Field)) + // Recursively call extractValue to grab + // the value of all the members of the struct. + if recurseLevel <= cfg.MaxVariableRecurse { + v.Children = make([]Variable, 0, len(t.Field)) + for i, field := range t.Field { + if cfg.MaxStructFields >= 0 && len(v.Children) >= cfg.MaxStructFields { + break + } + f, _ := v.toField(field) + v.Children = append(v.Children, *f) + v.Children[i].Name = field.Name + v.Children[i].loadValueInternal(recurseLevel+1, cfg) + } + } + + case reflect.Interface: + v.loadInterface(recurseLevel, true, cfg) + + case reflect.Complex64, reflect.Complex128: + v.readComplex(v.RealType.(*dwarf.ComplexType).ByteSize) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + var val int64 + val, v.Unreadable = readIntRaw(v.mem, v.Addr, v.RealType.(*dwarf.IntType).ByteSize) + v.Value = constant.MakeInt64(val) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + var val uint64 + val, v.Unreadable = readUintRaw(v.mem, v.Addr, v.RealType.(*dwarf.UintType).ByteSize) + v.Value = constant.MakeUint64(val) + + case reflect.Bool: + val, err := v.mem.readMemory(v.Addr, 1) + v.Unreadable = err + if err == nil { + v.Value = constant.MakeBool(val[0] != 0) + } + case reflect.Float32, reflect.Float64: + var val float64 + val, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) + v.Value = constant.MakeFloat64(val) + switch { + case math.IsInf(val, +1): + v.FloatSpecial = FloatIsPosInf + case math.IsInf(val, -1): + v.FloatSpecial = FloatIsNegInf + case math.IsNaN(val): + v.FloatSpecial = FloatIsNaN + } + case reflect.Func: + v.readFunctionPtr() + default: + v.Unreadable = fmt.Errorf("unknown or unsupported kind: \"%s\"", v.Kind.String()) + } +} + +func (v *Variable) setValue(y *Variable) error { + var err error + switch v.Kind { + case reflect.Float32, reflect.Float64: + f, _ := constant.Float64Val(y.Value) + err = v.writeFloatRaw(f, v.RealType.Size()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, _ := constant.Int64Val(y.Value) + err = v.writeUint(uint64(n), v.RealType.Size()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + n, _ := constant.Uint64Val(y.Value) + err = v.writeUint(n, v.RealType.Size()) + case reflect.Bool: + err = v.writeBool(constant.BoolVal(y.Value)) + case reflect.Complex64, reflect.Complex128: + real, _ := constant.Float64Val(constant.Real(y.Value)) + imag, _ := constant.Float64Val(constant.Imag(y.Value)) + err = v.writeComplex(real, imag, v.RealType.Size()) + default: + if t, isptr := v.RealType.(*dwarf.PtrType); isptr { + err = v.writeUint(uint64(y.Children[0].Addr), int64(t.ByteSize)) + } else { + return fmt.Errorf("can not set variables of type %s (not implemented)", v.Kind.String()) + } + } + + return err +} + +func readStringInfo(mem memoryReadWriter, arch Arch, addr uintptr) (uintptr, int64, error) { + // string data structure is always two ptrs in size. Addr, followed by len + // http://research.swtch.com/godata + + mem = cacheMemory(mem, addr, arch.PtrSize()*2) + + // read len + val, err := mem.readMemory(addr+uintptr(arch.PtrSize()), arch.PtrSize()) + if err != nil { + return 0, 0, fmt.Errorf("could not read string len %s", err) + } + strlen := int64(binary.LittleEndian.Uint64(val)) + if strlen < 0 { + return 0, 0, fmt.Errorf("invalid length: %d", strlen) + } + + // read addr + val, err = mem.readMemory(addr, arch.PtrSize()) + if err != nil { + return 0, 0, fmt.Errorf("could not read string pointer %s", err) + } + addr = uintptr(binary.LittleEndian.Uint64(val)) + if addr == 0 { + return 0, 0, nil + } + + return addr, strlen, nil +} + +func readStringValue(mem memoryReadWriter, addr uintptr, strlen int64, cfg LoadConfig) (string, error) { + count := strlen + if count > int64(cfg.MaxStringLen) { + count = int64(cfg.MaxStringLen) + } + + val, err := mem.readMemory(addr, int(count)) + if err != nil { + return "", fmt.Errorf("could not read string at %#v due to %s", addr, err) + } + + retstr := *(*string)(unsafe.Pointer(&val)) + + return retstr, nil +} + +func (v *Variable) loadSliceInfo(t *dwarf.SliceType) { + v.mem = cacheMemory(v.mem, v.Addr, int(t.Size())) + + var err error + for _, f := range t.Field { + switch f.Name { + case "array": + var base uint64 + base, err = readUintRaw(v.mem, uintptr(int64(v.Addr)+f.ByteOffset), f.Type.Size()) + if err == nil { + v.Base = uintptr(base) + // Dereference array type to get value type + ptrType, ok := f.Type.(*dwarf.PtrType) + if !ok { + v.Unreadable = fmt.Errorf("Invalid type %s in slice array", f.Type) + return + } + v.fieldType = ptrType.Type + } + case "len": + lstrAddr, _ := v.toField(f) + lstrAddr.loadValue(loadSingleValue) + err = lstrAddr.Unreadable + if err == nil { + v.Len, _ = constant.Int64Val(lstrAddr.Value) + } + case "cap": + cstrAddr, _ := v.toField(f) + cstrAddr.loadValue(loadSingleValue) + err = cstrAddr.Unreadable + if err == nil { + v.Cap, _ = constant.Int64Val(cstrAddr.Value) + } + } + if err != nil { + v.Unreadable = err + return + } + } + + v.stride = v.fieldType.Size() + if t, ok := v.fieldType.(*dwarf.PtrType); ok { + v.stride = t.ByteSize + } + + return +} + +func (v *Variable) loadArrayValues(recurseLevel int, cfg LoadConfig) { + if v.Unreadable != nil { + return + } + if v.Len < 0 { + v.Unreadable = errors.New("Negative array length") + return + } + + count := v.Len + // Cap number of elements + if count > int64(cfg.MaxArrayValues) { + count = int64(cfg.MaxArrayValues) + } + + if v.stride < maxArrayStridePrefetch { + v.mem = cacheMemory(v.mem, v.Base, int(v.stride*count)) + } + + errcount := 0 + + for i := int64(0); i < count; i++ { + fieldvar := v.newVariable("", uintptr(int64(v.Base)+(i*v.stride)), v.fieldType) + fieldvar.loadValueInternal(recurseLevel+1, cfg) + + if fieldvar.Unreadable != nil { + errcount++ + } + + v.Children = append(v.Children, *fieldvar) + if errcount > maxErrCount { + break + } + } +} + +func (v *Variable) readComplex(size int64) { + var fs int64 + switch size { + case 8: + fs = 4 + case 16: + fs = 8 + default: + v.Unreadable = fmt.Errorf("invalid size (%d) for complex type", size) + return + } + + ftyp := &dwarf.FloatType{BasicType: dwarf.BasicType{CommonType: dwarf.CommonType{ByteSize: fs, Name: fmt.Sprintf("float%d", fs)}, BitSize: fs * 8, BitOffset: 0}} + + realvar := v.newVariable("real", v.Addr, ftyp) + imagvar := v.newVariable("imaginary", v.Addr+uintptr(fs), ftyp) + realvar.loadValue(loadSingleValue) + imagvar.loadValue(loadSingleValue) + v.Value = constant.BinaryOp(realvar.Value, token.ADD, constant.MakeImag(imagvar.Value)) +} + +func (v *Variable) writeComplex(real, imag float64, size int64) error { + err := v.writeFloatRaw(real, int64(size/2)) + if err != nil { + return err + } + imagaddr := *v + imagaddr.Addr += uintptr(size / 2) + return imagaddr.writeFloatRaw(imag, int64(size/2)) +} + +func readIntRaw(mem memoryReadWriter, addr uintptr, size int64) (int64, error) { + var n int64 + + val, err := mem.readMemory(addr, int(size)) + if err != nil { + return 0, err + } + + switch size { + case 1: + n = int64(int8(val[0])) + case 2: + n = int64(int16(binary.LittleEndian.Uint16(val))) + case 4: + n = int64(int32(binary.LittleEndian.Uint32(val))) + case 8: + n = int64(binary.LittleEndian.Uint64(val)) + } + + return n, nil +} + +func (v *Variable) writeUint(value uint64, size int64) error { + val := make([]byte, size) + + switch size { + case 1: + val[0] = byte(value) + case 2: + binary.LittleEndian.PutUint16(val, uint16(value)) + case 4: + binary.LittleEndian.PutUint32(val, uint32(value)) + case 8: + binary.LittleEndian.PutUint64(val, uint64(value)) + } + + _, err := v.mem.writeMemory(v.Addr, val) + return err +} + +func readUintRaw(mem memoryReadWriter, addr uintptr, size int64) (uint64, error) { + var n uint64 + + val, err := mem.readMemory(addr, int(size)) + if err != nil { + return 0, err + } + + switch size { + case 1: + n = uint64(val[0]) + case 2: + n = uint64(binary.LittleEndian.Uint16(val)) + case 4: + n = uint64(binary.LittleEndian.Uint32(val)) + case 8: + n = uint64(binary.LittleEndian.Uint64(val)) + } + + return n, nil +} + +func (v *Variable) readFloatRaw(size int64) (float64, error) { + val, err := v.mem.readMemory(v.Addr, int(size)) + if err != nil { + return 0.0, err + } + buf := bytes.NewBuffer(val) + + switch size { + case 4: + n := float32(0) + binary.Read(buf, binary.LittleEndian, &n) + return float64(n), nil + case 8: + n := float64(0) + binary.Read(buf, binary.LittleEndian, &n) + return n, nil + } + + return 0.0, fmt.Errorf("could not read float") +} + +func (v *Variable) writeFloatRaw(f float64, size int64) error { + buf := bytes.NewBuffer(make([]byte, 0, size)) + + switch size { + case 4: + n := float32(f) + binary.Write(buf, binary.LittleEndian, n) + case 8: + n := float64(f) + binary.Write(buf, binary.LittleEndian, n) + } + + _, err := v.mem.writeMemory(v.Addr, buf.Bytes()) + return err +} + +func (v *Variable) writeBool(value bool) error { + val := []byte{0} + val[0] = *(*byte)(unsafe.Pointer(&value)) + _, err := v.mem.writeMemory(v.Addr, val) + return err +} + +func (v *Variable) readFunctionPtr() { + val, err := v.mem.readMemory(v.Addr, v.dbp.arch.PtrSize()) + if err != nil { + v.Unreadable = err + return + } + + // dereference pointer to find function pc + fnaddr := uintptr(binary.LittleEndian.Uint64(val)) + if fnaddr == 0 { + v.Base = 0 + v.Value = constant.MakeString("") + return + } + + val, err = v.mem.readMemory(fnaddr, v.dbp.arch.PtrSize()) + if err != nil { + v.Unreadable = err + return + } + + v.Base = uintptr(binary.LittleEndian.Uint64(val)) + fn := v.dbp.goSymTable.PCToFunc(uint64(v.Base)) + if fn == nil { + v.Unreadable = fmt.Errorf("could not find function for %#v", v.Base) + return + } + + v.Value = constant.MakeString(fn.Name) +} + +func (v *Variable) loadMap(recurseLevel int, cfg LoadConfig) { + it := v.mapIterator() + if it == nil { + return + } + + for skip := 0; skip < v.mapSkip; skip++ { + if ok := it.next(); !ok { + v.Unreadable = fmt.Errorf("map index out of bounds") + return + } + } + + count := 0 + errcount := 0 + for it.next() { + if count >= cfg.MaxArrayValues { + break + } + key := it.key() + val := it.value() + key.loadValueInternal(recurseLevel+1, cfg) + val.loadValueInternal(recurseLevel+1, cfg) + if key.Unreadable != nil || val.Unreadable != nil { + errcount++ + } + v.Children = append(v.Children, *key) + v.Children = append(v.Children, *val) + count++ + if errcount > maxErrCount { + break + } + } +} + +type mapIterator struct { + v *Variable + numbuckets uint64 + oldmask uint64 + buckets *Variable + oldbuckets *Variable + b *Variable + bidx uint64 + + tophashes *Variable + keys *Variable + values *Variable + overflow *Variable + + idx int64 +} + +// Code derived from go/src/runtime/hashmap.go +func (v *Variable) mapIterator() *mapIterator { + sv := v.clone() + sv.RealType = resolveTypedef(&(sv.RealType.(*dwarf.MapType).TypedefType)) + sv = sv.maybeDereference() + v.Base = sv.Addr + + maptype, ok := sv.RealType.(*dwarf.StructType) + if !ok { + v.Unreadable = fmt.Errorf("wrong real type for map") + return nil + } + + it := &mapIterator{v: v, bidx: 0, b: nil, idx: 0} + + if sv.Addr == 0 { + it.numbuckets = 0 + return it + } + + v.mem = cacheMemory(v.mem, v.Base, int(v.RealType.Size())) + + for _, f := range maptype.Field { + var err error + field, _ := sv.toField(f) + switch f.Name { + case "count": + v.Len, err = field.asInt() + case "B": + var b uint64 + b, err = field.asUint() + it.numbuckets = 1 << b + it.oldmask = (1 << (b - 1)) - 1 + case "buckets": + it.buckets = field.maybeDereference() + case "oldbuckets": + it.oldbuckets = field.maybeDereference() + } + if err != nil { + v.Unreadable = err + return nil + } + } + + if it.buckets.Kind != reflect.Struct || it.oldbuckets.Kind != reflect.Struct { + v.Unreadable = mapBucketsNotStructErr + return nil + } + + return it +} + +var mapBucketContentsNotArrayErr = errors.New("malformed map type: keys, values or tophash of a bucket is not an array") +var mapBucketContentsInconsistentLenErr = errors.New("malformed map type: inconsistent array length in bucket") +var mapBucketsNotStructErr = errors.New("malformed map type: buckets, oldbuckets or overflow field not a struct") + +func (it *mapIterator) nextBucket() bool { + if it.overflow != nil && it.overflow.Addr > 0 { + it.b = it.overflow + } else { + it.b = nil + + for it.bidx < it.numbuckets { + it.b = it.buckets.clone() + it.b.Addr += uintptr(uint64(it.buckets.DwarfType.Size()) * it.bidx) + + if it.oldbuckets.Addr <= 0 { + break + } + + // if oldbuckets is not nil we are iterating through a map that is in + // the middle of a grow. + // if the bucket we are looking at hasn't been filled in we iterate + // instead through its corresponding "oldbucket" (i.e. the bucket the + // elements of this bucket are coming from) but only if this is the first + // of the two buckets being created from the same oldbucket (otherwise we + // would print some keys twice) + + oldbidx := it.bidx & it.oldmask + oldb := it.oldbuckets.clone() + oldb.Addr += uintptr(uint64(it.oldbuckets.DwarfType.Size()) * oldbidx) + + if mapEvacuated(oldb) { + break + } + + if oldbidx == it.bidx { + it.b = oldb + break + } + + // oldbucket origin for current bucket has not been evacuated but we have already + // iterated over it so we should just skip it + it.b = nil + it.bidx++ + } + + if it.b == nil { + return false + } + it.bidx++ + } + + if it.b.Addr <= 0 { + return false + } + + it.b.mem = cacheMemory(it.b.mem, it.b.Addr, int(it.b.RealType.Size())) + + it.tophashes = nil + it.keys = nil + it.values = nil + it.overflow = nil + + for _, f := range it.b.DwarfType.(*dwarf.StructType).Field { + field, err := it.b.toField(f) + if err != nil { + it.v.Unreadable = err + return false + } + if field.Unreadable != nil { + it.v.Unreadable = field.Unreadable + return false + } + + switch f.Name { + case "tophash": + it.tophashes = field + case "keys": + it.keys = field + case "values": + it.values = field + case "overflow": + it.overflow = field.maybeDereference() + } + } + + // sanity checks + if it.tophashes == nil || it.keys == nil || it.values == nil { + it.v.Unreadable = fmt.Errorf("malformed map type") + return false + } + + if it.tophashes.Kind != reflect.Array || it.keys.Kind != reflect.Array || it.values.Kind != reflect.Array { + it.v.Unreadable = mapBucketContentsNotArrayErr + return false + } + + if it.tophashes.Len != it.keys.Len || it.tophashes.Len != it.values.Len { + it.v.Unreadable = mapBucketContentsInconsistentLenErr + return false + } + + if it.overflow.Kind != reflect.Struct { + it.v.Unreadable = mapBucketsNotStructErr + return false + } + + return true +} + +func (it *mapIterator) next() bool { + for { + if it.b == nil || it.idx >= it.tophashes.Len { + r := it.nextBucket() + if !r { + return false + } + it.idx = 0 + } + tophash, _ := it.tophashes.sliceAccess(int(it.idx)) + h, err := tophash.asUint() + if err != nil { + it.v.Unreadable = fmt.Errorf("unreadable tophash: %v", err) + return false + } + it.idx++ + if h != hashTophashEmpty { + return true + } + } +} + +func (it *mapIterator) key() *Variable { + k, _ := it.keys.sliceAccess(int(it.idx - 1)) + return k +} + +func (it *mapIterator) value() *Variable { + v, _ := it.values.sliceAccess(int(it.idx - 1)) + return v +} + +func mapEvacuated(b *Variable) bool { + if b.Addr == 0 { + return true + } + for _, f := range b.DwarfType.(*dwarf.StructType).Field { + if f.Name != "tophash" { + continue + } + tophashes, _ := b.toField(f) + tophash0var, _ := tophashes.sliceAccess(0) + tophash0, err := tophash0var.asUint() + if err != nil { + return true + } + return tophash0 > hashTophashEmpty && tophash0 < hashMinTopHash + } + return true +} + +func (v *Variable) loadInterface(recurseLevel int, loadData bool, cfg LoadConfig) { + var _type, typestring, data *Variable + var typ dwarf.Type + var err error + isnil := false + + // An interface variable is implemented either by a runtime.iface + // struct or a runtime.eface struct. The difference being that empty + // interfaces (i.e. "interface {}") are represented by runtime.eface + // and non-empty interfaces by runtime.iface. + // + // For both runtime.ifaces and runtime.efaces the data is stored in v.data + // + // The concrete type however is stored in v.tab._type for non-empty + // interfaces and in v._type for empty interfaces. + // + // For nil empty interface variables _type will be nil, for nil + // non-empty interface variables tab will be nil + // + // In either case the _type field is a pointer to a runtime._type struct. + // + // Before go1.7 _type used to have a field named 'string' containing + // the name of the type. Since go1.7 the field has been replaced by a + // str field that contains an offset in the module data, the concrete + // type must be calculated using the str address along with the value + // of v.tab._type (v._type for empty interfaces). + // + // The following code works for both runtime.iface and runtime.eface + // and sets the go17 flag when the 'string' field can not be found + // but the str field was found + + go17 := false + + v.mem = cacheMemory(v.mem, v.Addr, int(v.RealType.Size())) + + ityp := resolveTypedef(&v.RealType.(*dwarf.InterfaceType).TypedefType).(*dwarf.StructType) + + for _, f := range ityp.Field { + switch f.Name { + case "tab": // for runtime.iface + tab, _ := v.toField(f) + tab = tab.maybeDereference() + isnil = tab.Addr == 0 + if !isnil { + _type, err = tab.structMember("_type") + if err != nil { + v.Unreadable = fmt.Errorf("invalid interface type: %v", err) + return + } + typestring, err = _type.structMember("_string") + if err == nil { + typestring = typestring.maybeDereference() + } else { + go17 = true + } + } + case "_type": // for runtime.eface + _type, _ = v.toField(f) + _type = _type.maybeDereference() + isnil = _type.Addr == 0 + if !isnil { + typestring, err = _type.structMember("_string") + if err == nil { + typestring = typestring.maybeDereference() + } else { + go17 = true + } + } + case "data": + data, _ = v.toField(f) + } + } + + if isnil { + // interface to nil + data = data.maybeDereference() + v.Children = []Variable{*data} + if loadData { + v.Children[0].loadValueInternal(recurseLevel, cfg) + } + return + } + + if data == nil { + v.Unreadable = fmt.Errorf("invalid interface type") + return + } + + var kind int64 + + if go17 { + // No 'string' field use 'str' and 'runtime.firstmoduledata' to + // find out what the concrete type is + _type = _type.maybeDereference() + + var typename string + typename, kind, err = nameOfRuntimeType(_type) + if err != nil { + v.Unreadable = fmt.Errorf("invalid interface type: %v", err) + return + } + + typ, err = v.dbp.findType(typename) + if err != nil { + v.Unreadable = fmt.Errorf("interface type %q not found for %#x: %v", typename, data.Addr, err) + return + } + } else { + if typestring == nil || typestring.Addr == 0 || typestring.Kind != reflect.String { + v.Unreadable = fmt.Errorf("invalid interface type") + return + } + typestring.loadValue(LoadConfig{false, 0, 512, 0, 0}) + if typestring.Unreadable != nil { + v.Unreadable = fmt.Errorf("invalid interface type: %v", typestring.Unreadable) + return + } + + typename := constant.StringVal(typestring.Value) + + t, err := parser.ParseExpr(typename) + if err != nil { + v.Unreadable = fmt.Errorf("invalid interface type, unparsable data type: %v", err) + return + } + + typ, err = v.dbp.findTypeExpr(t) + if err != nil { + v.Unreadable = fmt.Errorf("interface type %q not found for %#x: %v", typename, data.Addr, err) + return + } + } + + if kind&kindDirectIface == 0 { + realtyp := resolveTypedef(typ) + if _, isptr := realtyp.(*dwarf.PtrType); !isptr { + typ = v.dbp.pointerTo(typ) + } + } + + data = data.newVariable("data", data.Addr, typ) + + v.Children = []Variable{*data} + if loadData && recurseLevel <= cfg.MaxVariableRecurse { + v.Children[0].loadValueInternal(recurseLevel, cfg) + } else { + v.Children[0].OnlyAddr = true + } + return +} + +// Fetches all variables of a specific type in the current function scope +func (scope *EvalScope) variablesByTag(tag dwarf.Tag, cfg LoadConfig) ([]*Variable, error) { + reader := scope.DwarfReader() + off, err := scope.Thread.dbp.findFunctionDebugInfo(scope.PC) + if err != nil { + return nil, err + } + reader.Seek(off) + reader.Next() + + var vars []*Variable + for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() { + if err != nil { + return nil, err + } + if entry.Tag == 0 { + break + } + + if entry.Tag == tag { + val, err := scope.extractVariableFromEntry(entry, cfg) + if err != nil { + // skip variables that we can't parse yet + continue + } + + vars = append(vars, val) + } + } + if len(vars) <= 0 { + return vars, nil + } + + // prefetch the whole chunk of memory relative to these variables + + minaddr := vars[0].Addr + var maxaddr uintptr + var size int64 + + for _, v := range vars { + if v.Addr < minaddr { + minaddr = v.Addr + } + + size += v.DwarfType.Size() + + if end := v.Addr + uintptr(v.DwarfType.Size()); end > maxaddr { + maxaddr = end + } + } + + // check that we aren't trying to cache too much memory: we shouldn't + // exceed the real size of the variables by more than the number of + // variables times the size of an architecture pointer (to allow for memory + // alignment). + if int64(maxaddr-minaddr)-size <= int64(len(vars))*int64(scope.PtrSize()) { + mem := cacheMemory(vars[0].mem, minaddr, int(maxaddr-minaddr)) + + for _, v := range vars { + v.mem = mem + } + } + + for _, v := range vars { + v.loadValue(cfg) + } + + return vars, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/zsyscall_windows.go b/vendor/github.com/derekparker/delve/pkg/proc/zsyscall_windows.go new file mode 100644 index 0000000..ee2b33c --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/proc/zsyscall_windows.go @@ -0,0 +1,181 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package proc + +import ( + "syscall" + "unsafe" +) + +var _ unsafe.Pointer + +var ( + modntdll = syscall.NewLazyDLL("ntdll.dll") + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + + procNtQueryInformationThread = modntdll.NewProc("NtQueryInformationThread") + procGetThreadContext = modkernel32.NewProc("GetThreadContext") + procSetThreadContext = modkernel32.NewProc("SetThreadContext") + procSuspendThread = modkernel32.NewProc("SuspendThread") + procResumeThread = modkernel32.NewProc("ResumeThread") + procContinueDebugEvent = modkernel32.NewProc("ContinueDebugEvent") + procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory") + procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory") + procDebugBreakProcess = modkernel32.NewProc("DebugBreakProcess") + procWaitForDebugEvent = modkernel32.NewProc("WaitForDebugEvent") + procDebugActiveProcess = modkernel32.NewProc("DebugActiveProcess") + procDebugActiveProcessStop = modkernel32.NewProc("DebugActiveProcessStop") + procQueryFullProcessImageNameW = modkernel32.NewProc("QueryFullProcessImageNameW") +) + +func _NtQueryInformationThread(threadHandle syscall.Handle, infoclass int32, info uintptr, infolen uint32, retlen *uint32) (status _NTSTATUS) { + r0, _, _ := syscall.Syscall6(procNtQueryInformationThread.Addr(), 5, uintptr(threadHandle), uintptr(infoclass), uintptr(info), uintptr(infolen), uintptr(unsafe.Pointer(retlen)), 0) + status = _NTSTATUS(r0) + return +} + +func _GetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) { + r1, _, e1 := syscall.Syscall(procGetThreadContext.Addr(), 2, uintptr(thread), uintptr(unsafe.Pointer(context)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _SetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) { + r1, _, e1 := syscall.Syscall(procSetThreadContext.Addr(), 2, uintptr(thread), uintptr(unsafe.Pointer(context)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _SuspendThread(threadid syscall.Handle) (prevsuspcount uint32, err error) { + r0, _, e1 := syscall.Syscall(procSuspendThread.Addr(), 1, uintptr(threadid), 0, 0) + prevsuspcount = uint32(r0) + if prevsuspcount == 0xffffffff { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _ResumeThread(threadid syscall.Handle) (prevsuspcount uint32, err error) { + r0, _, e1 := syscall.Syscall(procResumeThread.Addr(), 1, uintptr(threadid), 0, 0) + prevsuspcount = uint32(r0) + if prevsuspcount == 0xffffffff { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _ContinueDebugEvent(processid uint32, threadid uint32, continuestatus uint32) (err error) { + r1, _, e1 := syscall.Syscall(procContinueDebugEvent.Addr(), 3, uintptr(processid), uintptr(threadid), uintptr(continuestatus)) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _WriteProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, byteswritten *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procWriteProcessMemory.Addr(), 5, uintptr(process), uintptr(baseaddr), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(byteswritten)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _ReadProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, bytesread *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(process), uintptr(baseaddr), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(bytesread)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _DebugBreakProcess(process syscall.Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDebugBreakProcess.Addr(), 1, uintptr(process), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err error) { + r1, _, e1 := syscall.Syscall(procWaitForDebugEvent.Addr(), 2, uintptr(unsafe.Pointer(debugevent)), uintptr(milliseconds), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _DebugActiveProcess(processid uint32) (err error) { + r1, _, e1 := syscall.Syscall(procDebugActiveProcess.Addr(), 1, uintptr(processid), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _DebugActiveProcessStop(processid uint32) (err error) { + r1, _, e1 := syscall.Syscall(procDebugActiveProcessStop.Addr(), 1, uintptr(processid), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _QueryFullProcessImageName(process syscall.Handle, flags uint32, exename *uint16, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryFullProcessImageNameW.Addr(), 4, uintptr(process), uintptr(flags), uintptr(unsafe.Pointer(exename)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} diff --git a/vendor/github.com/derekparker/delve/pkg/target/target.go b/vendor/github.com/derekparker/delve/pkg/target/target.go new file mode 100644 index 0000000..4455160 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/target/target.go @@ -0,0 +1,84 @@ +package target + +import ( + "debug/gosym" + "go/ast" + "time" + + "github.com/derekparker/delve/pkg/proc" +) + +// Target represents the target of the debugger. This +// target could be a system process, core file, etc. +type Interface interface { + Info + ProcessManipulation + BreakpointManipulation + VariableEval +} + +// Info is an interface that provides general information on the target. +type Info interface { + Pid() int + Exited() bool + Running() bool + + BinaryInfo + ThreadInfo + GoroutineInfo +} + +// BinaryInfo is an interface for accessing information on the binary file +// and the contents of binary sections. +type BinaryInfo interface { + LastModified() time.Time + Sources() map[string]*gosym.Obj + FindFileLocation(fileName string, lineNumber int) (uint64, error) + FindFunctionLocation(funcName string, firstLine bool, lineOffset int) (uint64, error) + Funcs() []gosym.Func + Types() ([]string, error) + PCToLine(uint64) (string, int, *gosym.Func) + FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error) +} + +// ThreadInfo is an interface for getting information on active threads +// in the process. +type ThreadInfo interface { + Threads() map[int]*proc.Thread + CurrentThread() *proc.Thread +} + +// GoroutineInfo is an interface for getting information on running goroutines. +type GoroutineInfo interface { + GoroutinesInfo() ([]*proc.G, error) + SelectedGoroutine() *proc.G + FindGoroutine(int) (*proc.G, error) +} + +// ProcessManipulation is an interface for changing the execution state of a process. +type ProcessManipulation interface { + Continue() error + Next() error + Step() error + StepOut() error + StepInstruction() error + SwitchThread(int) error + SwitchGoroutine(int) error + RequestManualStop() error + Halt() error + Kill() error + Detach(bool) error +} + +// BreakpointManipulation is an interface for managing breakpoints. +type BreakpointManipulation interface { + Breakpoints() map[uint64]*proc.Breakpoint + SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) + ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) + ClearInternalBreakpoints() error +} + +// VariableEval is an interface for dealing with eval scopes. +type VariableEval interface { + ConvertEvalScope(gid, frame int) (*proc.EvalScope, error) +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/command.go b/vendor/github.com/derekparker/delve/pkg/terminal/command.go new file mode 100644 index 0000000..764c3e8 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/terminal/command.go @@ -0,0 +1,1426 @@ +// Package terminal implements functions for responding to user +// input and dispatching to appropriate backend commands. +package terminal + +import ( + "bufio" + "errors" + "fmt" + "go/parser" + "go/scanner" + "io" + "math" + "os" + "regexp" + "sort" + "strconv" + "strings" + "text/tabwriter" + + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/api" + "github.com/derekparker/delve/service/debugger" +) + +type cmdPrefix int + +const ( + noPrefix = cmdPrefix(0) + scopePrefix = cmdPrefix(1 << iota) + onPrefix +) + +type callContext struct { + Prefix cmdPrefix + Scope api.EvalScope + Breakpoint *api.Breakpoint +} + +type cmdfunc func(t *Term, ctx callContext, args string) error + +type command struct { + aliases []string + allowedPrefixes cmdPrefix + helpMsg string + cmdFn cmdfunc +} + +// Returns true if the command string matches one of the aliases for this command +func (c command) match(cmdstr string) bool { + for _, v := range c.aliases { + if v == cmdstr { + return true + } + } + return false +} + +// Commands represents the commands for Delve terminal process. +type Commands struct { + cmds []command + lastCmd cmdfunc + client service.Client +} + +var ( + LongLoadConfig = api.LoadConfig{true, 1, 64, 64, -1} + ShortLoadConfig = api.LoadConfig{false, 0, 64, 0, 3} +) + +type ByFirstAlias []command + +func (a ByFirstAlias) Len() int { return len(a) } +func (a ByFirstAlias) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a ByFirstAlias) Less(i, j int) bool { return a[i].aliases[0] < a[j].aliases[0] } + +// DebugCommands returns a Commands struct with default commands defined. +func DebugCommands(client service.Client) *Commands { + c := &Commands{client: client} + + c.cmds = []command{ + {aliases: []string{"help", "h"}, cmdFn: c.help, helpMsg: `Prints the help message. + + help [command] + +Type "help" followed by the name of a command for more information about it.`}, + {aliases: []string{"break", "b"}, cmdFn: breakpoint, helpMsg: `Sets a breakpoint. + + break [name] + +See $GOPATH/src/github.com/derekparker/delve/Documentation/cli/locspec.md for the syntax of linespec. + +See also: "help on", "help cond" and "help clear"`}, + {aliases: []string{"trace", "t"}, cmdFn: tracepoint, helpMsg: `Set tracepoint. + + trace [name] + +A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See $GOPATH/src/github.com/derekparker/delve/Documentation/cli/locspec.md for the syntax of linespec. + +See also: "help on", "help cond" and "help clear"`}, + {aliases: []string{"restart", "r"}, cmdFn: restart, helpMsg: "Restart process."}, + {aliases: []string{"continue", "c"}, cmdFn: cont, helpMsg: "Run until breakpoint or program termination."}, + {aliases: []string{"step", "s"}, allowedPrefixes: scopePrefix, cmdFn: step, helpMsg: "Single step through program."}, + {aliases: []string{"step-instruction", "si"}, allowedPrefixes: scopePrefix, cmdFn: stepInstruction, helpMsg: "Single step a single cpu instruction."}, + {aliases: []string{"next", "n"}, allowedPrefixes: scopePrefix, cmdFn: next, helpMsg: "Step over to next source line."}, + {aliases: []string{"stepout"}, allowedPrefixes: scopePrefix, cmdFn: stepout, helpMsg: "Step out of the current function."}, + {aliases: []string{"threads"}, cmdFn: threads, helpMsg: "Print out info for every traced thread."}, + {aliases: []string{"thread", "tr"}, cmdFn: thread, helpMsg: `Switch to the specified thread. + + thread `}, + {aliases: []string{"clear"}, cmdFn: clear, helpMsg: `Deletes breakpoint. + + clear `}, + {aliases: []string{"clearall"}, cmdFn: clearAll, helpMsg: `Deletes multiple breakpoints. + + clearall [] + +If called with the linespec argument it will delete all the breakpoints matching the linespec. If linespec is omitted all breakpoints are deleted.`}, + {aliases: []string{"goroutines"}, cmdFn: goroutines, helpMsg: `List program goroutines. + + goroutines [-u (default: user location)|-r (runtime location)|-g (go statement location)] + +Print out info for every goroutine. The flag controls what information is shown along with each goroutine: + + -u displays location of topmost stackframe in user code + -r displays location of topmost stackframe (including frames inside private runtime functions) + -g displays location of go instruction that created the goroutine + +If no flag is specified the default is -u.`}, + {aliases: []string{"goroutine"}, allowedPrefixes: onPrefix | scopePrefix, cmdFn: c.goroutine, helpMsg: `Shows or changes current goroutine + + goroutine + goroutine + goroutine + +Called without arguments it will show information about the current goroutine. +Called with a single argument it will switch to the specified goroutine. +Called with more arguments it will execute a command on the specified goroutine.`}, + {aliases: []string{"breakpoints", "bp"}, cmdFn: breakpoints, helpMsg: "Print out info for active breakpoints."}, + {aliases: []string{"print", "p"}, allowedPrefixes: onPrefix | scopePrefix, cmdFn: printVar, helpMsg: `Evaluate an expression. + + [goroutine ] [frame ] print + +See $GOPATH/src/github.com/derekparker/delve/Documentation/cli/expr.md for a description of supported expressions.`}, + {aliases: []string{"set"}, allowedPrefixes: scopePrefix, cmdFn: setVar, helpMsg: `Changes the value of a variable. + + [goroutine ] [frame ] set = + +See $GOPATH/src/github.com/derekparker/delve/Documentation/cli/expr.md for a description of supported expressions. Only numerical variables and pointers can be changed.`}, + {aliases: []string{"sources"}, cmdFn: sources, helpMsg: `Print list of source files. + + sources [] + +If regex is specified only the source files matching it will be returned.`}, + {aliases: []string{"funcs"}, cmdFn: funcs, helpMsg: `Print list of functions. + + funcs [] + +If regex is specified only the functions matching it will be returned.`}, + {aliases: []string{"types"}, cmdFn: types, helpMsg: `Print list of types + + types [] + +If regex is specified only the functions matching it will be returned.`}, + {aliases: []string{"args"}, allowedPrefixes: scopePrefix | onPrefix, cmdFn: args, helpMsg: `Print function arguments. + + [goroutine ] [frame ] args [-v] [] + +If regex is specified only function arguments with a name matching it will be returned. If -v is specified more information about each function argument will be shown.`}, + {aliases: []string{"locals"}, allowedPrefixes: scopePrefix | onPrefix, cmdFn: locals, helpMsg: `Print local variables. + + [goroutine ] [frame ] locals [-v] [] + +If regex is specified only local variables with a name matching it will be returned. If -v is specified more information about each local variable will be shown.`}, + {aliases: []string{"vars"}, cmdFn: vars, helpMsg: `Print package variables. + + vars [-v] [] + +If regex is specified only package variables with a name matching it will be returned. If -v is specified more information about each package variable will be shown.`}, + {aliases: []string{"regs"}, cmdFn: regs, helpMsg: `Print contents of CPU registers. + + regs [-a] + +Argument -a shows more registers.`}, + {aliases: []string{"exit", "quit", "q"}, cmdFn: exitCommand, helpMsg: "Exit the debugger."}, + {aliases: []string{"list", "ls"}, allowedPrefixes: scopePrefix, cmdFn: listCommand, helpMsg: `Show source code. + + [goroutine ] [frame ] list [] + +Show source around current point or provided linespec.`}, + {aliases: []string{"stack", "bt"}, allowedPrefixes: scopePrefix | onPrefix, cmdFn: stackCommand, helpMsg: `Print stack trace. + + [goroutine ] [frame ] stack [] [-full] + +If -full is specified every stackframe will be decorated by the value of its local variables and function arguments.`}, + {aliases: []string{"frame"}, allowedPrefixes: scopePrefix, cmdFn: c.frame, helpMsg: `Executes command on a different frame. + + frame .`}, + {aliases: []string{"source"}, cmdFn: c.sourceCommand, helpMsg: `Executes a file containing a list of delve commands + + source `}, + {aliases: []string{"disassemble", "disass"}, allowedPrefixes: scopePrefix, cmdFn: disassCommand, helpMsg: `Disassembler. + + [goroutine ] [frame ] disassemble [-a ] [-l ] + +If no argument is specified the function being executed in the selected stack frame will be executed. + + -a disassembles the specified address range + -l disassembles the specified function`}, + {aliases: []string{"on"}, cmdFn: c.onCmd, helpMsg: `Executes a command when a breakpoint is hit. + + on . + +Supported commands: print, stack and goroutine)`}, + {aliases: []string{"condition", "cond"}, cmdFn: conditionCmd, helpMsg: `Set breakpoint condition. + + condition . + +Specifies that the breakpoint or tracepoint should break only if the boolean expression is true.`}, + } + + sort.Sort(ByFirstAlias(c.cmds)) + return c +} + +// Register custom commands. Expects cf to be a func of type cmdfunc, +// returning only an error. +func (c *Commands) Register(cmdstr string, cf cmdfunc, helpMsg string) { + for _, v := range c.cmds { + if v.match(cmdstr) { + v.cmdFn = cf + return + } + } + + c.cmds = append(c.cmds, command{aliases: []string{cmdstr}, cmdFn: cf, helpMsg: helpMsg}) +} + +// Find will look up the command function for the given command input. +// If it cannot find the command it will default to noCmdAvailable(). +// If the command is an empty string it will replay the last command. +func (c *Commands) Find(cmdstr string, prefix cmdPrefix) cmdfunc { + // If use last command, if there was one. + if cmdstr == "" { + if c.lastCmd != nil { + return c.lastCmd + } + return nullCommand + } + + for _, v := range c.cmds { + if v.match(cmdstr) { + if prefix != noPrefix && v.allowedPrefixes&prefix == 0 { + continue + } + c.lastCmd = v.cmdFn + return v.cmdFn + } + } + + return noCmdAvailable +} + +func (c *Commands) CallWithContext(cmdstr, args string, t *Term, ctx callContext) error { + return c.Find(cmdstr, ctx.Prefix)(t, ctx, args) +} + +func (c *Commands) Call(cmdstr, args string, t *Term) error { + ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: 0}} + return c.CallWithContext(cmdstr, args, t, ctx) +} + +// Merge takes aliases defined in the config struct and merges them with the default aliases. +func (c *Commands) Merge(allAliases map[string][]string) { + for i := range c.cmds { + if aliases, ok := allAliases[c.cmds[i].aliases[0]]; ok { + c.cmds[i].aliases = append(c.cmds[i].aliases, aliases...) + } + } +} + +var noCmdError = errors.New("command not available") + +func noCmdAvailable(t *Term, ctx callContext, args string) error { + return noCmdError +} + +func nullCommand(t *Term, ctx callContext, args string) error { + return nil +} + +func (c *Commands) help(t *Term, ctx callContext, args string) error { + if args != "" { + for _, cmd := range c.cmds { + for _, alias := range cmd.aliases { + if alias == args { + fmt.Println(cmd.helpMsg) + return nil + } + } + } + return noCmdError + } + + fmt.Println("The following commands are available:") + w := new(tabwriter.Writer) + w.Init(os.Stdout, 0, 8, 0, '-', 0) + for _, cmd := range c.cmds { + h := cmd.helpMsg + if idx := strings.Index(h, "\n"); idx >= 0 { + h = h[:idx] + } + if len(cmd.aliases) > 1 { + fmt.Fprintf(w, " %s (alias: %s) \t %s\n", cmd.aliases[0], strings.Join(cmd.aliases[1:], " | "), h) + } else { + fmt.Fprintf(w, " %s \t %s\n", cmd.aliases[0], h) + } + } + if err := w.Flush(); err != nil { + return err + } + fmt.Println("Type help followed by a command for full documentation.") + return nil +} + +type byThreadID []*api.Thread + +func (a byThreadID) Len() int { return len(a) } +func (a byThreadID) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byThreadID) Less(i, j int) bool { return a[i].ID < a[j].ID } + +func threads(t *Term, ctx callContext, args string) error { + threads, err := t.client.ListThreads() + if err != nil { + return err + } + state, err := t.client.GetState() + if err != nil { + return err + } + sort.Sort(byThreadID(threads)) + for _, th := range threads { + prefix := " " + if state.CurrentThread != nil && state.CurrentThread.ID == th.ID { + prefix = "* " + } + if th.Function != nil { + fmt.Printf("%sThread %d at %#v %s:%d %s\n", + prefix, th.ID, th.PC, ShortenFilePath(th.File), + th.Line, th.Function.Name) + } else { + fmt.Printf("%sThread %s\n", prefix, formatThread(th)) + } + } + return nil +} + +func thread(t *Term, ctx callContext, args string) error { + if len(args) == 0 { + return fmt.Errorf("you must specify a thread") + } + tid, err := strconv.Atoi(args) + if err != nil { + return err + } + oldState, err := t.client.GetState() + if err != nil { + return err + } + newState, err := t.client.SwitchThread(tid) + if err != nil { + return err + } + + oldThread := "" + newThread := "" + if oldState.CurrentThread != nil { + oldThread = strconv.Itoa(oldState.CurrentThread.ID) + } + if newState.CurrentThread != nil { + newThread = strconv.Itoa(newState.CurrentThread.ID) + } + fmt.Printf("Switched from %s to %s\n", oldThread, newThread) + return nil +} + +type byGoroutineID []*api.Goroutine + +func (a byGoroutineID) Len() int { return len(a) } +func (a byGoroutineID) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byGoroutineID) Less(i, j int) bool { return a[i].ID < a[j].ID } + +func goroutines(t *Term, ctx callContext, argstr string) error { + args := strings.Split(argstr, " ") + var fgl = fglUserCurrent + + switch len(args) { + case 0: + // nothing to do + case 1: + switch args[0] { + case "-u": + fgl = fglUserCurrent + case "-r": + fgl = fglRuntimeCurrent + case "-g": + fgl = fglGo + case "": + // nothing to do + default: + return fmt.Errorf("wrong argument: '%s'", args[0]) + } + default: + return fmt.Errorf("too many arguments") + } + state, err := t.client.GetState() + if err != nil { + return err + } + gs, err := t.client.ListGoroutines() + if err != nil { + return err + } + sort.Sort(byGoroutineID(gs)) + fmt.Printf("[%d goroutines]\n", len(gs)) + for _, g := range gs { + prefix := " " + if state.SelectedGoroutine != nil && g.ID == state.SelectedGoroutine.ID { + prefix = "* " + } + fmt.Printf("%sGoroutine %s\n", prefix, formatGoroutine(g, fgl)) + } + return nil +} + +func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error { + args := strings.SplitN(argstr, " ", 3) + + if ctx.Prefix == onPrefix { + if len(args) != 1 || args[0] != "" { + return errors.New("too many arguments to goroutine") + } + ctx.Breakpoint.Goroutine = true + return nil + } + + switch len(args) { + case 1: + if ctx.Prefix == scopePrefix { + return errors.New("no command passed to goroutine") + } + if args[0] == "" { + return printscope(t) + } + gid, err := strconv.Atoi(argstr) + if err != nil { + return err + } + + oldState, err := t.client.GetState() + if err != nil { + return err + } + newState, err := t.client.SwitchGoroutine(gid) + if err != nil { + return err + } + + fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID) + return nil + case 2: + args = append(args, "") + } + + var err error + ctx.Prefix = scopePrefix + ctx.Scope.GoroutineID, err = strconv.Atoi(args[0]) + if err != nil { + return err + } + return c.CallWithContext(args[1], args[2], t, ctx) +} + +func (c *Commands) frame(t *Term, ctx callContext, args string) error { + v := strings.SplitN(args, " ", 3) + + switch len(v) { + case 0, 1: + return errors.New("not enough arguments") + case 2: + v = append(v, "") + } + + var err error + ctx.Prefix = scopePrefix + ctx.Scope.Frame, err = strconv.Atoi(v[0]) + if err != nil { + return err + } + return c.CallWithContext(v[1], v[2], t, ctx) +} + +func printscope(t *Term) error { + state, err := t.client.GetState() + if err != nil { + return err + } + + fmt.Printf("Thread %s\n", formatThread(state.CurrentThread)) + if state.SelectedGoroutine != nil { + writeGoroutineLong(os.Stdout, state.SelectedGoroutine, "") + } + return nil +} + +func formatThread(th *api.Thread) string { + if th == nil { + return "" + } + return fmt.Sprintf("%d at %s:%d", th.ID, ShortenFilePath(th.File), th.Line) +} + +type formatGoroutineLoc int + +const ( + fglRuntimeCurrent = formatGoroutineLoc(iota) + fglUserCurrent + fglGo +) + +func formatLocation(loc api.Location) string { + fname := "" + if loc.Function != nil { + fname = loc.Function.Name + } + return fmt.Sprintf("%s:%d %s (%#v)", ShortenFilePath(loc.File), loc.Line, fname, loc.PC) +} + +func formatGoroutine(g *api.Goroutine, fgl formatGoroutineLoc) string { + if g == nil { + return "" + } + var locname string + var loc api.Location + switch fgl { + case fglRuntimeCurrent: + locname = "Runtime" + loc = g.CurrentLoc + case fglUserCurrent: + locname = "User" + loc = g.UserCurrentLoc + case fglGo: + locname = "Go" + loc = g.GoStatementLoc + } + thread := "" + if g.ThreadID != 0 { + thread = fmt.Sprintf(" (thread %d)", g.ThreadID) + } + return fmt.Sprintf("%d - %s: %s%s", g.ID, locname, formatLocation(loc), thread) +} + +func writeGoroutineLong(w io.Writer, g *api.Goroutine, prefix string) { + fmt.Fprintf(w, "%sGoroutine %d:\n%s\tRuntime: %s\n%s\tUser: %s\n%s\tGo: %s\n", + prefix, g.ID, + prefix, formatLocation(g.CurrentLoc), + prefix, formatLocation(g.UserCurrentLoc), + prefix, formatLocation(g.GoStatementLoc)) +} + +func restart(t *Term, ctx callContext, args string) error { + discarded, err := t.client.Restart() + if err != nil { + return err + } + fmt.Println("Process restarted with PID", t.client.ProcessPid()) + for i := range discarded { + fmt.Printf("Discarded %s at %s: %v\n", formatBreakpointName(discarded[i].Breakpoint, false), formatBreakpointLocation(discarded[i].Breakpoint), discarded[i].Reason) + } + return nil +} + +func cont(t *Term, ctx callContext, args string) error { + stateChan := t.client.Continue() + var state *api.DebuggerState + for state = range stateChan { + if state.Err != nil { + return state.Err + } + printcontext(t, state) + } + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + return nil +} + +func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string) error { + if !state.NextInProgress { + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + return nil + } + for { + stateChan := t.client.Continue() + var state *api.DebuggerState + for state = range stateChan { + if state.Err != nil { + return state.Err + } + printcontext(t, state) + } + if !state.NextInProgress { + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + return nil + } + fmt.Printf("\tbreakpoint hit during %s, continuing...\n", op) + } +} + +func scopePrefixSwitch(t *Term, ctx callContext) error { + if ctx.Prefix != scopePrefix { + return nil + } + if ctx.Scope.Frame != 0 { + return errors.New("frame prefix not accepted") + } + if ctx.Scope.GoroutineID > 0 { + _, err := t.client.SwitchGoroutine(ctx.Scope.GoroutineID) + if err != nil { + return err + } + } + return nil +} + +func step(t *Term, ctx callContext, args string) error { + if err := scopePrefixSwitch(t, ctx); err != nil { + return err + } + state, err := t.client.Step() + if err != nil { + return err + } + printcontext(t, state) + return continueUntilCompleteNext(t, state, "step") +} + +func stepInstruction(t *Term, ctx callContext, args string) error { + if err := scopePrefixSwitch(t, ctx); err != nil { + return err + } + state, err := t.client.StepInstruction() + if err != nil { + return err + } + printcontext(t, state) + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + return nil +} + +func next(t *Term, ctx callContext, args string) error { + if err := scopePrefixSwitch(t, ctx); err != nil { + return err + } + state, err := t.client.Next() + if err != nil { + return err + } + printcontext(t, state) + return continueUntilCompleteNext(t, state, "next") +} + +func stepout(t *Term, ctx callContext, args string) error { + if err := scopePrefixSwitch(t, ctx); err != nil { + return err + } + state, err := t.client.StepOut() + if err != nil { + return err + } + printcontext(t, state) + return continueUntilCompleteNext(t, state, "stepout") +} + +func clear(t *Term, ctx callContext, args string) error { + if len(args) == 0 { + return fmt.Errorf("not enough arguments") + } + id, err := strconv.Atoi(args) + var bp *api.Breakpoint + if err == nil { + bp, err = t.client.ClearBreakpoint(id) + } else { + bp, err = t.client.ClearBreakpointByName(args) + } + if err != nil { + return err + } + fmt.Printf("%s cleared at %s\n", formatBreakpointName(bp, true), formatBreakpointLocation(bp)) + return nil +} + +func clearAll(t *Term, ctx callContext, args string) error { + breakPoints, err := t.client.ListBreakpoints() + if err != nil { + return err + } + + var locPCs map[uint64]struct{} + if args != "" { + locs, err := t.client.FindLocation(api.EvalScope{GoroutineID: -1, Frame: 0}, args) + if err != nil { + return err + } + locPCs = make(map[uint64]struct{}) + for _, loc := range locs { + locPCs[loc.PC] = struct{}{} + } + } + + for _, bp := range breakPoints { + if locPCs != nil { + if _, ok := locPCs[bp.Addr]; !ok { + continue + } + } + + if bp.ID < 0 { + continue + } + + _, err := t.client.ClearBreakpoint(bp.ID) + if err != nil { + fmt.Printf("Couldn't delete %s at %s: %s\n", formatBreakpointName(bp, false), formatBreakpointLocation(bp), err) + } + fmt.Printf("%s cleared at %s\n", formatBreakpointName(bp, true), formatBreakpointLocation(bp)) + } + return nil +} + +// ByID sorts breakpoints by ID. +type ByID []*api.Breakpoint + +func (a ByID) Len() int { return len(a) } +func (a ByID) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a ByID) Less(i, j int) bool { return a[i].ID < a[j].ID } + +func breakpoints(t *Term, ctx callContext, args string) error { + breakPoints, err := t.client.ListBreakpoints() + if err != nil { + return err + } + sort.Sort(ByID(breakPoints)) + for _, bp := range breakPoints { + fmt.Printf("%s at %v (%d)\n", formatBreakpointName(bp, true), formatBreakpointLocation(bp), bp.TotalHitCount) + + var attrs []string + if bp.Cond != "" { + attrs = append(attrs, fmt.Sprintf("\tcond %s", bp.Cond)) + } + if bp.Stacktrace > 0 { + attrs = append(attrs, fmt.Sprintf("\tstack %d", bp.Stacktrace)) + } + if bp.Goroutine { + attrs = append(attrs, "\tgoroutine") + } + if bp.LoadArgs != nil { + if *(bp.LoadArgs) == LongLoadConfig { + attrs = append(attrs, "\targs -v") + } else { + attrs = append(attrs, "\targs") + } + } + if bp.LoadLocals != nil { + if *(bp.LoadLocals) == LongLoadConfig { + attrs = append(attrs, "\tlocals -v") + } else { + attrs = append(attrs, "\tlocals") + } + } + for i := range bp.Variables { + attrs = append(attrs, fmt.Sprintf("\tprint %s", bp.Variables[i])) + } + if len(attrs) > 0 { + fmt.Printf("%s\n", strings.Join(attrs, "\n")) + } + } + return nil +} + +func setBreakpoint(t *Term, tracepoint bool, argstr string) error { + args := strings.SplitN(argstr, " ", 2) + + requestedBp := &api.Breakpoint{} + locspec := "" + switch len(args) { + case 1: + locspec = argstr + case 2: + if api.ValidBreakpointName(args[0]) == nil { + requestedBp.Name = args[0] + locspec = args[1] + } else { + locspec = argstr + } + default: + return fmt.Errorf("address required") + } + + requestedBp.Tracepoint = tracepoint + locs, err := t.client.FindLocation(api.EvalScope{GoroutineID: -1, Frame: 0}, locspec) + if err != nil { + if requestedBp.Name == "" { + return err + } + requestedBp.Name = "" + locspec = argstr + var err2 error + locs, err2 = t.client.FindLocation(api.EvalScope{GoroutineID: -1, Frame: 0}, locspec) + if err2 != nil { + return err + } + } + for _, loc := range locs { + requestedBp.Addr = loc.PC + + bp, err := t.client.CreateBreakpoint(requestedBp) + if err != nil { + return err + } + + fmt.Printf("%s set at %s\n", formatBreakpointName(bp, true), formatBreakpointLocation(bp)) + } + return nil +} + +func breakpoint(t *Term, ctx callContext, args string) error { + return setBreakpoint(t, false, args) +} + +func tracepoint(t *Term, ctx callContext, args string) error { + return setBreakpoint(t, true, args) +} + +func printVar(t *Term, ctx callContext, args string) error { + if len(args) == 0 { + return fmt.Errorf("not enough arguments") + } + if ctx.Prefix == onPrefix { + ctx.Breakpoint.Variables = append(ctx.Breakpoint.Variables, args) + return nil + } + val, err := t.client.EvalVariable(ctx.Scope, args, LongLoadConfig) + if err != nil { + return err + } + + fmt.Println(val.MultilineString("")) + return nil +} + +func setVar(t *Term, ctx callContext, args string) error { + // HACK: in go '=' is not an operator, we detect the error and try to recover from it by splitting the input string + _, err := parser.ParseExpr(args) + if err == nil { + return fmt.Errorf("syntax error '=' not found") + } + + el, ok := err.(scanner.ErrorList) + if !ok || el[0].Msg != "expected '==', found '='" { + return err + } + + lexpr := args[:el[0].Pos.Offset] + rexpr := args[el[0].Pos.Offset+1:] + return t.client.SetVariable(ctx.Scope, lexpr, rexpr) +} + +func printFilteredVariables(varType string, vars []api.Variable, filter string, cfg api.LoadConfig) error { + reg, err := regexp.Compile(filter) + if err != nil { + return err + } + match := false + for _, v := range vars { + if reg == nil || reg.Match([]byte(v.Name)) { + match = true + if cfg == ShortLoadConfig { + fmt.Printf("%s = %s\n", v.Name, v.SinglelineString()) + } else { + fmt.Printf("%s = %s\n", v.Name, v.MultilineString("")) + } + } + } + if !match { + fmt.Printf("(no %s)\n", varType) + } + return nil +} + +func printSortedStrings(v []string, err error) error { + if err != nil { + return err + } + sort.Strings(v) + for _, d := range v { + fmt.Println(d) + } + return nil +} + +func sources(t *Term, ctx callContext, args string) error { + return printSortedStrings(t.client.ListSources(args)) +} + +func funcs(t *Term, ctx callContext, args string) error { + return printSortedStrings(t.client.ListFunctions(args)) +} + +func types(t *Term, ctx callContext, args string) error { + return printSortedStrings(t.client.ListTypes(args)) +} + +func parseVarArguments(args string) (filter string, cfg api.LoadConfig) { + if v := strings.SplitN(args, " ", 2); len(v) >= 1 && v[0] == "-v" { + if len(v) == 2 { + return v[1], LongLoadConfig + } else { + return "", LongLoadConfig + } + } + return args, ShortLoadConfig +} + +func args(t *Term, ctx callContext, args string) error { + filter, cfg := parseVarArguments(args) + if ctx.Prefix == onPrefix { + if filter != "" { + return fmt.Errorf("filter not supported on breakpoint") + } + ctx.Breakpoint.LoadArgs = &cfg + return nil + } + vars, err := t.client.ListFunctionArgs(ctx.Scope, cfg) + if err != nil { + return err + } + return printFilteredVariables("args", vars, filter, cfg) +} + +func locals(t *Term, ctx callContext, args string) error { + filter, cfg := parseVarArguments(args) + if ctx.Prefix == onPrefix { + if filter != "" { + return fmt.Errorf("filter not supported on breakpoint") + } + ctx.Breakpoint.LoadLocals = &cfg + return nil + } + locals, err := t.client.ListLocalVariables(ctx.Scope, cfg) + if err != nil { + return err + } + return printFilteredVariables("locals", locals, filter, cfg) +} + +func vars(t *Term, ctx callContext, args string) error { + filter, cfg := parseVarArguments(args) + vars, err := t.client.ListPackageVariables(filter, cfg) + if err != nil { + return err + } + return printFilteredVariables("vars", vars, filter, cfg) +} + +func regs(t *Term, ctx callContext, args string) error { + includeFp := false + if args == "-a" { + includeFp = true + } + regs, err := t.client.ListRegisters(0, includeFp) + if err != nil { + return err + } + fmt.Println(regs) + return nil +} + +func stackCommand(t *Term, ctx callContext, args string) error { + depth, full, err := parseStackArgs(args) + if err != nil { + return err + } + if ctx.Prefix == onPrefix { + ctx.Breakpoint.Stacktrace = depth + return nil + } + var cfg *api.LoadConfig + if full { + cfg = &ShortLoadConfig + } + stack, err := t.client.Stacktrace(ctx.Scope.GoroutineID, depth, cfg) + if err != nil { + return err + } + printStack(stack, "") + return nil +} + +func parseStackArgs(argstr string) (int, bool, error) { + var ( + depth = 10 + full = false + ) + if argstr != "" { + args := strings.Split(argstr, " ") + for i := range args { + if args[i] == "-full" { + full = true + } else { + n, err := strconv.Atoi(args[i]) + if err != nil { + return 0, false, fmt.Errorf("depth must be a number") + } + depth = n + } + } + } + return depth, full, nil +} + +func listCommand(t *Term, ctx callContext, args string) error { + if ctx.Prefix == scopePrefix { + locs, err := t.client.Stacktrace(ctx.Scope.GoroutineID, ctx.Scope.Frame, nil) + if err != nil { + return err + } + if ctx.Scope.Frame >= len(locs) { + return fmt.Errorf("Frame %d does not exist in goroutine %d", ctx.Scope.Frame, ctx.Scope.GoroutineID) + } + loc := locs[ctx.Scope.Frame] + return printfile(t, loc.File, loc.Line, true) + } + + if len(args) == 0 { + state, err := t.client.GetState() + if err != nil { + return err + } + printcontext(t, state) + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + return nil + } + + locs, err := t.client.FindLocation(api.EvalScope{GoroutineID: -1, Frame: 0}, args) + if err != nil { + return err + } + if len(locs) > 1 { + return debugger.AmbiguousLocationError{Location: args, CandidatesLocation: locs} + } + printfile(t, locs[0].File, locs[0].Line, false) + return nil +} + +func (c *Commands) sourceCommand(t *Term, ctx callContext, args string) error { + if len(args) == 0 { + return fmt.Errorf("wrong number of arguments: source ") + } + + return c.executeFile(t, args) +} + +var disasmUsageError = errors.New("wrong number of arguments: disassemble [-a ] [-l ]") + +func disassCommand(t *Term, ctx callContext, args string) error { + var cmd, rest string + + if args != "" { + argv := strings.SplitN(args, " ", 2) + if len(argv) != 2 { + return disasmUsageError + } + cmd = argv[0] + rest = argv[1] + } + + var disasm api.AsmInstructions + var disasmErr error + + switch cmd { + case "": + locs, err := t.client.FindLocation(ctx.Scope, "+0") + if err != nil { + return err + } + disasm, disasmErr = t.client.DisassemblePC(ctx.Scope, locs[0].PC, api.IntelFlavour) + case "-a": + v := strings.SplitN(rest, " ", 2) + if len(v) != 2 { + return disasmUsageError + } + startpc, err := strconv.ParseInt(v[0], 0, 64) + if err != nil { + return fmt.Errorf("wrong argument: %s is not a number", v[0]) + } + endpc, err := strconv.ParseInt(v[1], 0, 64) + if err != nil { + return fmt.Errorf("wrong argument: %s is not a number", v[1]) + } + disasm, disasmErr = t.client.DisassembleRange(ctx.Scope, uint64(startpc), uint64(endpc), api.IntelFlavour) + case "-l": + locs, err := t.client.FindLocation(ctx.Scope, rest) + if err != nil { + return err + } + if len(locs) != 1 { + return errors.New("expression specifies multiple locations") + } + disasm, disasmErr = t.client.DisassemblePC(ctx.Scope, locs[0].PC, api.IntelFlavour) + default: + return disasmUsageError + } + + if disasmErr != nil { + return disasmErr + } + + fmt.Printf("printing\n") + DisasmPrint(disasm, os.Stdout) + + return nil +} + +func digits(n int) int { + if n <= 0 { + return 1 + } + return int(math.Floor(math.Log10(float64(n)))) + 1 +} + +func printStack(stack []api.Stackframe, ind string) { + if len(stack) == 0 { + return + } + d := digits(len(stack) - 1) + fmtstr := "%s%" + strconv.Itoa(d) + "d 0x%016x in %s\n" + s := ind + strings.Repeat(" ", d+2+len(ind)) + + for i := range stack { + name := "(nil)" + if stack[i].Function != nil { + name = stack[i].Function.Name + } + fmt.Printf(fmtstr, ind, i, stack[i].PC, name) + fmt.Printf("%sat %s:%d\n", s, ShortenFilePath(stack[i].File), stack[i].Line) + + for j := range stack[i].Arguments { + fmt.Printf("%s %s = %s\n", s, stack[i].Arguments[j].Name, stack[i].Arguments[j].SinglelineString()) + } + for j := range stack[i].Locals { + fmt.Printf("%s %s = %s\n", s, stack[i].Locals[j].Name, stack[i].Locals[j].SinglelineString()) + } + } +} + +func printcontext(t *Term, state *api.DebuggerState) error { + for i := range state.Threads { + if (state.CurrentThread != nil) && (state.Threads[i].ID == state.CurrentThread.ID) { + continue + } + if state.Threads[i].Breakpoint != nil { + printcontextThread(t, state.Threads[i]) + } + } + + if state.CurrentThread == nil { + fmt.Println("No current thread available") + return nil + } + if len(state.CurrentThread.File) == 0 { + fmt.Printf("Stopped at: 0x%x\n", state.CurrentThread.PC) + t.Println("=>", "no source available") + return nil + } + + printcontextThread(t, state.CurrentThread) + + return nil +} + +func printcontextThread(t *Term, th *api.Thread) { + fn := th.Function + + if th.Breakpoint == nil { + fmt.Printf("> %s() %s:%d (PC: %#v)\n", fn.Name, ShortenFilePath(th.File), th.Line, th.PC) + return + } + + args := "" + if th.BreakpointInfo != nil && th.Breakpoint.LoadArgs != nil && *th.Breakpoint.LoadArgs == ShortLoadConfig { + var arg []string + for _, ar := range th.BreakpointInfo.Arguments { + arg = append(arg, ar.SinglelineString()) + } + args = strings.Join(arg, ", ") + } + + bpname := "" + if th.Breakpoint.Name != "" { + bpname = fmt.Sprintf("[%s] ", th.Breakpoint.Name) + } + + if hitCount, ok := th.Breakpoint.HitCount[strconv.Itoa(th.GoroutineID)]; ok { + fmt.Printf("> %s%s(%s) %s:%d (hits goroutine(%d):%d total:%d) (PC: %#v)\n", + bpname, + fn.Name, + args, + ShortenFilePath(th.File), + th.Line, + th.GoroutineID, + hitCount, + th.Breakpoint.TotalHitCount, + th.PC) + } else { + fmt.Printf("> %s%s(%s) %s:%d (hits total:%d) (PC: %#v)\n", + bpname, + fn.Name, + args, + ShortenFilePath(th.File), + th.Line, + th.Breakpoint.TotalHitCount, + th.PC) + } + + if th.BreakpointInfo != nil { + bp := th.Breakpoint + bpi := th.BreakpointInfo + + if bpi.Goroutine != nil { + writeGoroutineLong(os.Stdout, bpi.Goroutine, "\t") + } + + for _, v := range bpi.Variables { + fmt.Printf("\t%s: %s\n", v.Name, v.MultilineString("\t")) + } + + for _, v := range bpi.Locals { + if *bp.LoadLocals == LongLoadConfig { + fmt.Printf("\t%s: %s\n", v.Name, v.MultilineString("\t")) + } else { + fmt.Printf("\t%s: %s\n", v.Name, v.SinglelineString()) + } + } + + if bp.LoadArgs != nil && *bp.LoadArgs == LongLoadConfig { + for _, v := range bpi.Arguments { + fmt.Printf("\t%s: %s\n", v.Name, v.MultilineString("\t")) + } + } + + if bpi.Stacktrace != nil { + fmt.Printf("\tStack:\n") + printStack(bpi.Stacktrace, "\t\t") + } + } +} + +func printfile(t *Term, filename string, line int, showArrow bool) error { + file, err := os.Open(t.substitutePath(filename)) + if err != nil { + return err + } + defer file.Close() + + fi, _ := file.Stat() + lastModExe := t.client.LastModified() + if fi.ModTime().After(lastModExe) { + fmt.Println("Warning: listing may not match stale executable") + } + + buf := bufio.NewScanner(file) + l := line + for i := 1; i < l-5; i++ { + if !buf.Scan() { + return nil + } + } + + s := l - 5 + if s < 1 { + s = 1 + } + + for i := s; i <= l+5; i++ { + if !buf.Scan() { + return nil + } + + var prefix string + if showArrow { + prefix = " " + if i == l { + prefix = "=>" + } + } + + prefix = fmt.Sprintf("%s%4d:\t", prefix, i) + t.Println(prefix, buf.Text()) + } + return nil +} + +// ExitRequestError is returned when the user +// exits Delve. +type ExitRequestError struct{} + +func (ere ExitRequestError) Error() string { + return "" +} + +func exitCommand(t *Term, ctx callContext, args string) error { + return ExitRequestError{} +} + +func getBreakpointByIDOrName(t *Term, arg string) (*api.Breakpoint, error) { + if id, err := strconv.Atoi(arg); err == nil { + return t.client.GetBreakpoint(id) + } + return t.client.GetBreakpointByName(arg) +} + +func (c *Commands) onCmd(t *Term, ctx callContext, argstr string) error { + args := strings.SplitN(argstr, " ", 3) + + if len(args) < 2 { + return errors.New("not enough arguments") + } + + if len(args) < 3 { + args = append(args, "") + } + + bp, err := getBreakpointByIDOrName(t, args[0]) + if err != nil { + return err + } + + ctx.Prefix = onPrefix + ctx.Breakpoint = bp + err = c.CallWithContext(args[1], args[2], t, ctx) + if err != nil { + return err + } + return t.client.AmendBreakpoint(ctx.Breakpoint) +} + +func conditionCmd(t *Term, ctx callContext, argstr string) error { + args := strings.SplitN(argstr, " ", 2) + + if len(args) < 2 { + return fmt.Errorf("not enough arguments") + } + + bp, err := getBreakpointByIDOrName(t, args[0]) + if err != nil { + return err + } + bp.Cond = args[1] + + return t.client.AmendBreakpoint(bp) +} + +// ShortenFilePath take a full file path and attempts to shorten +// it by replacing the current directory to './'. +func ShortenFilePath(fullPath string) string { + workingDir, _ := os.Getwd() + return strings.Replace(fullPath, workingDir, ".", 1) +} + +func (c *Commands) executeFile(t *Term, name string) error { + fh, err := os.Open(name) + if err != nil { + return err + } + defer fh.Close() + + scanner := bufio.NewScanner(fh) + lineno := 0 + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + lineno++ + + if line == "" || line[0] == '#' { + continue + } + + cmdstr, args := parseCommand(line) + + if err := c.Call(cmdstr, args, t); err != nil { + fmt.Printf("%s:%d: %v\n", name, lineno, err) + } + } + + return scanner.Err() +} + +func formatBreakpointName(bp *api.Breakpoint, upcase bool) string { + thing := "breakpoint" + if bp.Tracepoint { + thing = "tracepoint" + } + if upcase { + thing = strings.Title(thing) + } + id := bp.Name + if id == "" { + id = strconv.Itoa(bp.ID) + } + return fmt.Sprintf("%s %s", thing, id) +} + +func formatBreakpointLocation(bp *api.Breakpoint) string { + p := ShortenFilePath(bp.File) + if bp.FunctionName != "" { + return fmt.Sprintf("%#v for %s() %s:%d", bp.Addr, bp.FunctionName, p, bp.Line) + } + return fmt.Sprintf("%#v for %s:%d", bp.Addr, p, bp.Line) +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go b/vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go new file mode 100644 index 0000000..7c27374 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go @@ -0,0 +1,31 @@ +package terminal + +import ( + "bufio" + "fmt" + "github.com/derekparker/delve/service/api" + "io" + "path/filepath" + "text/tabwriter" +) + +func DisasmPrint(dv api.AsmInstructions, out io.Writer) { + bw := bufio.NewWriter(out) + defer bw.Flush() + if len(dv) > 0 && dv[0].Loc.Function != nil { + fmt.Fprintf(bw, "TEXT %s(SB) %s\n", dv[0].Loc.Function.Name, dv[0].Loc.File) + } + tw := tabwriter.NewWriter(bw, 1, 8, 1, '\t', 0) + defer tw.Flush() + for _, inst := range dv { + atbp := "" + if inst.Breakpoint { + atbp = "*" + } + atpc := "" + if inst.AtPC { + atpc = "=>" + } + fmt.Fprintf(tw, "%s\t%s:%d\t%#x%s\t%x\t%s\n", atpc, filepath.Base(inst.Loc.File), inst.Loc.Line, inst.Loc.PC, atbp, inst.Bytes, inst.Text) + } +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/docgen.go b/vendor/github.com/derekparker/delve/pkg/terminal/docgen.go new file mode 100644 index 0000000..a9632d9 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/terminal/docgen.go @@ -0,0 +1,54 @@ +package terminal + +import ( + "fmt" + "io" + "strings" +) + +func replaceDocPath(s string) string { + const docpath = "$GOPATH/src/github.com/derekparker/delve/" + + for { + start := strings.Index(s, docpath) + if start < 0 { + return s + } + var end int + for end = start + len(docpath); end < len(s); end++ { + if s[end] == ' ' { + break + } + } + + text := s[start+len(docpath) : end] + s = s[:start] + fmt.Sprintf("[%s](//github.com/derekparker/delve/tree/master/%s)", text, text) + s[end:] + } +} + +func (commands *Commands) WriteMarkdown(w io.Writer) { + fmt.Fprintf(w, "# Commands\n\n") + + fmt.Fprintf(w, "Command | Description\n") + fmt.Fprintf(w, "--------|------------\n") + for _, cmd := range commands.cmds { + h := cmd.helpMsg + if idx := strings.Index(h, "\n"); idx >= 0 { + h = h[:idx] + } + fmt.Fprintf(w, "[%s](#%s) | %s\n", cmd.aliases[0], cmd.aliases[0], h) + } + fmt.Fprintf(w, "\n") + + for _, cmd := range commands.cmds { + fmt.Fprintf(w, "## %s\n%s\n\n", cmd.aliases[0], replaceDocPath(cmd.helpMsg)) + if len(cmd.aliases) > 1 { + fmt.Fprintf(w, "Aliases:") + for _, alias := range cmd.aliases[1:] { + fmt.Fprintf(w, " %s", alias) + } + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "\n") + } +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/terminal.go b/vendor/github.com/derekparker/delve/pkg/terminal/terminal.go new file mode 100644 index 0000000..74a7f52 --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/terminal/terminal.go @@ -0,0 +1,251 @@ +package terminal + +import ( + "fmt" + "io" + "os" + "os/signal" + "runtime" + "strings" + + "syscall" + + "github.com/peterh/liner" + + "github.com/derekparker/delve/pkg/config" + "github.com/derekparker/delve/service" +) + +const ( + historyFile string = ".dbg_history" + terminalBlueEscapeCode string = "\033[34m" + terminalResetEscapeCode string = "\033[0m" +) + +// Term represents the terminal running dlv. +type Term struct { + client service.Client + conf *config.Config + prompt string + line *liner.State + cmds *Commands + dumb bool + stdout io.Writer + InitFile string +} + +// New returns a new Term. +func New(client service.Client, conf *config.Config) *Term { + cmds := DebugCommands(client) + if conf != nil && conf.Aliases != nil { + cmds.Merge(conf.Aliases) + } + + var w io.Writer + + dumb := strings.ToLower(os.Getenv("TERM")) == "dumb" + if dumb { + w = os.Stdout + } else { + w = getColorableWriter() + } + + return &Term{ + client: client, + conf: conf, + prompt: "(dlv) ", + line: liner.NewLiner(), + cmds: cmds, + dumb: dumb, + stdout: w, + } +} + +// Close returns the terminal to its previous mode. +func (t *Term) Close() { + t.line.Close() +} + +// Run begins running dlv in the terminal. +func (t *Term) Run() (int, error) { + defer t.Close() + + // Send the debugger a halt command on SIGINT + ch := make(chan os.Signal) + signal.Notify(ch, syscall.SIGINT) + go func() { + for range ch { + fmt.Printf("received SIGINT, stopping process (will not forward signal)") + _, err := t.client.Halt() + if err != nil { + fmt.Fprintf(os.Stderr, "%v", err) + } + } + }() + + t.line.SetCompleter(func(line string) (c []string) { + for _, cmd := range t.cmds.cmds { + for _, alias := range cmd.aliases { + if strings.HasPrefix(alias, strings.ToLower(line)) { + c = append(c, alias) + } + } + } + return + }) + + fullHistoryFile, err := config.GetConfigFilePath(historyFile) + if err != nil { + fmt.Printf("Unable to load history file: %v.", err) + } + + f, err := os.Open(fullHistoryFile) + if err != nil { + f, err = os.Create(fullHistoryFile) + if err != nil { + fmt.Printf("Unable to open history file: %v. History will not be saved for this session.", err) + } + } + + t.line.ReadHistory(f) + f.Close() + fmt.Println("Type 'help' for list of commands.") + + if t.InitFile != "" { + err := t.cmds.executeFile(t, t.InitFile) + if err != nil { + fmt.Fprintf(os.Stderr, "Error executing init file: %s\n", err) + } + } + + for { + cmdstr, err := t.promptForInput() + if err != nil { + if err == io.EOF { + fmt.Println("exit") + return t.handleExit() + } + return 1, fmt.Errorf("Prompt for input failed.\n") + } + + cmdstr, args := parseCommand(cmdstr) + if err := t.cmds.Call(cmdstr, args, t); err != nil { + if _, ok := err.(ExitRequestError); ok { + return t.handleExit() + } + // The type information gets lost in serialization / de-serialization, + // so we do a string compare on the error message to see if the process + // has exited, or if the command actually failed. + if strings.Contains(err.Error(), "exited") { + fmt.Fprintln(os.Stderr, err.Error()) + } else { + fmt.Fprintf(os.Stderr, "Command failed: %s\n", err) + } + } + } +} + +// Println prints a line to the terminal. +func (t *Term) Println(prefix, str string) { + if !t.dumb { + prefix = fmt.Sprintf("%s%s%s", terminalBlueEscapeCode, prefix, terminalResetEscapeCode) + } + fmt.Fprintf(t.stdout, "%s%s\n", prefix, str) +} + +// Substitues directory to source file. +// +// Ensures that only directory is substitued, for example: +// substitute from `/dir/subdir`, substitute to `/new` +// for file path `/dir/subdir/file` will return file path `/new/file`. +// for file path `/dir/subdir-2/file` substitution will not be applied. +// +// If more than one substitution rule is defined, the rules are applied +// in the order they are defined, first rule that matches is used for +// substitution. +func (t *Term) substitutePath(path string) string { + path = crossPlatformPath(path) + if t.conf == nil { + return path + } + separator := string(os.PathSeparator) + for _, r := range t.conf.SubstitutePath { + from := crossPlatformPath(r.From) + to := r.To + + if !strings.HasSuffix(from, separator) { + from = from + separator + } + if !strings.HasSuffix(to, separator) { + to = to + separator + } + if strings.HasPrefix(path, from) { + return strings.Replace(path, from, to, 1) + } + } + return path +} + +func crossPlatformPath(path string) string { + if runtime.GOOS == "darwin" || runtime.GOOS == "windows" { + return strings.ToLower(path) + } + return path +} + +func (t *Term) promptForInput() (string, error) { + l, err := t.line.Prompt(t.prompt) + if err != nil { + return "", err + } + + l = strings.TrimSuffix(l, "\n") + if l != "" { + t.line.AppendHistory(l) + } + + return l, nil +} + +func (t *Term) handleExit() (int, error) { + fullHistoryFile, err := config.GetConfigFilePath(historyFile) + if err != nil { + fmt.Println("Error saving history file:", err) + } else { + if f, err := os.OpenFile(fullHistoryFile, os.O_RDWR, 0666); err == nil { + _, err = t.line.WriteHistory(f) + if err != nil { + fmt.Println("readline history error:", err) + } + f.Close() + } + } + + s, err := t.client.GetState() + if err != nil { + return 1, err + } + if !s.Exited { + kill := true + if t.client.AttachedToExistingProcess() { + answer, err := t.line.Prompt("Would you like to kill the process? [Y/n] ") + if err != nil { + return 2, io.EOF + } + answer = strings.ToLower(strings.TrimSpace(answer)) + kill = (answer != "n" && answer != "no") + } + if err := t.client.Detach(kill); err != nil { + return 1, err + } + } + return 0, nil +} + +func parseCommand(cmdstr string) (string, string) { + vals := strings.SplitN(cmdstr, " ", 2) + if len(vals) == 1 { + return vals[0], "" + } + return vals[0], strings.TrimSpace(vals[1]) +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/terminal_other.go b/vendor/github.com/derekparker/delve/pkg/terminal/terminal_other.go new file mode 100644 index 0000000..70a8fee --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/terminal/terminal_other.go @@ -0,0 +1,14 @@ +// +build !windows + +package terminal + +import ( + "io" + "os" +) + +// getColorableWriter simply returns stdout on +// *nix machines. +func getColorableWriter() io.Writer { + return os.Stdout +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/terminal_windows.go b/vendor/github.com/derekparker/delve/pkg/terminal/terminal_windows.go new file mode 100644 index 0000000..1d525be --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/terminal/terminal_windows.go @@ -0,0 +1,35 @@ +package terminal + +import ( + "io" + "os" + "strings" + "syscall" + + "github.com/mattn/go-colorable" +) + +// getColorableWriter will return a writer that is capable +// of interpreting ANSI escape codes for terminal colors. +func getColorableWriter() io.Writer { + if strings.ToLower(os.Getenv("ConEmuANSI")) == "on" { + // The ConEmu terminal is installed. Use it. + return os.Stdout + } + + const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + + h, err := syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE) + if err != nil { + return os.Stdout + } + var m uint32 + err = syscall.GetConsoleMode(h, &m) + if err != nil { + return os.Stdout + } + if m&ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { + return os.Stdout + } + return colorable.NewColorableStdout() +} diff --git a/vendor/github.com/derekparker/delve/pkg/version/version.go b/vendor/github.com/derekparker/delve/pkg/version/version.go new file mode 100644 index 0000000..f89e9df --- /dev/null +++ b/vendor/github.com/derekparker/delve/pkg/version/version.go @@ -0,0 +1,25 @@ +package version + +import "fmt" + +// Version represents the current version of Delve. +type Version struct { + Major string + Minor string + Patch string + Metadata string + Build string +} + +var ( + // DelveVersion is the current version of Delve. + DelveVersion = Version{Major: "0", Minor: "12", Patch: "1", Metadata: ""} +) + +func (v Version) String() string { + ver := fmt.Sprintf("Version: %s.%s.%s", v.Major, v.Minor, v.Patch) + if v.Metadata != "" { + ver += "-" + v.Metadata + } + return fmt.Sprintf("%s\nBuild: %s", ver, v.Build) +} diff --git a/vendor/github.com/derekparker/delve/service/api/conversions.go b/vendor/github.com/derekparker/delve/service/api/conversions.go new file mode 100644 index 0000000..e407d0e --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/api/conversions.go @@ -0,0 +1,276 @@ +package api + +import ( + "bytes" + "debug/gosym" + "go/constant" + "go/printer" + "go/token" + "reflect" + "strconv" + + "github.com/derekparker/delve/pkg/proc" + + "golang.org/x/debug/dwarf" +) + +// ConvertBreakpoint converts from a proc.Breakpoint to +// an api.Breakpoint. +func ConvertBreakpoint(bp *proc.Breakpoint) *Breakpoint { + b := &Breakpoint{ + Name: bp.Name, + ID: bp.ID, + FunctionName: bp.FunctionName, + File: bp.File, + Line: bp.Line, + Addr: bp.Addr, + Tracepoint: bp.Tracepoint, + Stacktrace: bp.Stacktrace, + Goroutine: bp.Goroutine, + Variables: bp.Variables, + LoadArgs: LoadConfigFromProc(bp.LoadArgs), + LoadLocals: LoadConfigFromProc(bp.LoadLocals), + TotalHitCount: bp.TotalHitCount, + } + + b.HitCount = map[string]uint64{} + for idx := range bp.HitCount { + b.HitCount[strconv.Itoa(idx)] = bp.HitCount[idx] + } + + var buf bytes.Buffer + printer.Fprint(&buf, token.NewFileSet(), bp.Cond) + b.Cond = buf.String() + + return b +} + +// ConvertThread converts a proc.Thread into an +// api thread. +func ConvertThread(th *proc.Thread) *Thread { + var ( + function *Function + file string + line int + pc uint64 + gid int + ) + + loc, err := th.Location() + if err == nil { + pc = loc.PC + file = loc.File + line = loc.Line + function = ConvertFunction(loc.Fn) + } + + var bp *Breakpoint + + if th.CurrentBreakpoint != nil && th.BreakpointConditionMet { + bp = ConvertBreakpoint(th.CurrentBreakpoint) + } + + if g, _ := th.GetG(); g != nil { + gid = g.ID + } + + return &Thread{ + ID: th.ID, + PC: pc, + File: file, + Line: line, + Function: function, + GoroutineID: gid, + Breakpoint: bp, + } +} + +func prettyTypeName(typ dwarf.Type) string { + if typ == nil { + return "" + } + if typ.Common().Name != "" { + return typ.Common().Name + } + r := typ.String() + if r == "*void" { + return "unsafe.Pointer" + } + return r +} + +func convertFloatValue(v *proc.Variable, sz int) string { + switch v.FloatSpecial { + case proc.FloatIsPosInf: + return "+Inf" + case proc.FloatIsNegInf: + return "-Inf" + case proc.FloatIsNaN: + return "NaN" + } + f, _ := constant.Float64Val(v.Value) + return strconv.FormatFloat(f, 'f', -1, sz) +} + +// ConvertVar converts from proc.Variable to api.Variable. +func ConvertVar(v *proc.Variable) *Variable { + r := Variable{ + Addr: v.Addr, + OnlyAddr: v.OnlyAddr, + Name: v.Name, + Kind: v.Kind, + Len: v.Len, + Cap: v.Cap, + } + + r.Type = prettyTypeName(v.DwarfType) + r.RealType = prettyTypeName(v.RealType) + + if v.Unreadable != nil { + r.Unreadable = v.Unreadable.Error() + } + + if v.Value != nil { + switch v.Kind { + case reflect.Float32: + r.Value = convertFloatValue(v, 32) + case reflect.Float64: + r.Value = convertFloatValue(v, 64) + case reflect.String, reflect.Func: + r.Value = constant.StringVal(v.Value) + default: + r.Value = v.Value.String() + } + } + + switch v.Kind { + case reflect.Complex64: + r.Children = make([]Variable, 2) + r.Len = 2 + + real, _ := constant.Float64Val(constant.Real(v.Value)) + imag, _ := constant.Float64Val(constant.Imag(v.Value)) + + r.Children[0].Name = "real" + r.Children[0].Kind = reflect.Float32 + r.Children[0].Value = strconv.FormatFloat(real, 'f', -1, 32) + + r.Children[1].Name = "imaginary" + r.Children[1].Kind = reflect.Float32 + r.Children[1].Value = strconv.FormatFloat(imag, 'f', -1, 32) + case reflect.Complex128: + r.Children = make([]Variable, 2) + r.Len = 2 + + real, _ := constant.Float64Val(constant.Real(v.Value)) + imag, _ := constant.Float64Val(constant.Imag(v.Value)) + + r.Children[0].Name = "real" + r.Children[0].Kind = reflect.Float64 + r.Children[0].Value = strconv.FormatFloat(real, 'f', -1, 64) + + r.Children[1].Name = "imaginary" + r.Children[1].Kind = reflect.Float64 + r.Children[1].Value = strconv.FormatFloat(imag, 'f', -1, 64) + + default: + r.Children = make([]Variable, len(v.Children)) + + for i := range v.Children { + r.Children[i] = *ConvertVar(&v.Children[i]) + } + } + + return &r +} + +// ConvertFunction converts from gosym.Func to +// api.Function. +func ConvertFunction(fn *gosym.Func) *Function { + if fn == nil { + return nil + } + + return &Function{ + Name: fn.Name, + Type: fn.Type, + Value: fn.Value, + GoType: fn.GoType, + } +} + +// ConvertGoroutine converts from proc.G to api.Goroutine. +func ConvertGoroutine(g *proc.G) *Goroutine { + th := g.Thread() + tid := 0 + if th != nil { + tid = th.ID + } + return &Goroutine{ + ID: g.ID, + CurrentLoc: ConvertLocation(g.CurrentLoc), + UserCurrentLoc: ConvertLocation(g.UserCurrent()), + GoStatementLoc: ConvertLocation(g.Go()), + ThreadID: tid, + } +} + +// ConvertLocation converts from proc.Location to api.Location. +func ConvertLocation(loc proc.Location) Location { + return Location{ + PC: loc.PC, + File: loc.File, + Line: loc.Line, + Function: ConvertFunction(loc.Fn), + } +} + +func ConvertAsmInstruction(inst proc.AsmInstruction, text string) AsmInstruction { + var destloc *Location + if inst.DestLoc != nil { + r := ConvertLocation(*inst.DestLoc) + destloc = &r + } + return AsmInstruction{ + Loc: ConvertLocation(inst.Loc), + DestLoc: destloc, + Text: text, + Bytes: inst.Bytes, + Breakpoint: inst.Breakpoint, + AtPC: inst.AtPC, + } +} + +func LoadConfigToProc(cfg *LoadConfig) *proc.LoadConfig { + if cfg == nil { + return nil + } + return &proc.LoadConfig{ + cfg.FollowPointers, + cfg.MaxVariableRecurse, + cfg.MaxStringLen, + cfg.MaxArrayValues, + cfg.MaxStructFields, + } +} + +func LoadConfigFromProc(cfg *proc.LoadConfig) *LoadConfig { + if cfg == nil { + return nil + } + return &LoadConfig{ + cfg.FollowPointers, + cfg.MaxVariableRecurse, + cfg.MaxStringLen, + cfg.MaxArrayValues, + cfg.MaxStructFields, + } +} + +func ConvertRegisters(in []proc.Register) (out []Register) { + out = make([]Register, len(in)) + for i := range in { + out[i] = Register{in[i].Name, in[i].Value} + } + return +} diff --git a/vendor/github.com/derekparker/delve/service/api/prettyprint.go b/vendor/github.com/derekparker/delve/service/api/prettyprint.go new file mode 100644 index 0000000..7c53c1b --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/api/prettyprint.go @@ -0,0 +1,323 @@ +package api + +import ( + "bytes" + "fmt" + "io" + "reflect" +) + +const ( + // strings longer than this will cause slices, arrays and structs to be printed on multiple lines when newlines is enabled + maxShortStringLen = 7 + // string used for one indentation level (when printing on multiple lines) + indentString = "\t" +) + +// SinglelineString returns a representation of v on a single line. +func (v *Variable) SinglelineString() string { + var buf bytes.Buffer + v.writeTo(&buf, true, false, true, "") + return buf.String() +} + +// MultilineString returns a representation of v on multiple lines. +func (v *Variable) MultilineString(indent string) string { + var buf bytes.Buffer + v.writeTo(&buf, true, true, true, indent) + return buf.String() +} + +func (v *Variable) writeTo(buf io.Writer, top, newlines, includeType bool, indent string) { + if v.Unreadable != "" { + fmt.Fprintf(buf, "(unreadable %s)", v.Unreadable) + return + } + + if !top && v.Addr == 0 { + if includeType && v.Type != "void" { + fmt.Fprintf(buf, "%s nil", v.Type) + } else { + fmt.Fprintf(buf, "nil") + } + return + } + + switch v.Kind { + case reflect.Slice: + v.writeSliceTo(buf, newlines, includeType, indent) + case reflect.Array: + v.writeArrayTo(buf, newlines, includeType, indent) + case reflect.Ptr: + if v.Type == "" { + fmt.Fprintf(buf, "nil") + } else if v.Children[0].OnlyAddr && v.Children[0].Addr != 0 { + fmt.Fprintf(buf, "(%s)(0x%x)", v.Type, v.Children[0].Addr) + } else { + fmt.Fprintf(buf, "*") + v.Children[0].writeTo(buf, false, newlines, includeType, indent) + } + case reflect.UnsafePointer: + fmt.Fprintf(buf, "unsafe.Pointer(0x%x)", v.Children[0].Addr) + case reflect.String: + v.writeStringTo(buf) + case reflect.Chan: + if newlines { + v.writeStructTo(buf, newlines, includeType, indent) + } else { + if len(v.Children) == 0 { + fmt.Fprintf(buf, "%s nil", v.Type) + } else { + fmt.Fprintf(buf, "%s %s/%s", v.Type, v.Children[0].Value, v.Children[1].Value) + } + } + case reflect.Struct: + v.writeStructTo(buf, newlines, includeType, indent) + case reflect.Interface: + if includeType { + if v.Children[0].Kind == reflect.Invalid { + fmt.Fprintf(buf, "%s ", v.Type) + if v.Children[0].Addr == 0 { + fmt.Fprintf(buf, "nil") + return + } + } else { + fmt.Fprintf(buf, "%s(%s) ", v.Type, v.Children[0].Type) + } + } + data := v.Children[0] + if data.Kind == reflect.Ptr { + if len(data.Children) == 0 { + fmt.Fprintf(buf, "...") + } else if data.Children[0].Addr == 0 { + fmt.Fprintf(buf, "nil") + } else if data.Children[0].OnlyAddr { + fmt.Fprintf(buf, "0x%x", v.Children[0].Addr) + } else { + v.Children[0].writeTo(buf, false, newlines, !includeType, indent) + } + } else { + v.Children[0].writeTo(buf, false, newlines, !includeType, indent) + } + case reflect.Map: + v.writeMapTo(buf, newlines, includeType, indent) + case reflect.Func: + if v.Value == "" { + fmt.Fprintf(buf, "nil") + } else { + fmt.Fprintf(buf, "%s", v.Value) + } + case reflect.Complex64, reflect.Complex128: + fmt.Fprintf(buf, "(%s + %si)", v.Children[0].Value, v.Children[1].Value) + default: + if v.Value != "" { + buf.Write([]byte(v.Value)) + } else { + fmt.Fprintf(buf, "(unknown %s)", v.Kind) + } + } +} + +func (v *Variable) writeStringTo(buf io.Writer) { + s := v.Value + if len(s) != int(v.Len) { + s = fmt.Sprintf("%s...+%d more", s, int(v.Len)-len(s)) + } + fmt.Fprintf(buf, "%q", s) +} + +func (v *Variable) writeSliceTo(buf io.Writer, newlines, includeType bool, indent string) { + if includeType { + fmt.Fprintf(buf, "%s len: %d, cap: %d, ", v.Type, v.Len, v.Cap) + } + v.writeSliceOrArrayTo(buf, newlines, indent) +} + +func (v *Variable) writeArrayTo(buf io.Writer, newlines, includeType bool, indent string) { + if includeType { + fmt.Fprintf(buf, "%s ", v.Type) + } + v.writeSliceOrArrayTo(buf, newlines, indent) +} + +func (v *Variable) writeStructTo(buf io.Writer, newlines, includeType bool, indent string) { + if int(v.Len) != len(v.Children) && len(v.Children) == 0 { + fmt.Fprintf(buf, "(*%s)(0x%x)", v.Type, v.Addr) + return + } + + if includeType { + fmt.Fprintf(buf, "%s ", v.Type) + } + + nl := v.shouldNewlineStruct(newlines) + + fmt.Fprintf(buf, "{") + + for i := range v.Children { + if nl { + fmt.Fprintf(buf, "\n%s%s", indent, indentString) + } + fmt.Fprintf(buf, "%s: ", v.Children[i].Name) + v.Children[i].writeTo(buf, false, nl, true, indent+indentString) + if i != len(v.Children)-1 || nl { + fmt.Fprintf(buf, ",") + if !nl { + fmt.Fprintf(buf, " ") + } + } + } + + if len(v.Children) != int(v.Len) { + if nl { + fmt.Fprintf(buf, "\n%s%s", indent, indentString) + } else { + fmt.Fprintf(buf, ",") + } + fmt.Fprintf(buf, "...+%d more", int(v.Len)-len(v.Children)) + } + + fmt.Fprintf(buf, "}") +} + +func (v *Variable) writeMapTo(buf io.Writer, newlines, includeType bool, indent string) { + if includeType { + fmt.Fprintf(buf, "%s ", v.Type) + } + + nl := newlines && (len(v.Children) > 0) + + fmt.Fprintf(buf, "[") + + for i := 0; i < len(v.Children); i += 2 { + key := &v.Children[i] + value := &v.Children[i+1] + + if nl { + fmt.Fprintf(buf, "\n%s%s", indent, indentString) + } + + key.writeTo(buf, false, false, false, indent+indentString) + fmt.Fprintf(buf, ": ") + value.writeTo(buf, false, nl, false, indent+indentString) + if i != len(v.Children)-1 || nl { + fmt.Fprintf(buf, ", ") + } + } + + if len(v.Children)/2 != int(v.Len) { + if len(v.Children) != 0 { + if nl { + fmt.Fprintf(buf, "\n%s%s", indent, indentString) + } else { + fmt.Fprintf(buf, ",") + } + fmt.Fprintf(buf, "...+%d more", int(v.Len)-(len(v.Children)/2)) + } else { + fmt.Fprintf(buf, "...") + } + } + + if nl { + fmt.Fprintf(buf, "\n%s", indent) + } + fmt.Fprintf(buf, "]") +} + +func (v *Variable) shouldNewlineArray(newlines bool) bool { + if !newlines || len(v.Children) == 0 { + return false + } + + kind, hasptr := (&v.Children[0]).recursiveKind() + + switch kind { + case reflect.Slice, reflect.Array, reflect.Struct, reflect.Map, reflect.Interface: + return true + case reflect.String: + if hasptr { + return true + } + for i := range v.Children { + if len(v.Children[i].Value) > maxShortStringLen { + return true + } + } + return false + default: + return false + } +} + +func (v *Variable) recursiveKind() (reflect.Kind, bool) { + hasptr := false + var kind reflect.Kind + for { + kind = v.Kind + if kind == reflect.Ptr { + hasptr = true + v = &(v.Children[0]) + } else { + break + } + } + return kind, hasptr +} + +func (v *Variable) shouldNewlineStruct(newlines bool) bool { + if !newlines || len(v.Children) == 0 { + return false + } + + for i := range v.Children { + kind, hasptr := (&v.Children[i]).recursiveKind() + + switch kind { + case reflect.Slice, reflect.Array, reflect.Struct, reflect.Map, reflect.Interface: + return true + case reflect.String: + if hasptr { + return true + } + if len(v.Children[i].Value) > maxShortStringLen { + return true + } + } + } + + return false +} + +func (v *Variable) writeSliceOrArrayTo(buf io.Writer, newlines bool, indent string) { + nl := v.shouldNewlineArray(newlines) + fmt.Fprintf(buf, "[") + + for i := range v.Children { + if nl { + fmt.Fprintf(buf, "\n%s%s", indent, indentString) + } + v.Children[i].writeTo(buf, false, nl, false, indent+indentString) + if i != len(v.Children)-1 || nl { + fmt.Fprintf(buf, ",") + } + } + + if len(v.Children) != int(v.Len) { + if len(v.Children) != 0 { + if nl { + fmt.Fprintf(buf, "\n%s%s", indent, indentString) + } else { + fmt.Fprintf(buf, ",") + } + fmt.Fprintf(buf, "...+%d more", int(v.Len)-len(v.Children)) + } else { + fmt.Fprintf(buf, "...") + } + } + + if nl { + fmt.Fprintf(buf, "\n%s", indent) + } + + fmt.Fprintf(buf, "]") +} diff --git a/vendor/github.com/derekparker/delve/service/api/types.go b/vendor/github.com/derekparker/delve/service/api/types.go new file mode 100644 index 0000000..677a8d3 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/api/types.go @@ -0,0 +1,320 @@ +package api + +import ( + "bytes" + "errors" + "fmt" + "reflect" + "strconv" + "unicode" + + "github.com/derekparker/delve/pkg/proc" +) + +var NotExecutableErr = proc.NotExecutableErr + +// DebuggerState represents the current context of the debugger. +type DebuggerState struct { + // CurrentThread is the currently selected debugger thread. + CurrentThread *Thread `json:"currentThread,omitempty"` + // SelectedGoroutine is the currently selected goroutine + SelectedGoroutine *Goroutine `json:"currentGoroutine,omitempty"` + // List of all the process threads + Threads []*Thread + // NextInProgress indicates that a next or step operation was interrupted by another breakpoint + // or a manual stop and is waiting to complete. + // While NextInProgress is set further requests for next or step may be rejected. + // Either execute continue until NextInProgress is false or call CancelNext + NextInProgress bool + // Exited indicates whether the debugged process has exited. + Exited bool `json:"exited"` + ExitStatus int `json:"exitStatus"` + // Filled by RPCClient.Continue, indicates an error + Err error `json:"-"` +} + +// Breakpoint addresses a location at which process execution may be +// suspended. +type Breakpoint struct { + // ID is a unique identifier for the breakpoint. + ID int `json:"id"` + // User defined name of the breakpoint + Name string `json:"name"` + // Addr is the address of the breakpoint. + Addr uint64 `json:"addr"` + // File is the source file for the breakpoint. + File string `json:"file"` + // Line is a line in File for the breakpoint. + Line int `json:"line"` + // FunctionName is the name of the function at the current breakpoint, and + // may not always be available. + FunctionName string `json:"functionName,omitempty"` + + // Breakpoint condition + Cond string + + // tracepoint flag + Tracepoint bool `json:"continue"` + // retrieve goroutine information + Goroutine bool `json:"goroutine"` + // number of stack frames to retrieve + Stacktrace int `json:"stacktrace"` + // expressions to evaluate + Variables []string `json:"variables,omitempty"` + // LoadArgs requests loading function arguments when the breakpoint is hit + LoadArgs *LoadConfig + // LoadLocals requests loading function locals when the breakpoint is hit + LoadLocals *LoadConfig + // number of times a breakpoint has been reached in a certain goroutine + HitCount map[string]uint64 `json:"hitCount"` + // number of times a breakpoint has been reached + TotalHitCount uint64 `json:"totalHitCount"` +} + +func ValidBreakpointName(name string) error { + if _, err := strconv.Atoi(name); err == nil { + return errors.New("breakpoint name can not be a number") + } + + for _, ch := range name { + if !(unicode.IsLetter(ch) || unicode.IsDigit(ch)) { + return fmt.Errorf("invalid character in breakpoint name '%c'", ch) + } + } + + return nil +} + +// Thread is a thread within the debugged process. +type Thread struct { + // ID is a unique identifier for the thread. + ID int `json:"id"` + // PC is the current program counter for the thread. + PC uint64 `json:"pc"` + // File is the file for the program counter. + File string `json:"file"` + // Line is the line number for the program counter. + Line int `json:"line"` + // Function is function information at the program counter. May be nil. + Function *Function `json:"function,omitempty"` + + // ID of the goroutine running on this thread + GoroutineID int `json:"goroutineID"` + + // Breakpoint this thread is stopped at + Breakpoint *Breakpoint `json:"breakPoint,omitempty"` + // Informations requested by the current breakpoint + BreakpointInfo *BreakpointInfo `json:"breakPointInfo,omitrempty"` +} + +type Location struct { + PC uint64 `json:"pc"` + File string `json:"file"` + Line int `json:"line"` + Function *Function `json:"function,omitempty"` +} + +type Stackframe struct { + Location + Locals []Variable + Arguments []Variable +} + +func (frame *Stackframe) Var(name string) *Variable { + for i := range frame.Locals { + if frame.Locals[i].Name == name { + return &frame.Locals[i] + } + } + for i := range frame.Arguments { + if frame.Arguments[i].Name == name { + return &frame.Arguments[i] + } + } + return nil +} + +// Function represents thread-scoped function information. +type Function struct { + // Name is the function name. + Name string `json:"name"` + Value uint64 `json:"value"` + Type byte `json:"type"` + GoType uint64 `json:"goType"` +} + +// Variable describes a variable. +type Variable struct { + // Name of the variable or struct member + Name string `json:"name"` + // Address of the variable or struct member + Addr uintptr `json:"addr"` + // Only the address field is filled (result of evaluating expressions like &) + OnlyAddr bool `json:"onlyAddr"` + // Go type of the variable + Type string `json:"type"` + // Type of the variable after resolving any typedefs + RealType string `json:"realType"` + + Kind reflect.Kind `json:"kind"` + + //Strings have their length capped at proc.maxArrayValues, use Len for the real length of a string + //Function variables will store the name of the function in this field + Value string `json:"value"` + + // Number of elements in an array or a slice, number of keys for a map, number of struct members for a struct, length of strings + Len int64 `json:"len"` + // Cap value for slices + Cap int64 `json:"cap"` + + // Array and slice elements, member fields of structs, key/value pairs of maps, value of complex numbers + // The Name field in this slice will always be the empty string except for structs (when it will be the field name) and for complex numbers (when it will be "real" and "imaginary") + // For maps each map entry will have to items in this slice, even numbered items will represent map keys and odd numbered items will represent their values + // This field's length is capped at proc.maxArrayValues for slices and arrays and 2*proc.maxArrayValues for maps, in the circumnstances where the cap takes effect len(Children) != Len + // The other length cap applied to this field is related to maximum recursion depth, when the maximum recursion depth is reached this field is left empty, contrary to the previous one this cap also applies to structs (otherwise structs will always have all their member fields returned) + Children []Variable `json:"children"` + + // Unreadable addresses will have this field set + Unreadable string `json:"unreadable"` +} + +// LoadConfig describes how to load values from target's memory +type LoadConfig struct { + // FollowPointers requests pointers to be automatically dereferenced. + FollowPointers bool + // MaxVariableRecurse is how far to recurse when evaluating nested types. + MaxVariableRecurse int + // MaxStringLen is the maximum number of bytes read from a string + MaxStringLen int + // MaxArrayValues is the maximum number of elements read from an array, a slice or a map. + MaxArrayValues int + // MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields. + MaxStructFields int +} + +// Goroutine represents the information relevant to Delve from the runtime's +// internal G structure. +type Goroutine struct { + // ID is a unique identifier for the goroutine. + ID int `json:"id"` + // Current location of the goroutine + CurrentLoc Location `json:"currentLoc"` + // Current location of the goroutine, excluding calls inside runtime + UserCurrentLoc Location `json:"userCurrentLoc"` + // Location of the go instruction that started this goroutine + GoStatementLoc Location `json:"goStatementLoc"` + // ID of the associated thread for running goroutines + ThreadID int `json:"threadID"` +} + +// DebuggerCommand is a command which changes the debugger's execution state. +type DebuggerCommand struct { + // Name is the command to run. + Name string `json:"name"` + // ThreadID is used to specify which thread to use with the SwitchThread + // command. + ThreadID int `json:"threadID,omitempty"` + // GoroutineID is used to specify which thread to use with the SwitchGoroutine + // command. + GoroutineID int `json:"goroutineID,omitempty"` +} + +// Informations about the current breakpoint +type BreakpointInfo struct { + Stacktrace []Stackframe `json:"stacktrace,omitempty"` + Goroutine *Goroutine `json:"goroutine,omitempty"` + Variables []Variable `json:"variables,omitempty"` + Arguments []Variable `json:"arguments,omitempty"` + Locals []Variable `json:"locals,omitempty"` +} + +type EvalScope struct { + GoroutineID int + Frame int +} + +const ( + // Continue resumes process execution. + Continue = "continue" + // Step continues to next source line, entering function calls. + Step = "step" + // StepOut continues to the return address of the current function + StepOut = "stepOut" + // SingleStep continues for exactly 1 cpu instruction. + StepInstruction = "stepInstruction" + // Next continues to the next source line, not entering function calls. + Next = "next" + // SwitchThread switches the debugger's current thread context. + SwitchThread = "switchThread" + // SwitchGoroutine switches the debugger's current thread context to the thread running the specified goroutine + SwitchGoroutine = "switchGoroutine" + // Halt suspends the process. + Halt = "halt" +) + +type AssemblyFlavour int + +const ( + GNUFlavour = AssemblyFlavour(proc.GNUFlavour) + IntelFlavour = AssemblyFlavour(proc.IntelFlavour) +) + +// AsmInstruction represents one assembly instruction at some address +type AsmInstruction struct { + // Loc is the location of this instruction + Loc Location + // Destination of CALL instructions + DestLoc *Location + // Text is the formatted representation of the instruction + Text string + // Bytes is the instruction as read from memory + Bytes []byte + // If Breakpoint is true a breakpoint is set at this instruction + Breakpoint bool + // In AtPC is true this is the instruction the current thread is stopped at + AtPC bool +} + +type AsmInstructions []AsmInstruction + +type GetVersionIn struct { +} + +type GetVersionOut struct { + DelveVersion string + APIVersion int +} + +type SetAPIVersionIn struct { + APIVersion int +} + +type SetAPIVersionOut struct { +} + +type Register struct { + Name string + Value string +} + +type Registers []Register + +func (regs Registers) String() string { + maxlen := 0 + for _, reg := range regs { + if n := len(reg.Name); n > maxlen { + maxlen = n + } + } + + var buf bytes.Buffer + for _, reg := range regs { + fmt.Fprintf(&buf, "%*s = %s\n", maxlen, reg.Name, reg.Value) + } + return buf.String() +} + +type DiscardedBreakpoint struct { + Breakpoint *Breakpoint + Reason string +} diff --git a/vendor/github.com/derekparker/delve/service/client.go b/vendor/github.com/derekparker/delve/service/client.go new file mode 100644 index 0000000..fe06a94 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/client.go @@ -0,0 +1,115 @@ +package service + +import ( + "time" + + "github.com/derekparker/delve/service/api" +) + +// Client represents a debugger service client. All client methods are +// synchronous. +type Client interface { + // Returns the pid of the process we are debugging. + ProcessPid() int + + // LastModified returns the time that the process' executable was modified. + LastModified() time.Time + + // Detach detaches the debugger, optionally killing the process. + Detach(killProcess bool) error + + // Restarts program. + Restart() ([]api.DiscardedBreakpoint, error) + + // GetState returns the current debugger state. + GetState() (*api.DebuggerState, error) + + // Continue resumes process execution. + Continue() <-chan *api.DebuggerState + // Next continues to the next source line, not entering function calls. + Next() (*api.DebuggerState, error) + // Step continues to the next source line, entering function calls. + Step() (*api.DebuggerState, error) + // StepOut continues to the return address of the current function + StepOut() (*api.DebuggerState, error) + + // SingleStep will step a single cpu instruction. + StepInstruction() (*api.DebuggerState, error) + // SwitchThread switches the current thread context. + SwitchThread(threadID int) (*api.DebuggerState, error) + // SwitchGoroutine switches the current goroutine (and the current thread as well) + SwitchGoroutine(goroutineID int) (*api.DebuggerState, error) + // Halt suspends the process. + Halt() (*api.DebuggerState, error) + + // GetBreakpoint gets a breakpoint by ID. + GetBreakpoint(id int) (*api.Breakpoint, error) + // GetBreakpointByName gets a breakpoint by name. + GetBreakpointByName(name string) (*api.Breakpoint, error) + // CreateBreakpoint creates a new breakpoint. + CreateBreakpoint(*api.Breakpoint) (*api.Breakpoint, error) + // ListBreakpoints gets all breakpoints. + ListBreakpoints() ([]*api.Breakpoint, error) + // ClearBreakpoint deletes a breakpoint by ID. + ClearBreakpoint(id int) (*api.Breakpoint, error) + // ClearBreakpointByName deletes a breakpoint by name + ClearBreakpointByName(name string) (*api.Breakpoint, error) + // Allows user to update an existing breakpoint for example to change the information + // retrieved when the breakpoint is hit or to change, add or remove the break condition + AmendBreakpoint(*api.Breakpoint) error + // Cancels a Next or Step call that was interrupted by a manual stop or by another breakpoint + CancelNext() error + + // ListThreads lists all threads. + ListThreads() ([]*api.Thread, error) + // GetThread gets a thread by its ID. + GetThread(id int) (*api.Thread, error) + + // ListPackageVariables lists all package variables in the context of the current thread. + ListPackageVariables(filter string, cfg api.LoadConfig) ([]api.Variable, error) + // EvalVariable returns a variable in the context of the current thread. + EvalVariable(scope api.EvalScope, symbol string, cfg api.LoadConfig) (*api.Variable, error) + + // SetVariable sets the value of a variable + SetVariable(scope api.EvalScope, symbol, value string) error + + // ListSources lists all source files in the process matching filter. + ListSources(filter string) ([]string, error) + // ListFunctions lists all functions in the process matching filter. + ListFunctions(filter string) ([]string, error) + // ListTypes lists all types in the process matching filter. + ListTypes(filter string) ([]string, error) + // ListLocals lists all local variables in scope. + ListLocalVariables(scope api.EvalScope, cfg api.LoadConfig) ([]api.Variable, error) + // ListFunctionArgs lists all arguments to the current function. + ListFunctionArgs(scope api.EvalScope, cfg api.LoadConfig) ([]api.Variable, error) + // ListRegisters lists registers and their values. + ListRegisters(threadID int, includeFp bool) (api.Registers, error) + + // ListGoroutines lists all goroutines. + ListGoroutines() ([]*api.Goroutine, error) + + // Returns stacktrace + Stacktrace(int, int, *api.LoadConfig) ([]api.Stackframe, error) + + // Returns whether we attached to a running process or not + AttachedToExistingProcess() bool + + // Returns concrete location information described by a location expression + // loc ::= : | [:] | // | (+|-) | | *
+ // * can be the full path of a file or just a suffix + // * ::= .. | .(*). | . | . | (*). | + // * must be unambiguous + // * // will return a location for each function matched by regex + // * + returns a location for the line that is lines after the current line + // * - returns a location for the line that is lines before the current line + // * returns a location for a line in the current file + // * *
returns the location corresponding to the specified address + // NOTE: this function does not actually set breakpoints. + FindLocation(scope api.EvalScope, loc string) ([]api.Location, error) + + // Disassemble code between startPC and endPC + DisassembleRange(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) + // Disassemble code of the function containing PC + DisassemblePC(scope api.EvalScope, pc uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) +} diff --git a/vendor/github.com/derekparker/delve/service/config.go b/vendor/github.com/derekparker/delve/service/config.go new file mode 100644 index 0000000..dd2991c --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/config.go @@ -0,0 +1,28 @@ +package service + +import "net" + +// Config provides the configuration to start a Debugger and expose it with a +// service. +// +// Only one of ProcessArgs or AttachPid should be specified. If ProcessArgs is +// provided, a new process will be launched. Otherwise, the debugger will try +// to attach to an existing process with AttachPid. +type Config struct { + // Listener is used to serve requests. + Listener net.Listener + // ProcessArgs are the arguments to launch a new process. + ProcessArgs []string + // WorkingDir is working directory of the new process. This field is used + // only when launching a new process. + WorkingDir string + + // AttachPid is the PID of an existing process to which the debugger should + // attach. + AttachPid int + // AcceptMulti configures the server to accept multiple connection. + // Note that the server API is not reentrant and clients will have to coordinate. + AcceptMulti bool + // APIVersion selects which version of the API to serve (default: 1). + APIVersion int +} diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger.go b/vendor/github.com/derekparker/delve/service/debugger/debugger.go new file mode 100644 index 0000000..705a2f1 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/debugger/debugger.go @@ -0,0 +1,835 @@ +package debugger + +import ( + "debug/gosym" + "errors" + "fmt" + "go/parser" + "log" + "path/filepath" + "regexp" + "runtime" + "strings" + "sync" + "time" + + "github.com/derekparker/delve/pkg/proc" + "github.com/derekparker/delve/pkg/target" + "github.com/derekparker/delve/service/api" +) + +// Debugger service. +// +// Debugger provides a higher level of +// abstraction over proc.Process. +// It handles converting from internal types to +// the types expected by clients. It also handles +// functionality needed by clients, but not needed in +// lower lever packages such as proc. +type Debugger struct { + config *Config + // TODO(DO NOT MERGE WITHOUT) rename to targetMutex + processMutex sync.Mutex + target target.Interface +} + +// Config provides the configuration to start a Debugger. +// +// Only one of ProcessArgs or AttachPid should be specified. If ProcessArgs is +// provided, a new process will be launched. Otherwise, the debugger will try +// to attach to an existing process with AttachPid. +type Config struct { + // ProcessArgs are the arguments to launch a new process. + ProcessArgs []string + // WorkingDir is working directory of the new process. This field is used + // only when launching a new process. + WorkingDir string + + // AttachPid is the PID of an existing process to which the debugger should + // attach. + AttachPid int +} + +// New creates a new Debugger. +func New(config *Config) (*Debugger, error) { + d := &Debugger{ + config: config, + } + + // Create the process by either attaching or launching. + if d.config.AttachPid > 0 { + log.Printf("attaching to pid %d", d.config.AttachPid) + p, err := proc.Attach(d.config.AttachPid) + if err != nil { + return nil, attachErrorMessage(d.config.AttachPid, err) + } + d.target = p + } else { + log.Printf("launching process with args: %v", d.config.ProcessArgs) + p, err := proc.Launch(d.config.ProcessArgs, d.config.WorkingDir) + if err != nil { + if err != proc.NotExecutableErr && err != proc.UnsupportedArchErr { + err = fmt.Errorf("could not launch process: %s", err) + } + return nil, err + } + d.target = p + } + return d, nil +} + +// ProcessPid returns the PID of the process +// the debugger is debugging. +func (d *Debugger) ProcessPid() int { + return d.target.Pid() +} + +// LastModified returns the time that the process' executable was last +// modified. +func (d *Debugger) LastModified() time.Time { + return d.target.LastModified() +} + +// Detach detaches from the target process. +// If `kill` is true we will kill the process after +// detaching. +func (d *Debugger) Detach(kill bool) error { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + return d.detach(kill) +} + +func (d *Debugger) detach(kill bool) error { + if d.config.AttachPid != 0 { + return d.target.Detach(kill) + } + return d.target.Kill() +} + +// Restart will restart the target process, first killing +// and then exec'ing it again. +func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + if !d.target.Exited() { + if d.target.Running() { + d.target.Halt() + } + // Ensure the process is in a PTRACE_STOP. + if err := stopProcess(d.ProcessPid()); err != nil { + return nil, err + } + if err := d.detach(true); err != nil { + return nil, err + } + } + p, err := proc.Launch(d.config.ProcessArgs, d.config.WorkingDir) + if err != nil { + return nil, fmt.Errorf("could not launch process: %s", err) + } + discarded := []api.DiscardedBreakpoint{} + for _, oldBp := range d.breakpoints() { + if oldBp.ID < 0 { + continue + } + if len(oldBp.File) > 0 { + oldBp.Addr, err = p.FindFileLocation(oldBp.File, oldBp.Line) + if err != nil { + discarded = append(discarded, api.DiscardedBreakpoint{oldBp, err.Error()}) + continue + } + } + newBp, err := p.SetBreakpoint(oldBp.Addr, proc.UserBreakpoint, nil) + if err != nil { + return nil, err + } + if err := copyBreakpointInfo(newBp, oldBp); err != nil { + return nil, err + } + } + d.target = p + return discarded, nil +} + +// State returns the current state of the debugger. +func (d *Debugger) State() (*api.DebuggerState, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + return d.state() +} + +func (d *Debugger) state() (*api.DebuggerState, error) { + if d.target.Exited() { + return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} + } + + var ( + state *api.DebuggerState + goroutine *api.Goroutine + ) + + if d.target.SelectedGoroutine() != nil { + goroutine = api.ConvertGoroutine(d.target.SelectedGoroutine()) + } + + state = &api.DebuggerState{ + SelectedGoroutine: goroutine, + Exited: d.target.Exited(), + } + + for i := range d.target.Threads() { + th := api.ConvertThread(d.target.Threads()[i]) + state.Threads = append(state.Threads, th) + if i == d.target.CurrentThread().ID { + state.CurrentThread = th + } + } + + for _, bp := range d.target.Breakpoints() { + if bp.Internal() { + state.NextInProgress = true + break + } + } + + return state, nil +} + +// CreateBreakpoint creates a breakpoint. +func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + var ( + createdBp *api.Breakpoint + addr uint64 + err error + ) + + if requestedBp.Name != "" { + if err = api.ValidBreakpointName(requestedBp.Name); err != nil { + return nil, err + } + if d.findBreakpointByName(requestedBp.Name) != nil { + return nil, errors.New("breakpoint name already exists") + } + } + + switch { + case len(requestedBp.File) > 0: + fileName := requestedBp.File + if runtime.GOOS == "windows" { + // Accept fileName which is case-insensitive and slash-insensitive match + fileNameNormalized := strings.ToLower(filepath.ToSlash(fileName)) + for symFile := range d.target.Sources() { + if fileNameNormalized == strings.ToLower(filepath.ToSlash(symFile)) { + fileName = symFile + break + } + } + } + addr, err = d.target.FindFileLocation(fileName, requestedBp.Line) + case len(requestedBp.FunctionName) > 0: + if requestedBp.Line >= 0 { + addr, err = d.target.FindFunctionLocation(requestedBp.FunctionName, false, requestedBp.Line) + } else { + addr, err = d.target.FindFunctionLocation(requestedBp.FunctionName, true, 0) + } + default: + addr = requestedBp.Addr + } + + if err != nil { + return nil, err + } + + bp, err := d.target.SetBreakpoint(addr, proc.UserBreakpoint, nil) + if err != nil { + return nil, err + } + if err := copyBreakpointInfo(bp, requestedBp); err != nil { + if _, err1 := d.target.ClearBreakpoint(bp.Addr); err1 != nil { + err = fmt.Errorf("error while creating breakpoint: %v, additionally the breakpoint could not be properly rolled back: %v", err, err1) + } + return nil, err + } + createdBp = api.ConvertBreakpoint(bp) + log.Printf("created breakpoint: %#v", createdBp) + return createdBp, nil +} + +func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + original := d.findBreakpoint(amend.ID) + if original == nil { + return fmt.Errorf("no breakpoint with ID %d", amend.ID) + } + if err := api.ValidBreakpointName(amend.Name); err != nil { + return err + } + return copyBreakpointInfo(original, amend) +} + +func (d *Debugger) CancelNext() error { + return d.target.ClearInternalBreakpoints() +} + +func copyBreakpointInfo(bp *proc.Breakpoint, requested *api.Breakpoint) (err error) { + bp.Name = requested.Name + bp.Tracepoint = requested.Tracepoint + bp.Goroutine = requested.Goroutine + bp.Stacktrace = requested.Stacktrace + bp.Variables = requested.Variables + bp.LoadArgs = api.LoadConfigToProc(requested.LoadArgs) + bp.LoadLocals = api.LoadConfigToProc(requested.LoadLocals) + bp.Cond = nil + if requested.Cond != "" { + bp.Cond, err = parser.ParseExpr(requested.Cond) + } + return err +} + +// ClearBreakpoint clears a breakpoint. +func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + var clearedBp *api.Breakpoint + bp, err := d.target.ClearBreakpoint(requestedBp.Addr) + if err != nil { + return nil, fmt.Errorf("Can't clear breakpoint @%x: %s", requestedBp.Addr, err) + } + clearedBp = api.ConvertBreakpoint(bp) + log.Printf("cleared breakpoint: %#v", clearedBp) + return clearedBp, err +} + +// Breakpoints returns the list of current breakpoints. +func (d *Debugger) Breakpoints() []*api.Breakpoint { + d.processMutex.Lock() + defer d.processMutex.Unlock() + return d.breakpoints() +} + +func (d *Debugger) breakpoints() []*api.Breakpoint { + bps := []*api.Breakpoint{} + for _, bp := range d.target.Breakpoints() { + if bp.Internal() { + continue + } + bps = append(bps, api.ConvertBreakpoint(bp)) + } + return bps +} + +// FindBreakpoint returns the breakpoint specified by 'id'. +func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + bp := d.findBreakpoint(id) + if bp == nil { + return nil + } + return api.ConvertBreakpoint(bp) +} + +func (d *Debugger) findBreakpoint(id int) *proc.Breakpoint { + for _, bp := range d.target.Breakpoints() { + if bp.ID == id { + return bp + } + } + return nil +} + +// FindBreakpointByName returns the breakpoint specified by 'name' +func (d *Debugger) FindBreakpointByName(name string) *api.Breakpoint { + d.processMutex.Lock() + defer d.processMutex.Unlock() + return d.findBreakpointByName(name) +} + +func (d *Debugger) findBreakpointByName(name string) *api.Breakpoint { + for _, bp := range d.breakpoints() { + if bp.Name == name { + return bp + } + } + return nil +} + +// Threads returns the threads of the target process. +func (d *Debugger) Threads() ([]*api.Thread, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + if d.target.Exited() { + return nil, &proc.ProcessExitedError{} + } + threads := []*api.Thread{} + for _, th := range d.target.Threads() { + threads = append(threads, api.ConvertThread(th)) + } + return threads, nil +} + +// FindThread returns the thread for the given 'id'. +func (d *Debugger) FindThread(id int) (*api.Thread, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + if d.target.Exited() { + return nil, &proc.ProcessExitedError{} + } + + for _, th := range d.target.Threads() { + if th.ID == id { + return api.ConvertThread(th), nil + } + } + return nil, nil +} + +// Command handles commands which control the debugger lifecycle +func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, error) { + var err error + + if command.Name == api.Halt { + // RequestManualStop does not invoke any ptrace syscalls, so it's safe to + // access the process directly. + log.Print("halting") + err = d.target.RequestManualStop() + } + + d.processMutex.Lock() + defer d.processMutex.Unlock() + + switch command.Name { + case api.Continue: + log.Print("continuing") + err = d.target.Continue() + if err != nil { + if exitedErr, exited := err.(proc.ProcessExitedError); exited { + state := &api.DebuggerState{} + state.Exited = true + state.ExitStatus = exitedErr.Status + state.Err = errors.New(exitedErr.Error()) + return state, nil + } + return nil, err + } + state, stateErr := d.state() + if stateErr != nil { + return state, stateErr + } + err = d.collectBreakpointInformation(state) + return state, err + + case api.Next: + log.Print("nexting") + err = d.target.Next() + case api.Step: + log.Print("stepping") + err = d.target.Step() + case api.StepInstruction: + log.Print("single stepping") + err = d.target.StepInstruction() + case api.StepOut: + log.Print("step out") + err = d.target.StepOut() + case api.SwitchThread: + log.Printf("switching to thread %d", command.ThreadID) + err = d.target.SwitchThread(command.ThreadID) + case api.SwitchGoroutine: + log.Printf("switching to goroutine %d", command.GoroutineID) + err = d.target.SwitchGoroutine(command.GoroutineID) + case api.Halt: + // RequestManualStop already called + } + if err != nil { + return nil, err + } + return d.state() +} + +func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error { + if state == nil { + return nil + } + + for i := range state.Threads { + if state.Threads[i].Breakpoint == nil { + continue + } + + bp := state.Threads[i].Breakpoint + bpi := &api.BreakpointInfo{} + state.Threads[i].BreakpointInfo = bpi + + if bp.Goroutine { + g, err := d.target.CurrentThread().GetG() + if err != nil { + return err + } + bpi.Goroutine = api.ConvertGoroutine(g) + } + + if bp.Stacktrace > 0 { + rawlocs, err := d.target.CurrentThread().Stacktrace(bp.Stacktrace) + if err != nil { + return err + } + bpi.Stacktrace, err = d.convertStacktrace(rawlocs, nil) + if err != nil { + return err + } + } + + s, err := d.target.Threads()[state.Threads[i].ID].Scope() + if err != nil { + return err + } + + if len(bp.Variables) > 0 { + bpi.Variables = make([]api.Variable, len(bp.Variables)) + } + for i := range bp.Variables { + v, err := s.EvalVariable(bp.Variables[i], proc.LoadConfig{true, 1, 64, 64, -1}) + if err != nil { + return err + } + bpi.Variables[i] = *api.ConvertVar(v) + } + if bp.LoadArgs != nil { + if vars, err := s.FunctionArguments(*api.LoadConfigToProc(bp.LoadArgs)); err == nil { + bpi.Arguments = convertVars(vars) + } + } + if bp.LoadLocals != nil { + if locals, err := s.LocalVariables(*api.LoadConfigToProc(bp.LoadLocals)); err == nil { + bpi.Locals = convertVars(locals) + } + } + } + + return nil +} + +// Sources returns a list of the source files for target binary. +func (d *Debugger) Sources(filter string) ([]string, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + regex, err := regexp.Compile(filter) + if err != nil { + return nil, fmt.Errorf("invalid filter argument: %s", err.Error()) + } + + files := []string{} + for f := range d.target.Sources() { + if regex.Match([]byte(f)) { + files = append(files, f) + } + } + return files, nil +} + +// Functions returns a list of functions in the target process. +func (d *Debugger) Functions(filter string) ([]string, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + return regexFilterFuncs(filter, d.target.Funcs()) +} + +func (d *Debugger) Types(filter string) ([]string, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + regex, err := regexp.Compile(filter) + if err != nil { + return nil, fmt.Errorf("invalid filter argument: %s", err.Error()) + } + + types, err := d.target.Types() + if err != nil { + return nil, err + } + + r := make([]string, 0, len(types)) + for _, typ := range types { + if regex.Match([]byte(typ)) { + r = append(r, typ) + } + } + + return r, nil +} + +func regexFilterFuncs(filter string, allFuncs []gosym.Func) ([]string, error) { + regex, err := regexp.Compile(filter) + if err != nil { + return nil, fmt.Errorf("invalid filter argument: %s", err.Error()) + } + + funcs := []string{} + for _, f := range allFuncs { + if f.Sym != nil && regex.Match([]byte(f.Name)) { + funcs = append(funcs, f.Name) + } + } + return funcs, nil +} + +// PackageVariables returns a list of package variables for the thread, +// optionally regexp filtered using regexp described in 'filter'. +func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadConfig) ([]api.Variable, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + regex, err := regexp.Compile(filter) + if err != nil { + return nil, fmt.Errorf("invalid filter argument: %s", err.Error()) + } + + vars := []api.Variable{} + thread, found := d.target.Threads()[threadID] + if !found { + return nil, fmt.Errorf("couldn't find thread %d", threadID) + } + scope, err := thread.Scope() + if err != nil { + return nil, err + } + pv, err := scope.PackageVariables(cfg) + if err != nil { + return nil, err + } + for _, v := range pv { + if regex.Match([]byte(v.Name)) { + vars = append(vars, *api.ConvertVar(v)) + } + } + return vars, err +} + +// Registers returns string representation of the CPU registers. +func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + thread, found := d.target.Threads()[threadID] + if !found { + return nil, fmt.Errorf("couldn't find thread %d", threadID) + } + regs, err := thread.Registers(floatingPoint) + if err != nil { + return nil, err + } + return api.ConvertRegisters(regs.Slice()), err +} + +func convertVars(pv []*proc.Variable) []api.Variable { + vars := make([]api.Variable, 0, len(pv)) + for _, v := range pv { + vars = append(vars, *api.ConvertVar(v)) + } + return vars +} + +// LocalVariables returns a list of the local variables. +func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]api.Variable, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) + if err != nil { + return nil, err + } + pv, err := s.LocalVariables(cfg) + if err != nil { + return nil, err + } + return convertVars(pv), err +} + +// FunctionArguments returns the arguments to the current function. +func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) ([]api.Variable, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) + if err != nil { + return nil, err + } + pv, err := s.FunctionArguments(cfg) + if err != nil { + return nil, err + } + return convertVars(pv), nil +} + +// EvalVariableInScope will attempt to evaluate the variable represented by 'symbol' +// in the scope provided. +func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg proc.LoadConfig) (*api.Variable, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) + if err != nil { + return nil, err + } + v, err := s.EvalVariable(symbol, cfg) + if err != nil { + return nil, err + } + return api.ConvertVar(v), err +} + +// SetVariableInScope will set the value of the variable represented by +// 'symbol' to the value given, in the given scope. +func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string) error { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) + if err != nil { + return err + } + return s.SetVariable(symbol, value) +} + +// Goroutines will return a list of goroutines in the target process. +func (d *Debugger) Goroutines() ([]*api.Goroutine, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + goroutines := []*api.Goroutine{} + gs, err := d.target.GoroutinesInfo() + if err != nil { + return nil, err + } + for _, g := range gs { + goroutines = append(goroutines, api.ConvertGoroutine(g)) + } + return goroutines, err +} + +// Stacktrace returns a list of Stackframes for the given goroutine. The +// length of the returned list will be min(stack_len, depth). +// If 'full' is true, then local vars, function args, etc will be returned as well. +func (d *Debugger) Stacktrace(goroutineID, depth int, cfg *proc.LoadConfig) ([]api.Stackframe, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + var rawlocs []proc.Stackframe + + g, err := d.target.FindGoroutine(goroutineID) + if err != nil { + return nil, err + } + + if g == nil { + rawlocs, err = d.target.CurrentThread().Stacktrace(depth) + } else { + rawlocs, err = g.Stacktrace(depth) + } + if err != nil { + return nil, err + } + + return d.convertStacktrace(rawlocs, cfg) +} + +func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) { + locations := make([]api.Stackframe, 0, len(rawlocs)) + for i := range rawlocs { + frame := api.Stackframe{Location: api.ConvertLocation(rawlocs[i].Call)} + if cfg != nil && rawlocs[i].Current.Fn != nil { + var err error + scope := rawlocs[i].Scope(d.target.CurrentThread()) + locals, err := scope.LocalVariables(*cfg) + if err != nil { + return nil, err + } + arguments, err := scope.FunctionArguments(*cfg) + if err != nil { + return nil, err + } + + frame.Locals = convertVars(locals) + frame.Arguments = convertVars(arguments) + } + locations = append(locations, frame) + } + + return locations, nil +} + +// FindLocation will find the location specified by 'locStr'. +func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Location, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + loc, err := parseLocationSpec(locStr) + if err != nil { + return nil, err + } + + s, _ := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) + + locs, err := loc.Find(d, s, locStr) + for i := range locs { + file, line, fn := d.target.PCToLine(locs[i].PC) + locs[i].File = file + locs[i].Line = line + locs[i].Function = api.ConvertFunction(fn) + } + return locs, err +} + +// Disassembles code between startPC and endPC +// if endPC == 0 it will find the function containing startPC and disassemble the whole function +func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + if endPC == 0 { + _, _, fn := d.target.PCToLine(startPC) + if fn == nil { + return nil, fmt.Errorf("Address 0x%x does not belong to any function", startPC) + } + startPC = fn.Entry + endPC = fn.End + } + + currentGoroutine := true + thread := d.target.CurrentThread() + + if s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame); err == nil { + thread = s.Thread + if scope.GoroutineID != -1 { + g, _ := s.Thread.GetG() + if g == nil || g.ID != scope.GoroutineID { + currentGoroutine = false + } + } + } + + insts, err := thread.Disassemble(startPC, endPC, currentGoroutine) + if err != nil { + return nil, err + } + disass := make(api.AsmInstructions, len(insts)) + + for i := range insts { + disass[i] = api.ConvertAsmInstruction(insts[i], insts[i].Text(proc.AssemblyFlavour(flavour))) + } + + return disass, nil +} diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go b/vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go new file mode 100644 index 0000000..c317718 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go @@ -0,0 +1,15 @@ +package debugger + +import ( + "fmt" + sys "golang.org/x/sys/unix" +) + +func attachErrorMessage(pid int, err error) error { + //TODO: mention certificates? + return fmt.Errorf("could not attach to pid %d: %s", pid, err) +} + +func stopProcess(pid int) error { + return sys.Kill(pid, sys.SIGSTOP) +} diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go b/vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go new file mode 100644 index 0000000..1d567c0 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go @@ -0,0 +1,35 @@ +package debugger + +import ( + "fmt" + sys "golang.org/x/sys/unix" + "io/ioutil" + "os" + "syscall" +) + +func attachErrorMessage(pid int, err error) error { + fallbackerr := fmt.Errorf("could not attach to pid %d: %s", pid, err) + if serr, ok := err.(syscall.Errno); ok { + switch serr { + case syscall.EPERM: + bs, err := ioutil.ReadFile("/proc/sys/kernel/yama/ptrace_scope") + if err == nil && len(bs) >= 1 && bs[0] != '0' { + // Yama documentation: https://www.kernel.org/doc/Documentation/security/Yama.txt + return fmt.Errorf("Could not attach to pid %d: set /proc/sys/kernel/yama/ptrace_scope to 0", pid) + } + fi, err := os.Stat(fmt.Sprintf("/proc/%d", pid)) + if err != nil { + return fallbackerr + } + if fi.Sys().(*syscall.Stat_t).Uid != uint32(os.Getuid()) { + return fmt.Errorf("Could not attach to pid %d: current user does not own the process", pid) + } + } + } + return fallbackerr +} + +func stopProcess(pid int) error { + return sys.Kill(pid, sys.SIGSTOP) +} diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go b/vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go new file mode 100644 index 0000000..c80ce2a --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go @@ -0,0 +1,16 @@ +package debugger + +import ( + "fmt" +) + +func attachErrorMessage(pid int, err error) error { + return fmt.Errorf("could not attach to pid %d: %s", pid, err) +} + +func stopProcess(pid int) error { + // We cannot gracefully stop a process on Windows, + // so just ignore this request and let `Detach` kill + // the process. + return nil +} diff --git a/vendor/github.com/derekparker/delve/service/debugger/locations.go b/vendor/github.com/derekparker/delve/service/debugger/locations.go new file mode 100644 index 0000000..ddc5576 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/debugger/locations.go @@ -0,0 +1,411 @@ +package debugger + +import ( + "debug/gosym" + "fmt" + "go/constant" + "path/filepath" + "reflect" + "runtime" + "strconv" + "strings" + + "github.com/derekparker/delve/pkg/proc" + "github.com/derekparker/delve/service/api" +) + +const maxFindLocationCandidates = 5 + +type LocationSpec interface { + Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) +} + +type NormalLocationSpec struct { + Base string + FuncBase *FuncLocationSpec + LineOffset int +} + +type RegexLocationSpec struct { + FuncRegex string +} + +type AddrLocationSpec struct { + AddrExpr string +} + +type OffsetLocationSpec struct { + Offset int +} + +type LineLocationSpec struct { + Line int +} + +type FuncLocationSpec struct { + PackageName string + AbsolutePackage bool + ReceiverName string + PackageOrReceiverName string + BaseName string +} + +func parseLocationSpec(locStr string) (LocationSpec, error) { + rest := locStr + + malformed := func(reason string) error { + return fmt.Errorf("Malformed breakpoint location \"%s\" at %d: %s", locStr, len(locStr)-len(rest), reason) + } + + if len(rest) <= 0 { + return nil, malformed("empty string") + } + + switch rest[0] { + case '+', '-': + offset, err := strconv.Atoi(rest) + if err != nil { + return nil, malformed(err.Error()) + } + return &OffsetLocationSpec{offset}, nil + + case '/': + if rest[len(rest)-1] == '/' { + rx, rest := readRegex(rest[1:]) + if len(rest) < 0 { + return nil, malformed("non-terminated regular expression") + } + if len(rest) > 1 { + return nil, malformed("no line offset can be specified for regular expression locations") + } + return &RegexLocationSpec{rx}, nil + } else { + return parseLocationSpecDefault(locStr, rest) + } + + case '*': + return &AddrLocationSpec{rest[1:]}, nil + + default: + return parseLocationSpecDefault(locStr, rest) + } +} + +func parseLocationSpecDefault(locStr, rest string) (LocationSpec, error) { + malformed := func(reason string) error { + return fmt.Errorf("Malformed breakpoint location \"%s\" at %d: %s", locStr, len(locStr)-len(rest), reason) + } + + v := strings.Split(rest, ":") + if len(v) > 2 { + // On Windows, path may contain ":", so split only on last ":" + v = []string{strings.Join(v[0:len(v)-1], ":"), v[len(v)-1]} + } + + if len(v) == 1 { + n, err := strconv.ParseInt(v[0], 0, 64) + if err == nil { + return &LineLocationSpec{int(n)}, nil + } + } + + spec := &NormalLocationSpec{} + + spec.Base = v[0] + spec.FuncBase = parseFuncLocationSpec(spec.Base) + + if len(v) < 2 { + spec.LineOffset = -1 + return spec, nil + } + + rest = v[1] + + var err error + spec.LineOffset, err = strconv.Atoi(rest) + if err != nil || spec.LineOffset < 0 { + return nil, malformed("line offset negative or not a number") + } + + return spec, nil +} + +func readRegex(in string) (rx string, rest string) { + out := make([]rune, 0, len(in)) + escaped := false + for i, ch := range in { + if escaped { + if ch == '/' { + out = append(out, '/') + } else { + out = append(out, '\\') + out = append(out, ch) + } + escaped = false + } else { + switch ch { + case '\\': + escaped = true + case '/': + return string(out), in[i:] + default: + out = append(out, ch) + } + } + } + return string(out), "" +} + +func parseFuncLocationSpec(in string) *FuncLocationSpec { + var v []string + pathend := strings.LastIndex(in, "/") + if pathend < 0 { + v = strings.Split(in, ".") + } else { + v = strings.Split(in[pathend:], ".") + if len(v) > 0 { + v[0] = in[:pathend] + v[0] + } + } + + var spec FuncLocationSpec + switch len(v) { + case 1: + spec.BaseName = v[0] + + case 2: + spec.BaseName = v[1] + r := stripReceiverDecoration(v[0]) + if r != v[0] { + spec.ReceiverName = r + } else if strings.Index(r, "/") >= 0 { + spec.PackageName = r + } else { + spec.PackageOrReceiverName = r + } + + case 3: + spec.BaseName = v[2] + spec.ReceiverName = stripReceiverDecoration(v[1]) + spec.PackageName = v[0] + + default: + return nil + } + + if strings.HasPrefix(spec.PackageName, "/") { + spec.PackageName = spec.PackageName[1:] + spec.AbsolutePackage = true + } + + if strings.Index(spec.BaseName, "/") >= 0 || strings.Index(spec.ReceiverName, "/") >= 0 { + return nil + } + + return &spec +} + +func stripReceiverDecoration(in string) string { + if len(in) < 3 { + return in + } + if (in[0] != '(') || (in[1] != '*') || (in[len(in)-1] != ')') { + return in + } + + return in[2 : len(in)-1] +} + +func (spec *FuncLocationSpec) Match(sym *gosym.Sym) bool { + if spec.BaseName != sym.BaseName() { + return false + } + + recv := stripReceiverDecoration(sym.ReceiverName()) + if spec.ReceiverName != "" && spec.ReceiverName != recv { + return false + } + if spec.PackageName != "" { + if spec.AbsolutePackage { + if spec.PackageName != sym.PackageName() { + return false + } + } else { + if !partialPathMatch(spec.PackageName, sym.PackageName()) { + return false + } + } + } + if spec.PackageOrReceiverName != "" && !partialPathMatch(spec.PackageOrReceiverName, sym.PackageName()) && spec.PackageOrReceiverName != recv { + return false + } + return true +} + +func (loc *RegexLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { + funcs := d.target.Funcs() + matches, err := regexFilterFuncs(loc.FuncRegex, funcs) + if err != nil { + return nil, err + } + r := make([]api.Location, 0, len(matches)) + for i := range matches { + addr, err := d.target.FindFunctionLocation(matches[i], true, 0) + if err == nil { + r = append(r, api.Location{PC: addr}) + } + } + return r, nil +} + +func (loc *AddrLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { + if scope == nil { + addr, err := strconv.ParseInt(loc.AddrExpr, 0, 64) + if err != nil { + return nil, fmt.Errorf("could not determine current location (scope is nil)") + } + return []api.Location{{PC: uint64(addr)}}, nil + } else { + v, err := scope.EvalExpression(loc.AddrExpr, proc.LoadConfig{true, 0, 0, 0, 0}) + if err != nil { + return nil, err + } + if v.Unreadable != nil { + return nil, v.Unreadable + } + switch v.Kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + addr, _ := constant.Uint64Val(v.Value) + return []api.Location{{PC: addr}}, nil + case reflect.Func: + _, _, fn := d.target.PCToLine(uint64(v.Base)) + pc, err := d.target.FirstPCAfterPrologue(fn, false) + if err != nil { + return nil, err + } + return []api.Location{{PC: uint64(pc)}}, nil + default: + return nil, fmt.Errorf("wrong expression kind: %v", v.Kind) + } + } +} + +func (loc *NormalLocationSpec) FileMatch(path string) bool { + return partialPathMatch(loc.Base, path) +} + +func partialPathMatch(expr, path string) bool { + if runtime.GOOS == "windows" { + // Accept `expr` which is case-insensitive and slash-insensitive match to `path` + expr = strings.ToLower(filepath.ToSlash(expr)) + path = strings.ToLower(filepath.ToSlash(path)) + } + if len(expr) < len(path)-1 { + return strings.HasSuffix(path, expr) && (path[len(path)-len(expr)-1] == '/') + } else { + return expr == path + } +} + +type AmbiguousLocationError struct { + Location string + CandidatesString []string + CandidatesLocation []api.Location +} + +func (ale AmbiguousLocationError) Error() string { + var candidates []string + if ale.CandidatesLocation != nil { + for i := range ale.CandidatesLocation { + candidates = append(candidates, ale.CandidatesLocation[i].Function.Name) + } + + } else { + candidates = ale.CandidatesString + } + return fmt.Sprintf("Location \"%s\" ambiguous: %s…", ale.Location, strings.Join(candidates, ", ")) +} + +func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { + funcs := d.target.Funcs() + files := d.target.Sources() + + candidates := []string{} + for file := range files { + if loc.FileMatch(file) { + candidates = append(candidates, file) + if len(candidates) >= maxFindLocationCandidates { + break + } + } + } + + if loc.FuncBase != nil { + for _, f := range funcs { + if f.Sym == nil { + continue + } + if loc.FuncBase.Match(f.Sym) { + if loc.Base == f.Name { + // if an exact match for the function name is found use it + candidates = []string{f.Name} + break + } + if len(candidates) < maxFindLocationCandidates { + candidates = append(candidates, f.Name) + } + } + } + } + + switch len(candidates) { + case 1: + var addr uint64 + var err error + if filepath.IsAbs(candidates[0]) { + if loc.LineOffset < 0 { + return nil, fmt.Errorf("Malformed breakpoint location, no line offset specified") + } + addr, err = d.target.FindFileLocation(candidates[0], loc.LineOffset) + } else { + if loc.LineOffset < 0 { + addr, err = d.target.FindFunctionLocation(candidates[0], true, 0) + } else { + addr, err = d.target.FindFunctionLocation(candidates[0], false, loc.LineOffset) + } + } + if err != nil { + return nil, err + } + return []api.Location{{PC: addr}}, nil + + case 0: + return nil, fmt.Errorf("Location \"%s\" not found", locStr) + default: + return nil, AmbiguousLocationError{Location: locStr, CandidatesString: candidates} + } +} + +func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { + if scope == nil { + return nil, fmt.Errorf("could not determine current location (scope is nil)") + } + file, line, fn := d.target.PCToLine(scope.PC) + if fn == nil { + return nil, fmt.Errorf("could not determine current location") + } + addr, err := d.target.FindFileLocation(file, line+loc.Offset) + return []api.Location{{PC: addr}}, err +} + +func (loc *LineLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { + if scope == nil { + return nil, fmt.Errorf("could not determine current location (scope is nil)") + } + file, _, fn := d.target.PCToLine(scope.PC) + if fn == nil { + return nil, fmt.Errorf("could not determine current location") + } + addr, err := d.target.FindFileLocation(file, loc.Line) + return []api.Location{{PC: addr}}, err +} diff --git a/vendor/github.com/derekparker/delve/service/rpc1/client.go b/vendor/github.com/derekparker/delve/service/rpc1/client.go new file mode 100644 index 0000000..43c76c4 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpc1/client.go @@ -0,0 +1,312 @@ +package rpc1 + +import ( + "errors" + "fmt" + "log" + "net/rpc" + "net/rpc/jsonrpc" + + "sync" + + "github.com/derekparker/delve/service/api" +) + +// Client is a RPC service.Client. +type RPCClient struct { + addr string + processPid int + client *rpc.Client + haltMu sync.Mutex + haltReq bool +} + +var unsupportedApiError = errors.New("unsupported") + +// NewClient creates a new RPCClient. +func NewClient(addr string) *RPCClient { + client, err := jsonrpc.Dial("tcp", addr) + if err != nil { + log.Fatal("dialing:", err) + } + return &RPCClient{ + addr: addr, + client: client, + } +} + +func (c *RPCClient) ProcessPid() int { + var pid int + c.call("ProcessPid", nil, &pid) + return pid +} + +func (c *RPCClient) Detach(kill bool) error { + return c.call("Detach", kill, nil) +} + +func (c *RPCClient) Restart() error { + return c.call("Restart", nil, nil) +} + +func (c *RPCClient) GetState() (*api.DebuggerState, error) { + state := new(api.DebuggerState) + err := c.call("State", nil, state) + return state, err +} + +func (c *RPCClient) Continue() <-chan *api.DebuggerState { + ch := make(chan *api.DebuggerState) + c.haltMu.Lock() + c.haltReq = false + c.haltMu.Unlock() + go func() { + for { + c.haltMu.Lock() + if c.haltReq { + c.haltMu.Unlock() + close(ch) + return + } + c.haltMu.Unlock() + state := new(api.DebuggerState) + err := c.call("Command", &api.DebuggerCommand{Name: api.Continue}, state) + if err != nil { + state.Err = err + } + if state.Exited { + // Error types apparently cannot be marshalled by Go correctly. Must reset error here. + state.Err = fmt.Errorf("Process %d has exited with status %d", c.ProcessPid(), state.ExitStatus) + } + ch <- state + if err != nil || state.Exited { + close(ch) + return + } + + isbreakpoint := false + istracepoint := true + for i := range state.Threads { + if state.Threads[i].Breakpoint != nil { + isbreakpoint = true + istracepoint = istracepoint && state.Threads[i].Breakpoint.Tracepoint + } + } + + if !isbreakpoint || !istracepoint { + close(ch) + return + } + } + }() + return ch +} + +func (c *RPCClient) Next() (*api.DebuggerState, error) { + state := new(api.DebuggerState) + err := c.call("Command", &api.DebuggerCommand{Name: api.Next}, state) + return state, err +} + +func (c *RPCClient) Step() (*api.DebuggerState, error) { + state := new(api.DebuggerState) + err := c.call("Command", &api.DebuggerCommand{Name: api.Step}, state) + return state, err +} + +func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) { + state := new(api.DebuggerState) + err := c.call("Command", &api.DebuggerCommand{Name: api.StepInstruction}, state) + return state, err +} + +func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) { + state := new(api.DebuggerState) + cmd := &api.DebuggerCommand{ + Name: api.SwitchThread, + ThreadID: threadID, + } + err := c.call("Command", cmd, state) + return state, err +} + +func (c *RPCClient) SwitchGoroutine(goroutineID int) (*api.DebuggerState, error) { + state := new(api.DebuggerState) + cmd := &api.DebuggerCommand{ + Name: api.SwitchGoroutine, + GoroutineID: goroutineID, + } + err := c.call("Command", cmd, state) + return state, err +} + +func (c *RPCClient) Halt() (*api.DebuggerState, error) { + state := new(api.DebuggerState) + c.haltMu.Lock() + c.haltReq = true + c.haltMu.Unlock() + err := c.call("Command", &api.DebuggerCommand{Name: api.Halt}, state) + return state, err +} + +func (c *RPCClient) GetBreakpoint(id int) (*api.Breakpoint, error) { + breakpoint := new(api.Breakpoint) + err := c.call("GetBreakpoint", id, breakpoint) + return breakpoint, err +} + +func (c *RPCClient) GetBreakpointByName(name string) (*api.Breakpoint, error) { + breakpoint := new(api.Breakpoint) + err := c.call("GetBreakpointByName", name, breakpoint) + return breakpoint, err +} + +func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) { + newBreakpoint := new(api.Breakpoint) + err := c.call("CreateBreakpoint", breakPoint, &newBreakpoint) + return newBreakpoint, err +} + +func (c *RPCClient) ListBreakpoints() ([]*api.Breakpoint, error) { + var breakpoints []*api.Breakpoint + err := c.call("ListBreakpoints", nil, &breakpoints) + return breakpoints, err +} + +func (c *RPCClient) ClearBreakpoint(id int) (*api.Breakpoint, error) { + bp := new(api.Breakpoint) + err := c.call("ClearBreakpoint", id, bp) + return bp, err +} + +func (c *RPCClient) ClearBreakpointByName(name string) (*api.Breakpoint, error) { + bp := new(api.Breakpoint) + err := c.call("ClearBreakpointByName", name, bp) + return bp, err +} + +func (c *RPCClient) AmendBreakpoint(bp *api.Breakpoint) error { + err := c.call("AmendBreakpoint", bp, nil) + return err +} + +func (c *RPCClient) CancelNext() error { + return unsupportedApiError +} + +func (c *RPCClient) ListThreads() ([]*api.Thread, error) { + var threads []*api.Thread + err := c.call("ListThreads", nil, &threads) + return threads, err +} + +func (c *RPCClient) GetThread(id int) (*api.Thread, error) { + thread := new(api.Thread) + err := c.call("GetThread", id, &thread) + return thread, err +} + +func (c *RPCClient) EvalVariable(scope api.EvalScope, symbol string) (*api.Variable, error) { + v := new(api.Variable) + err := c.call("EvalSymbol", EvalSymbolArgs{scope, symbol}, v) + return v, err +} + +func (c *RPCClient) SetVariable(scope api.EvalScope, symbol, value string) error { + var unused int + return c.call("SetSymbol", SetSymbolArgs{scope, symbol, value}, &unused) +} + +func (c *RPCClient) ListSources(filter string) ([]string, error) { + var sources []string + err := c.call("ListSources", filter, &sources) + return sources, err +} + +func (c *RPCClient) ListFunctions(filter string) ([]string, error) { + var funcs []string + err := c.call("ListFunctions", filter, &funcs) + return funcs, err +} + +func (c *RPCClient) ListTypes(filter string) ([]string, error) { + var types []string + err := c.call("ListTypes", filter, &types) + return types, err +} + +func (c *RPCClient) ListPackageVariables(filter string) ([]api.Variable, error) { + var vars []api.Variable + err := c.call("ListPackageVars", filter, &vars) + return vars, err +} + +func (c *RPCClient) ListPackageVariablesFor(threadID int, filter string) ([]api.Variable, error) { + var vars []api.Variable + err := c.call("ListThreadPackageVars", &ThreadListArgs{Id: threadID, Filter: filter}, &vars) + return vars, err +} + +func (c *RPCClient) ListLocalVariables(scope api.EvalScope) ([]api.Variable, error) { + var vars []api.Variable + err := c.call("ListLocalVars", scope, &vars) + return vars, err +} + +func (c *RPCClient) ListRegisters() (string, error) { + var regs string + err := c.call("ListRegisters", nil, ®s) + return regs, err +} + +func (c *RPCClient) ListFunctionArgs(scope api.EvalScope) ([]api.Variable, error) { + var vars []api.Variable + err := c.call("ListFunctionArgs", scope, &vars) + return vars, err +} + +func (c *RPCClient) ListGoroutines() ([]*api.Goroutine, error) { + var goroutines []*api.Goroutine + err := c.call("ListGoroutines", nil, &goroutines) + return goroutines, err +} + +func (c *RPCClient) Stacktrace(goroutineId, depth int, full bool) ([]api.Stackframe, error) { + var locations []api.Stackframe + err := c.call("StacktraceGoroutine", &StacktraceGoroutineArgs{Id: goroutineId, Depth: depth, Full: full}, &locations) + return locations, err +} + +func (c *RPCClient) AttachedToExistingProcess() bool { + var answer bool + c.call("AttachedToExistingProcess", nil, &answer) + return answer +} + +func (c *RPCClient) FindLocation(scope api.EvalScope, loc string) ([]api.Location, error) { + var answer []api.Location + err := c.call("FindLocation", FindLocationArgs{scope, loc}, &answer) + return answer, err +} + +// Disassemble code between startPC and endPC +func (c *RPCClient) DisassembleRange(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) { + var r api.AsmInstructions + err := c.call("Disassemble", DisassembleRequest{scope, startPC, endPC, flavour}, &r) + return r, err +} + +// Disassemble function containing pc +func (c *RPCClient) DisassemblePC(scope api.EvalScope, pc uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) { + var r api.AsmInstructions + err := c.call("Disassemble", DisassembleRequest{scope, pc, 0, flavour}, &r) + return r, err +} + +func (c *RPCClient) url(path string) string { + return fmt.Sprintf("http://%s%s", c.addr, path) +} + +func (c *RPCClient) call(method string, args, reply interface{}) error { + return c.client.Call("RPCServer."+method, args, reply) +} diff --git a/vendor/github.com/derekparker/delve/service/rpc1/readme.txtr b/vendor/github.com/derekparker/delve/service/rpc1/readme.txtr new file mode 100644 index 0000000..c25192d --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpc1/readme.txtr @@ -0,0 +1,5 @@ +This package implements version 1 of Delve's API and is only +kept here for backwards compatibility. Client.go is the old +client code used by Delve's frontend (delve/cmd/dlv), it is +only preserved here for the backwards compatibility tests in +service/test/integration1_test.go. diff --git a/vendor/github.com/derekparker/delve/service/rpc1/server.go b/vendor/github.com/derekparker/delve/service/rpc1/server.go new file mode 100644 index 0000000..02b18e4 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpc1/server.go @@ -0,0 +1,318 @@ +package rpc1 + +import ( + "errors" + "fmt" + + "github.com/derekparker/delve/pkg/proc" + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/api" + "github.com/derekparker/delve/service/debugger" +) + +var defaultLoadConfig = proc.LoadConfig{true, 1, 64, 64, -1} + +type RPCServer struct { + // config is all the information necessary to start the debugger and server. + config *service.Config + // debugger is a debugger service. + debugger *debugger.Debugger +} + +func NewServer(config *service.Config, debugger *debugger.Debugger) *RPCServer { + return &RPCServer{config, debugger} +} + +func (s *RPCServer) ProcessPid(arg1 interface{}, pid *int) error { + *pid = s.debugger.ProcessPid() + return nil +} + +func (s *RPCServer) Detach(kill bool, ret *int) error { + return s.debugger.Detach(kill) +} + +func (s *RPCServer) Restart(arg1 interface{}, arg2 *int) error { + if s.config.AttachPid != 0 { + return errors.New("cannot restart process Delve did not create") + } + _, err := s.debugger.Restart() + return err +} + +func (s *RPCServer) State(arg interface{}, state *api.DebuggerState) error { + st, err := s.debugger.State() + if err != nil { + return err + } + *state = *st + return nil +} + +func (s *RPCServer) Command(command *api.DebuggerCommand, cb service.RPCCallback) { + st, err := s.debugger.Command(command) + cb.Return(st, err) +} + +func (s *RPCServer) GetBreakpoint(id int, breakpoint *api.Breakpoint) error { + bp := s.debugger.FindBreakpoint(id) + if bp == nil { + return fmt.Errorf("no breakpoint with id %d", id) + } + *breakpoint = *bp + return nil +} + +func (s *RPCServer) GetBreakpointByName(name string, breakpoint *api.Breakpoint) error { + bp := s.debugger.FindBreakpointByName(name) + if bp == nil { + return fmt.Errorf("no breakpoint with name %s", name) + } + *breakpoint = *bp + return nil +} + +type StacktraceGoroutineArgs struct { + Id int + Depth int + Full bool +} + +func (s *RPCServer) StacktraceGoroutine(args *StacktraceGoroutineArgs, locations *[]api.Stackframe) error { + var loadcfg *proc.LoadConfig = nil + if args.Full { + loadcfg = &defaultLoadConfig + } + locs, err := s.debugger.Stacktrace(args.Id, args.Depth, loadcfg) + if err != nil { + return err + } + *locations = locs + return nil +} + +func (s *RPCServer) ListBreakpoints(arg interface{}, breakpoints *[]*api.Breakpoint) error { + *breakpoints = s.debugger.Breakpoints() + return nil +} + +func (s *RPCServer) CreateBreakpoint(bp, newBreakpoint *api.Breakpoint) error { + createdbp, err := s.debugger.CreateBreakpoint(bp) + if err != nil { + return err + } + *newBreakpoint = *createdbp + return nil +} + +func (s *RPCServer) ClearBreakpoint(id int, breakpoint *api.Breakpoint) error { + bp := s.debugger.FindBreakpoint(id) + if bp == nil { + return fmt.Errorf("no breakpoint with id %d", id) + } + deleted, err := s.debugger.ClearBreakpoint(bp) + if err != nil { + return err + } + *breakpoint = *deleted + return nil +} + +func (s *RPCServer) ClearBreakpointByName(name string, breakpoint *api.Breakpoint) error { + bp := s.debugger.FindBreakpointByName(name) + if bp == nil { + return fmt.Errorf("no breakpoint with name %s", name) + } + deleted, err := s.debugger.ClearBreakpoint(bp) + if err != nil { + return err + } + *breakpoint = *deleted + return nil +} + +func (s *RPCServer) AmendBreakpoint(amend *api.Breakpoint, unused *int) error { + *unused = 0 + return s.debugger.AmendBreakpoint(amend) +} + +func (s *RPCServer) ListThreads(arg interface{}, threads *[]*api.Thread) (err error) { + *threads, err = s.debugger.Threads() + return err +} + +func (s *RPCServer) GetThread(id int, thread *api.Thread) error { + t, err := s.debugger.FindThread(id) + if err != nil { + return err + } + if t == nil { + return fmt.Errorf("no thread with id %d", id) + } + *thread = *t + return nil +} + +func (s *RPCServer) ListPackageVars(filter string, variables *[]api.Variable) error { + state, err := s.debugger.State() + if err != nil { + return err + } + + current := state.CurrentThread + if current == nil { + return fmt.Errorf("no current thread") + } + + vars, err := s.debugger.PackageVariables(current.ID, filter, defaultLoadConfig) + if err != nil { + return err + } + *variables = vars + return nil +} + +type ThreadListArgs struct { + Id int + Filter string +} + +func (s *RPCServer) ListThreadPackageVars(args *ThreadListArgs, variables *[]api.Variable) error { + thread, err := s.debugger.FindThread(args.Id) + if err != nil { + return err + } + if thread == nil { + return fmt.Errorf("no thread with id %d", args.Id) + } + + vars, err := s.debugger.PackageVariables(args.Id, args.Filter, defaultLoadConfig) + if err != nil { + return err + } + *variables = vars + return nil +} + +func (s *RPCServer) ListRegisters(arg interface{}, registers *string) error { + state, err := s.debugger.State() + if err != nil { + return err + } + + regs, err := s.debugger.Registers(state.CurrentThread.ID, false) + if err != nil { + return err + } + *registers = regs.String() + return nil +} + +func (s *RPCServer) ListLocalVars(scope api.EvalScope, variables *[]api.Variable) error { + vars, err := s.debugger.LocalVariables(scope, defaultLoadConfig) + if err != nil { + return err + } + *variables = vars + return nil +} + +func (s *RPCServer) ListFunctionArgs(scope api.EvalScope, variables *[]api.Variable) error { + vars, err := s.debugger.FunctionArguments(scope, defaultLoadConfig) + if err != nil { + return err + } + *variables = vars + return nil +} + +type EvalSymbolArgs struct { + Scope api.EvalScope + Symbol string +} + +func (s *RPCServer) EvalSymbol(args EvalSymbolArgs, variable *api.Variable) error { + v, err := s.debugger.EvalVariableInScope(args.Scope, args.Symbol, defaultLoadConfig) + if err != nil { + return err + } + *variable = *v + return nil +} + +type SetSymbolArgs struct { + Scope api.EvalScope + Symbol string + Value string +} + +func (s *RPCServer) SetSymbol(args SetSymbolArgs, unused *int) error { + *unused = 0 + return s.debugger.SetVariableInScope(args.Scope, args.Symbol, args.Value) +} + +func (s *RPCServer) ListSources(filter string, sources *[]string) error { + ss, err := s.debugger.Sources(filter) + if err != nil { + return err + } + *sources = ss + return nil +} + +func (s *RPCServer) ListFunctions(filter string, funcs *[]string) error { + fns, err := s.debugger.Functions(filter) + if err != nil { + return err + } + *funcs = fns + return nil +} + +func (s *RPCServer) ListTypes(filter string, types *[]string) error { + tps, err := s.debugger.Types(filter) + if err != nil { + return err + } + *types = tps + return nil +} + +func (s *RPCServer) ListGoroutines(arg interface{}, goroutines *[]*api.Goroutine) error { + gs, err := s.debugger.Goroutines() + if err != nil { + return err + } + *goroutines = gs + return nil +} + +func (c *RPCServer) AttachedToExistingProcess(arg interface{}, answer *bool) error { + if c.config.AttachPid != 0 { + *answer = true + } + return nil +} + +type FindLocationArgs struct { + Scope api.EvalScope + Loc string +} + +func (c *RPCServer) FindLocation(args FindLocationArgs, answer *[]api.Location) error { + var err error + *answer, err = c.debugger.FindLocation(args.Scope, args.Loc) + return err +} + +type DisassembleRequest struct { + Scope api.EvalScope + StartPC, EndPC uint64 + Flavour api.AssemblyFlavour +} + +func (c *RPCServer) Disassemble(args DisassembleRequest, answer *api.AsmInstructions) error { + var err error + *answer, err = c.debugger.Disassemble(args.Scope, args.StartPC, args.EndPC, args.Flavour) + return err +} diff --git a/vendor/github.com/derekparker/delve/service/rpc2/client.go b/vendor/github.com/derekparker/delve/service/rpc2/client.go new file mode 100644 index 0000000..1489044 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpc2/client.go @@ -0,0 +1,308 @@ +package rpc2 + +import ( + "fmt" + "log" + "net/rpc" + "net/rpc/jsonrpc" + "time" + + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/api" +) + +// Client is a RPC service.Client. +type RPCClient struct { + addr string + processPid int + client *rpc.Client +} + +// Ensure the implementation satisfies the interface. +var _ service.Client = &RPCClient{} + +// NewClient creates a new RPCClient. +func NewClient(addr string) *RPCClient { + client, err := jsonrpc.Dial("tcp", addr) + if err != nil { + log.Fatal("dialing:", err) + } + c := &RPCClient{addr: addr, client: client} + c.call("SetApiVersion", api.SetAPIVersionIn{2}, &api.SetAPIVersionOut{}) + return c +} + +func (c *RPCClient) ProcessPid() int { + out := new(ProcessPidOut) + c.call("ProcessPid", ProcessPidIn{}, out) + return out.Pid +} + +func (c *RPCClient) LastModified() time.Time { + out := new(LastModifiedOut) + c.call("LastModified", LastModifiedIn{}, out) + return out.Time +} + +func (c *RPCClient) Detach(kill bool) error { + out := new(DetachOut) + return c.call("Detach", DetachIn{kill}, out) +} + +func (c *RPCClient) Restart() ([]api.DiscardedBreakpoint, error) { + out := new(RestartOut) + err := c.call("Restart", RestartIn{}, out) + return out.DiscardedBreakpoints, err +} + +func (c *RPCClient) GetState() (*api.DebuggerState, error) { + var out StateOut + err := c.call("State", StateIn{}, &out) + return out.State, err +} + +func (c *RPCClient) Continue() <-chan *api.DebuggerState { + ch := make(chan *api.DebuggerState) + go func() { + for { + out := new(CommandOut) + err := c.call("Command", &api.DebuggerCommand{Name: api.Continue}, &out) + state := out.State + if err != nil { + state.Err = err + } + if state.Exited { + // Error types apparantly cannot be marshalled by Go correctly. Must reset error here. + state.Err = fmt.Errorf("Process %d has exited with status %d", c.ProcessPid(), state.ExitStatus) + } + ch <- &state + if err != nil || state.Exited { + close(ch) + return + } + + isbreakpoint := false + istracepoint := true + for i := range state.Threads { + if state.Threads[i].Breakpoint != nil { + isbreakpoint = true + istracepoint = istracepoint && state.Threads[i].Breakpoint.Tracepoint + } + } + + if !isbreakpoint || !istracepoint { + close(ch) + return + } + } + }() + return ch +} + +func (c *RPCClient) Next() (*api.DebuggerState, error) { + var out CommandOut + err := c.call("Command", api.DebuggerCommand{Name: api.Next}, &out) + return &out.State, err +} + +func (c *RPCClient) Step() (*api.DebuggerState, error) { + var out CommandOut + err := c.call("Command", api.DebuggerCommand{Name: api.Step}, &out) + return &out.State, err +} + +func (c *RPCClient) StepOut() (*api.DebuggerState, error) { + var out CommandOut + err := c.call("Command", &api.DebuggerCommand{Name: api.StepOut}, &out) + return &out.State, err +} + +func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) { + var out CommandOut + err := c.call("Command", api.DebuggerCommand{Name: api.StepInstruction}, &out) + return &out.State, err +} + +func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) { + var out CommandOut + cmd := api.DebuggerCommand{ + Name: api.SwitchThread, + ThreadID: threadID, + } + err := c.call("Command", cmd, &out) + return &out.State, err +} + +func (c *RPCClient) SwitchGoroutine(goroutineID int) (*api.DebuggerState, error) { + var out CommandOut + cmd := api.DebuggerCommand{ + Name: api.SwitchGoroutine, + GoroutineID: goroutineID, + } + err := c.call("Command", cmd, &out) + return &out.State, err +} + +func (c *RPCClient) Halt() (*api.DebuggerState, error) { + var out CommandOut + err := c.call("Command", api.DebuggerCommand{Name: api.Halt}, &out) + return &out.State, err +} + +func (c *RPCClient) GetBreakpoint(id int) (*api.Breakpoint, error) { + var out GetBreakpointOut + err := c.call("GetBreakpoint", GetBreakpointIn{id, ""}, &out) + return &out.Breakpoint, err +} + +func (c *RPCClient) GetBreakpointByName(name string) (*api.Breakpoint, error) { + var out GetBreakpointOut + err := c.call("GetBreakpoint", GetBreakpointIn{0, name}, &out) + return &out.Breakpoint, err +} + +func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) { + var out CreateBreakpointOut + err := c.call("CreateBreakpoint", CreateBreakpointIn{*breakPoint}, &out) + return &out.Breakpoint, err +} + +func (c *RPCClient) ListBreakpoints() ([]*api.Breakpoint, error) { + var out ListBreakpointsOut + err := c.call("ListBreakpoints", ListBreakpointsIn{}, &out) + return out.Breakpoints, err +} + +func (c *RPCClient) ClearBreakpoint(id int) (*api.Breakpoint, error) { + var out ClearBreakpointOut + err := c.call("ClearBreakpoint", ClearBreakpointIn{id, ""}, &out) + return out.Breakpoint, err +} + +func (c *RPCClient) ClearBreakpointByName(name string) (*api.Breakpoint, error) { + var out ClearBreakpointOut + err := c.call("ClearBreakpoint", ClearBreakpointIn{0, name}, &out) + return out.Breakpoint, err +} + +func (c *RPCClient) AmendBreakpoint(bp *api.Breakpoint) error { + out := new(AmendBreakpointOut) + err := c.call("AmendBreakpoint", AmendBreakpointIn{*bp}, out) + return err +} + +func (c *RPCClient) CancelNext() error { + var out CancelNextOut + return c.call("CancelNext", CancelNextIn{}, &out) +} + +func (c *RPCClient) ListThreads() ([]*api.Thread, error) { + var out ListThreadsOut + err := c.call("ListThreads", ListThreadsIn{}, &out) + return out.Threads, err +} + +func (c *RPCClient) GetThread(id int) (*api.Thread, error) { + var out GetThreadOut + err := c.call("GetThread", GetThreadIn{id}, &out) + return out.Thread, err +} + +func (c *RPCClient) EvalVariable(scope api.EvalScope, expr string, cfg api.LoadConfig) (*api.Variable, error) { + var out EvalOut + err := c.call("Eval", EvalIn{scope, expr, &cfg}, &out) + return out.Variable, err +} + +func (c *RPCClient) SetVariable(scope api.EvalScope, symbol, value string) error { + out := new(SetOut) + return c.call("Set", SetIn{scope, symbol, value}, out) +} + +func (c *RPCClient) ListSources(filter string) ([]string, error) { + sources := new(ListSourcesOut) + err := c.call("ListSources", ListSourcesIn{filter}, sources) + return sources.Sources, err +} + +func (c *RPCClient) ListFunctions(filter string) ([]string, error) { + funcs := new(ListFunctionsOut) + err := c.call("ListFunctions", ListFunctionsIn{filter}, funcs) + return funcs.Funcs, err +} + +func (c *RPCClient) ListTypes(filter string) ([]string, error) { + types := new(ListTypesOut) + err := c.call("ListTypes", ListTypesIn{filter}, types) + return types.Types, err +} + +func (c *RPCClient) ListPackageVariables(filter string, cfg api.LoadConfig) ([]api.Variable, error) { + var out ListPackageVarsOut + err := c.call("ListPackageVars", ListPackageVarsIn{filter, cfg}, &out) + return out.Variables, err +} + +func (c *RPCClient) ListLocalVariables(scope api.EvalScope, cfg api.LoadConfig) ([]api.Variable, error) { + var out ListLocalVarsOut + err := c.call("ListLocalVars", ListLocalVarsIn{scope, cfg}, &out) + return out.Variables, err +} + +func (c *RPCClient) ListRegisters(threadID int, includeFp bool) (api.Registers, error) { + out := new(ListRegistersOut) + err := c.call("ListRegisters", ListRegistersIn{ThreadID: threadID, IncludeFp: includeFp}, out) + return out.Regs, err +} + +func (c *RPCClient) ListFunctionArgs(scope api.EvalScope, cfg api.LoadConfig) ([]api.Variable, error) { + var out ListFunctionArgsOut + err := c.call("ListFunctionArgs", ListFunctionArgsIn{scope, cfg}, &out) + return out.Args, err +} + +func (c *RPCClient) ListGoroutines() ([]*api.Goroutine, error) { + var out ListGoroutinesOut + err := c.call("ListGoroutines", ListGoroutinesIn{}, &out) + return out.Goroutines, err +} + +func (c *RPCClient) Stacktrace(goroutineId, depth int, cfg *api.LoadConfig) ([]api.Stackframe, error) { + var out StacktraceOut + err := c.call("Stacktrace", StacktraceIn{goroutineId, depth, false, cfg}, &out) + return out.Locations, err +} + +func (c *RPCClient) AttachedToExistingProcess() bool { + out := new(AttachedToExistingProcessOut) + c.call("AttachedToExistingProcess", AttachedToExistingProcessIn{}, out) + return out.Answer +} + +func (c *RPCClient) FindLocation(scope api.EvalScope, loc string) ([]api.Location, error) { + var out FindLocationOut + err := c.call("FindLocation", FindLocationIn{scope, loc}, &out) + return out.Locations, err +} + +// Disassemble code between startPC and endPC +func (c *RPCClient) DisassembleRange(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) { + var out DisassembleOut + err := c.call("Disassemble", DisassembleIn{scope, startPC, endPC, flavour}, &out) + return out.Disassemble, err +} + +// Disassemble function containing pc +func (c *RPCClient) DisassemblePC(scope api.EvalScope, pc uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) { + var out DisassembleOut + err := c.call("Disassemble", DisassembleIn{scope, pc, 0, flavour}, &out) + return out.Disassemble, err +} + +func (c *RPCClient) url(path string) string { + return fmt.Sprintf("http://%s%s", c.addr, path) +} + +func (c *RPCClient) call(method string, args, reply interface{}) error { + return c.client.Call("RPCServer."+method, args, reply) +} diff --git a/vendor/github.com/derekparker/delve/service/rpc2/server.go b/vendor/github.com/derekparker/delve/service/rpc2/server.go new file mode 100644 index 0000000..51c5954 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpc2/server.go @@ -0,0 +1,575 @@ +package rpc2 + +import ( + "errors" + "fmt" + "time" + + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/api" + "github.com/derekparker/delve/service/debugger" +) + +type RPCServer struct { + // config is all the information necessary to start the debugger and server. + config *service.Config + // debugger is a debugger service. + debugger *debugger.Debugger +} + +func NewServer(config *service.Config, debugger *debugger.Debugger) *RPCServer { + return &RPCServer{config, debugger} +} + +type ProcessPidIn struct { +} + +type ProcessPidOut struct { + Pid int +} + +// ProcessPid returns the pid of the process we are debugging. +func (s *RPCServer) ProcessPid(arg ProcessPidIn, out *ProcessPidOut) error { + out.Pid = s.debugger.ProcessPid() + return nil +} + +type LastModifiedIn struct { +} + +type LastModifiedOut struct { + Time time.Time +} + +func (s *RPCServer) LastModified(arg LastModifiedIn, out *LastModifiedOut) error { + out.Time = s.debugger.LastModified() + return nil +} + +type DetachIn struct { + Kill bool +} + +type DetachOut struct { +} + +// Detach detaches the debugger, optionally killing the process. +func (s *RPCServer) Detach(arg DetachIn, out *DetachOut) error { + return s.debugger.Detach(arg.Kill) +} + +type RestartIn struct { +} + +type RestartOut struct { + DiscardedBreakpoints []api.DiscardedBreakpoint +} + +// Restart restarts program. +func (s *RPCServer) Restart(arg RestartIn, out *RestartOut) error { + if s.config.AttachPid != 0 { + return errors.New("cannot restart process Delve did not create") + } + var err error + out.DiscardedBreakpoints, err = s.debugger.Restart() + return err +} + +type StateIn struct { +} + +type StateOut struct { + State *api.DebuggerState +} + +// State returns the current debugger state. +func (s *RPCServer) State(arg StateIn, out *StateOut) error { + st, err := s.debugger.State() + if err != nil { + return err + } + out.State = st + return nil +} + +type CommandOut struct { + State api.DebuggerState +} + +// Command interrupts, continues and steps through the program. +func (s *RPCServer) Command(command api.DebuggerCommand, cb service.RPCCallback) { + st, err := s.debugger.Command(&command) + if err != nil { + cb.Return(nil, err) + return + } + var out CommandOut + out.State = *st + cb.Return(out, nil) + return +} + +type GetBreakpointIn struct { + Id int + Name string +} + +type GetBreakpointOut struct { + Breakpoint api.Breakpoint +} + +// GetBreakpoint gets a breakpoint by Name (if Name is not an empty string) or by ID. +func (s *RPCServer) GetBreakpoint(arg GetBreakpointIn, out *GetBreakpointOut) error { + var bp *api.Breakpoint + if arg.Name != "" { + bp = s.debugger.FindBreakpointByName(arg.Name) + if bp == nil { + return fmt.Errorf("no breakpoint with name %s", arg.Name) + } + } else { + bp = s.debugger.FindBreakpoint(arg.Id) + if bp == nil { + return fmt.Errorf("no breakpoint with id %d", arg.Id) + } + } + out.Breakpoint = *bp + return nil +} + +type StacktraceIn struct { + Id int + Depth int + Full bool + Cfg *api.LoadConfig +} + +type StacktraceOut struct { + Locations []api.Stackframe +} + +// Stacktrace returns stacktrace of goroutine Id up to the specified Depth. +// +// If Full is set it will also the variable of all local variables +// and function arguments of all stack frames. +func (s *RPCServer) Stacktrace(arg StacktraceIn, out *StacktraceOut) error { + cfg := arg.Cfg + if cfg == nil && arg.Full { + cfg = &api.LoadConfig{true, 1, 64, 64, -1} + } + locs, err := s.debugger.Stacktrace(arg.Id, arg.Depth, api.LoadConfigToProc(cfg)) + if err != nil { + return err + } + out.Locations = locs + return nil +} + +type ListBreakpointsIn struct { +} + +type ListBreakpointsOut struct { + Breakpoints []*api.Breakpoint +} + +// ListBreakpoints gets all breakpoints. +func (s *RPCServer) ListBreakpoints(arg ListBreakpointsIn, out *ListBreakpointsOut) error { + out.Breakpoints = s.debugger.Breakpoints() + return nil +} + +type CreateBreakpointIn struct { + Breakpoint api.Breakpoint +} + +type CreateBreakpointOut struct { + Breakpoint api.Breakpoint +} + +// CreateBreakpoint creates a new breakpoint. +// +// - If arg.Breakpoint.File is not an empty string the breakpoint +// will be created on the specified file:line location +// +// - If arg.Breakpoint.FunctionName is not an empty string +// the breakpoint will be created on the specified function:line +// location. Note that setting a breakpoint on a function's entry point +// (line == 0) can have surprising consequences, it is advisable to +// use line = -1 instead which will skip the prologue. +// +// - Otherwise the value specified by arg.Breakpoint.Addr will be used. +func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error { + createdbp, err := s.debugger.CreateBreakpoint(&arg.Breakpoint) + if err != nil { + return err + } + out.Breakpoint = *createdbp + return nil +} + +type ClearBreakpointIn struct { + Id int + Name string +} + +type ClearBreakpointOut struct { + Breakpoint *api.Breakpoint +} + +// ClearBreakpoint deletes a breakpoint by Name (if Name is not an +// empty string) or by ID. +func (s *RPCServer) ClearBreakpoint(arg ClearBreakpointIn, out *ClearBreakpointOut) error { + var bp *api.Breakpoint + if arg.Name != "" { + bp = s.debugger.FindBreakpointByName(arg.Name) + if bp == nil { + return fmt.Errorf("no breakpoint with name %s", arg.Name) + } + } else { + bp = s.debugger.FindBreakpoint(arg.Id) + if bp == nil { + return fmt.Errorf("no breakpoint with id %d", arg.Id) + } + } + deleted, err := s.debugger.ClearBreakpoint(bp) + if err != nil { + return err + } + out.Breakpoint = deleted + return nil +} + +type AmendBreakpointIn struct { + Breakpoint api.Breakpoint +} + +type AmendBreakpointOut struct { +} + +// AmendBreakpoint allows user to update an existing breakpoint +// for example to change the information retrieved when the +// breakpoint is hit or to change, add or remove the break condition. +// +// arg.Breakpoint.ID must be a valid breakpoint ID +func (s *RPCServer) AmendBreakpoint(arg AmendBreakpointIn, out *AmendBreakpointOut) error { + return s.debugger.AmendBreakpoint(&arg.Breakpoint) +} + +type CancelNextIn struct { +} + +type CancelNextOut struct { +} + +func (s *RPCServer) CancelNext(arg CancelNextIn, out *CancelNextOut) error { + return s.debugger.CancelNext() +} + +type ListThreadsIn struct { +} + +type ListThreadsOut struct { + Threads []*api.Thread +} + +// ListThreads lists all threads. +func (s *RPCServer) ListThreads(arg ListThreadsIn, out *ListThreadsOut) (err error) { + out.Threads, err = s.debugger.Threads() + return err +} + +type GetThreadIn struct { + Id int +} + +type GetThreadOut struct { + Thread *api.Thread +} + +// GetThread gets a thread by its ID. +func (s *RPCServer) GetThread(arg GetThreadIn, out *GetThreadOut) error { + t, err := s.debugger.FindThread(arg.Id) + if err != nil { + return err + } + if t == nil { + return fmt.Errorf("no thread with id %d", arg.Id) + } + out.Thread = t + return nil +} + +type ListPackageVarsIn struct { + Filter string + Cfg api.LoadConfig +} + +type ListPackageVarsOut struct { + Variables []api.Variable +} + +// ListPackageVars lists all package variables in the context of the current thread. +func (s *RPCServer) ListPackageVars(arg ListPackageVarsIn, out *ListPackageVarsOut) error { + state, err := s.debugger.State() + if err != nil { + return err + } + + current := state.CurrentThread + if current == nil { + return fmt.Errorf("no current thread") + } + + vars, err := s.debugger.PackageVariables(current.ID, arg.Filter, *api.LoadConfigToProc(&arg.Cfg)) + if err != nil { + return err + } + out.Variables = vars + return nil +} + +type ListRegistersIn struct { + ThreadID int + IncludeFp bool +} + +type ListRegistersOut struct { + Registers string + Regs api.Registers +} + +// ListRegisters lists registers and their values. +func (s *RPCServer) ListRegisters(arg ListRegistersIn, out *ListRegistersOut) error { + if arg.ThreadID == 0 { + state, err := s.debugger.State() + if err != nil { + return err + } + arg.ThreadID = state.CurrentThread.ID + } + + regs, err := s.debugger.Registers(arg.ThreadID, arg.IncludeFp) + if err != nil { + return err + } + out.Regs = regs + out.Registers = out.Regs.String() + + return nil +} + +type ListLocalVarsIn struct { + Scope api.EvalScope + Cfg api.LoadConfig +} + +type ListLocalVarsOut struct { + Variables []api.Variable +} + +// ListLocalVars lists all local variables in scope. +func (s *RPCServer) ListLocalVars(arg ListLocalVarsIn, out *ListLocalVarsOut) error { + vars, err := s.debugger.LocalVariables(arg.Scope, *api.LoadConfigToProc(&arg.Cfg)) + if err != nil { + return err + } + out.Variables = vars + return nil +} + +type ListFunctionArgsIn struct { + Scope api.EvalScope + Cfg api.LoadConfig +} + +type ListFunctionArgsOut struct { + Args []api.Variable +} + +// ListFunctionArgs lists all arguments to the current function +func (s *RPCServer) ListFunctionArgs(arg ListFunctionArgsIn, out *ListFunctionArgsOut) error { + vars, err := s.debugger.FunctionArguments(arg.Scope, *api.LoadConfigToProc(&arg.Cfg)) + if err != nil { + return err + } + out.Args = vars + return nil +} + +type EvalIn struct { + Scope api.EvalScope + Expr string + Cfg *api.LoadConfig +} + +type EvalOut struct { + Variable *api.Variable +} + +// EvalVariable returns a variable in the specified context. +// +// See https://github.com/derekparker/delve/wiki/Expressions for +// a description of acceptable values of arg.Expr. +func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error { + cfg := arg.Cfg + if cfg == nil { + cfg = &api.LoadConfig{true, 1, 64, 64, -1} + } + v, err := s.debugger.EvalVariableInScope(arg.Scope, arg.Expr, *api.LoadConfigToProc(cfg)) + if err != nil { + return err + } + out.Variable = v + return nil +} + +type SetIn struct { + Scope api.EvalScope + Symbol string + Value string +} + +type SetOut struct { +} + +// Set sets the value of a variable. Only numerical types and +// pointers are currently supported. +func (s *RPCServer) Set(arg SetIn, out *SetOut) error { + return s.debugger.SetVariableInScope(arg.Scope, arg.Symbol, arg.Value) +} + +type ListSourcesIn struct { + Filter string +} + +type ListSourcesOut struct { + Sources []string +} + +// ListSources lists all source files in the process matching filter. +func (s *RPCServer) ListSources(arg ListSourcesIn, out *ListSourcesOut) error { + ss, err := s.debugger.Sources(arg.Filter) + if err != nil { + return err + } + out.Sources = ss + return nil +} + +type ListFunctionsIn struct { + Filter string +} + +type ListFunctionsOut struct { + Funcs []string +} + +// ListFunctions lists all functions in the process matching filter. +func (s *RPCServer) ListFunctions(arg ListFunctionsIn, out *ListFunctionsOut) error { + fns, err := s.debugger.Functions(arg.Filter) + if err != nil { + return err + } + out.Funcs = fns + return nil +} + +type ListTypesIn struct { + Filter string +} + +type ListTypesOut struct { + Types []string +} + +// ListTypes lists all types in the process matching filter. +func (s *RPCServer) ListTypes(arg ListTypesIn, out *ListTypesOut) error { + tps, err := s.debugger.Types(arg.Filter) + if err != nil { + return err + } + out.Types = tps + return nil +} + +type ListGoroutinesIn struct { +} + +type ListGoroutinesOut struct { + Goroutines []*api.Goroutine +} + +// ListGoroutines lists all goroutines. +func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error { + gs, err := s.debugger.Goroutines() + if err != nil { + return err + } + out.Goroutines = gs + return nil +} + +type AttachedToExistingProcessIn struct { +} + +type AttachedToExistingProcessOut struct { + Answer bool +} + +// AttachedToExistingProcess returns whether we attached to a running process or not +func (c *RPCServer) AttachedToExistingProcess(arg AttachedToExistingProcessIn, out *AttachedToExistingProcessOut) error { + if c.config.AttachPid != 0 { + out.Answer = true + } + return nil +} + +type FindLocationIn struct { + Scope api.EvalScope + Loc string +} + +type FindLocationOut struct { + Locations []api.Location +} + +// FindLocation returns concrete location information described by a location expression +// +// loc ::= : | [:] | // | (+|-) | | *
+// * can be the full path of a file or just a suffix +// * ::= .. | .(*). | . | . | (*). | +// * must be unambiguous +// * // will return a location for each function matched by regex +// * + returns a location for the line that is lines after the current line +// * - returns a location for the line that is lines before the current line +// * returns a location for a line in the current file +// * *
returns the location corresponding to the specified address +// +// NOTE: this function does not actually set breakpoints. +func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error { + var err error + out.Locations, err = c.debugger.FindLocation(arg.Scope, arg.Loc) + return err +} + +type DisassembleIn struct { + Scope api.EvalScope + StartPC, EndPC uint64 + Flavour api.AssemblyFlavour +} + +type DisassembleOut struct { + Disassemble api.AsmInstructions +} + +// Disassemble code. +// +// If both StartPC and EndPC are non-zero the specified range will be disassembled, otherwise the function containing StartPC will be disassembled. +// +// Scope is used to mark the instruction the specified gorutine is stopped at. +// +// Disassemble will also try to calculate the destination address of an absolute indirect CALL if it happens to be the instruction the selected goroutine is stopped at. +func (c *RPCServer) Disassemble(arg DisassembleIn, out *DisassembleOut) error { + var err error + out.Disassemble, err = c.debugger.Disassemble(arg.Scope, arg.StartPC, arg.EndPC, arg.Flavour) + return err +} diff --git a/vendor/github.com/derekparker/delve/service/rpccallback.go b/vendor/github.com/derekparker/delve/service/rpccallback.go new file mode 100644 index 0000000..9b04782 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpccallback.go @@ -0,0 +1,6 @@ +package service + +// RPCCallback is used by RPC methods to return their result asynchronously. +type RPCCallback interface { + Return(out interface{}, err error) +} diff --git a/vendor/github.com/derekparker/delve/service/rpccommon/server.go b/vendor/github.com/derekparker/delve/service/rpccommon/server.go new file mode 100644 index 0000000..765fd09 --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/rpccommon/server.go @@ -0,0 +1,409 @@ +package rpccommon + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "net" + "net/rpc" + "net/rpc/jsonrpc" + "reflect" + "runtime" + "sync" + "unicode" + "unicode/utf8" + + "github.com/derekparker/delve/pkg/version" + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/api" + "github.com/derekparker/delve/service/debugger" + "github.com/derekparker/delve/service/rpc1" + "github.com/derekparker/delve/service/rpc2" +) + +// ServerImpl implements a JSON-RPC server that can switch between two +// versions of the API. +type ServerImpl struct { + // config is all the information necessary to start the debugger and server. + config *service.Config + // listener is used to serve HTTP. + listener net.Listener + // stopChan is used to stop the listener goroutine. + stopChan chan struct{} + // debugger is the debugger service. + debugger *debugger.Debugger + // s1 is APIv1 server. + s1 *rpc1.RPCServer + // s2 is APIv2 server. + s2 *rpc2.RPCServer + // maps of served methods, one for each supported API. + methodMaps []map[string]*methodType +} + +type RPCCallback struct { + s *ServerImpl + sending *sync.Mutex + codec rpc.ServerCodec + req rpc.Request +} + +// RPCServer implements the RPC method calls common to all versions of the API. +type RPCServer struct { + s *ServerImpl +} + +type methodType struct { + method reflect.Method + Rcvr reflect.Value + ArgType reflect.Type + ReplyType reflect.Type + Synchronous bool +} + +// NewServer creates a new RPCServer. +func NewServer(config *service.Config, logEnabled bool) *ServerImpl { + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + if !logEnabled { + log.SetOutput(ioutil.Discard) + } + if config.APIVersion < 2 { + log.Printf("Using API v1") + } + return &ServerImpl{ + config: config, + listener: config.Listener, + stopChan: make(chan struct{}), + } +} + +// Stop stops the JSON-RPC server. +func (s *ServerImpl) Stop(kill bool) error { + if s.config.AcceptMulti { + close(s.stopChan) + s.listener.Close() + } + return s.debugger.Detach(kill) +} + +// Restart restarts the debugger. +func (s *ServerImpl) Restart() error { + if s.config.AttachPid != 0 { + return errors.New("cannot restart process Delve did not create") + } + return s.s2.Restart(rpc2.RestartIn{}, nil) +} + +// Run starts a debugger and exposes it with an HTTP server. The debugger +// itself can be stopped with the `detach` API. Run blocks until the HTTP +// server stops. +func (s *ServerImpl) Run() error { + var err error + + if s.config.APIVersion < 2 { + s.config.APIVersion = 1 + } + if s.config.APIVersion > 2 { + return fmt.Errorf("unknown API version") + } + + // Create and start the debugger + if s.debugger, err = debugger.New(&debugger.Config{ + ProcessArgs: s.config.ProcessArgs, + AttachPid: s.config.AttachPid, + WorkingDir: s.config.WorkingDir, + }); err != nil { + return err + } + + s.s1 = rpc1.NewServer(s.config, s.debugger) + s.s2 = rpc2.NewServer(s.config, s.debugger) + + rpcServer := &RPCServer{s} + + s.methodMaps = make([]map[string]*methodType, 2) + + s.methodMaps[0] = map[string]*methodType{} + s.methodMaps[1] = map[string]*methodType{} + suitableMethods(s.s1, s.methodMaps[0]) + suitableMethods(rpcServer, s.methodMaps[0]) + suitableMethods(s.s2, s.methodMaps[1]) + suitableMethods(rpcServer, s.methodMaps[1]) + + go func() { + defer s.listener.Close() + for { + c, err := s.listener.Accept() + if err != nil { + select { + case <-s.stopChan: + // We were supposed to exit, do nothing and return + return + default: + panic(err) + } + } + go s.serveJSONCodec(c) + if !s.config.AcceptMulti { + break + } + } + }() + return nil +} + +// Precompute the reflect type for error. Can't use error directly +// because Typeof takes an empty interface value. This is annoying. +var typeOfError = reflect.TypeOf((*error)(nil)).Elem() + +// Is this an exported - upper case - name? +func isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} + +// Is this type exported or a builtin? +func isExportedOrBuiltinType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + // PkgPath will be non-empty even for an exported type, + // so we need to check the type name as well. + return isExported(t.Name()) || t.PkgPath() == "" +} + +// Fills methods map with the methods of receiver that should be made +// available through the RPC interface. +// These are all the public methods of rcvr that have one of those +// two signatures: +// func (rcvr ReceiverType) Method(in InputType, out *ReplyType) error +// func (rcvr ReceiverType) Method(in InputType, cb service.RPCCallback) +func suitableMethods(rcvr interface{}, methods map[string]*methodType) { + typ := reflect.TypeOf(rcvr) + rcvrv := reflect.ValueOf(rcvr) + sname := reflect.Indirect(rcvrv).Type().Name() + if sname == "" { + log.Printf("rpc.Register: no service name for type %s", typ) + return + } + for m := 0; m < typ.NumMethod(); m++ { + method := typ.Method(m) + mname := method.Name + mtype := method.Type + // method must be exported + if method.PkgPath != "" { + continue + } + // Method needs three ins: (receive, *args, *reply) or (receiver, *args, *RPCCallback) + if mtype.NumIn() != 3 { + log.Println("method", mname, "has wrong number of ins:", mtype.NumIn()) + continue + } + // First arg need not be a pointer. + argType := mtype.In(1) + if !isExportedOrBuiltinType(argType) { + log.Println(mname, "argument type not exported:", argType) + continue + } + + replyType := mtype.In(2) + synchronous := replyType.String() != "service.RPCCallback" + + if synchronous { + // Second arg must be a pointer. + if replyType.Kind() != reflect.Ptr { + log.Println("method", mname, "reply type not a pointer:", replyType) + continue + } + // Reply type must be exported. + if !isExportedOrBuiltinType(replyType) { + log.Println("method", mname, "reply type not exported:", replyType) + continue + } + + // Method needs one out. + if mtype.NumOut() != 1 { + log.Println("method", mname, "has wrong number of outs:", mtype.NumOut()) + continue + } + // The return type of the method must be error. + if returnType := mtype.Out(0); returnType != typeOfError { + log.Println("method", mname, "returns", returnType.String(), "not error") + continue + } + } else { + // Method needs zero outs. + if mtype.NumOut() != 0 { + log.Println("method", mname, "has wrong number of outs:", mtype.NumOut()) + continue + } + } + methods[sname+"."+mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType, Synchronous: synchronous, Rcvr: rcvrv} + } + return +} + +func (s *ServerImpl) serveJSONCodec(conn io.ReadWriteCloser) { + sending := new(sync.Mutex) + codec := jsonrpc.NewServerCodec(conn) + var req rpc.Request + var resp rpc.Response + for { + req = rpc.Request{} + err := codec.ReadRequestHeader(&req) + if err != nil { + if err != io.EOF { + log.Println("rpc:", err) + } + break + } + + mtype, ok := s.methodMaps[s.config.APIVersion-1][req.ServiceMethod] + if !ok { + log.Printf("rpc: can't find method %s", req.ServiceMethod) + continue + } + + var argv, replyv reflect.Value + + // Decode the argument value. + argIsValue := false // if true, need to indirect before calling. + if mtype.ArgType.Kind() == reflect.Ptr { + argv = reflect.New(mtype.ArgType.Elem()) + } else { + argv = reflect.New(mtype.ArgType) + argIsValue = true + } + // argv guaranteed to be a pointer now. + if err = codec.ReadRequestBody(argv.Interface()); err != nil { + return + } + if argIsValue { + argv = argv.Elem() + } + + if mtype.Synchronous { + replyv = reflect.New(mtype.ReplyType.Elem()) + function := mtype.method.Func + var returnValues []reflect.Value + var errInter interface{} + func() { + defer func() { + if ierr := recover(); ierr != nil { + errInter = newInternalError(ierr, 2) + } + }() + returnValues = function.Call([]reflect.Value{mtype.Rcvr, argv, replyv}) + errInter = returnValues[0].Interface() + }() + + errmsg := "" + if errInter != nil { + errmsg = errInter.(error).Error() + } + resp = rpc.Response{} + s.sendResponse(sending, &req, &resp, replyv.Interface(), codec, errmsg) + } else { + function := mtype.method.Func + ctl := &RPCCallback{s, sending, codec, req} + go func() { + defer func() { + if ierr := recover(); ierr != nil { + ctl.Return(nil, newInternalError(ierr, 2)) + } + }() + function.Call([]reflect.Value{mtype.Rcvr, argv, reflect.ValueOf(ctl)}) + }() + } + } + codec.Close() +} + +// A value sent as a placeholder for the server's response value when the server +// receives an invalid request. It is never decoded by the client since the Response +// contains an error when it is used. +var invalidRequest = struct{}{} + +func (s *ServerImpl) sendResponse(sending *sync.Mutex, req *rpc.Request, resp *rpc.Response, reply interface{}, codec rpc.ServerCodec, errmsg string) { + resp.ServiceMethod = req.ServiceMethod + if errmsg != "" { + resp.Error = errmsg + reply = invalidRequest + } + resp.Seq = req.Seq + sending.Lock() + defer sending.Unlock() + err := codec.WriteResponse(resp, reply) + if err != nil { + log.Println("rpc: writing response:", err) + } +} + +func (cb *RPCCallback) Return(out interface{}, err error) { + errmsg := "" + if err != nil { + errmsg = err.Error() + } + var resp rpc.Response + cb.s.sendResponse(cb.sending, &cb.req, &resp, out, cb.codec, errmsg) +} + +// GetVersion returns the version of delve as well as the API version +// currently served. +func (s *RPCServer) GetVersion(args api.GetVersionIn, out *api.GetVersionOut) error { + out.DelveVersion = version.DelveVersion.String() + out.APIVersion = s.s.config.APIVersion + return nil +} + +// Changes version of the API being served. +func (s *RPCServer) SetApiVersion(args api.SetAPIVersionIn, out *api.SetAPIVersionOut) error { + if args.APIVersion < 2 { + args.APIVersion = 1 + } + if args.APIVersion > 2 { + return fmt.Errorf("unknown API version") + } + s.s.config.APIVersion = args.APIVersion + return nil +} + +type internalError struct { + Err interface{} + Stack []internalErrorFrame +} + +type internalErrorFrame struct { + Pc uintptr + Func string + File string + Line int +} + +func newInternalError(ierr interface{}, skip int) *internalError { + r := &internalError{ierr, nil} + for i := skip; ; i++ { + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + fname := "" + fn := runtime.FuncForPC(pc) + if fn != nil { + fname = fn.Name() + } + r.Stack = append(r.Stack, internalErrorFrame{pc, fname, file, line}) + } + return r +} + +func (err *internalError) Error() string { + var out bytes.Buffer + fmt.Fprintf(&out, "Internal debugger error: %v\n", err.Err) + for _, frame := range err.Stack { + fmt.Fprintf(&out, "%s (%#x)\n\t%s:%d\n", frame.Func, frame.Pc, frame.File, frame.Line) + } + return out.String() +} diff --git a/vendor/github.com/derekparker/delve/service/server.go b/vendor/github.com/derekparker/delve/service/server.go new file mode 100644 index 0000000..20a364b --- /dev/null +++ b/vendor/github.com/derekparker/delve/service/server.go @@ -0,0 +1,8 @@ +package service + +// Server represents a server for a remote client +// to connect to. +type Server interface { + Run() error + Stop(bool) error +} diff --git a/vendor/github.com/mattn/go-colorable/LICENSE b/vendor/github.com/mattn/go-colorable/LICENSE new file mode 100644 index 0000000..91b5cef --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +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. diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md new file mode 100644 index 0000000..e84226a --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -0,0 +1,43 @@ +# go-colorable + +Colorable writer for windows. + +For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) +This package is possible to handle escape sequence for ansi color on windows. + +## Too Bad! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) + + +## So Good! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) + +## Usage + +```go +logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) +logrus.SetOutput(colorable.NewColorableStdout()) + +logrus.Info("succeeded") +logrus.Warn("not correct") +logrus.Error("something error") +logrus.Fatal("panic") +``` + +You can compile above code on non-windows OSs. + +## Installation + +``` +$ go get github.com/mattn/go-colorable +``` + +# License + +MIT + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go new file mode 100644 index 0000000..52d6653 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -0,0 +1,24 @@ +// +build !windows + +package colorable + +import ( + "io" + "os" +) + +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + return file +} + +func NewColorableStdout() io.Writer { + return os.Stdout +} + +func NewColorableStderr() io.Writer { + return os.Stderr +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go new file mode 100644 index 0000000..c8f4e09 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -0,0 +1,783 @@ +package colorable + +import ( + "bytes" + "fmt" + "io" + "math" + "os" + "strconv" + "strings" + "syscall" + "unsafe" + + "github.com/mattn/go-isatty" +) + +const ( + foregroundBlue = 0x1 + foregroundGreen = 0x2 + foregroundRed = 0x4 + foregroundIntensity = 0x8 + foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity) + backgroundBlue = 0x10 + backgroundGreen = 0x20 + backgroundRed = 0x40 + backgroundIntensity = 0x80 + backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) +) + +type wchar uint16 +type short int16 +type dword uint32 +type word uint16 + +type coord struct { + x short + y short +} + +type smallRect struct { + left short + top short + right short + bottom short +} + +type consoleScreenBufferInfo struct { + size coord + cursorPosition coord + attributes word + window smallRect + maximumWindowSize coord +} + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") + procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") + procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") + procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") +) + +type Writer struct { + out io.Writer + handle syscall.Handle + lastbuf bytes.Buffer + oldattr word +} + +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + if isatty.IsTerminal(file.Fd()) { + var csbi consoleScreenBufferInfo + handle := syscall.Handle(file.Fd()) + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + return &Writer{out: file, handle: handle, oldattr: csbi.attributes} + } else { + return file + } +} + +func NewColorableStdout() io.Writer { + return NewColorable(os.Stdout) +} + +func NewColorableStderr() io.Writer { + return NewColorable(os.Stderr) +} + +var color256 = map[int]int{ + 0: 0x000000, + 1: 0x800000, + 2: 0x008000, + 3: 0x808000, + 4: 0x000080, + 5: 0x800080, + 6: 0x008080, + 7: 0xc0c0c0, + 8: 0x808080, + 9: 0xff0000, + 10: 0x00ff00, + 11: 0xffff00, + 12: 0x0000ff, + 13: 0xff00ff, + 14: 0x00ffff, + 15: 0xffffff, + 16: 0x000000, + 17: 0x00005f, + 18: 0x000087, + 19: 0x0000af, + 20: 0x0000d7, + 21: 0x0000ff, + 22: 0x005f00, + 23: 0x005f5f, + 24: 0x005f87, + 25: 0x005faf, + 26: 0x005fd7, + 27: 0x005fff, + 28: 0x008700, + 29: 0x00875f, + 30: 0x008787, + 31: 0x0087af, + 32: 0x0087d7, + 33: 0x0087ff, + 34: 0x00af00, + 35: 0x00af5f, + 36: 0x00af87, + 37: 0x00afaf, + 38: 0x00afd7, + 39: 0x00afff, + 40: 0x00d700, + 41: 0x00d75f, + 42: 0x00d787, + 43: 0x00d7af, + 44: 0x00d7d7, + 45: 0x00d7ff, + 46: 0x00ff00, + 47: 0x00ff5f, + 48: 0x00ff87, + 49: 0x00ffaf, + 50: 0x00ffd7, + 51: 0x00ffff, + 52: 0x5f0000, + 53: 0x5f005f, + 54: 0x5f0087, + 55: 0x5f00af, + 56: 0x5f00d7, + 57: 0x5f00ff, + 58: 0x5f5f00, + 59: 0x5f5f5f, + 60: 0x5f5f87, + 61: 0x5f5faf, + 62: 0x5f5fd7, + 63: 0x5f5fff, + 64: 0x5f8700, + 65: 0x5f875f, + 66: 0x5f8787, + 67: 0x5f87af, + 68: 0x5f87d7, + 69: 0x5f87ff, + 70: 0x5faf00, + 71: 0x5faf5f, + 72: 0x5faf87, + 73: 0x5fafaf, + 74: 0x5fafd7, + 75: 0x5fafff, + 76: 0x5fd700, + 77: 0x5fd75f, + 78: 0x5fd787, + 79: 0x5fd7af, + 80: 0x5fd7d7, + 81: 0x5fd7ff, + 82: 0x5fff00, + 83: 0x5fff5f, + 84: 0x5fff87, + 85: 0x5fffaf, + 86: 0x5fffd7, + 87: 0x5fffff, + 88: 0x870000, + 89: 0x87005f, + 90: 0x870087, + 91: 0x8700af, + 92: 0x8700d7, + 93: 0x8700ff, + 94: 0x875f00, + 95: 0x875f5f, + 96: 0x875f87, + 97: 0x875faf, + 98: 0x875fd7, + 99: 0x875fff, + 100: 0x878700, + 101: 0x87875f, + 102: 0x878787, + 103: 0x8787af, + 104: 0x8787d7, + 105: 0x8787ff, + 106: 0x87af00, + 107: 0x87af5f, + 108: 0x87af87, + 109: 0x87afaf, + 110: 0x87afd7, + 111: 0x87afff, + 112: 0x87d700, + 113: 0x87d75f, + 114: 0x87d787, + 115: 0x87d7af, + 116: 0x87d7d7, + 117: 0x87d7ff, + 118: 0x87ff00, + 119: 0x87ff5f, + 120: 0x87ff87, + 121: 0x87ffaf, + 122: 0x87ffd7, + 123: 0x87ffff, + 124: 0xaf0000, + 125: 0xaf005f, + 126: 0xaf0087, + 127: 0xaf00af, + 128: 0xaf00d7, + 129: 0xaf00ff, + 130: 0xaf5f00, + 131: 0xaf5f5f, + 132: 0xaf5f87, + 133: 0xaf5faf, + 134: 0xaf5fd7, + 135: 0xaf5fff, + 136: 0xaf8700, + 137: 0xaf875f, + 138: 0xaf8787, + 139: 0xaf87af, + 140: 0xaf87d7, + 141: 0xaf87ff, + 142: 0xafaf00, + 143: 0xafaf5f, + 144: 0xafaf87, + 145: 0xafafaf, + 146: 0xafafd7, + 147: 0xafafff, + 148: 0xafd700, + 149: 0xafd75f, + 150: 0xafd787, + 151: 0xafd7af, + 152: 0xafd7d7, + 153: 0xafd7ff, + 154: 0xafff00, + 155: 0xafff5f, + 156: 0xafff87, + 157: 0xafffaf, + 158: 0xafffd7, + 159: 0xafffff, + 160: 0xd70000, + 161: 0xd7005f, + 162: 0xd70087, + 163: 0xd700af, + 164: 0xd700d7, + 165: 0xd700ff, + 166: 0xd75f00, + 167: 0xd75f5f, + 168: 0xd75f87, + 169: 0xd75faf, + 170: 0xd75fd7, + 171: 0xd75fff, + 172: 0xd78700, + 173: 0xd7875f, + 174: 0xd78787, + 175: 0xd787af, + 176: 0xd787d7, + 177: 0xd787ff, + 178: 0xd7af00, + 179: 0xd7af5f, + 180: 0xd7af87, + 181: 0xd7afaf, + 182: 0xd7afd7, + 183: 0xd7afff, + 184: 0xd7d700, + 185: 0xd7d75f, + 186: 0xd7d787, + 187: 0xd7d7af, + 188: 0xd7d7d7, + 189: 0xd7d7ff, + 190: 0xd7ff00, + 191: 0xd7ff5f, + 192: 0xd7ff87, + 193: 0xd7ffaf, + 194: 0xd7ffd7, + 195: 0xd7ffff, + 196: 0xff0000, + 197: 0xff005f, + 198: 0xff0087, + 199: 0xff00af, + 200: 0xff00d7, + 201: 0xff00ff, + 202: 0xff5f00, + 203: 0xff5f5f, + 204: 0xff5f87, + 205: 0xff5faf, + 206: 0xff5fd7, + 207: 0xff5fff, + 208: 0xff8700, + 209: 0xff875f, + 210: 0xff8787, + 211: 0xff87af, + 212: 0xff87d7, + 213: 0xff87ff, + 214: 0xffaf00, + 215: 0xffaf5f, + 216: 0xffaf87, + 217: 0xffafaf, + 218: 0xffafd7, + 219: 0xffafff, + 220: 0xffd700, + 221: 0xffd75f, + 222: 0xffd787, + 223: 0xffd7af, + 224: 0xffd7d7, + 225: 0xffd7ff, + 226: 0xffff00, + 227: 0xffff5f, + 228: 0xffff87, + 229: 0xffffaf, + 230: 0xffffd7, + 231: 0xffffff, + 232: 0x080808, + 233: 0x121212, + 234: 0x1c1c1c, + 235: 0x262626, + 236: 0x303030, + 237: 0x3a3a3a, + 238: 0x444444, + 239: 0x4e4e4e, + 240: 0x585858, + 241: 0x626262, + 242: 0x6c6c6c, + 243: 0x767676, + 244: 0x808080, + 245: 0x8a8a8a, + 246: 0x949494, + 247: 0x9e9e9e, + 248: 0xa8a8a8, + 249: 0xb2b2b2, + 250: 0xbcbcbc, + 251: 0xc6c6c6, + 252: 0xd0d0d0, + 253: 0xdadada, + 254: 0xe4e4e4, + 255: 0xeeeeee, +} + +func (w *Writer) Write(data []byte) (n int, err error) { + var csbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + + er := bytes.NewBuffer(data) +loop: + for { + r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + if r1 == 0 { + break loop + } + + c1, _, err := er.ReadRune() + if err != nil { + break loop + } + if c1 != 0x1b { + fmt.Fprint(w.out, string(c1)) + continue + } + c2, _, err := er.ReadRune() + if err != nil { + w.lastbuf.WriteRune(c1) + break loop + } + if c2 != 0x5b { + w.lastbuf.WriteRune(c1) + w.lastbuf.WriteRune(c2) + continue + } + + var buf bytes.Buffer + var m rune + for { + c, _, err := er.ReadRune() + if err != nil { + w.lastbuf.WriteRune(c1) + w.lastbuf.WriteRune(c2) + w.lastbuf.Write(buf.Bytes()) + break loop + } + if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { + m = c + break + } + buf.Write([]byte(string(c))) + } + + var csbi consoleScreenBufferInfo + switch m { + case 'A': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.y -= short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'B': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.y += short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'C': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x -= short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'D': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + if n, err = strconv.Atoi(buf.String()); err == nil { + var csbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x += short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + } + case 'E': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = 0 + csbi.cursorPosition.y += short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'F': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = 0 + csbi.cursorPosition.y -= short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'G': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = short(n) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'H': + token := strings.Split(buf.String(), ";") + if len(token) != 2 { + continue + } + n1, err := strconv.Atoi(token[0]) + if err != nil { + continue + } + n2, err := strconv.Atoi(token[1]) + if err != nil { + continue + } + csbi.cursorPosition.x = short(n2) + csbi.cursorPosition.x = short(n1) + procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'J': + n, err := strconv.Atoi(buf.String()) + if err != nil { + continue + } + var cursor coord + switch n { + case 0: + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + case 1: + cursor = coord{x: csbi.window.left, y: csbi.window.top} + case 2: + cursor = coord{x: csbi.window.left, y: csbi.window.top} + } + var count, written dword + count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) + procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'K': + n, err := strconv.Atoi(buf.String()) + if err != nil { + continue + } + var cursor coord + switch n { + case 0: + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + case 1: + cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y} + case 2: + cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y} + } + var count, written dword + count = dword(csbi.size.x - csbi.cursorPosition.x) + procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'm': + attr := csbi.attributes + cs := buf.String() + if cs == "" { + procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr)) + continue + } + token := strings.Split(cs, ";") + for i := 0; i < len(token); i += 1 { + ns := token[i] + if n, err = strconv.Atoi(ns); err == nil { + switch { + case n == 0 || n == 100: + attr = w.oldattr + case 1 <= n && n <= 5: + attr |= foregroundIntensity + case n == 7: + attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) + case 22 == n || n == 25 || n == 25: + attr |= foregroundIntensity + case n == 27: + attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) + case 30 <= n && n <= 37: + attr = (attr & backgroundMask) + if (n-30)&1 != 0 { + attr |= foregroundRed + } + if (n-30)&2 != 0 { + attr |= foregroundGreen + } + if (n-30)&4 != 0 { + attr |= foregroundBlue + } + case n == 38: // set foreground color. + if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") { + if n256, err := strconv.Atoi(token[i+2]); err == nil { + if n256foreAttr == nil { + n256setup() + } + attr &= backgroundMask + attr |= n256foreAttr[n256] + i += 2 + } + } else { + attr = attr & (w.oldattr & backgroundMask) + } + case n == 39: // reset foreground color. + attr &= backgroundMask + attr |= w.oldattr & foregroundMask + case 40 <= n && n <= 47: + attr = (attr & foregroundMask) + if (n-40)&1 != 0 { + attr |= backgroundRed + } + if (n-40)&2 != 0 { + attr |= backgroundGreen + } + if (n-40)&4 != 0 { + attr |= backgroundBlue + } + case n == 48: // set background color. + if i < len(token)-2 && token[i+1] == "5" { + if n256, err := strconv.Atoi(token[i+2]); err == nil { + if n256backAttr == nil { + n256setup() + } + attr &= foregroundMask + attr |= n256backAttr[n256] + i += 2 + } + } else { + attr = attr & (w.oldattr & foregroundMask) + } + case n == 49: // reset foreground color. + attr &= foregroundMask + attr |= w.oldattr & backgroundMask + case 90 <= n && n <= 97: + attr = (attr & backgroundMask) + attr |= foregroundIntensity + if (n-90)&1 != 0 { + attr |= foregroundRed + } + if (n-90)&2 != 0 { + attr |= foregroundGreen + } + if (n-90)&4 != 0 { + attr |= foregroundBlue + } + case 100 <= n && n <= 107: + attr = (attr & foregroundMask) + attr |= backgroundIntensity + if (n-100)&1 != 0 { + attr |= backgroundRed + } + if (n-100)&2 != 0 { + attr |= backgroundGreen + } + if (n-100)&4 != 0 { + attr |= backgroundBlue + } + } + procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr)) + } + } + } + } + return len(data) - w.lastbuf.Len(), nil +} + +type consoleColor struct { + rgb int + red bool + green bool + blue bool + intensity bool +} + +func (c consoleColor) foregroundAttr() (attr word) { + if c.red { + attr |= foregroundRed + } + if c.green { + attr |= foregroundGreen + } + if c.blue { + attr |= foregroundBlue + } + if c.intensity { + attr |= foregroundIntensity + } + return +} + +func (c consoleColor) backgroundAttr() (attr word) { + if c.red { + attr |= backgroundRed + } + if c.green { + attr |= backgroundGreen + } + if c.blue { + attr |= backgroundBlue + } + if c.intensity { + attr |= backgroundIntensity + } + return +} + +var color16 = []consoleColor{ + consoleColor{0x000000, false, false, false, false}, + consoleColor{0x000080, false, false, true, false}, + consoleColor{0x008000, false, true, false, false}, + consoleColor{0x008080, false, true, true, false}, + consoleColor{0x800000, true, false, false, false}, + consoleColor{0x800080, true, false, true, false}, + consoleColor{0x808000, true, true, false, false}, + consoleColor{0xc0c0c0, true, true, true, false}, + consoleColor{0x808080, false, false, false, true}, + consoleColor{0x0000ff, false, false, true, true}, + consoleColor{0x00ff00, false, true, false, true}, + consoleColor{0x00ffff, false, true, true, true}, + consoleColor{0xff0000, true, false, false, true}, + consoleColor{0xff00ff, true, false, true, true}, + consoleColor{0xffff00, true, true, false, true}, + consoleColor{0xffffff, true, true, true, true}, +} + +type hsv struct { + h, s, v float32 +} + +func (a hsv) dist(b hsv) float32 { + dh := a.h - b.h + switch { + case dh > 0.5: + dh = 1 - dh + case dh < -0.5: + dh = -1 - dh + } + ds := a.s - b.s + dv := a.v - b.v + return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv))) +} + +func toHSV(rgb int) hsv { + r, g, b := float32((rgb&0xFF0000)>>16)/256.0, + float32((rgb&0x00FF00)>>8)/256.0, + float32(rgb&0x0000FF)/256.0 + min, max := minmax3f(r, g, b) + h := max - min + if h > 0 { + if max == r { + h = (g - b) / h + if h < 0 { + h += 6 + } + } else if max == g { + h = 2 + (b-r)/h + } else { + h = 4 + (r-g)/h + } + } + h /= 6.0 + s := max - min + if max != 0 { + s /= max + } + v := max + return hsv{h: h, s: s, v: v} +} + +type hsvTable []hsv + +func toHSVTable(rgbTable []consoleColor) hsvTable { + t := make(hsvTable, len(rgbTable)) + for i, c := range rgbTable { + t[i] = toHSV(c.rgb) + } + return t +} + +func (t hsvTable) find(rgb int) consoleColor { + hsv := toHSV(rgb) + n := 7 + l := float32(5.0) + for i, p := range t { + d := hsv.dist(p) + if d < l { + l, n = d, i + } + } + return color16[n] +} + +func minmax3f(a, b, c float32) (min, max float32) { + if a < b { + if b < c { + return a, c + } else if a < c { + return a, b + } else { + return c, b + } + } else { + if a < c { + return b, c + } else if b < c { + return b, a + } else { + return c, a + } + } +} + +var n256foreAttr []word +var n256backAttr []word + +func n256setup() { + n256foreAttr = make([]word, 256) + n256backAttr = make([]word, 256) + t := toHSVTable(color16) + for i, rgb := range color256 { + c := t.find(rgb) + n256foreAttr[i] = c.foregroundAttr() + n256backAttr[i] = c.backgroundAttr() + } +} diff --git a/vendor/github.com/mattn/go-isatty/LICENSE b/vendor/github.com/mattn/go-isatty/LICENSE new file mode 100644 index 0000000..65dc692 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) Yasuhiro MATSUMOTO + +MIT License (Expat) + +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. diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md new file mode 100644 index 0000000..74845de --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -0,0 +1,37 @@ +# go-isatty + +isatty for golang + +## Usage + +```go +package main + +import ( + "fmt" + "github.com/mattn/go-isatty" + "os" +) + +func main() { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Println("Is Terminal") + } else { + fmt.Println("Is Not Terminal") + } +} +``` + +## Installation + +``` +$ go get github.com/mattn/go-isatty +``` + +# License + +MIT + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-isatty/doc.go b/vendor/github.com/mattn/go-isatty/doc.go new file mode 100644 index 0000000..17d4f90 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/doc.go @@ -0,0 +1,2 @@ +// Package isatty implements interface to isatty +package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_appengine.go b/vendor/github.com/mattn/go-isatty/isatty_appengine.go new file mode 100644 index 0000000..83c5887 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_appengine.go @@ -0,0 +1,9 @@ +// +build appengine + +package isatty + +// IsTerminal returns true if the file descriptor is terminal which +// is always false on on appengine classic which is a sandboxed PaaS. +func IsTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go new file mode 100644 index 0000000..98ffe86 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -0,0 +1,18 @@ +// +build darwin freebsd openbsd netbsd +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TIOCGETA + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_linux.go b/vendor/github.com/mattn/go-isatty/isatty_linux.go new file mode 100644 index 0000000..9d24bac --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_linux.go @@ -0,0 +1,18 @@ +// +build linux +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TCGETS + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go new file mode 100644 index 0000000..1f0c6bf --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -0,0 +1,16 @@ +// +build solaris +// +build !appengine + +package isatty + +import ( + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +func IsTerminal(fd uintptr) bool { + var termio unix.Termio + err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + return err == nil +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go new file mode 100644 index 0000000..83c398b --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -0,0 +1,19 @@ +// +build windows +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +var kernel32 = syscall.NewLazyDLL("kernel32.dll") +var procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 +} diff --git a/vendor/github.com/peterh/liner/COPYING b/vendor/github.com/peterh/liner/COPYING new file mode 100644 index 0000000..9e8c9f2 --- /dev/null +++ b/vendor/github.com/peterh/liner/COPYING @@ -0,0 +1,21 @@ +Copyright © 2012 Peter Harris + +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 (including the next +paragraph) 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. + diff --git a/vendor/github.com/peterh/liner/README.md b/vendor/github.com/peterh/liner/README.md new file mode 100644 index 0000000..9148b24 --- /dev/null +++ b/vendor/github.com/peterh/liner/README.md @@ -0,0 +1,100 @@ +Liner +===== + +Liner is a command line editor with history. It was inspired by linenoise; +everything Unix-like is a VT100 (or is trying very hard to be). If your +terminal is not pretending to be a VT100, change it. Liner also support +Windows. + +Liner is released under the X11 license (which is similar to the new BSD +license). + +Line Editing +------------ + +The following line editing commands are supported on platforms and terminals +that Liner supports: + +Keystroke | Action +--------- | ------ +Ctrl-A, Home | Move cursor to beginning of line +Ctrl-E, End | Move cursor to end of line +Ctrl-B, Left | Move cursor one character left +Ctrl-F, Right| Move cursor one character right +Ctrl-Left, Alt-B | Move cursor to previous word +Ctrl-Right, Alt-F | Move cursor to next word +Ctrl-D, Del | (if line is *not* empty) Delete character under cursor +Ctrl-D | (if line *is* empty) End of File - usually quits application +Ctrl-C | Reset input (create new empty prompt) +Ctrl-L | Clear screen (line is unmodified) +Ctrl-T | Transpose previous character with current character +Ctrl-H, BackSpace | Delete character before cursor +Ctrl-W | Delete word leading up to cursor +Ctrl-K | Delete from cursor to end of line +Ctrl-U | Delete from start of line to cursor +Ctrl-P, Up | Previous match from history +Ctrl-N, Down | Next match from history +Ctrl-R | Reverse Search history (Ctrl-S forward, Ctrl-G cancel) +Ctrl-Y | Paste from Yank buffer (Alt-Y to paste next yank instead) +Tab | Next completion +Shift-Tab | (after Tab) Previous completion + +Getting started +----------------- + +```go +package main + +import ( + "log" + "os" + "path/filepath" + "strings" + + "github.com/peterh/liner" +) + +var ( + history_fn = filepath.Join(os.TempDir(), ".liner_example_history") + names = []string{"john", "james", "mary", "nancy"} +) + +func main() { + line := liner.NewLiner() + defer line.Close() + + line.SetCtrlCAborts(true) + + line.SetCompleter(func(line string) (c []string) { + for _, n := range names { + if strings.HasPrefix(n, strings.ToLower(line)) { + c = append(c, n) + } + } + return + }) + + if f, err := os.Open(history_fn); err == nil { + line.ReadHistory(f) + f.Close() + } + + if name, err := line.Prompt("What is your name? "); err == nil { + log.Print("Got: ", name) + line.AppendHistory(name) + } else if err == liner.ErrPromptAborted { + log.Print("Aborted") + } else { + log.Print("Error reading line: ", err) + } + + if f, err := os.Create(history_fn); err != nil { + log.Print("Error writing history file: ", err) + } else { + line.WriteHistory(f) + f.Close() + } +} +``` + +For documentation, see http://godoc.org/github.com/peterh/liner diff --git a/vendor/github.com/peterh/liner/bsdinput.go b/vendor/github.com/peterh/liner/bsdinput.go new file mode 100644 index 0000000..3593398 --- /dev/null +++ b/vendor/github.com/peterh/liner/bsdinput.go @@ -0,0 +1,41 @@ +// +build openbsd freebsd netbsd + +package liner + +import "syscall" + +const ( + getTermios = syscall.TIOCGETA + setTermios = syscall.TIOCSETA +) + +const ( + // Input flags + inpck = 0x010 + istrip = 0x020 + icrnl = 0x100 + ixon = 0x200 + + // Output flags + opost = 0x1 + + // Control flags + cs8 = 0x300 + + // Local flags + isig = 0x080 + icanon = 0x100 + iexten = 0x400 +) + +type termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]byte + Ispeed int32 + Ospeed int32 +} + +const cursorColumn = false diff --git a/vendor/github.com/peterh/liner/common.go b/vendor/github.com/peterh/liner/common.go new file mode 100644 index 0000000..b6162b6 --- /dev/null +++ b/vendor/github.com/peterh/liner/common.go @@ -0,0 +1,237 @@ +/* +Package liner implements a simple command line editor, inspired by linenoise +(https://github.com/antirez/linenoise/). This package supports WIN32 in +addition to the xterm codes supported by everything else. +*/ +package liner + +import ( + "bufio" + "container/ring" + "errors" + "fmt" + "io" + "strings" + "sync" + "unicode/utf8" +) + +type commonState struct { + terminalSupported bool + outputRedirected bool + inputRedirected bool + history []string + historyMutex sync.RWMutex + completer WordCompleter + columns int + killRing *ring.Ring + ctrlCAborts bool + r *bufio.Reader + tabStyle TabStyle + multiLineMode bool + cursorRows int + maxRows int + shouldRestart ShouldRestart +} + +// TabStyle is used to select how tab completions are displayed. +type TabStyle int + +// Two tab styles are currently available: +// +// TabCircular cycles through each completion item and displays it directly on +// the prompt +// +// TabPrints prints the list of completion items to the screen after a second +// tab key is pressed. This behaves similar to GNU readline and BASH (which +// uses readline) +const ( + TabCircular TabStyle = iota + TabPrints +) + +// ErrPromptAborted is returned from Prompt or PasswordPrompt when the user presses Ctrl-C +// if SetCtrlCAborts(true) has been called on the State +var ErrPromptAborted = errors.New("prompt aborted") + +// ErrNotTerminalOutput is returned from Prompt or PasswordPrompt if the +// platform is normally supported, but stdout has been redirected +var ErrNotTerminalOutput = errors.New("standard output is not a terminal") + +// Max elements to save on the killring +const KillRingMax = 60 + +// HistoryLimit is the maximum number of entries saved in the scrollback history. +const HistoryLimit = 1000 + +// ReadHistory reads scrollback history from r. Returns the number of lines +// read, and any read error (except io.EOF). +func (s *State) ReadHistory(r io.Reader) (num int, err error) { + s.historyMutex.Lock() + defer s.historyMutex.Unlock() + + in := bufio.NewReader(r) + num = 0 + for { + line, part, err := in.ReadLine() + if err == io.EOF { + break + } + if err != nil { + return num, err + } + if part { + return num, fmt.Errorf("line %d is too long", num+1) + } + if !utf8.Valid(line) { + return num, fmt.Errorf("invalid string at line %d", num+1) + } + num++ + s.history = append(s.history, string(line)) + if len(s.history) > HistoryLimit { + s.history = s.history[1:] + } + } + return num, nil +} + +// WriteHistory writes scrollback history to w. Returns the number of lines +// successfully written, and any write error. +// +// Unlike the rest of liner's API, WriteHistory is safe to call +// from another goroutine while Prompt is in progress. +// This exception is to facilitate the saving of the history buffer +// during an unexpected exit (for example, due to Ctrl-C being invoked) +func (s *State) WriteHistory(w io.Writer) (num int, err error) { + s.historyMutex.RLock() + defer s.historyMutex.RUnlock() + + for _, item := range s.history { + _, err := fmt.Fprintln(w, item) + if err != nil { + return num, err + } + num++ + } + return num, nil +} + +// AppendHistory appends an entry to the scrollback history. AppendHistory +// should be called iff Prompt returns a valid command. +func (s *State) AppendHistory(item string) { + s.historyMutex.Lock() + defer s.historyMutex.Unlock() + + if len(s.history) > 0 { + if item == s.history[len(s.history)-1] { + return + } + } + s.history = append(s.history, item) + if len(s.history) > HistoryLimit { + s.history = s.history[1:] + } +} + +// Returns the history lines starting with prefix +func (s *State) getHistoryByPrefix(prefix string) (ph []string) { + for _, h := range s.history { + if strings.HasPrefix(h, prefix) { + ph = append(ph, h) + } + } + return +} + +// Returns the history lines matching the inteligent search +func (s *State) getHistoryByPattern(pattern string) (ph []string, pos []int) { + if pattern == "" { + return + } + for _, h := range s.history { + if i := strings.Index(h, pattern); i >= 0 { + ph = append(ph, h) + pos = append(pos, i) + } + } + return +} + +// Completer takes the currently edited line content at the left of the cursor +// and returns a list of completion candidates. +// If the line is "Hello, wo!!!" and the cursor is before the first '!', "Hello, wo" is passed +// to the completer which may return {"Hello, world", "Hello, Word"} to have "Hello, world!!!". +type Completer func(line string) []string + +// WordCompleter takes the currently edited line with the cursor position and +// returns the completion candidates for the partial word to be completed. +// If the line is "Hello, wo!!!" and the cursor is before the first '!', ("Hello, wo!!!", 9) is passed +// to the completer which may returns ("Hello, ", {"world", "Word"}, "!!!") to have "Hello, world!!!". +type WordCompleter func(line string, pos int) (head string, completions []string, tail string) + +// SetCompleter sets the completion function that Liner will call to +// fetch completion candidates when the user presses tab. +func (s *State) SetCompleter(f Completer) { + if f == nil { + s.completer = nil + return + } + s.completer = func(line string, pos int) (string, []string, string) { + return "", f(string([]rune(line)[:pos])), string([]rune(line)[pos:]) + } +} + +// SetWordCompleter sets the completion function that Liner will call to +// fetch completion candidates when the user presses tab. +func (s *State) SetWordCompleter(f WordCompleter) { + s.completer = f +} + +// SetTabCompletionStyle sets the behvavior when the Tab key is pressed +// for auto-completion. TabCircular is the default behavior and cycles +// through the list of candidates at the prompt. TabPrints will print +// the available completion candidates to the screen similar to BASH +// and GNU Readline +func (s *State) SetTabCompletionStyle(tabStyle TabStyle) { + s.tabStyle = tabStyle +} + +// ModeApplier is the interface that wraps a representation of the terminal +// mode. ApplyMode sets the terminal to this mode. +type ModeApplier interface { + ApplyMode() error +} + +// SetCtrlCAborts sets whether Prompt on a supported terminal will return an +// ErrPromptAborted when Ctrl-C is pressed. The default is false (will not +// return when Ctrl-C is pressed). Unsupported terminals typically raise SIGINT +// (and Prompt does not return) regardless of the value passed to SetCtrlCAborts. +func (s *State) SetCtrlCAborts(aborts bool) { + s.ctrlCAborts = aborts +} + +// SetMultiLineMode sets whether line is auto-wrapped. The default is false (single line). +func (s *State) SetMultiLineMode(mlmode bool) { + s.multiLineMode = mlmode +} + +// ShouldRestart is passed the error generated by readNext and returns true if +// the the read should be restarted or false if the error should be returned. +type ShouldRestart func(err error) bool + +// SetShouldRestart sets the restart function that Liner will call to determine +// whether to retry the call to, or return the error returned by, readNext. +func (s *State) SetShouldRestart(f ShouldRestart) { + s.shouldRestart = f +} + +func (s *State) promptUnsupported(p string) (string, error) { + if !s.inputRedirected || !s.terminalSupported { + fmt.Print(p) + } + linebuf, _, err := s.r.ReadLine() + if err != nil { + return "", err + } + return string(linebuf), nil +} diff --git a/vendor/github.com/peterh/liner/fallbackinput.go b/vendor/github.com/peterh/liner/fallbackinput.go new file mode 100644 index 0000000..d9eb79d --- /dev/null +++ b/vendor/github.com/peterh/liner/fallbackinput.go @@ -0,0 +1,57 @@ +// +build !windows,!linux,!darwin,!openbsd,!freebsd,!netbsd + +package liner + +import ( + "bufio" + "errors" + "os" +) + +// State represents an open terminal +type State struct { + commonState +} + +// Prompt displays p, and then waits for user input. Prompt does not support +// line editing on this operating system. +func (s *State) Prompt(p string) (string, error) { + return s.promptUnsupported(p) +} + +// PasswordPrompt is not supported in this OS. +func (s *State) PasswordPrompt(p string) (string, error) { + return "", errors.New("liner: function not supported in this terminal") +} + +// NewLiner initializes a new *State +// +// Note that this operating system uses a fallback mode without line +// editing. Patches welcome. +func NewLiner() *State { + var s State + s.r = bufio.NewReader(os.Stdin) + return &s +} + +// Close returns the terminal to its previous mode +func (s *State) Close() error { + return nil +} + +// TerminalSupported returns false because line editing is not +// supported on this platform. +func TerminalSupported() bool { + return false +} + +type noopMode struct{} + +func (n noopMode) ApplyMode() error { + return nil +} + +// TerminalMode returns a noop InputModeSetter on this platform. +func TerminalMode() (ModeApplier, error) { + return noopMode{}, nil +} diff --git a/vendor/github.com/peterh/liner/input.go b/vendor/github.com/peterh/liner/input.go new file mode 100644 index 0000000..0ee6be7 --- /dev/null +++ b/vendor/github.com/peterh/liner/input.go @@ -0,0 +1,367 @@ +// +build linux darwin openbsd freebsd netbsd + +package liner + +import ( + "bufio" + "errors" + "os" + "os/signal" + "strconv" + "strings" + "syscall" + "time" +) + +type nexter struct { + r rune + err error +} + +// State represents an open terminal +type State struct { + commonState + origMode termios + defaultMode termios + next <-chan nexter + winch chan os.Signal + pending []rune + useCHA bool +} + +// NewLiner initializes a new *State, and sets the terminal into raw mode. To +// restore the terminal to its previous state, call State.Close(). +// +// Note if you are still using Go 1.0: NewLiner handles SIGWINCH, so it will +// leak a channel every time you call it. Therefore, it is recommened that you +// upgrade to a newer release of Go, or ensure that NewLiner is only called +// once. +func NewLiner() *State { + var s State + s.r = bufio.NewReader(os.Stdin) + + s.terminalSupported = TerminalSupported() + if m, err := TerminalMode(); err == nil { + s.origMode = *m.(*termios) + } else { + s.inputRedirected = true + } + if _, err := getMode(syscall.Stdout); err != 0 { + s.outputRedirected = true + } + if s.inputRedirected && s.outputRedirected { + s.terminalSupported = false + } + if s.terminalSupported && !s.inputRedirected && !s.outputRedirected { + mode := s.origMode + mode.Iflag &^= icrnl | inpck | istrip | ixon + mode.Cflag |= cs8 + mode.Lflag &^= syscall.ECHO | icanon | iexten + mode.ApplyMode() + + winch := make(chan os.Signal, 1) + signal.Notify(winch, syscall.SIGWINCH) + s.winch = winch + + s.checkOutput() + } + + if !s.outputRedirected { + s.outputRedirected = !s.getColumns() + } + + return &s +} + +var errTimedOut = errors.New("timeout") + +func (s *State) startPrompt() { + if s.terminalSupported { + if m, err := TerminalMode(); err == nil { + s.defaultMode = *m.(*termios) + mode := s.defaultMode + mode.Lflag &^= isig + mode.ApplyMode() + } + } + s.restartPrompt() +} + +func (s *State) restartPrompt() { + next := make(chan nexter) + go func() { + for { + var n nexter + n.r, _, n.err = s.r.ReadRune() + next <- n + // Shut down nexter loop when an end condition has been reached + if n.err != nil || n.r == '\n' || n.r == '\r' || n.r == ctrlC || n.r == ctrlD { + close(next) + return + } + } + }() + s.next = next +} + +func (s *State) stopPrompt() { + if s.terminalSupported { + s.defaultMode.ApplyMode() + } +} + +func (s *State) nextPending(timeout <-chan time.Time) (rune, error) { + select { + case thing, ok := <-s.next: + if !ok { + return 0, errors.New("liner: internal error") + } + if thing.err != nil { + return 0, thing.err + } + s.pending = append(s.pending, thing.r) + return thing.r, nil + case <-timeout: + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, errTimedOut + } + // not reached + return 0, nil +} + +func (s *State) readNext() (interface{}, error) { + if len(s.pending) > 0 { + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + var r rune + select { + case thing, ok := <-s.next: + if !ok { + return 0, errors.New("liner: internal error") + } + if thing.err != nil { + return nil, thing.err + } + r = thing.r + case <-s.winch: + s.getColumns() + return winch, nil + } + if r != esc { + return r, nil + } + s.pending = append(s.pending, r) + + // Wait at most 50 ms for the rest of the escape sequence + // If nothing else arrives, it was an actual press of the esc key + timeout := time.After(50 * time.Millisecond) + flag, err := s.nextPending(timeout) + if err != nil { + if err == errTimedOut { + return flag, nil + } + return unknown, err + } + + switch flag { + case '[': + code, err := s.nextPending(timeout) + if err != nil { + if err == errTimedOut { + return code, nil + } + return unknown, err + } + switch code { + case 'A': + s.pending = s.pending[:0] // escape code complete + return up, nil + case 'B': + s.pending = s.pending[:0] // escape code complete + return down, nil + case 'C': + s.pending = s.pending[:0] // escape code complete + return right, nil + case 'D': + s.pending = s.pending[:0] // escape code complete + return left, nil + case 'F': + s.pending = s.pending[:0] // escape code complete + return end, nil + case 'H': + s.pending = s.pending[:0] // escape code complete + return home, nil + case 'Z': + s.pending = s.pending[:0] // escape code complete + return shiftTab, nil + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + num := []rune{code} + for { + code, err := s.nextPending(timeout) + if err != nil { + if err == errTimedOut { + return code, nil + } + return nil, err + } + switch code { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + num = append(num, code) + case ';': + // Modifier code to follow + // This only supports Ctrl-left and Ctrl-right for now + x, _ := strconv.ParseInt(string(num), 10, 32) + if x != 1 { + // Can't be left or right + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + num = num[:0] + for { + code, err = s.nextPending(timeout) + if err != nil { + if err == errTimedOut { + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + return nil, err + } + switch code { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + num = append(num, code) + case 'C', 'D': + // right, left + mod, _ := strconv.ParseInt(string(num), 10, 32) + if mod != 5 { + // Not bare Ctrl + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + s.pending = s.pending[:0] // escape code complete + if code == 'C' { + return wordRight, nil + } + return wordLeft, nil + default: + // Not left or right + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + } + case '~': + s.pending = s.pending[:0] // escape code complete + x, _ := strconv.ParseInt(string(num), 10, 32) + switch x { + case 2: + return insert, nil + case 3: + return del, nil + case 5: + return pageUp, nil + case 6: + return pageDown, nil + case 7: + return home, nil + case 8: + return end, nil + case 15: + return f5, nil + case 17: + return f6, nil + case 18: + return f7, nil + case 19: + return f8, nil + case 20: + return f9, nil + case 21: + return f10, nil + case 23: + return f11, nil + case 24: + return f12, nil + default: + return unknown, nil + } + default: + // unrecognized escape code + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + } + } + + case 'O': + code, err := s.nextPending(timeout) + if err != nil { + if err == errTimedOut { + return code, nil + } + return nil, err + } + s.pending = s.pending[:0] // escape code complete + switch code { + case 'c': + return wordRight, nil + case 'd': + return wordLeft, nil + case 'H': + return home, nil + case 'F': + return end, nil + case 'P': + return f1, nil + case 'Q': + return f2, nil + case 'R': + return f3, nil + case 'S': + return f4, nil + default: + return unknown, nil + } + case 'b': + s.pending = s.pending[:0] // escape code complete + return altB, nil + case 'f': + s.pending = s.pending[:0] // escape code complete + return altF, nil + case 'y': + s.pending = s.pending[:0] // escape code complete + return altY, nil + default: + rv := s.pending[0] + s.pending = s.pending[1:] + return rv, nil + } + + // not reached + return r, nil +} + +// Close returns the terminal to its previous mode +func (s *State) Close() error { + stopSignal(s.winch) + if !s.inputRedirected { + s.origMode.ApplyMode() + } + return nil +} + +// TerminalSupported returns true if the current terminal supports +// line editing features, and false if liner will use the 'dumb' +// fallback for input. +// Note that TerminalSupported does not check all factors that may +// cause liner to not fully support the terminal (such as stdin redirection) +func TerminalSupported() bool { + bad := map[string]bool{"": true, "dumb": true, "cons25": true} + return !bad[strings.ToLower(os.Getenv("TERM"))] +} diff --git a/vendor/github.com/peterh/liner/input_darwin.go b/vendor/github.com/peterh/liner/input_darwin.go new file mode 100644 index 0000000..e98ab4a --- /dev/null +++ b/vendor/github.com/peterh/liner/input_darwin.go @@ -0,0 +1,43 @@ +// +build darwin + +package liner + +import "syscall" + +const ( + getTermios = syscall.TIOCGETA + setTermios = syscall.TIOCSETA +) + +const ( + // Input flags + inpck = 0x010 + istrip = 0x020 + icrnl = 0x100 + ixon = 0x200 + + // Output flags + opost = 0x1 + + // Control flags + cs8 = 0x300 + + // Local flags + isig = 0x080 + icanon = 0x100 + iexten = 0x400 +) + +type termios struct { + Iflag uintptr + Oflag uintptr + Cflag uintptr + Lflag uintptr + Cc [20]byte + Ispeed uintptr + Ospeed uintptr +} + +// Terminal.app needs a column for the cursor when the input line is at the +// bottom of the window. +const cursorColumn = true diff --git a/vendor/github.com/peterh/liner/input_linux.go b/vendor/github.com/peterh/liner/input_linux.go new file mode 100644 index 0000000..56ed185 --- /dev/null +++ b/vendor/github.com/peterh/liner/input_linux.go @@ -0,0 +1,28 @@ +// +build linux + +package liner + +import "syscall" + +const ( + getTermios = syscall.TCGETS + setTermios = syscall.TCSETS +) + +const ( + icrnl = syscall.ICRNL + inpck = syscall.INPCK + istrip = syscall.ISTRIP + ixon = syscall.IXON + opost = syscall.OPOST + cs8 = syscall.CS8 + isig = syscall.ISIG + icanon = syscall.ICANON + iexten = syscall.IEXTEN +) + +type termios struct { + syscall.Termios +} + +const cursorColumn = false diff --git a/vendor/github.com/peterh/liner/input_windows.go b/vendor/github.com/peterh/liner/input_windows.go new file mode 100644 index 0000000..199b942 --- /dev/null +++ b/vendor/github.com/peterh/liner/input_windows.go @@ -0,0 +1,324 @@ +package liner + +import ( + "bufio" + "os" + "syscall" + "unsafe" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + + procGetStdHandle = kernel32.NewProc("GetStdHandle") + procReadConsoleInput = kernel32.NewProc("ReadConsoleInputW") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") + procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") +) + +// These names are from the Win32 api, so they use underscores (contrary to +// what golint suggests) +const ( + std_input_handle = uint32(-10 & 0xFFFFFFFF) + std_output_handle = uint32(-11 & 0xFFFFFFFF) + std_error_handle = uint32(-12 & 0xFFFFFFFF) + invalid_handle_value = ^uintptr(0) +) + +type inputMode uint32 + +// State represents an open terminal +type State struct { + commonState + handle syscall.Handle + hOut syscall.Handle + origMode inputMode + defaultMode inputMode + key interface{} + repeat uint16 +} + +const ( + enableEchoInput = 0x4 + enableInsertMode = 0x20 + enableLineInput = 0x2 + enableMouseInput = 0x10 + enableProcessedInput = 0x1 + enableQuickEditMode = 0x40 + enableWindowInput = 0x8 +) + +// NewLiner initializes a new *State, and sets the terminal into raw mode. To +// restore the terminal to its previous state, call State.Close(). +func NewLiner() *State { + var s State + hIn, _, _ := procGetStdHandle.Call(uintptr(std_input_handle)) + s.handle = syscall.Handle(hIn) + hOut, _, _ := procGetStdHandle.Call(uintptr(std_output_handle)) + s.hOut = syscall.Handle(hOut) + + s.terminalSupported = true + if m, err := TerminalMode(); err == nil { + s.origMode = m.(inputMode) + mode := s.origMode + mode &^= enableEchoInput + mode &^= enableInsertMode + mode &^= enableLineInput + mode &^= enableMouseInput + mode |= enableWindowInput + mode.ApplyMode() + } else { + s.inputRedirected = true + s.r = bufio.NewReader(os.Stdin) + } + + s.getColumns() + s.outputRedirected = s.columns <= 0 + + return &s +} + +// These names are from the Win32 api, so they use underscores (contrary to +// what golint suggests) +const ( + focus_event = 0x0010 + key_event = 0x0001 + menu_event = 0x0008 + mouse_event = 0x0002 + window_buffer_size_event = 0x0004 +) + +type input_record struct { + eventType uint16 + pad uint16 + blob [16]byte +} + +type key_event_record struct { + KeyDown int32 + RepeatCount uint16 + VirtualKeyCode uint16 + VirtualScanCode uint16 + Char int16 + ControlKeyState uint32 +} + +// These names are from the Win32 api, so they use underscores (contrary to +// what golint suggests) +const ( + vk_tab = 0x09 + vk_prior = 0x21 + vk_next = 0x22 + vk_end = 0x23 + vk_home = 0x24 + vk_left = 0x25 + vk_up = 0x26 + vk_right = 0x27 + vk_down = 0x28 + vk_insert = 0x2d + vk_delete = 0x2e + vk_f1 = 0x70 + vk_f2 = 0x71 + vk_f3 = 0x72 + vk_f4 = 0x73 + vk_f5 = 0x74 + vk_f6 = 0x75 + vk_f7 = 0x76 + vk_f8 = 0x77 + vk_f9 = 0x78 + vk_f10 = 0x79 + vk_f11 = 0x7a + vk_f12 = 0x7b + bKey = 0x42 + fKey = 0x46 + yKey = 0x59 +) + +const ( + shiftPressed = 0x0010 + leftAltPressed = 0x0002 + leftCtrlPressed = 0x0008 + rightAltPressed = 0x0001 + rightCtrlPressed = 0x0004 + + modKeys = shiftPressed | leftAltPressed | rightAltPressed | leftCtrlPressed | rightCtrlPressed +) + +func (s *State) readNext() (interface{}, error) { + if s.repeat > 0 { + s.repeat-- + return s.key, nil + } + + var input input_record + pbuf := uintptr(unsafe.Pointer(&input)) + var rv uint32 + prv := uintptr(unsafe.Pointer(&rv)) + + for { + ok, _, err := procReadConsoleInput.Call(uintptr(s.handle), pbuf, 1, prv) + + if ok == 0 { + return nil, err + } + + if input.eventType == window_buffer_size_event { + xy := (*coord)(unsafe.Pointer(&input.blob[0])) + s.columns = int(xy.x) + if s.columns > 1 { + s.columns-- + } + return winch, nil + } + if input.eventType != key_event { + continue + } + ke := (*key_event_record)(unsafe.Pointer(&input.blob[0])) + if ke.KeyDown == 0 { + continue + } + + if ke.VirtualKeyCode == vk_tab && ke.ControlKeyState&modKeys == shiftPressed { + s.key = shiftTab + } else if ke.VirtualKeyCode == bKey && (ke.ControlKeyState&modKeys == leftAltPressed || + ke.ControlKeyState&modKeys == rightAltPressed) { + s.key = altB + } else if ke.VirtualKeyCode == fKey && (ke.ControlKeyState&modKeys == leftAltPressed || + ke.ControlKeyState&modKeys == rightAltPressed) { + s.key = altF + } else if ke.VirtualKeyCode == yKey && (ke.ControlKeyState&modKeys == leftAltPressed || + ke.ControlKeyState&modKeys == rightAltPressed) { + s.key = altY + } else if ke.Char > 0 { + s.key = rune(ke.Char) + } else { + switch ke.VirtualKeyCode { + case vk_prior: + s.key = pageUp + case vk_next: + s.key = pageDown + case vk_end: + s.key = end + case vk_home: + s.key = home + case vk_left: + s.key = left + if ke.ControlKeyState&(leftCtrlPressed|rightCtrlPressed) != 0 { + if ke.ControlKeyState&modKeys == ke.ControlKeyState&(leftCtrlPressed|rightCtrlPressed) { + s.key = wordLeft + } + } + case vk_right: + s.key = right + if ke.ControlKeyState&(leftCtrlPressed|rightCtrlPressed) != 0 { + if ke.ControlKeyState&modKeys == ke.ControlKeyState&(leftCtrlPressed|rightCtrlPressed) { + s.key = wordRight + } + } + case vk_up: + s.key = up + case vk_down: + s.key = down + case vk_insert: + s.key = insert + case vk_delete: + s.key = del + case vk_f1: + s.key = f1 + case vk_f2: + s.key = f2 + case vk_f3: + s.key = f3 + case vk_f4: + s.key = f4 + case vk_f5: + s.key = f5 + case vk_f6: + s.key = f6 + case vk_f7: + s.key = f7 + case vk_f8: + s.key = f8 + case vk_f9: + s.key = f9 + case vk_f10: + s.key = f10 + case vk_f11: + s.key = f11 + case vk_f12: + s.key = f12 + default: + // Eat modifier keys + // TODO: return Action(Unknown) if the key isn't a + // modifier. + continue + } + } + + if ke.RepeatCount > 1 { + s.repeat = ke.RepeatCount - 1 + } + return s.key, nil + } + return unknown, nil +} + +// Close returns the terminal to its previous mode +func (s *State) Close() error { + s.origMode.ApplyMode() + return nil +} + +func (s *State) startPrompt() { + if m, err := TerminalMode(); err == nil { + s.defaultMode = m.(inputMode) + mode := s.defaultMode + mode &^= enableProcessedInput + mode.ApplyMode() + } +} + +func (s *State) restartPrompt() { +} + +func (s *State) stopPrompt() { + s.defaultMode.ApplyMode() +} + +// TerminalSupported returns true because line editing is always +// supported on Windows. +func TerminalSupported() bool { + return true +} + +func (mode inputMode) ApplyMode() error { + hIn, _, err := procGetStdHandle.Call(uintptr(std_input_handle)) + if hIn == invalid_handle_value || hIn == 0 { + return err + } + ok, _, err := procSetConsoleMode.Call(hIn, uintptr(mode)) + if ok != 0 { + err = nil + } + return err +} + +// TerminalMode returns the current terminal input mode as an InputModeSetter. +// +// This function is provided for convenience, and should +// not be necessary for most users of liner. +func TerminalMode() (ModeApplier, error) { + var mode inputMode + hIn, _, err := procGetStdHandle.Call(uintptr(std_input_handle)) + if hIn == invalid_handle_value || hIn == 0 { + return nil, err + } + ok, _, err := procGetConsoleMode.Call(hIn, uintptr(unsafe.Pointer(&mode))) + if ok != 0 { + err = nil + } + return mode, err +} diff --git a/vendor/github.com/peterh/liner/line.go b/vendor/github.com/peterh/liner/line.go new file mode 100644 index 0000000..903dd24 --- /dev/null +++ b/vendor/github.com/peterh/liner/line.go @@ -0,0 +1,1033 @@ +// +build windows linux darwin openbsd freebsd netbsd + +package liner + +import ( + "container/ring" + "errors" + "fmt" + "io" + "strings" + "unicode" + "unicode/utf8" +) + +type action int + +const ( + left action = iota + right + up + down + home + end + insert + del + pageUp + pageDown + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + altB + altF + altY + shiftTab + wordLeft + wordRight + winch + unknown +) + +const ( + ctrlA = 1 + ctrlB = 2 + ctrlC = 3 + ctrlD = 4 + ctrlE = 5 + ctrlF = 6 + ctrlG = 7 + ctrlH = 8 + tab = 9 + lf = 10 + ctrlK = 11 + ctrlL = 12 + cr = 13 + ctrlN = 14 + ctrlO = 15 + ctrlP = 16 + ctrlQ = 17 + ctrlR = 18 + ctrlS = 19 + ctrlT = 20 + ctrlU = 21 + ctrlV = 22 + ctrlW = 23 + ctrlX = 24 + ctrlY = 25 + ctrlZ = 26 + esc = 27 + bs = 127 +) + +const ( + beep = "\a" +) + +type tabDirection int + +const ( + tabForward tabDirection = iota + tabReverse +) + +func (s *State) refresh(prompt []rune, buf []rune, pos int) error { + if s.multiLineMode { + return s.refreshMultiLine(prompt, buf, pos) + } else { + return s.refreshSingleLine(prompt, buf, pos) + } +} + +func (s *State) refreshSingleLine(prompt []rune, buf []rune, pos int) error { + s.cursorPos(0) + _, err := fmt.Print(string(prompt)) + if err != nil { + return err + } + + pLen := countGlyphs(prompt) + bLen := countGlyphs(buf) + pos = countGlyphs(buf[:pos]) + if pLen+bLen < s.columns { + _, err = fmt.Print(string(buf)) + s.eraseLine() + s.cursorPos(pLen + pos) + } else { + // Find space available + space := s.columns - pLen + space-- // space for cursor + start := pos - space/2 + end := start + space + if end > bLen { + end = bLen + start = end - space + } + if start < 0 { + start = 0 + end = space + } + pos -= start + + // Leave space for markers + if start > 0 { + start++ + } + if end < bLen { + end-- + } + startRune := len(getPrefixGlyphs(buf, start)) + line := getPrefixGlyphs(buf[startRune:], end-start) + + // Output + if start > 0 { + fmt.Print("{") + } + fmt.Print(string(line)) + if end < bLen { + fmt.Print("}") + } + + // Set cursor position + s.eraseLine() + s.cursorPos(pLen + pos) + } + return err +} + +func (s *State) refreshMultiLine(prompt []rune, buf []rune, pos int) error { + promptColumns := countMultiLineGlyphs(prompt, s.columns, 0) + totalColumns := countMultiLineGlyphs(buf, s.columns, promptColumns) + totalRows := (totalColumns + s.columns - 1) / s.columns + maxRows := s.maxRows + if totalRows > s.maxRows { + s.maxRows = totalRows + } + cursorRows := s.cursorRows + if cursorRows == 0 { + cursorRows = 1 + } + + /* First step: clear all the lines used before. To do so start by + * going to the last row. */ + if maxRows-cursorRows > 0 { + s.moveDown(maxRows - cursorRows) + } + + /* Now for every row clear it, go up. */ + for i := 0; i < maxRows-1; i++ { + s.cursorPos(0) + s.eraseLine() + s.moveUp(1) + } + + /* Clean the top line. */ + s.cursorPos(0) + s.eraseLine() + + /* Write the prompt and the current buffer content */ + if _, err := fmt.Print(string(prompt)); err != nil { + return err + } + if _, err := fmt.Print(string(buf)); err != nil { + return err + } + + /* If we are at the very end of the screen with our prompt, we need to + * emit a newline and move the prompt to the first column. */ + cursorColumns := countMultiLineGlyphs(buf[:pos], s.columns, promptColumns) + if cursorColumns == totalColumns && totalColumns%s.columns == 0 { + s.emitNewLine() + s.cursorPos(0) + totalRows++ + if totalRows > s.maxRows { + s.maxRows = totalRows + } + } + + /* Move cursor to right position. */ + cursorRows = (cursorColumns + s.columns) / s.columns + if s.cursorRows > 0 && totalRows-cursorRows > 0 { + s.moveUp(totalRows - cursorRows) + } + /* Set column. */ + s.cursorPos(cursorColumns % s.columns) + + s.cursorRows = cursorRows + return nil +} + +func (s *State) resetMultiLine(prompt []rune, buf []rune, pos int) { + columns := countMultiLineGlyphs(prompt, s.columns, 0) + columns = countMultiLineGlyphs(buf[:pos], s.columns, columns) + columns += 2 // ^C + cursorRows := (columns + s.columns) / s.columns + if s.maxRows-cursorRows > 0 { + for i := 0; i < s.maxRows-cursorRows; i++ { + fmt.Println() // always moves the cursor down or scrolls the window up as needed + } + } + s.maxRows = 1 + s.cursorRows = 0 +} + +func longestCommonPrefix(strs []string) string { + if len(strs) == 0 { + return "" + } + longest := strs[0] + + for _, str := range strs[1:] { + for !strings.HasPrefix(str, longest) { + longest = longest[:len(longest)-1] + } + } + // Remove trailing partial runes + longest = strings.TrimRight(longest, "\uFFFD") + return longest +} + +func (s *State) circularTabs(items []string) func(tabDirection) (string, error) { + item := -1 + return func(direction tabDirection) (string, error) { + if direction == tabForward { + if item < len(items)-1 { + item++ + } else { + item = 0 + } + } else if direction == tabReverse { + if item > 0 { + item-- + } else { + item = len(items) - 1 + } + } + return items[item], nil + } +} + +func calculateColumns(screenWidth int, items []string) (numColumns, numRows, maxWidth int) { + for _, item := range items { + if len(item) >= screenWidth { + return 1, len(items), screenWidth - 1 + } + if len(item) >= maxWidth { + maxWidth = len(item) + 1 + } + } + + numColumns = screenWidth / maxWidth + numRows = len(items) / numColumns + if len(items)%numColumns > 0 { + numRows++ + } + + if len(items) <= numColumns { + maxWidth = 0 + } + + return +} + +func (s *State) printedTabs(items []string) func(tabDirection) (string, error) { + numTabs := 1 + prefix := longestCommonPrefix(items) + return func(direction tabDirection) (string, error) { + if len(items) == 1 { + return items[0], nil + } + + if numTabs == 2 { + if len(items) > 100 { + fmt.Printf("\nDisplay all %d possibilities? (y or n) ", len(items)) + prompt: + for { + next, err := s.readNext() + if err != nil { + return prefix, err + } + + if key, ok := next.(rune); ok { + switch key { + case 'n', 'N': + return prefix, nil + case 'y', 'Y': + break prompt + case ctrlC, ctrlD, cr, lf: + s.restartPrompt() + } + } + } + } + fmt.Println("") + + numColumns, numRows, maxWidth := calculateColumns(s.columns, items) + + for i := 0; i < numRows; i++ { + for j := 0; j < numColumns*numRows; j += numRows { + if i+j < len(items) { + if maxWidth > 0 { + fmt.Printf("%-*.[1]*s", maxWidth, items[i+j]) + } else { + fmt.Printf("%v ", items[i+j]) + } + } + } + fmt.Println("") + } + } else { + numTabs++ + } + return prefix, nil + } +} + +func (s *State) tabComplete(p []rune, line []rune, pos int) ([]rune, int, interface{}, error) { + if s.completer == nil { + return line, pos, rune(esc), nil + } + head, list, tail := s.completer(string(line), pos) + if len(list) <= 0 { + return line, pos, rune(esc), nil + } + hl := utf8.RuneCountInString(head) + if len(list) == 1 { + s.refresh(p, []rune(head+list[0]+tail), hl+utf8.RuneCountInString(list[0])) + return []rune(head + list[0] + tail), hl + utf8.RuneCountInString(list[0]), rune(esc), nil + } + + direction := tabForward + tabPrinter := s.circularTabs(list) + if s.tabStyle == TabPrints { + tabPrinter = s.printedTabs(list) + } + + for { + pick, err := tabPrinter(direction) + if err != nil { + return line, pos, rune(esc), err + } + s.refresh(p, []rune(head+pick+tail), hl+utf8.RuneCountInString(pick)) + + next, err := s.readNext() + if err != nil { + return line, pos, rune(esc), err + } + if key, ok := next.(rune); ok { + if key == tab { + direction = tabForward + continue + } + if key == esc { + return line, pos, rune(esc), nil + } + } + if a, ok := next.(action); ok && a == shiftTab { + direction = tabReverse + continue + } + return []rune(head + pick + tail), hl + utf8.RuneCountInString(pick), next, nil + } + // Not reached + return line, pos, rune(esc), nil +} + +// reverse intelligent search, implements a bash-like history search. +func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, interface{}, error) { + p := "(reverse-i-search)`': " + s.refresh([]rune(p), origLine, origPos) + + line := []rune{} + pos := 0 + foundLine := string(origLine) + foundPos := origPos + + getLine := func() ([]rune, []rune, int) { + search := string(line) + prompt := "(reverse-i-search)`%s': " + return []rune(fmt.Sprintf(prompt, search)), []rune(foundLine), foundPos + } + + history, positions := s.getHistoryByPattern(string(line)) + historyPos := len(history) - 1 + + for { + next, err := s.readNext() + if err != nil { + return []rune(foundLine), foundPos, rune(esc), err + } + + switch v := next.(type) { + case rune: + switch v { + case ctrlR: // Search backwards + if historyPos > 0 && historyPos < len(history) { + historyPos-- + foundLine = history[historyPos] + foundPos = positions[historyPos] + } else { + fmt.Print(beep) + } + case ctrlS: // Search forward + if historyPos < len(history)-1 && historyPos >= 0 { + historyPos++ + foundLine = history[historyPos] + foundPos = positions[historyPos] + } else { + fmt.Print(beep) + } + case ctrlH, bs: // Backspace + if pos <= 0 { + fmt.Print(beep) + } else { + n := len(getSuffixGlyphs(line[:pos], 1)) + line = append(line[:pos-n], line[pos:]...) + pos -= n + + // For each char deleted, display the last matching line of history + history, positions := s.getHistoryByPattern(string(line)) + historyPos = len(history) - 1 + if len(history) > 0 { + foundLine = history[historyPos] + foundPos = positions[historyPos] + } else { + foundLine = "" + foundPos = 0 + } + } + case ctrlG: // Cancel + return origLine, origPos, rune(esc), err + + case tab, cr, lf, ctrlA, ctrlB, ctrlD, ctrlE, ctrlF, ctrlK, + ctrlL, ctrlN, ctrlO, ctrlP, ctrlQ, ctrlT, ctrlU, ctrlV, ctrlW, ctrlX, ctrlY, ctrlZ: + fallthrough + case 0, ctrlC, esc, 28, 29, 30, 31: + return []rune(foundLine), foundPos, next, err + default: + line = append(line[:pos], append([]rune{v}, line[pos:]...)...) + pos++ + + // For each keystroke typed, display the last matching line of history + history, positions = s.getHistoryByPattern(string(line)) + historyPos = len(history) - 1 + if len(history) > 0 { + foundLine = history[historyPos] + foundPos = positions[historyPos] + } else { + foundLine = "" + foundPos = 0 + } + } + case action: + return []rune(foundLine), foundPos, next, err + } + s.refresh(getLine()) + } +} + +// addToKillRing adds some text to the kill ring. If mode is 0 it adds it to a +// new node in the end of the kill ring, and move the current pointer to the new +// node. If mode is 1 or 2 it appends or prepends the text to the current entry +// of the killRing. +func (s *State) addToKillRing(text []rune, mode int) { + // Don't use the same underlying array as text + killLine := make([]rune, len(text)) + copy(killLine, text) + + // Point killRing to a newNode, procedure depends on the killring state and + // append mode. + if mode == 0 { // Add new node to killRing + if s.killRing == nil { // if killring is empty, create a new one + s.killRing = ring.New(1) + } else if s.killRing.Len() >= KillRingMax { // if killring is "full" + s.killRing = s.killRing.Next() + } else { // Normal case + s.killRing.Link(ring.New(1)) + s.killRing = s.killRing.Next() + } + } else { + if s.killRing == nil { // if killring is empty, create a new one + s.killRing = ring.New(1) + s.killRing.Value = []rune{} + } + if mode == 1 { // Append to last entry + killLine = append(s.killRing.Value.([]rune), killLine...) + } else if mode == 2 { // Prepend to last entry + killLine = append(killLine, s.killRing.Value.([]rune)...) + } + } + + // Save text in the current killring node + s.killRing.Value = killLine +} + +func (s *State) yank(p []rune, text []rune, pos int) ([]rune, int, interface{}, error) { + if s.killRing == nil { + return text, pos, rune(esc), nil + } + + lineStart := text[:pos] + lineEnd := text[pos:] + var line []rune + + for { + value := s.killRing.Value.([]rune) + line = make([]rune, 0) + line = append(line, lineStart...) + line = append(line, value...) + line = append(line, lineEnd...) + + pos = len(lineStart) + len(value) + s.refresh(p, line, pos) + + next, err := s.readNext() + if err != nil { + return line, pos, next, err + } + + switch v := next.(type) { + case rune: + return line, pos, next, nil + case action: + switch v { + case altY: + s.killRing = s.killRing.Prev() + default: + return line, pos, next, nil + } + } + } + + return line, pos, esc, nil +} + +// Prompt displays p and returns a line of user input, not including a trailing +// newline character. An io.EOF error is returned if the user signals end-of-file +// by pressing Ctrl-D. Prompt allows line editing if the terminal supports it. +func (s *State) Prompt(prompt string) (string, error) { + return s.PromptWithSuggestion(prompt, "", 0) +} + +// PromptWithSuggestion displays prompt and an editable text with cursor at +// given position. The cursor will be set to the end of the line if given position +// is negative or greater than length of text. Returns a line of user input, not +// including a trailing newline character. An io.EOF error is returned if the user +// signals end-of-file by pressing Ctrl-D. +func (s *State) PromptWithSuggestion(prompt string, text string, pos int) (string, error) { + if s.inputRedirected || !s.terminalSupported { + return s.promptUnsupported(prompt) + } + if s.outputRedirected { + return "", ErrNotTerminalOutput + } + + s.historyMutex.RLock() + defer s.historyMutex.RUnlock() + + fmt.Print(prompt) + p := []rune(prompt) + var line = []rune(text) + historyEnd := "" + prefixHistory := s.getHistoryByPrefix(string(line)) + historyPos := len(prefixHistory) + historyAction := false // used to mark history related actions + killAction := 0 // used to mark kill related actions + + defer s.stopPrompt() + + if pos < 0 || len(text) < pos { + pos = len(text) + } + if len(line) > 0 { + s.refresh(p, line, pos) + } + +restart: + s.startPrompt() + s.getColumns() + +mainLoop: + for { + next, err := s.readNext() + haveNext: + if err != nil { + if s.shouldRestart != nil && s.shouldRestart(err) { + goto restart + } + return "", err + } + + historyAction = false + switch v := next.(type) { + case rune: + switch v { + case cr, lf: + if s.multiLineMode { + s.resetMultiLine(p, line, pos) + } + fmt.Println() + break mainLoop + case ctrlA: // Start of line + pos = 0 + s.refresh(p, line, pos) + case ctrlE: // End of line + pos = len(line) + s.refresh(p, line, pos) + case ctrlB: // left + if pos > 0 { + pos -= len(getSuffixGlyphs(line[:pos], 1)) + s.refresh(p, line, pos) + } else { + fmt.Print(beep) + } + case ctrlF: // right + if pos < len(line) { + pos += len(getPrefixGlyphs(line[pos:], 1)) + s.refresh(p, line, pos) + } else { + fmt.Print(beep) + } + case ctrlD: // del + if pos == 0 && len(line) == 0 { + // exit + return "", io.EOF + } + + // ctrlD is a potential EOF, so the rune reader shuts down. + // Therefore, if it isn't actually an EOF, we must re-startPrompt. + s.restartPrompt() + + if pos >= len(line) { + fmt.Print(beep) + } else { + n := len(getPrefixGlyphs(line[pos:], 1)) + line = append(line[:pos], line[pos+n:]...) + s.refresh(p, line, pos) + } + case ctrlK: // delete remainder of line + if pos >= len(line) { + fmt.Print(beep) + } else { + if killAction > 0 { + s.addToKillRing(line[pos:], 1) // Add in apend mode + } else { + s.addToKillRing(line[pos:], 0) // Add in normal mode + } + + killAction = 2 // Mark that there was a kill action + line = line[:pos] + s.refresh(p, line, pos) + } + case ctrlP: // up + historyAction = true + if historyPos > 0 { + if historyPos == len(prefixHistory) { + historyEnd = string(line) + } + historyPos-- + line = []rune(prefixHistory[historyPos]) + pos = len(line) + s.refresh(p, line, pos) + } else { + fmt.Print(beep) + } + case ctrlN: // down + historyAction = true + if historyPos < len(prefixHistory) { + historyPos++ + if historyPos == len(prefixHistory) { + line = []rune(historyEnd) + } else { + line = []rune(prefixHistory[historyPos]) + } + pos = len(line) + s.refresh(p, line, pos) + } else { + fmt.Print(beep) + } + case ctrlT: // transpose prev glyph with glyph under cursor + if len(line) < 2 || pos < 1 { + fmt.Print(beep) + } else { + if pos == len(line) { + pos -= len(getSuffixGlyphs(line, 1)) + } + prev := getSuffixGlyphs(line[:pos], 1) + next := getPrefixGlyphs(line[pos:], 1) + scratch := make([]rune, len(prev)) + copy(scratch, prev) + copy(line[pos-len(prev):], next) + copy(line[pos-len(prev)+len(next):], scratch) + pos += len(next) + s.refresh(p, line, pos) + } + case ctrlL: // clear screen + s.eraseScreen() + s.refresh(p, line, pos) + case ctrlC: // reset + fmt.Println("^C") + if s.multiLineMode { + s.resetMultiLine(p, line, pos) + } + if s.ctrlCAborts { + return "", ErrPromptAborted + } + line = line[:0] + pos = 0 + fmt.Print(prompt) + s.restartPrompt() + case ctrlH, bs: // Backspace + if pos <= 0 { + fmt.Print(beep) + } else { + n := len(getSuffixGlyphs(line[:pos], 1)) + line = append(line[:pos-n], line[pos:]...) + pos -= n + s.refresh(p, line, pos) + } + case ctrlU: // Erase line before cursor + if killAction > 0 { + s.addToKillRing(line[:pos], 2) // Add in prepend mode + } else { + s.addToKillRing(line[:pos], 0) // Add in normal mode + } + + killAction = 2 // Mark that there was some killing + line = line[pos:] + pos = 0 + s.refresh(p, line, pos) + case ctrlW: // Erase word + if pos == 0 { + fmt.Print(beep) + break + } + // Remove whitespace to the left + var buf []rune // Store the deleted chars in a buffer + for { + if pos == 0 || !unicode.IsSpace(line[pos-1]) { + break + } + buf = append(buf, line[pos-1]) + line = append(line[:pos-1], line[pos:]...) + pos-- + } + // Remove non-whitespace to the left + for { + if pos == 0 || unicode.IsSpace(line[pos-1]) { + break + } + buf = append(buf, line[pos-1]) + line = append(line[:pos-1], line[pos:]...) + pos-- + } + // Invert the buffer and save the result on the killRing + var newBuf []rune + for i := len(buf) - 1; i >= 0; i-- { + newBuf = append(newBuf, buf[i]) + } + if killAction > 0 { + s.addToKillRing(newBuf, 2) // Add in prepend mode + } else { + s.addToKillRing(newBuf, 0) // Add in normal mode + } + killAction = 2 // Mark that there was some killing + + s.refresh(p, line, pos) + case ctrlY: // Paste from Yank buffer + line, pos, next, err = s.yank(p, line, pos) + goto haveNext + case ctrlR: // Reverse Search + line, pos, next, err = s.reverseISearch(line, pos) + s.refresh(p, line, pos) + goto haveNext + case tab: // Tab completion + line, pos, next, err = s.tabComplete(p, line, pos) + goto haveNext + // Catch keys that do nothing, but you don't want them to beep + case esc: + // DO NOTHING + // Unused keys + case ctrlG, ctrlO, ctrlQ, ctrlS, ctrlV, ctrlX, ctrlZ: + fallthrough + // Catch unhandled control codes (anything <= 31) + case 0, 28, 29, 30, 31: + fmt.Print(beep) + default: + if pos == len(line) && !s.multiLineMode && countGlyphs(p)+countGlyphs(line) < s.columns-1 { + line = append(line, v) + fmt.Printf("%c", v) + pos++ + } else { + line = append(line[:pos], append([]rune{v}, line[pos:]...)...) + pos++ + s.refresh(p, line, pos) + } + } + case action: + switch v { + case del: + if pos >= len(line) { + fmt.Print(beep) + } else { + n := len(getPrefixGlyphs(line[pos:], 1)) + line = append(line[:pos], line[pos+n:]...) + } + case left: + if pos > 0 { + pos -= len(getSuffixGlyphs(line[:pos], 1)) + } else { + fmt.Print(beep) + } + case wordLeft, altB: + if pos > 0 { + var spaceHere, spaceLeft, leftKnown bool + for { + pos-- + if pos == 0 { + break + } + if leftKnown { + spaceHere = spaceLeft + } else { + spaceHere = unicode.IsSpace(line[pos]) + } + spaceLeft, leftKnown = unicode.IsSpace(line[pos-1]), true + if !spaceHere && spaceLeft { + break + } + } + } else { + fmt.Print(beep) + } + case right: + if pos < len(line) { + pos += len(getPrefixGlyphs(line[pos:], 1)) + } else { + fmt.Print(beep) + } + case wordRight, altF: + if pos < len(line) { + var spaceHere, spaceLeft, hereKnown bool + for { + pos++ + if pos == len(line) { + break + } + if hereKnown { + spaceLeft = spaceHere + } else { + spaceLeft = unicode.IsSpace(line[pos-1]) + } + spaceHere, hereKnown = unicode.IsSpace(line[pos]), true + if spaceHere && !spaceLeft { + break + } + } + } else { + fmt.Print(beep) + } + case up: + historyAction = true + if historyPos > 0 { + if historyPos == len(prefixHistory) { + historyEnd = string(line) + } + historyPos-- + line = []rune(prefixHistory[historyPos]) + pos = len(line) + } else { + fmt.Print(beep) + } + case down: + historyAction = true + if historyPos < len(prefixHistory) { + historyPos++ + if historyPos == len(prefixHistory) { + line = []rune(historyEnd) + } else { + line = []rune(prefixHistory[historyPos]) + } + pos = len(line) + } else { + fmt.Print(beep) + } + case home: // Start of line + pos = 0 + case end: // End of line + pos = len(line) + case winch: // Window change + if s.multiLineMode { + if s.maxRows-s.cursorRows > 0 { + s.moveDown(s.maxRows - s.cursorRows) + } + for i := 0; i < s.maxRows-1; i++ { + s.cursorPos(0) + s.eraseLine() + s.moveUp(1) + } + s.maxRows = 1 + s.cursorRows = 1 + } + } + s.refresh(p, line, pos) + } + if !historyAction { + prefixHistory = s.getHistoryByPrefix(string(line)) + historyPos = len(prefixHistory) + } + if killAction > 0 { + killAction-- + } + } + return string(line), nil +} + +// PasswordPrompt displays p, and then waits for user input. The input typed by +// the user is not displayed in the terminal. +func (s *State) PasswordPrompt(prompt string) (string, error) { + if !s.terminalSupported { + return "", errors.New("liner: function not supported in this terminal") + } + if s.inputRedirected { + return s.promptUnsupported(prompt) + } + if s.outputRedirected { + return "", ErrNotTerminalOutput + } + + defer s.stopPrompt() + +restart: + s.startPrompt() + s.getColumns() + + fmt.Print(prompt) + p := []rune(prompt) + var line []rune + pos := 0 + +mainLoop: + for { + next, err := s.readNext() + if err != nil { + if s.shouldRestart != nil && s.shouldRestart(err) { + goto restart + } + return "", err + } + + switch v := next.(type) { + case rune: + switch v { + case cr, lf: + if s.multiLineMode { + s.resetMultiLine(p, line, pos) + } + fmt.Println() + break mainLoop + case ctrlD: // del + if pos == 0 && len(line) == 0 { + // exit + return "", io.EOF + } + + // ctrlD is a potential EOF, so the rune reader shuts down. + // Therefore, if it isn't actually an EOF, we must re-startPrompt. + s.restartPrompt() + case ctrlL: // clear screen + s.eraseScreen() + s.refresh(p, []rune{}, 0) + case ctrlH, bs: // Backspace + if pos <= 0 { + fmt.Print(beep) + } else { + n := len(getSuffixGlyphs(line[:pos], 1)) + line = append(line[:pos-n], line[pos:]...) + pos -= n + } + case ctrlC: + fmt.Println("^C") + if s.multiLineMode { + s.resetMultiLine(p, line, pos) + } + if s.ctrlCAborts { + return "", ErrPromptAborted + } + line = line[:0] + pos = 0 + fmt.Print(prompt) + s.restartPrompt() + // Unused keys + case esc, tab, ctrlA, ctrlB, ctrlE, ctrlF, ctrlG, ctrlK, ctrlN, ctrlO, ctrlP, ctrlQ, ctrlR, ctrlS, + ctrlT, ctrlU, ctrlV, ctrlW, ctrlX, ctrlY, ctrlZ: + fallthrough + // Catch unhandled control codes (anything <= 31) + case 0, 28, 29, 30, 31: + fmt.Print(beep) + default: + line = append(line[:pos], append([]rune{v}, line[pos:]...)...) + pos++ + } + } + } + return string(line), nil +} diff --git a/vendor/github.com/peterh/liner/output.go b/vendor/github.com/peterh/liner/output.go new file mode 100644 index 0000000..6d83d4e --- /dev/null +++ b/vendor/github.com/peterh/liner/output.go @@ -0,0 +1,79 @@ +// +build linux darwin openbsd freebsd netbsd + +package liner + +import ( + "fmt" + "os" + "strings" + "syscall" + "unsafe" +) + +func (s *State) cursorPos(x int) { + if s.useCHA { + // 'G' is "Cursor Character Absolute (CHA)" + fmt.Printf("\x1b[%dG", x+1) + } else { + // 'C' is "Cursor Forward (CUF)" + fmt.Print("\r") + if x > 0 { + fmt.Printf("\x1b[%dC", x) + } + } +} + +func (s *State) eraseLine() { + fmt.Print("\x1b[0K") +} + +func (s *State) eraseScreen() { + fmt.Print("\x1b[H\x1b[2J") +} + +func (s *State) moveUp(lines int) { + fmt.Printf("\x1b[%dA", lines) +} + +func (s *State) moveDown(lines int) { + fmt.Printf("\x1b[%dB", lines) +} + +func (s *State) emitNewLine() { + fmt.Print("\n") +} + +type winSize struct { + row, col uint16 + xpixel, ypixel uint16 +} + +func (s *State) getColumns() bool { + var ws winSize + ok, _, _ := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdout), + syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))) + if int(ok) < 0 { + return false + } + s.columns = int(ws.col) + if cursorColumn && s.columns > 1 { + s.columns-- + } + return true +} + +func (s *State) checkOutput() { + // xterm is known to support CHA + if strings.Contains(strings.ToLower(os.Getenv("TERM")), "xterm") { + s.useCHA = true + return + } + + // The test for functional ANSI CHA is unreliable (eg the Windows + // telnet command does not support reading the cursor position with + // an ANSI DSR request, despite setting TERM=ansi) + + // Assume CHA isn't supported (which should be safe, although it + // does result in occasional visible cursor jitter) + s.useCHA = false +} diff --git a/vendor/github.com/peterh/liner/output_windows.go b/vendor/github.com/peterh/liner/output_windows.go new file mode 100644 index 0000000..63c9c5d --- /dev/null +++ b/vendor/github.com/peterh/liner/output_windows.go @@ -0,0 +1,76 @@ +package liner + +import ( + "unsafe" +) + +type coord struct { + x, y int16 +} +type smallRect struct { + left, top, right, bottom int16 +} + +type consoleScreenBufferInfo struct { + dwSize coord + dwCursorPosition coord + wAttributes int16 + srWindow smallRect + dwMaximumWindowSize coord +} + +func (s *State) cursorPos(x int) { + var sbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi))) + procSetConsoleCursorPosition.Call(uintptr(s.hOut), + uintptr(int(x)&0xFFFF|int(sbi.dwCursorPosition.y)<<16)) +} + +func (s *State) eraseLine() { + var sbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi))) + var numWritten uint32 + procFillConsoleOutputCharacter.Call(uintptr(s.hOut), uintptr(' '), + uintptr(sbi.dwSize.x-sbi.dwCursorPosition.x), + uintptr(int(sbi.dwCursorPosition.x)&0xFFFF|int(sbi.dwCursorPosition.y)<<16), + uintptr(unsafe.Pointer(&numWritten))) +} + +func (s *State) eraseScreen() { + var sbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi))) + var numWritten uint32 + procFillConsoleOutputCharacter.Call(uintptr(s.hOut), uintptr(' '), + uintptr(sbi.dwSize.x)*uintptr(sbi.dwSize.y), + 0, + uintptr(unsafe.Pointer(&numWritten))) + procSetConsoleCursorPosition.Call(uintptr(s.hOut), 0) +} + +func (s *State) moveUp(lines int) { + var sbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi))) + procSetConsoleCursorPosition.Call(uintptr(s.hOut), + uintptr(int(sbi.dwCursorPosition.x)&0xFFFF|(int(sbi.dwCursorPosition.y)-lines)<<16)) +} + +func (s *State) moveDown(lines int) { + var sbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi))) + procSetConsoleCursorPosition.Call(uintptr(s.hOut), + uintptr(int(sbi.dwCursorPosition.x)&0xFFFF|(int(sbi.dwCursorPosition.y)+lines)<<16)) +} + +func (s *State) emitNewLine() { + // windows doesn't need to omit a new line +} + +func (s *State) getColumns() { + var sbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi))) + s.columns = int(sbi.dwSize.x) + if s.columns > 1 { + // Windows 10 needs a spare column for the cursor + s.columns-- + } +} diff --git a/vendor/github.com/peterh/liner/signal.go b/vendor/github.com/peterh/liner/signal.go new file mode 100644 index 0000000..0cba79e --- /dev/null +++ b/vendor/github.com/peterh/liner/signal.go @@ -0,0 +1,12 @@ +// +build go1.1,!windows + +package liner + +import ( + "os" + "os/signal" +) + +func stopSignal(c chan<- os.Signal) { + signal.Stop(c) +} diff --git a/vendor/github.com/peterh/liner/signal_legacy.go b/vendor/github.com/peterh/liner/signal_legacy.go new file mode 100644 index 0000000..fa3672d --- /dev/null +++ b/vendor/github.com/peterh/liner/signal_legacy.go @@ -0,0 +1,11 @@ +// +build !go1.1,!windows + +package liner + +import ( + "os" +) + +func stopSignal(c chan<- os.Signal) { + // signal.Stop does not exist before Go 1.1 +} diff --git a/vendor/github.com/peterh/liner/unixmode.go b/vendor/github.com/peterh/liner/unixmode.go new file mode 100644 index 0000000..9838923 --- /dev/null +++ b/vendor/github.com/peterh/liner/unixmode.go @@ -0,0 +1,37 @@ +// +build linux darwin freebsd openbsd netbsd + +package liner + +import ( + "syscall" + "unsafe" +) + +func (mode *termios) ApplyMode() error { + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), setTermios, uintptr(unsafe.Pointer(mode))) + + if errno != 0 { + return errno + } + return nil +} + +// TerminalMode returns the current terminal input mode as an InputModeSetter. +// +// This function is provided for convenience, and should +// not be necessary for most users of liner. +func TerminalMode() (ModeApplier, error) { + mode, errno := getMode(syscall.Stdin) + + if errno != 0 { + return nil, errno + } + return mode, nil +} + +func getMode(handle int) (*termios, syscall.Errno) { + var mode termios + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(handle), getTermios, uintptr(unsafe.Pointer(&mode))) + + return &mode, errno +} diff --git a/vendor/github.com/peterh/liner/width.go b/vendor/github.com/peterh/liner/width.go new file mode 100644 index 0000000..d8984aa --- /dev/null +++ b/vendor/github.com/peterh/liner/width.go @@ -0,0 +1,79 @@ +package liner + +import "unicode" + +// These character classes are mostly zero width (when combined). +// A few might not be, depending on the user's font. Fixing this +// is non-trivial, given that some terminals don't support +// ANSI DSR/CPR +var zeroWidth = []*unicode.RangeTable{ + unicode.Mn, + unicode.Me, + unicode.Cc, + unicode.Cf, +} + +var doubleWidth = []*unicode.RangeTable{ + unicode.Han, + unicode.Hangul, + unicode.Hiragana, + unicode.Katakana, +} + +// countGlyphs considers zero-width characters to be zero glyphs wide, +// and members of Chinese, Japanese, and Korean scripts to be 2 glyphs wide. +func countGlyphs(s []rune) int { + n := 0 + for _, r := range s { + switch { + case unicode.IsOneOf(zeroWidth, r): + case unicode.IsOneOf(doubleWidth, r): + n += 2 + default: + n++ + } + } + return n +} + +func countMultiLineGlyphs(s []rune, columns int, start int) int { + n := start + for _, r := range s { + switch { + case unicode.IsOneOf(zeroWidth, r): + case unicode.IsOneOf(doubleWidth, r): + n += 2 + // no room for a 2-glyphs-wide char in the ending + // so skip a column and display it at the beginning + if n%columns == 1 { + n++ + } + default: + n++ + } + } + return n +} + +func getPrefixGlyphs(s []rune, num int) []rune { + p := 0 + for n := 0; n < num && p < len(s); p++ { + if !unicode.IsOneOf(zeroWidth, s[p]) { + n++ + } + } + for p < len(s) && unicode.IsOneOf(zeroWidth, s[p]) { + p++ + } + return s[:p] +} + +func getSuffixGlyphs(s []rune, num int) []rune { + p := len(s) + for n := 0; n < num && p > 0; p-- { + if !unicode.IsOneOf(zeroWidth, s[p-1]) { + n++ + } + } + return s[p:] +} diff --git a/vendor/golang.org/x/debug/LICENSE b/vendor/golang.org/x/debug/LICENSE new file mode 100644 index 0000000..a2dd15f --- /dev/null +++ b/vendor/golang.org/x/debug/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/debug/dwarf/buf.go b/vendor/golang.org/x/debug/dwarf/buf.go new file mode 100644 index 0000000..73fcc9a --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/buf.go @@ -0,0 +1,203 @@ +// 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. + +// Buffered reading and decoding of DWARF data streams. + +package dwarf + +import ( + "encoding/binary" + "fmt" + "strconv" +) + +// Data buffer being decoded. +type buf struct { + dwarf *Data + order binary.ByteOrder + format dataFormat + name string + off Offset + data []byte + err error +} + +// Data format, other than byte order. This affects the handling of +// certain field formats. +type dataFormat interface { + // DWARF version number. Zero means unknown. + version() int + + // 64-bit DWARF format? + dwarf64() (dwarf64 bool, isKnown bool) + + // Size of an address, in bytes. Zero means unknown. + addrsize() int +} + +// Some parts of DWARF have no data format, e.g., abbrevs. +type unknownFormat struct{} + +func (u unknownFormat) version() int { + return 0 +} + +func (u unknownFormat) dwarf64() (bool, bool) { + return false, false +} + +func (u unknownFormat) addrsize() int { + return 0 +} + +func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf { + return buf{d, d.order, format, name, off, data, nil} +} + +func (b *buf) slice(length int) buf { + n := *b + data := b.data + b.skip(length) // Will validate length. + n.data = data[:length] + return n +} + +func (b *buf) uint8() uint8 { + if len(b.data) < 1 { + b.error("underflow") + return 0 + } + val := b.data[0] + b.data = b.data[1:] + b.off++ + return val +} + +func (b *buf) bytes(n int) []byte { + if len(b.data) < n { + b.error("underflow") + return nil + } + data := b.data[0:n] + b.data = b.data[n:] + b.off += Offset(n) + return data +} + +func (b *buf) skip(n int) { b.bytes(n) } + +// string returns the NUL-terminated (C-like) string at the start of the buffer. +// The terminal NUL is discarded. +func (b *buf) string() string { + for i := 0; i < len(b.data); i++ { + if b.data[i] == 0 { + s := string(b.data[0:i]) + b.data = b.data[i+1:] + b.off += Offset(i + 1) + return s + } + } + b.error("underflow") + return "" +} + +func (b *buf) uint16() uint16 { + a := b.bytes(2) + if a == nil { + return 0 + } + return b.order.Uint16(a) +} + +func (b *buf) uint32() uint32 { + a := b.bytes(4) + if a == nil { + return 0 + } + return b.order.Uint32(a) +} + +func (b *buf) uint64() uint64 { + a := b.bytes(8) + if a == nil { + return 0 + } + return b.order.Uint64(a) +} + +// Read a varint, which is 7 bits per byte, little endian. +// the 0x80 bit means read another byte. +func (b *buf) varint() (c uint64, bits uint) { + for i := 0; i < len(b.data); i++ { + byte := b.data[i] + c |= uint64(byte&0x7F) << bits + bits += 7 + if byte&0x80 == 0 { + b.off += Offset(i + 1) + b.data = b.data[i+1:] + return c, bits + } + } + return 0, 0 +} + +// Unsigned int is just a varint. +func (b *buf) uint() uint64 { + x, _ := b.varint() + return x +} + +// Signed int is a sign-extended varint. +func (b *buf) int() int64 { + ux, bits := b.varint() + x := int64(ux) + if x&(1<<(bits-1)) != 0 { + x |= -1 << bits + } + return x +} + +// Address-sized uint. +func (b *buf) addr() uint64 { + switch b.format.addrsize() { + case 1: + return uint64(b.uint8()) + case 2: + return uint64(b.uint16()) + case 4: + return uint64(b.uint32()) + case 8: + return uint64(b.uint64()) + } + b.error("unknown address size") + return 0 +} + +// assertEmpty checks that everything has been read from b. +func (b *buf) assertEmpty() { + if len(b.data) == 0 { + return + } + if len(b.data) > 5 { + b.error(fmt.Sprintf("unexpected extra data: %x...", b.data[0:5])) + } + b.error(fmt.Sprintf("unexpected extra data: %x", b.data)) +} + +func (b *buf) error(s string) { + if b.err == nil { + b.data = nil + b.err = DecodeError{b.name, b.off, s} + } +} + +type DecodeError struct { + Name string + Offset Offset + Err string +} + +func (e DecodeError) Error() string { + return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err +} diff --git a/vendor/golang.org/x/debug/dwarf/cache.go b/vendor/golang.org/x/debug/dwarf/cache.go new file mode 100644 index 0000000..cf795e7 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/cache.go @@ -0,0 +1,249 @@ +// Copyright 2016 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 dwarf + +import ( + "sort" +) + +// pcToFuncEntries maps PC ranges to function entries. +// +// Each element contains a *Entry for a function and its corresponding start PC. +// If we know the address one past the last instruction of a function, and it is +// not equal to the start address of the next function, we mark that with +// another element containing that address and a nil entry. The elements are +// sorted by PC. Among elements with the same PC, those with non-nil *Entry +// are put earlier. +type pcToFuncEntries []pcToFuncEntry +type pcToFuncEntry struct { + pc uint64 + entry *Entry +} + +func (p pcToFuncEntries) Len() int { return len(p) } +func (p pcToFuncEntries) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p pcToFuncEntries) Less(i, j int) bool { + if p[i].pc != p[j].pc { + return p[i].pc < p[j].pc + } + return p[i].entry != nil && p[j].entry == nil +} + +// nameCache maps each symbol name to a linked list of the entries with that name. +type nameCache map[string]*nameCacheEntry +type nameCacheEntry struct { + entry *Entry + link *nameCacheEntry +} + +// pcToLineEntries maps PCs to line numbers. +// +// It is a slice of (PC, line, file number) triples, sorted by PC. The file +// number is an index into the source files slice. +// If (PC1, line1, file1) and (PC2, line2, file2) are two consecutive elements, +// then the span of addresses [PC1, PC2) belongs to (line1, file1). If an +// element's file number is zero, it only marks the end of a span. +// +// TODO: could save memory by changing pcToLineEntries and lineToPCEntries to use +// interval trees containing references into .debug_line. +type pcToLineEntries []pcToLineEntry +type pcToLineEntry struct { + pc uint64 + line uint64 + file uint64 +} + +func (p pcToLineEntries) Len() int { return len(p) } +func (p pcToLineEntries) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p pcToLineEntries) Less(i, j int) bool { + if p[i].pc != p[j].pc { + return p[i].pc < p[j].pc + } + return p[i].file > p[j].file +} + +// byFileLine is used temporarily while building lineToPCEntries. +type byFileLine []pcToLineEntry + +func (b byFileLine) Len() int { return len(b) } +func (b byFileLine) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b byFileLine) Less(i, j int) bool { + if b[i].file != b[j].file { + return b[i].file < b[j].file + } + return b[i].line < b[j].line +} + +// lineToPCEntries maps line numbers to breakpoint addresses. +// +// The slice contains, for each source file in Data, a slice of (line, PC) +// pairs, sorted by line. Note that there may be more than one PC for a line. +type lineToPCEntries [][]lineToPCEntry +type lineToPCEntry struct { + line uint64 + pc uint64 +} + +func (d *Data) buildLineToPCCache(pclfs pcToLineEntries) { + // TODO: only include lines where is_stmt is true + sort.Sort(byFileLine(pclfs)) + // Make a slice of (line, PC) pairs for each (non-zero) file. + var ( + c = make(lineToPCEntries, len(d.sourceFiles)) + curSlice []lineToPCEntry + ) + for i, pclf := range pclfs { + if pclf.file == 0 { + // This entry indicated the end of an instruction sequence, not a breakpoint. + continue + } + curSlice = append(curSlice, lineToPCEntry{line: pclf.line, pc: pclf.pc}) + if i+1 == len(pclfs) || pclf.file != pclfs[i+1].file { + // curSlice now contains all of the entries for pclf.file. + if pclf.file > 0 && pclf.file < uint64(len(c)) { + c[pclf.file] = curSlice + } + curSlice = nil + } + } + d.lineToPCEntries = c +} + +func (d *Data) buildPCToLineCache(cache pcToLineEntries) { + // Sort cache by PC (in increasing order), then by file number (in decreasing order). + sort.Sort(cache) + + // Build a copy without redundant entries. + var out pcToLineEntries + for i, pclf := range cache { + if i > 0 && pclf.pc == cache[i-1].pc { + // This entry is for the same PC as the previous entry. + continue + } + if i > 0 && pclf.file == cache[i-1].file && pclf.line == cache[i-1].line { + // This entry is for the same file and line as the previous entry. + continue + } + out = append(out, pclf) + } + d.pcToLineEntries = out +} + +// buildLineCaches constructs d.sourceFiles, d.lineToPCEntries, d.pcToLineEntries. +func (d *Data) buildLineCaches() { + if len(d.line) == 0 { + return + } + var m lineMachine + // Assume the address_size in the first unit applies to the whole program. + // TODO: we could handle executables containing code for multiple address + // sizes using DW_AT_stmt_list attributes. + if len(d.unit) == 0 { + return + } + buf := makeBuf(d, &d.unit[0], "line", 0, d.line) + if err := m.parseHeader(&buf); err != nil { + return + } + for _, f := range m.header.file { + d.sourceFiles = append(d.sourceFiles, f.name) + } + var cache pcToLineEntries + fn := func(m *lineMachine) bool { + if m.endSequence { + cache = append(cache, pcToLineEntry{ + pc: m.address, + line: 0, + file: 0, + }) + } else { + cache = append(cache, pcToLineEntry{ + pc: m.address, + line: m.line, + file: m.file, + }) + } + return true + } + m.evalCompilationUnit(&buf, fn) + d.buildLineToPCCache(cache) + d.buildPCToLineCache(cache) +} + +// buildInfoCaches initializes nameCache and pcToFuncEntries by walking the +// top-level entries under each compile unit. It swallows any errors in parsing. +func (d *Data) buildInfoCaches() { + // TODO: record errors somewhere? + d.nameCache = make(map[string]*nameCacheEntry) + + var pcToFuncEntries pcToFuncEntries + + r := d.Reader() +loop: + for { + entry, err := r.Next() + if entry == nil || err != nil { + break loop + } + if entry.Tag != TagCompileUnit /* DW_TAG_compile_unit */ { + r.SkipChildren() + continue + } + for { + entry, err := r.Next() + if entry == nil || err != nil { + break loop + } + if entry.Tag == 0 { + // End of children of current compile unit. + break + } + r.SkipChildren() + // Update name-to-entry cache. + if name, ok := entry.Val(AttrName).(string); ok { + d.nameCache[name] = &nameCacheEntry{entry: entry, link: d.nameCache[name]} + } + + // If this entry is a function, update PC-to-containing-function cache. + if entry.Tag != TagSubprogram /* DW_TAG_subprogram */ { + continue + } + + // DW_AT_low_pc, if present, is the address of the first instruction of + // the function. + lowpc, ok := entry.Val(AttrLowpc).(uint64) + if !ok { + continue + } + pcToFuncEntries = append(pcToFuncEntries, pcToFuncEntry{lowpc, entry}) + + // DW_AT_high_pc, if present (TODO: and of class address) is the address + // one past the last instruction of the function. + highpc, ok := entry.Val(AttrHighpc).(uint64) + if !ok { + continue + } + pcToFuncEntries = append(pcToFuncEntries, pcToFuncEntry{highpc, nil}) + } + } + // Sort elements by PC. If there are multiple elements with the same PC, + // those with non-nil *Entry are placed earlier. + sort.Sort(pcToFuncEntries) + + // Copy only the first element for each PC to out. + n := 0 + for i, ce := range pcToFuncEntries { + if i == 0 || ce.pc != pcToFuncEntries[i-1].pc { + n++ + } + } + out := make([]pcToFuncEntry, 0, n) + for i, ce := range pcToFuncEntries { + if i == 0 || ce.pc != pcToFuncEntries[i-1].pc { + out = append(out, ce) + } + } + d.pcToFuncEntries = out +} diff --git a/vendor/golang.org/x/debug/dwarf/const.go b/vendor/golang.org/x/debug/dwarf/const.go new file mode 100644 index 0000000..454f789 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/const.go @@ -0,0 +1,467 @@ +// 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. + +// Constants + +package dwarf + +import "strconv" + +// An Attr identifies the attribute type in a DWARF Entry's Field. +type Attr uint32 + +const ( + AttrSibling Attr = 0x01 + AttrLocation Attr = 0x02 + AttrName Attr = 0x03 + AttrOrdering Attr = 0x09 + AttrByteSize Attr = 0x0B + AttrBitOffset Attr = 0x0C + AttrBitSize Attr = 0x0D + AttrStmtList Attr = 0x10 + AttrLowpc Attr = 0x11 + AttrHighpc Attr = 0x12 + AttrLanguage Attr = 0x13 + AttrDiscr Attr = 0x15 + AttrDiscrValue Attr = 0x16 + AttrVisibility Attr = 0x17 + AttrImport Attr = 0x18 + AttrStringLength Attr = 0x19 + AttrCommonRef Attr = 0x1A + AttrCompDir Attr = 0x1B + AttrConstValue Attr = 0x1C + AttrContainingType Attr = 0x1D + AttrDefaultValue Attr = 0x1E + AttrInline Attr = 0x20 + AttrIsOptional Attr = 0x21 + AttrLowerBound Attr = 0x22 + AttrProducer Attr = 0x25 + AttrPrototyped Attr = 0x27 + AttrReturnAddr Attr = 0x2A + AttrStartScope Attr = 0x2C + AttrStrideSize Attr = 0x2E + AttrUpperBound Attr = 0x2F + AttrAbstractOrigin Attr = 0x31 + AttrAccessibility Attr = 0x32 + AttrAddrClass Attr = 0x33 + AttrArtificial Attr = 0x34 + AttrBaseTypes Attr = 0x35 + AttrCalling Attr = 0x36 + AttrCount Attr = 0x37 + AttrDataMemberLoc Attr = 0x38 + AttrDeclColumn Attr = 0x39 + AttrDeclFile Attr = 0x3A + AttrDeclLine Attr = 0x3B + AttrDeclaration Attr = 0x3C + AttrDiscrList Attr = 0x3D + AttrEncoding Attr = 0x3E + AttrExternal Attr = 0x3F + AttrFrameBase Attr = 0x40 + AttrFriend Attr = 0x41 + AttrIdentifierCase Attr = 0x42 + AttrMacroInfo Attr = 0x43 + AttrNamelistItem Attr = 0x44 + AttrPriority Attr = 0x45 + AttrSegment Attr = 0x46 + AttrSpecification Attr = 0x47 + AttrStaticLink Attr = 0x48 + AttrType Attr = 0x49 + AttrUseLocation Attr = 0x4A + AttrVarParam Attr = 0x4B + AttrVirtuality Attr = 0x4C + AttrVtableElemLoc Attr = 0x4D + AttrAllocated Attr = 0x4E + AttrAssociated Attr = 0x4F + AttrDataLocation Attr = 0x50 + AttrStride Attr = 0x51 + AttrEntrypc Attr = 0x52 + AttrUseUTF8 Attr = 0x53 + AttrExtension Attr = 0x54 + AttrRanges Attr = 0x55 + AttrTrampoline Attr = 0x56 + AttrCallColumn Attr = 0x57 + AttrCallFile Attr = 0x58 + AttrCallLine Attr = 0x59 + AttrDescription Attr = 0x5A + + // Go-specific attributes. + AttrGoKind Attr = 0x2900 + AttrGoKey Attr = 0x2901 + AttrGoElem Attr = 0x2902 +) + +var attrNames = [...]string{ + AttrSibling: "Sibling", + AttrLocation: "Location", + AttrName: "Name", + AttrOrdering: "Ordering", + AttrByteSize: "ByteSize", + AttrBitOffset: "BitOffset", + AttrBitSize: "BitSize", + AttrStmtList: "StmtList", + AttrLowpc: "Lowpc", + AttrHighpc: "Highpc", + AttrLanguage: "Language", + AttrDiscr: "Discr", + AttrDiscrValue: "DiscrValue", + AttrVisibility: "Visibility", + AttrImport: "Import", + AttrStringLength: "StringLength", + AttrCommonRef: "CommonRef", + AttrCompDir: "CompDir", + AttrConstValue: "ConstValue", + AttrContainingType: "ContainingType", + AttrDefaultValue: "DefaultValue", + AttrInline: "Inline", + AttrIsOptional: "IsOptional", + AttrLowerBound: "LowerBound", + AttrProducer: "Producer", + AttrPrototyped: "Prototyped", + AttrReturnAddr: "ReturnAddr", + AttrStartScope: "StartScope", + AttrStrideSize: "StrideSize", + AttrUpperBound: "UpperBound", + AttrAbstractOrigin: "AbstractOrigin", + AttrAccessibility: "Accessibility", + AttrAddrClass: "AddrClass", + AttrArtificial: "Artificial", + AttrBaseTypes: "BaseTypes", + AttrCalling: "Calling", + AttrCount: "Count", + AttrDataMemberLoc: "DataMemberLoc", + AttrDeclColumn: "DeclColumn", + AttrDeclFile: "DeclFile", + AttrDeclLine: "DeclLine", + AttrDeclaration: "Declaration", + AttrDiscrList: "DiscrList", + AttrEncoding: "Encoding", + AttrExternal: "External", + AttrFrameBase: "FrameBase", + AttrFriend: "Friend", + AttrIdentifierCase: "IdentifierCase", + AttrMacroInfo: "MacroInfo", + AttrNamelistItem: "NamelistItem", + AttrPriority: "Priority", + AttrSegment: "Segment", + AttrSpecification: "Specification", + AttrStaticLink: "StaticLink", + AttrType: "Type", + AttrUseLocation: "UseLocation", + AttrVarParam: "VarParam", + AttrVirtuality: "Virtuality", + AttrVtableElemLoc: "VtableElemLoc", + AttrAllocated: "Allocated", + AttrAssociated: "Associated", + AttrDataLocation: "DataLocation", + AttrStride: "Stride", + AttrEntrypc: "Entrypc", + AttrUseUTF8: "UseUTF8", + AttrExtension: "Extension", + AttrRanges: "Ranges", + AttrTrampoline: "Trampoline", + AttrCallColumn: "CallColumn", + AttrCallFile: "CallFile", + AttrCallLine: "CallLine", + AttrDescription: "Description", +} + +func (a Attr) String() string { + if int(a) < len(attrNames) { + s := attrNames[a] + if s != "" { + return s + } + } + switch a { + case AttrGoKind: + return "GoKind" + case AttrGoKey: + return "GoKey" + case AttrGoElem: + return "GoElem" + } + return strconv.Itoa(int(a)) +} + +func (a Attr) GoString() string { + if int(a) < len(attrNames) { + s := attrNames[a] + if s != "" { + return "dwarf.Attr" + s + } + } + return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")" +} + +// A format is a DWARF data encoding format. +type format uint32 + +const ( + // value formats + formAddr format = 0x01 + formDwarfBlock2 format = 0x03 + formDwarfBlock4 format = 0x04 + formData2 format = 0x05 + formData4 format = 0x06 + formData8 format = 0x07 + formString format = 0x08 + formDwarfBlock format = 0x09 + formDwarfBlock1 format = 0x0A + formData1 format = 0x0B + formFlag format = 0x0C + formSdata format = 0x0D + formStrp format = 0x0E + formUdata format = 0x0F + formRefAddr format = 0x10 + formRef1 format = 0x11 + formRef2 format = 0x12 + formRef4 format = 0x13 + formRef8 format = 0x14 + formRefUdata format = 0x15 + formIndirect format = 0x16 + // The following are new in DWARF 4. + formSecOffset format = 0x17 + formExprloc format = 0x18 + formFlagPresent format = 0x19 + formRefSig8 format = 0x20 + // Extensions for multi-file compression (.dwz) + // http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 + formGnuRefAlt format = 0x1f20 + formGnuStrpAlt format = 0x1f21 +) + +// A Tag is the classification (the type) of an Entry. +type Tag uint32 + +const ( + TagArrayType Tag = 0x01 + TagClassType Tag = 0x02 + TagEntryPoint Tag = 0x03 + TagEnumerationType Tag = 0x04 + TagFormalParameter Tag = 0x05 + TagImportedDeclaration Tag = 0x08 + TagLabel Tag = 0x0A + TagLexDwarfBlock Tag = 0x0B + TagMember Tag = 0x0D + TagPointerType Tag = 0x0F + TagReferenceType Tag = 0x10 + TagCompileUnit Tag = 0x11 + TagStringType Tag = 0x12 + TagStructType Tag = 0x13 + TagSubroutineType Tag = 0x15 + TagTypedef Tag = 0x16 + TagUnionType Tag = 0x17 + TagUnspecifiedParameters Tag = 0x18 + TagVariant Tag = 0x19 + TagCommonDwarfBlock Tag = 0x1A + TagCommonInclusion Tag = 0x1B + TagInheritance Tag = 0x1C + TagInlinedSubroutine Tag = 0x1D + TagModule Tag = 0x1E + TagPtrToMemberType Tag = 0x1F + TagSetType Tag = 0x20 + TagSubrangeType Tag = 0x21 + TagWithStmt Tag = 0x22 + TagAccessDeclaration Tag = 0x23 + TagBaseType Tag = 0x24 + TagCatchDwarfBlock Tag = 0x25 + TagConstType Tag = 0x26 + TagConstant Tag = 0x27 + TagEnumerator Tag = 0x28 + TagFileType Tag = 0x29 + TagFriend Tag = 0x2A + TagNamelist Tag = 0x2B + TagNamelistItem Tag = 0x2C + TagPackedType Tag = 0x2D + TagSubprogram Tag = 0x2E + TagTemplateTypeParameter Tag = 0x2F + TagTemplateValueParameter Tag = 0x30 + TagThrownType Tag = 0x31 + TagTryDwarfBlock Tag = 0x32 + TagVariantPart Tag = 0x33 + TagVariable Tag = 0x34 + TagVolatileType Tag = 0x35 + // The following are new in DWARF 3. + TagDwarfProcedure Tag = 0x36 + TagRestrictType Tag = 0x37 + TagInterfaceType Tag = 0x38 + TagNamespace Tag = 0x39 + TagImportedModule Tag = 0x3A + TagUnspecifiedType Tag = 0x3B + TagPartialUnit Tag = 0x3C + TagImportedUnit Tag = 0x3D + TagMutableType Tag = 0x3E // Later removed from DWARF. + TagCondition Tag = 0x3F + TagSharedType Tag = 0x40 + // The following are new in DWARF 4. + TagTypeUnit Tag = 0x41 + TagRvalueReferenceType Tag = 0x42 + TagTemplateAlias Tag = 0x43 +) + +var tagNames = [...]string{ + TagArrayType: "ArrayType", + TagClassType: "ClassType", + TagEntryPoint: "EntryPoint", + TagEnumerationType: "EnumerationType", + TagFormalParameter: "FormalParameter", + TagImportedDeclaration: "ImportedDeclaration", + TagLabel: "Label", + TagLexDwarfBlock: "LexDwarfBlock", + TagMember: "Member", + TagPointerType: "PointerType", + TagReferenceType: "ReferenceType", + TagCompileUnit: "CompileUnit", + TagStringType: "StringType", + TagStructType: "StructType", + TagSubroutineType: "SubroutineType", + TagTypedef: "Typedef", + TagUnionType: "UnionType", + TagUnspecifiedParameters: "UnspecifiedParameters", + TagVariant: "Variant", + TagCommonDwarfBlock: "CommonDwarfBlock", + TagCommonInclusion: "CommonInclusion", + TagInheritance: "Inheritance", + TagInlinedSubroutine: "InlinedSubroutine", + TagModule: "Module", + TagPtrToMemberType: "PtrToMemberType", + TagSetType: "SetType", + TagSubrangeType: "SubrangeType", + TagWithStmt: "WithStmt", + TagAccessDeclaration: "AccessDeclaration", + TagBaseType: "BaseType", + TagCatchDwarfBlock: "CatchDwarfBlock", + TagConstType: "ConstType", + TagConstant: "Constant", + TagEnumerator: "Enumerator", + TagFileType: "FileType", + TagFriend: "Friend", + TagNamelist: "Namelist", + TagNamelistItem: "NamelistItem", + TagPackedType: "PackedType", + TagSubprogram: "Subprogram", + TagTemplateTypeParameter: "TemplateTypeParameter", + TagTemplateValueParameter: "TemplateValueParameter", + TagThrownType: "ThrownType", + TagTryDwarfBlock: "TryDwarfBlock", + TagVariantPart: "VariantPart", + TagVariable: "Variable", + TagVolatileType: "VolatileType", + TagDwarfProcedure: "DwarfProcedure", + TagRestrictType: "RestrictType", + TagInterfaceType: "InterfaceType", + TagNamespace: "Namespace", + TagImportedModule: "ImportedModule", + TagUnspecifiedType: "UnspecifiedType", + TagPartialUnit: "PartialUnit", + TagImportedUnit: "ImportedUnit", + TagMutableType: "MutableType", + TagCondition: "Condition", + TagSharedType: "SharedType", + TagTypeUnit: "TypeUnit", + TagRvalueReferenceType: "RvalueReferenceType", + TagTemplateAlias: "TemplateAlias", +} + +func (t Tag) String() string { + if int(t) < len(tagNames) { + s := tagNames[t] + if s != "" { + return s + } + } + return strconv.Itoa(int(t)) +} + +func (t Tag) GoString() string { + if int(t) < len(tagNames) { + s := tagNames[t] + if s != "" { + return "dwarf.Tag" + s + } + } + return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")" +} + +// Location expression operators. +// The debug info encodes value locations like 8(R3) +// as a sequence of these op codes. +// This package does not implement full expressions; +// the opPlusUconst operator is expected by the type parser. +const ( + opAddr = 0x03 /* 1 op, const addr */ + opDeref = 0x06 + opConst1u = 0x08 /* 1 op, 1 byte const */ + opConst1s = 0x09 /* " signed */ + opConst2u = 0x0A /* 1 op, 2 byte const */ + opConst2s = 0x0B /* " signed */ + opConst4u = 0x0C /* 1 op, 4 byte const */ + opConst4s = 0x0D /* " signed */ + opConst8u = 0x0E /* 1 op, 8 byte const */ + opConst8s = 0x0F /* " signed */ + opConstu = 0x10 /* 1 op, LEB128 const */ + opConsts = 0x11 /* " signed */ + opDup = 0x12 + opDrop = 0x13 + opOver = 0x14 + opPick = 0x15 /* 1 op, 1 byte stack index */ + opSwap = 0x16 + opRot = 0x17 + opXderef = 0x18 + opAbs = 0x19 + opAnd = 0x1A + opDiv = 0x1B + opMinus = 0x1C + opMod = 0x1D + opMul = 0x1E + opNeg = 0x1F + opNot = 0x20 + opOr = 0x21 + opPlus = 0x22 + opPlusUconst = 0x23 /* 1 op, ULEB128 addend */ + opShl = 0x24 + opShr = 0x25 + opShra = 0x26 + opXor = 0x27 + opSkip = 0x2F /* 1 op, signed 2-byte constant */ + opBra = 0x28 /* 1 op, signed 2-byte constant */ + opEq = 0x29 + opGe = 0x2A + opGt = 0x2B + opLe = 0x2C + opLt = 0x2D + opNe = 0x2E + opLit0 = 0x30 + /* OpLitN = OpLit0 + N for N = 0..31 */ + opReg0 = 0x50 + /* OpRegN = OpReg0 + N for N = 0..31 */ + opBreg0 = 0x70 /* 1 op, signed LEB128 constant */ + /* OpBregN = OpBreg0 + N for N = 0..31 */ + opRegx = 0x90 /* 1 op, ULEB128 register */ + opFbreg = 0x91 /* 1 op, SLEB128 offset */ + opBregx = 0x92 /* 2 op, ULEB128 reg; SLEB128 off */ + opPiece = 0x93 /* 1 op, ULEB128 size of piece */ + opDerefSize = 0x94 /* 1-byte size of data retrieved */ + opXderefSize = 0x95 /* 1-byte size of data retrieved */ + opNop = 0x96 + /* next four new in Dwarf v3 */ + opPushObjAddr = 0x97 + opCall2 = 0x98 /* 2-byte offset of DIE */ + opCall4 = 0x99 /* 4-byte offset of DIE */ + opCallRef = 0x9A /* 4- or 8- byte offset of DIE */ + /* 0xE0-0xFF reserved for user-specific */ +) + +// Basic type encodings -- the value for AttrEncoding in a TagBaseType Entry. +const ( + encAddress = 0x01 + encBoolean = 0x02 + encComplexFloat = 0x03 + encFloat = 0x04 + encSigned = 0x05 + encSignedChar = 0x06 + encUnsigned = 0x07 + encUnsignedChar = 0x08 + encImaginaryFloat = 0x09 +) diff --git a/vendor/golang.org/x/debug/dwarf/entry.go b/vendor/golang.org/x/debug/dwarf/entry.go new file mode 100644 index 0000000..4076ec1 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/entry.go @@ -0,0 +1,407 @@ +// 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. + +// DWARF debug information entry parser. +// An entry is a sequence of data items of a given format. +// The first word in the entry is an index into what DWARF +// calls the ``abbreviation table.'' An abbreviation is really +// just a type descriptor: it's an array of attribute tag/value format pairs. + +package dwarf + +import ( + "errors" + "strconv" +) + +// a single entry's description: a sequence of attributes +type abbrev struct { + tag Tag + children bool + field []afield +} + +type afield struct { + attr Attr + fmt format +} + +// a map from entry format ids to their descriptions +type abbrevTable map[uint32]abbrev + +// ParseAbbrev returns the abbreviation table that starts at byte off +// in the .debug_abbrev section. +func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) { + if m, ok := d.abbrevCache[off]; ok { + return m, nil + } + + data := d.abbrev + if off > uint32(len(data)) { + data = nil + } else { + data = data[off:] + } + b := makeBuf(d, unknownFormat{}, "abbrev", 0, data) + + // Error handling is simplified by the buf getters + // returning an endless stream of 0s after an error. + m := make(abbrevTable) + for { + // Table ends with id == 0. + id := uint32(b.uint()) + if id == 0 { + break + } + + // Walk over attributes, counting. + n := 0 + b1 := b // Read from copy of b. + b1.uint() + b1.uint8() + for { + tag := b1.uint() + fmt := b1.uint() + if tag == 0 && fmt == 0 { + break + } + n++ + } + if b1.err != nil { + return nil, b1.err + } + + // Walk over attributes again, this time writing them down. + var a abbrev + a.tag = Tag(b.uint()) + a.children = b.uint8() != 0 + a.field = make([]afield, n) + for i := range a.field { + a.field[i].attr = Attr(b.uint()) + a.field[i].fmt = format(b.uint()) + } + b.uint() + b.uint() + + m[id] = a + } + if b.err != nil { + return nil, b.err + } + d.abbrevCache[off] = m + return m, nil +} + +// An entry is a sequence of attribute/value pairs. +type Entry struct { + Offset Offset // offset of Entry in DWARF info + Tag Tag // tag (kind of Entry) + Children bool // whether Entry is followed by children + Field []Field +} + +// A Field is a single attribute/value pair in an Entry. +type Field struct { + Attr Attr + Val interface{} +} + +// Val returns the value associated with attribute Attr in Entry, +// or nil if there is no such attribute. +// +// A common idiom is to merge the check for nil return with +// the check that the value has the expected dynamic type, as in: +// v, ok := e.Val(AttrSibling).(int64); +// +func (e *Entry) Val(a Attr) interface{} { + for _, f := range e.Field { + if f.Attr == a { + return f.Val + } + } + return nil +} + +// An Offset represents the location of an Entry within the DWARF info. +// (See Reader.Seek.) +type Offset uint32 + +// Entry reads a single entry from buf, decoding +// according to the given abbreviation table. +func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { + off := b.off + id := uint32(b.uint()) + if id == 0 { + return &Entry{} + } + a, ok := atab[id] + if !ok { + b.error("unknown abbreviation table index") + return nil + } + e := &Entry{ + Offset: off, + Tag: a.tag, + Children: a.children, + Field: make([]Field, len(a.field)), + } + for i := range e.Field { + e.Field[i].Attr = a.field[i].attr + fmt := a.field[i].fmt + if fmt == formIndirect { + fmt = format(b.uint()) + } + var val interface{} + switch fmt { + default: + b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) + + // address + case formAddr: + val = b.addr() + + // block + case formDwarfBlock1: + val = b.bytes(int(b.uint8())) + case formDwarfBlock2: + val = b.bytes(int(b.uint16())) + case formDwarfBlock4: + val = b.bytes(int(b.uint32())) + case formDwarfBlock: + val = b.bytes(int(b.uint())) + + // constant + case formData1: + val = int64(b.uint8()) + case formData2: + val = int64(b.uint16()) + case formData4: + val = int64(b.uint32()) + case formData8: + val = int64(b.uint64()) + case formSdata: + val = int64(b.int()) + case formUdata: + val = int64(b.uint()) + + // flag + case formFlag: + val = b.uint8() == 1 + // New in DWARF 4. + case formFlagPresent: + // The attribute is implicitly indicated as present, and no value is + // encoded in the debugging information entry itself. + val = true + + // reference to other entry + case formRefAddr: + vers := b.format.version() + if vers == 0 { + b.error("unknown version for DW_FORM_ref_addr") + } else if vers == 2 { + val = Offset(b.addr()) + } else { + is64, known := b.format.dwarf64() + if !known { + b.error("unknown size for DW_FORM_ref_addr") + } else if is64 { + val = Offset(b.uint64()) + } else { + val = Offset(b.uint32()) + } + } + case formRef1: + val = Offset(b.uint8()) + ubase + case formRef2: + val = Offset(b.uint16()) + ubase + case formRef4: + val = Offset(b.uint32()) + ubase + case formRef8: + val = Offset(b.uint64()) + ubase + case formRefUdata: + val = Offset(b.uint()) + ubase + + // string + case formString: + val = b.string() + case formStrp: + off := b.uint32() // offset into .debug_str + if b.err != nil { + return nil + } + b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str) + b1.skip(int(off)) + val = b1.string() + if b1.err != nil { + b.err = b1.err + return nil + } + + // lineptr, loclistptr, macptr, rangelistptr + // New in DWARF 4, but clang can generate them with -gdwarf-2. + // Section reference, replacing use of formData4 and formData8. + case formSecOffset, formGnuRefAlt, formGnuStrpAlt: + is64, known := b.format.dwarf64() + if !known { + b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) + } else if is64 { + val = int64(b.uint64()) + } else { + val = int64(b.uint32()) + } + + // exprloc + // New in DWARF 4. + case formExprloc: + val = b.bytes(int(b.uint())) + + // reference + // New in DWARF 4. + case formRefSig8: + // 64-bit type signature. + val = b.uint64() + } + e.Field[i].Val = val + } + if b.err != nil { + return nil + } + return e +} + +// A Reader allows reading Entry structures from a DWARF ``info'' section. +// The Entry structures are arranged in a tree. The Reader's Next function +// return successive entries from a pre-order traversal of the tree. +// If an entry has children, its Children field will be true, and the children +// follow, terminated by an Entry with Tag 0. +type Reader struct { + b buf + d *Data + err error + unit int + lastChildren bool // .Children of last entry returned by Next + lastSibling Offset // .Val(AttrSibling) of last entry returned by Next +} + +// Reader returns a new Reader for Data. +// The reader is positioned at byte offset 0 in the DWARF ``info'' section. +func (d *Data) Reader() *Reader { + r := &Reader{d: d} + r.Seek(0) + return r +} + +// AddressSize returns the size in bytes of addresses in the current compilation +// unit. +func (r *Reader) AddressSize() int { + return r.d.unit[r.unit].asize +} + +// Seek positions the Reader at offset off in the encoded entry stream. +// Offset 0 can be used to denote the first entry. +func (r *Reader) Seek(off Offset) { + d := r.d + r.err = nil + r.lastChildren = false + if off == 0 { + if len(d.unit) == 0 { + return + } + u := &d.unit[0] + r.unit = 0 + r.b = makeBuf(r.d, u, "info", u.off, u.data) + return + } + + // TODO(rsc): binary search (maybe a new package) + var i int + var u *unit + for i = range d.unit { + u = &d.unit[i] + if u.off <= off && off < u.off+Offset(len(u.data)) { + r.unit = i + r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) + return + } + } + r.err = errors.New("offset out of range") +} + +// maybeNextUnit advances to the next unit if this one is finished. +func (r *Reader) maybeNextUnit() { + for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { + r.unit++ + u := &r.d.unit[r.unit] + r.b = makeBuf(r.d, u, "info", u.off, u.data) + } +} + +// Next reads the next entry from the encoded entry stream. +// It returns nil, nil when it reaches the end of the section. +// It returns an error if the current offset is invalid or the data at the +// offset cannot be decoded as a valid Entry. +func (r *Reader) Next() (*Entry, error) { + if r.err != nil { + return nil, r.err + } + r.maybeNextUnit() + if len(r.b.data) == 0 { + return nil, nil + } + u := &r.d.unit[r.unit] + e := r.b.entry(u.atable, u.base) + if r.b.err != nil { + r.err = r.b.err + return nil, r.err + } + if e != nil { + r.lastChildren = e.Children + if r.lastChildren { + r.lastSibling, _ = e.Val(AttrSibling).(Offset) + } + } else { + r.lastChildren = false + } + return e, nil +} + +// SkipChildren skips over the child entries associated with +// the last Entry returned by Next. If that Entry did not have +// children or Next has not been called, SkipChildren is a no-op. +func (r *Reader) SkipChildren() { + if r.err != nil || !r.lastChildren { + return + } + + // If the last entry had a sibling attribute, + // that attribute gives the offset of the next + // sibling, so we can avoid decoding the + // child subtrees. + if r.lastSibling >= r.b.off { + r.Seek(r.lastSibling) + return + } + + for { + e, err := r.Next() + if err != nil || e == nil || e.Tag == 0 { + break + } + if e.Children { + r.SkipChildren() + } + } +} + +// clone returns a copy of the reader. This is used by the typeReader +// interface. +func (r *Reader) clone() typeReader { + return r.d.Reader() +} + +// offset returns the current buffer offset. This is used by the +// typeReader interface. +func (r *Reader) offset() Offset { + return r.b.off +} diff --git a/vendor/golang.org/x/debug/dwarf/frame.go b/vendor/golang.org/x/debug/dwarf/frame.go new file mode 100644 index 0000000..c112c02 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/frame.go @@ -0,0 +1,299 @@ +// Copyright 2014 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. + +// Mapping from PC to SP offset (called CFA - Canonical Frame Address - in DWARF). +// This value is the offset from the stack pointer to the virtual frame pointer +// (address of zeroth argument) at each PC value in the program. + +package dwarf + +import "fmt" + +// http://www.dwarfstd.org/doc/DWARF4.pdf Section 6.4 page 126 +// We implement only the CFA column of the table, not the location +// information about other registers. In other words, we implement +// only what we need to understand Go programs compiled by gc. + +// PCToSPOffset returns the offset, at the specified PC, to add to the +// SP to reach the virtual frame pointer, which corresponds to the +// address of the zeroth argument of the function, the word on the +// stack immediately above the return PC. +func (d *Data) PCToSPOffset(pc uint64) (offset int64, err error) { + if len(d.frame) == 0 { + return 0, fmt.Errorf("PCToSPOffset: no frame table") + } + var m frameMachine + // Assume the first info unit is the same as us. Extremely likely. TODO? + if len(d.unit) == 0 { + return 0, fmt.Errorf("PCToSPOffset: no info section") + } + buf := makeBuf(d, &d.unit[0], "frame", 0, d.frame) + for len(buf.data) > 0 { + offset, err := m.evalCompilationUnit(&buf, pc) + if err != nil { + return 0, err + } + return offset, nil + } + return 0, fmt.Errorf("PCToSPOffset: no frame defined for PC %#x", pc) +} + +// Call Frame instructions. Figure 40, page 181. +// Structure is high two bits plus low 6 bits specified by + in comment. +// Some take one or two operands. +const ( + frameNop = 0<<6 + 0x00 + frameAdvanceLoc = 1<<6 + 0x00 // + delta + frameOffset = 2<<6 + 0x00 // + register op: ULEB128 offset + frameRestore = 3<<6 + 0x00 // + register + frameSetLoc = 0<<6 + 0x01 // op: address + frameAdvanceLoc1 = 0<<6 + 0x02 // op: 1-byte delta + frameAdvanceLoc2 = 0<<6 + 0x03 // op: 2-byte delta + frameAdvanceLoc4 = 0<<6 + 0x04 // op: 4-byte delta + frameOffsetExtended = 0<<6 + 0x05 // ops: ULEB128 register ULEB128 offset + frameRestoreExtended = 0<<6 + 0x06 // op: ULEB128 register + frameUndefined = 0<<6 + 0x07 // op: ULEB128 register + frameSameValue = 0<<6 + 0x08 // op: ULEB128 register + frameRegister = 0<<6 + 0x09 // op: ULEB128 register ULEB128 register + frameRememberState = 0<<6 + 0x0a + frameRestoreState = 0<<6 + 0x0b + frameDefCFA = 0<<6 + 0x0c // op: ULEB128 register ULEB128 offset + frameDefCFARegister = 0<<6 + 0x0d // op: ULEB128 register + frameDefCFAOffset = 0<<6 + 0x0e // op: ULEB128 offset + frameDefCFAExpression = 0<<6 + 0x0f // op: BLOCK + frameExpression = 0<<6 + 0x10 // op: ULEB128 register BLOCK + frameOffsetExtendedSf = 0<<6 + 0x11 // op: ULEB128 register SLEB128 offset + frameDefCFASf = 0<<6 + 0x12 // op: ULEB128 register SLEB128 offset + frameDefCFAOffsetSf = 0<<6 + 0x13 // op: SLEB128 offset + frameValOffset = 0<<6 + 0x14 // op: ULEB128 ULEB128 + frameValOffsetSf = 0<<6 + 0x15 // op: ULEB128 SLEB128 + frameValExpression = 0<<6 + 0x16 // op: ULEB128 BLOCK + frameLoUser = 0<<6 + 0x1c + frameHiUser = 0<<6 + 0x3f +) + +// frameMachine represents the PC/SP engine. +// Section 6.4, page 129. +type frameMachine struct { + // Initial values from CIE. + version uint8 // Version number, "independent of DWARF version" + augmentation string // Augmentation; treated as unexpected for now. TODO. + addressSize uint8 // In DWARF v4 and above. Size of a target address. + segmentSize uint8 // In DWARF v4 and above. Size of a segment selector. + codeAlignmentFactor uint64 // Unit of code size in advance instructions. + dataAlignmentFactor int64 // Unit of data size in certain offset instructions. + returnAddressRegister int // Pseudo-register (actually data column) representing return address. + returnRegisterOffset int64 // Offset to saved PC from CFA in bytes. + // CFA definition. + cfaRegister int // Which register represents the SP. + cfaOffset int64 // CFA offset value. + // Running machine. + location uint64 +} + +// evalCompilationUnit scans the frame data for one compilation unit to retrieve +// the offset information for the specified pc. +func (m *frameMachine) evalCompilationUnit(b *buf, pc uint64) (int64, error) { + err := m.parseCIE(b) + if err != nil { + return 0, err + } + for { + offset, found, err := m.scanFDE(b, pc) + if err != nil { + return 0, err + } + if found { + return offset, nil + } + } +} + +// parseCIE assumes the incoming buffer starts with a CIE block and parses it +// to initialize a frameMachine. +func (m *frameMachine) parseCIE(allBuf *buf) error { + length := int(allBuf.uint32()) + if len(allBuf.data) < length { + return fmt.Errorf("CIE parse error: too short") + } + // Create buffer for just this section. + b := allBuf.slice(length) + cie := b.uint32() + if cie != 0xFFFFFFFF { + return fmt.Errorf("CIE parse error: not CIE: %x", cie) + } + m.version = b.uint8() + if m.version != 3 && m.version != 4 { + return fmt.Errorf("CIE parse error: unsupported version %d", m.version) + } + m.augmentation = b.string() + if len(m.augmentation) > 0 { + return fmt.Errorf("CIE: can't handled augmentation string %q", m.augmentation) + } + if m.version >= 4 { + m.addressSize = b.uint8() + m.segmentSize = b.uint8() + } else { + // Unused. Gc generates version 3, so these values will not be + // set, but they are also not used so it's OK. + } + m.codeAlignmentFactor = b.uint() + m.dataAlignmentFactor = b.int() + m.returnAddressRegister = int(b.uint()) + + // Initial instructions. At least for Go, establishes SP register number + // and initial value of CFA offset at start of function. + _, err := m.run(&b, ^uint64(0)) + if err != nil { + return err + } + + // There's padding, but we can ignore it. + return nil +} + +// scanFDE assumes the incoming buffer starts with a FDE block and parses it +// to run a frameMachine and, if the PC is represented in its range, return +// the CFA offset for that PC. The boolean returned reports whether the +// PC is in range for this FDE. +func (m *frameMachine) scanFDE(allBuf *buf, pc uint64) (int64, bool, error) { + length := int(allBuf.uint32()) + if len(allBuf.data) < length { + return 0, false, fmt.Errorf("FDE parse error: too short") + } + if length <= 0 { + if length == 0 { + // EOF. + return 0, false, fmt.Errorf("PC %#x not found in PC/SP table", pc) + } + return 0, false, fmt.Errorf("bad FDE length %d", length) + } + // Create buffer for just this section. + b := allBuf.slice(length) + cieOffset := b.uint32() // TODO assumes 32 bits. + // Expect 0: first CIE in this segment. TODO. + if cieOffset != 0 { + return 0, false, fmt.Errorf("FDE parse error: bad CIE offset: %.2x", cieOffset) + } + // Initial location. + m.location = b.addr() + addressRange := b.addr() + // If the PC is not in this function, there's no point in executing the instructions. + if pc < m.location || m.location+addressRange <= pc { + return 0, false, nil + } + // The PC appears in this FDE. Scan to find the location. + offset, err := m.run(&b, pc) + if err != nil { + return 0, false, err + } + + // There's padding, but we can ignore it. + return offset, true, nil +} + +// run executes the instructions in the buffer, which has been sliced to contain +// only the data for this block. When we run out of data, we return. +// Since we are only called when we know the PC is in this block, reaching +// EOF is not an error, it just means the final CFA definition matches the +// tail of the block that holds the PC. +// The return value is the CFA at the end of the block or the PC, whichever +// comes first. +func (m *frameMachine) run(b *buf, pc uint64) (int64, error) { + // We run the machine at location == PC because if the PC is at the first + // instruction of a block, the definition of its offset arrives as an + // offset-defining operand after the PC is set to that location. + for m.location <= pc && len(b.data) > 0 { + op := b.uint8() + // Ops with embedded operands + switch op & 0xC0 { + case frameAdvanceLoc: // (6.4.2.1) + // delta in low bits + m.location += uint64(op & 0x3F) + continue + case frameOffset: // (6.4.2.3) + // Register in low bits; ULEB128 offset. + // For Go binaries we only see this in the CIE for the return address register. + if int(op&0x3F) != m.returnAddressRegister { + return 0, fmt.Errorf("invalid frameOffset register R%d should be R%d", op&0x3f, m.returnAddressRegister) + } + m.returnRegisterOffset = int64(b.uint()) * m.dataAlignmentFactor + continue + case frameRestore: // (6.4.2.3) + // register in low bits + return 0, fmt.Errorf("unimplemented frameRestore(R%d)\n", op&0x3F) + } + + // The remaining ops do not have embedded operands. + + switch op { + // Row creation instructions (6.4.2.1) + case frameNop: + case frameSetLoc: // op: address + return 0, fmt.Errorf("unimplemented setloc") // what size is operand? + case frameAdvanceLoc1: // op: 1-byte delta + m.location += uint64(b.uint8()) + case frameAdvanceLoc2: // op: 2-byte delta + m.location += uint64(b.uint16()) + case frameAdvanceLoc4: // op: 4-byte delta + m.location += uint64(b.uint32()) + + // CFA definition instructions (6.4.2.2) + case frameDefCFA: // op: ULEB128 register ULEB128 offset + m.cfaRegister = int(b.int()) + m.cfaOffset = int64(b.uint()) + case frameDefCFASf: // op: ULEB128 register SLEB128 offset + return 0, fmt.Errorf("unimplemented frameDefCFASf") + case frameDefCFARegister: // op: ULEB128 register + return 0, fmt.Errorf("unimplemented frameDefCFARegister") + case frameDefCFAOffset: // op: ULEB128 offset + return 0, fmt.Errorf("unimplemented frameDefCFAOffset") + case frameDefCFAOffsetSf: // op: SLEB128 offset + offset := b.int() + m.cfaOffset = offset * m.dataAlignmentFactor + // TODO: Verify we are using a factored offset. + case frameDefCFAExpression: // op: BLOCK + return 0, fmt.Errorf("unimplemented frameDefCFAExpression") + + // Register Rule instructions (6.4.2.3) + case frameOffsetExtended: // ops: ULEB128 register ULEB128 offset + // The same as frameOffset, but with the register specified in an operand. + reg := b.uint() + // For Go binaries we only see this in the CIE for the return address register. + if reg != uint64(m.returnAddressRegister) { + return 0, fmt.Errorf("invalid frameOffsetExtended: register R%d should be R%d", reg, m.returnAddressRegister) + } + m.returnRegisterOffset = int64(b.uint()) * m.dataAlignmentFactor + case frameRestoreExtended: // op: ULEB128 register + return 0, fmt.Errorf("unimplemented frameRestoreExtended") + case frameUndefined: // op: ULEB128 register; unimplemented + return 0, fmt.Errorf("unimplemented frameUndefined") + case frameSameValue: // op: ULEB128 register + return 0, fmt.Errorf("unimplemented frameSameValue") + case frameRegister: // op: ULEB128 register ULEB128 register + return 0, fmt.Errorf("unimplemented frameRegister") + case frameRememberState: + return 0, fmt.Errorf("unimplemented frameRememberState") + case frameRestoreState: + return 0, fmt.Errorf("unimplemented frameRestoreState") + case frameExpression: // op: ULEB128 register BLOCK + return 0, fmt.Errorf("unimplemented frameExpression") + case frameOffsetExtendedSf: // op: ULEB128 register SLEB128 offset + return 0, fmt.Errorf("unimplemented frameOffsetExtended_sf") + case frameValOffset: // op: ULEB128 ULEB128 + return 0, fmt.Errorf("unimplemented frameValOffset") + case frameValOffsetSf: // op: ULEB128 SLEB128 + return 0, fmt.Errorf("unimplemented frameValOffsetSf") + case frameValExpression: // op: ULEB128 BLOCK + return 0, fmt.Errorf("unimplemented frameValExpression") + + default: + if frameLoUser <= op && op <= frameHiUser { + return 0, fmt.Errorf("unknown user-defined frame op %#x", op) + } + return 0, fmt.Errorf("unknown frame op %#x", op) + } + } + return m.cfaOffset, nil +} diff --git a/vendor/golang.org/x/debug/dwarf/line.go b/vendor/golang.org/x/debug/dwarf/line.go new file mode 100644 index 0000000..2f47739 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/line.go @@ -0,0 +1,448 @@ +// Copyright 2014 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 dwarf + +// This file implements the mapping from PC to lines. +// TODO: Find a way to test this properly. + +// http://www.dwarfstd.org/doc/DWARF4.pdf Section 6.2 page 108 + +import ( + "fmt" + "sort" + "strings" +) + +// PCToLine returns the file and line number corresponding to the PC value. +// It returns an error if a correspondence cannot be found. +func (d *Data) PCToLine(pc uint64) (file string, line uint64, err error) { + c := d.pcToLineEntries + if len(c) == 0 { + return "", 0, fmt.Errorf("PCToLine: no line table") + } + i := sort.Search(len(c), func(i int) bool { return c[i].pc > pc }) - 1 + // c[i] is now the entry in pcToLineEntries with the largest pc that is not + // larger than the query pc. + // The search has failed if: + // - All pcs in c were larger than the query pc (i == -1). + // - c[i] marked the end of a sequence of instructions (c[i].file == 0). + // - c[i] is the last element of c, and isn't the end of a sequence of + // instructions, and the search pc is much larger than c[i].pc. In this + // case, we don't know the range of the last instruction, but the search + // pc is probably past it. + if i == -1 || c[i].file == 0 || (i+1 == len(c) && pc-c[i].pc > 1024) { + return "", 0, fmt.Errorf("no source line defined for PC %#x", pc) + } + if c[i].file >= uint64(len(d.sourceFiles)) { + return "", 0, fmt.Errorf("invalid file number in DWARF data") + } + return d.sourceFiles[c[i].file], c[i].line, nil +} + +// LineToBreakpointPCs returns the PCs that should be used as breakpoints +// corresponding to the given file and line number. +// It returns an empty slice if no PCs were found. +func (d *Data) LineToBreakpointPCs(file string, line uint64) ([]uint64, error) { + compDir := d.compilationDirectory() + + // Find the closest match in the executable for the specified file. + // We choose the file with the largest number of path components matching + // at the end of the name. If there is a tie, we prefer files that are + // under the compilation directory. If there is still a tie, we choose + // the file with the shortest name. + // TODO: handle duplicate file names in the DWARF? + var bestFile struct { + fileNum uint64 // Index of the file in the DWARF data. + components int // Number of matching path components. + length int // Length of the filename. + underComp bool // File is under the compilation directory. + } + for filenum, filename := range d.sourceFiles { + c := matchingPathComponentSuffixSize(filename, file) + underComp := strings.HasPrefix(filename, compDir) + better := false + if c != bestFile.components { + better = c > bestFile.components + } else if underComp != bestFile.underComp { + better = underComp + } else { + better = len(filename) < bestFile.length + } + if better { + bestFile.fileNum = uint64(filenum) + bestFile.components = c + bestFile.length = len(filename) + bestFile.underComp = underComp + } + } + if bestFile.components == 0 { + return nil, fmt.Errorf("couldn't find file %q", file) + } + + c := d.lineToPCEntries[bestFile.fileNum] + // c contains all (pc, line) pairs for the appropriate file. + start := sort.Search(len(c), func(i int) bool { return c[i].line >= line }) + end := sort.Search(len(c), func(i int) bool { return c[i].line > line }) + // c[i].line == line for all i in the range [start, end). + pcs := make([]uint64, 0, end-start) + for i := start; i < end; i++ { + pcs = append(pcs, c[i].pc) + } + return pcs, nil +} + +// compilationDirectory finds the first compilation unit entry in d and returns +// the compilation directory contained in it. +// If it fails, it returns the empty string. +func (d *Data) compilationDirectory() string { + r := d.Reader() + for { + entry, err := r.Next() + if entry == nil || err != nil { + return "" + } + if entry.Tag == TagCompileUnit { + name, _ := entry.Val(AttrCompDir).(string) + return name + } + } +} + +// matchingPathComponentSuffixSize returns the largest n such that the last n +// components of the paths p1 and p2 are equal. +// e.g. matchingPathComponentSuffixSize("a/b/x/y.go", "b/a/x/y.go") returns 2. +func matchingPathComponentSuffixSize(p1, p2 string) int { + // TODO: deal with other path separators. + c1 := strings.Split(p1, "/") + c2 := strings.Split(p2, "/") + min := len(c1) + if len(c2) < min { + min = len(c2) + } + var n int + for n = 0; n < min; n++ { + if c1[len(c1)-1-n] != c2[len(c2)-1-n] { + break + } + } + return n +} + +// Standard opcodes. Figure 37, page 178. +// If an opcode >= lineMachine.prologue.opcodeBase, it is a special +// opcode rather than the opcode defined in this table. +const ( + lineStdCopy = 0x01 + lineStdAdvancePC = 0x02 + lineStdAdvanceLine = 0x03 + lineStdSetFile = 0x04 + lineStdSetColumn = 0x05 + lineStdNegateStmt = 0x06 + lineStdSetBasicBlock = 0x07 + lineStdConstAddPC = 0x08 + lineStdFixedAdvancePC = 0x09 + lineStdSetPrologueEnd = 0x0a + lineStdSetEpilogueBegin = 0x0b + lineStdSetISA = 0x0c +) + +// Extended opcodes. Figure 38, page 179. +const ( + lineStartExtendedOpcode = 0x00 // Not defined as a named constant in the spec. + lineExtEndSequence = 0x01 + lineExtSetAddress = 0x02 + lineExtDefineFile = 0x03 + lineExtSetDiscriminator = 0x04 // New in version 4. + lineExtLoUser = 0x80 + lineExtHiUser = 0xff +) + +// lineHeader holds the information stored in the header of the line table for a +// single compilation unit. +// Section 6.2.4, page 112. +type lineHeader struct { + unitLength int + version int + headerLength int + minInstructionLength int + maxOpsPerInstruction int + defaultIsStmt bool + lineBase int + lineRange int + opcodeBase byte + stdOpcodeLengths []byte + include []string // entry 0 is empty; means current directory + file []lineFile // entry 0 is empty. +} + +// lineFile represents a file name stored in the PC/line table, usually in the header. +type lineFile struct { + name string + index int // index into include directories + time int // implementation-defined time of last modification + length int // length in bytes, 0 if not available. +} + +// lineMachine holds the registers evaluated during executing of the PC/line mapping engine. +// Section 6.2.2, page 109. +type lineMachine struct { + // The program-counter value corresponding to a machine instruction generated by the compiler. + address uint64 + + // An unsigned integer representing the index of an operation within a VLIW + // instruction. The index of the first operation is 0. For non-VLIW + // architectures, this register will always be 0. + // The address and op_index registers, taken together, form an operation + // pointer that can reference any individual operation with the instruction + // stream. + opIndex uint64 + + // An unsigned integer indicating the identity of the source file corresponding to a machine instruction. + file uint64 + + // An unsigned integer indicating a source line number. Lines are numbered + // beginning at 1. The compiler may emit the value 0 in cases where an + // instruction cannot be attributed to any source line. + line uint64 + + // An unsigned integer indicating a column number within a source line. + // Columns are numbered beginning at 1. The value 0 is reserved to indicate + // that a statement begins at the “left edge” of the line. + column uint64 + + // A boolean indicating that the current instruction is a recommended + // breakpoint location. A recommended breakpoint location is intended to + // “represent” a line, a statement and/or a semantically distinct subpart of a + // statement. + isStmt bool + + // A boolean indicating that the current instruction is the beginning of a basic + // block. + basicBlock bool + + // A boolean indicating that the current address is that of the first byte after + // the end of a sequence of target machine instructions. end_sequence + // terminates a sequence of lines; therefore other information in the same + // row is not meaningful. + endSequence bool + + // A boolean indicating that the current address is one (of possibly many) + // where execution should be suspended for an entry breakpoint of a + // function. + prologueEnd bool + + // A boolean indicating that the current address is one (of possibly many) + // where execution should be suspended for an exit breakpoint of a function. + epilogueBegin bool + + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + // The encoding of instruction sets should be shared by all users of a given + // architecture. It is recommended that this encoding be defined by the ABI + // authoring committee for each architecture. + isa uint64 + + // An unsigned integer identifying the block to which the current instruction + // belongs. Discriminator values are assigned arbitrarily by the DWARF + // producer and serve to distinguish among multiple blocks that may all be + // associated with the same source file, line, and column. Where only one + // block exists for a given source position, the discriminator value should be + // zero. + discriminator uint64 + + // The header for the current compilation unit. + // Not an actual register, but stored here for cleanliness. + header lineHeader +} + +// parseHeader parses the header describing the compilation unit in the line +// table starting at the specified offset. +func (m *lineMachine) parseHeader(b *buf) error { + m.header = lineHeader{} + m.header.unitLength = int(b.uint32()) // Note: We are assuming 32-bit DWARF format. + if m.header.unitLength > len(b.data) { + return fmt.Errorf("DWARF: bad PC/line header length") + } + m.header.version = int(b.uint16()) + m.header.headerLength = int(b.uint32()) + m.header.minInstructionLength = int(b.uint8()) + if m.header.version >= 4 { + m.header.maxOpsPerInstruction = int(b.uint8()) + } else { + m.header.maxOpsPerInstruction = 1 + } + m.header.defaultIsStmt = b.uint8() != 0 + m.header.lineBase = int(int8(b.uint8())) + m.header.lineRange = int(b.uint8()) + m.header.opcodeBase = b.uint8() + m.header.stdOpcodeLengths = make([]byte, m.header.opcodeBase-1) + copy(m.header.stdOpcodeLengths, b.bytes(int(m.header.opcodeBase-1))) + m.header.include = make([]string, 1) // First entry is empty; file index entries are 1-indexed. + // Includes + for { + name := b.string() + if name == "" { + break + } + m.header.include = append(m.header.include, name) + } + // Files + m.header.file = make([]lineFile, 1, 10) // entries are 1-indexed in line number program. + for { + name := b.string() + if name == "" { + break + } + index := b.uint() + time := b.uint() + length := b.uint() + f := lineFile{ + name: name, + index: int(index), + time: int(time), + length: int(length), + } + m.header.file = append(m.header.file, f) + } + return nil +} + +// Special opcodes, page 117. +// There are seven steps to processing special opcodes. We break them up here +// because the caller needs to output a row between steps 2 and 4, and because +// we need to perform just step 2 for the opcode DW_LNS_const_add_pc. + +func (m *lineMachine) specialOpcodeStep1(opcode byte) { + adjustedOpcode := int(opcode - m.header.opcodeBase) + lineAdvance := m.header.lineBase + (adjustedOpcode % m.header.lineRange) + m.line += uint64(lineAdvance) +} + +func (m *lineMachine) specialOpcodeStep2(opcode byte) { + adjustedOpcode := int(opcode - m.header.opcodeBase) + advance := adjustedOpcode / m.header.lineRange + delta := (int(m.opIndex) + advance) / m.header.maxOpsPerInstruction + m.address += uint64(m.header.minInstructionLength * delta) + m.opIndex = (m.opIndex + uint64(advance)) % uint64(m.header.maxOpsPerInstruction) +} + +func (m *lineMachine) specialOpcodeSteps4To7() { + m.basicBlock = false + m.prologueEnd = false + m.epilogueBegin = false + m.discriminator = 0 +} + +// evalCompilationUnit reads the next compilation unit and calls f at each output row. +// Line machine execution continues while f returns true. +func (m *lineMachine) evalCompilationUnit(b *buf, f func(m *lineMachine) (cont bool)) error { + m.reset() + for len(b.data) > 0 { + op := b.uint8() + if op >= m.header.opcodeBase { + m.specialOpcodeStep1(op) + m.specialOpcodeStep2(op) + // Step 3 is to output a row, so we call f here. + if !f(m) { + return nil + } + m.specialOpcodeSteps4To7() + continue + } + switch op { + case lineStartExtendedOpcode: + if len(b.data) == 0 { + return fmt.Errorf("DWARF: short extended opcode (1)") + } + size := b.uint() + if uint64(len(b.data)) < size { + return fmt.Errorf("DWARF: short extended opcode (2)") + } + op = b.uint8() + switch op { + case lineExtEndSequence: + m.endSequence = true + if !f(m) { + return nil + } + if len(b.data) == 0 { + return nil + } + m.reset() + case lineExtSetAddress: + m.address = b.addr() + m.opIndex = 0 + case lineExtDefineFile: + return fmt.Errorf("DWARF: unimplemented define_file op") + case lineExtSetDiscriminator: + discriminator := b.uint() + m.discriminator = discriminator + default: + return fmt.Errorf("DWARF: unknown extended opcode %#x", op) + } + case lineStdCopy: + if !f(m) { + return nil + } + m.discriminator = 0 + m.basicBlock = false + m.prologueEnd = false + m.epilogueBegin = false + case lineStdAdvancePC: + advance := b.uint() + delta := (int(m.opIndex) + int(advance)) / m.header.maxOpsPerInstruction + m.address += uint64(m.header.minInstructionLength * delta) + m.opIndex = (m.opIndex + uint64(advance)) % uint64(m.header.maxOpsPerInstruction) + m.basicBlock = false + m.prologueEnd = false + m.epilogueBegin = false + m.discriminator = 0 + case lineStdAdvanceLine: + advance := b.int() + m.line = uint64(int64(m.line) + advance) + case lineStdSetFile: + index := b.uint() + m.file = index + case lineStdSetColumn: + column := b.uint() + m.column = column + case lineStdNegateStmt: + m.isStmt = !m.isStmt + case lineStdSetBasicBlock: + m.basicBlock = true + case lineStdFixedAdvancePC: + m.address += uint64(b.uint16()) + m.opIndex = 0 + case lineStdSetPrologueEnd: + m.prologueEnd = true + case lineStdSetEpilogueBegin: + m.epilogueBegin = true + case lineStdSetISA: + m.isa = b.uint() + case lineStdConstAddPC: + // Update the the address and op_index registers. + m.specialOpcodeStep2(255) + default: + panic("not reached") + } + } + return fmt.Errorf("DWARF: unexpected end of line number information") +} + +// reset sets the machine's registers to the initial state. Page 111. +func (m *lineMachine) reset() { + m.address = 0 + m.opIndex = 0 + m.file = 1 + m.line = 1 + m.column = 0 + m.isStmt = m.header.defaultIsStmt + m.basicBlock = false + m.endSequence = false + m.prologueEnd = false + m.epilogueBegin = false + m.isa = 0 + m.discriminator = 0 +} diff --git a/vendor/golang.org/x/debug/dwarf/open.go b/vendor/golang.org/x/debug/dwarf/open.go new file mode 100644 index 0000000..c727e8b --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/open.go @@ -0,0 +1,94 @@ +// 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 dwarf provides access to DWARF debugging information loaded from +// executable files, as defined in the DWARF 2.0 Standard at +// http://dwarfstd.org/doc/dwarf-2.0.0.pdf +package dwarf + +import "encoding/binary" + +// Data represents the DWARF debugging information +// loaded from an executable file (for example, an ELF or Mach-O executable). +type Data struct { + // raw data + abbrev []byte + aranges []byte + frame []byte + info []byte + line []byte + pubnames []byte + ranges []byte + str []byte + + // parsed data + abbrevCache map[uint32]abbrevTable + order binary.ByteOrder + typeCache map[Offset]Type + typeSigs map[uint64]*typeUnit + unit []unit + sourceFiles []string // source files listed in .debug_line. + nameCache // map from name to top-level entries in .debug_info. + pcToFuncEntries // cache of .debug_info data for function bounds. + pcToLineEntries // cache of .debug_line data, used for efficient PC-to-line mapping. + lineToPCEntries // cache of .debug_line data, used for efficient line-to-[]PC mapping. +} + +// New returns a new Data object initialized from the given parameters. +// Rather than calling this function directly, clients should typically use +// the DWARF method of the File type of the appropriate package debug/elf, +// debug/macho, or debug/pe. +// +// The []byte arguments are the data from the corresponding debug section +// in the object file; for example, for an ELF object, abbrev is the contents of +// the ".debug_abbrev" section. +func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) { + d := &Data{ + abbrev: abbrev, + aranges: aranges, + frame: frame, + info: info, + line: line, + pubnames: pubnames, + ranges: ranges, + str: str, + abbrevCache: make(map[uint32]abbrevTable), + typeCache: make(map[Offset]Type), + typeSigs: make(map[uint64]*typeUnit), + } + + // Sniff .debug_info to figure out byte order. + // bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3). + if len(d.info) < 6 { + return nil, DecodeError{"info", Offset(len(d.info)), "too short"} + } + x, y := d.info[4], d.info[5] + switch { + case x == 0 && y == 0: + return nil, DecodeError{"info", 4, "unsupported version 0"} + case x == 0: + d.order = binary.BigEndian + case y == 0: + d.order = binary.LittleEndian + default: + return nil, DecodeError{"info", 4, "cannot determine byte order"} + } + + u, err := d.parseUnits() + if err != nil { + return nil, err + } + d.unit = u + d.buildInfoCaches() + d.buildLineCaches() + return d, nil +} + +// AddTypes will add one .debug_types section to the DWARF data. A +// typical object with DWARF version 4 debug info will have multiple +// .debug_types sections. The name is used for error reporting only, +// and serves to distinguish one .debug_types section from another. +func (d *Data) AddTypes(name string, types []byte) error { + return d.parseTypes(name, types) +} diff --git a/vendor/golang.org/x/debug/dwarf/symbol.go b/vendor/golang.org/x/debug/dwarf/symbol.go new file mode 100644 index 0000000..52d6829 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/symbol.go @@ -0,0 +1,119 @@ +// Copyright 2014 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 dwarf + +// This file provides simple methods to access the symbol table by name and address. + +import ( + "fmt" + "regexp" + "sort" +) + +// lookupEntry returns the first Entry for the name. +// If tag is non-zero, only entries with that tag are considered. +func (d *Data) lookupEntry(name string, tag Tag) (*Entry, error) { + x, ok := d.nameCache[name] + if !ok { + return nil, fmt.Errorf("DWARF entry for %q not found", name) + } + for ; x != nil; x = x.link { + if tag == 0 || x.entry.Tag == tag { + return x.entry, nil + } + } + return nil, fmt.Errorf("no DWARF entry for %q with tag %s", name, tag) +} + +// LookupMatchingSymbols returns the names of all top-level entries matching +// the given regular expression. +func (d *Data) LookupMatchingSymbols(nameRE *regexp.Regexp) (result []string, err error) { + for name := range d.nameCache { + if nameRE.MatchString(name) { + result = append(result, name) + } + } + return result, nil +} + +// LookupEntry returns the Entry for the named symbol. +func (d *Data) LookupEntry(name string) (*Entry, error) { + return d.lookupEntry(name, 0) +} + +// LookupFunction returns the entry for a function. +func (d *Data) LookupFunction(name string) (*Entry, error) { + return d.lookupEntry(name, TagSubprogram) +} + +// LookupVariable returns the entry for a (global) variable. +func (d *Data) LookupVariable(name string) (*Entry, error) { + return d.lookupEntry(name, TagVariable) +} + +// EntryLocation returns the address of the object referred to by the given Entry. +func (d *Data) EntryLocation(e *Entry) (uint64, error) { + loc, _ := e.Val(AttrLocation).([]byte) + if len(loc) == 0 { + return 0, fmt.Errorf("DWARF entry has no Location attribute") + } + // TODO: implement the DWARF Location bytecode. What we have here only + // recognizes a program with a single literal opAddr bytecode. + if asize := d.unit[0].asize; loc[0] == opAddr && len(loc) == 1+asize { + switch asize { + case 1: + return uint64(loc[1]), nil + case 2: + return uint64(d.order.Uint16(loc[1:])), nil + case 4: + return uint64(d.order.Uint32(loc[1:])), nil + case 8: + return d.order.Uint64(loc[1:]), nil + } + } + return 0, fmt.Errorf("DWARF entry has an unimplemented Location op") +} + +// EntryType returns the Type for an Entry. +func (d *Data) EntryType(e *Entry) (Type, error) { + off, err := d.EntryTypeOffset(e) + if err != nil { + return nil, err + } + return d.Type(off) +} + +// EntryTypeOffset returns the offset in the given Entry's type attribute. +func (d *Data) EntryTypeOffset(e *Entry) (Offset, error) { + v := e.Val(AttrType) + if v == nil { + return 0, fmt.Errorf("DWARF entry has no Type attribute") + } + off, ok := v.(Offset) + if !ok { + return 0, fmt.Errorf("DWARF entry has an invalid Type attribute") + } + return off, nil +} + +// PCToFunction returns the entry and address for the function containing the +// specified PC. +func (d *Data) PCToFunction(pc uint64) (entry *Entry, lowpc uint64, err error) { + p := d.pcToFuncEntries + if len(p) == 0 { + return nil, 0, fmt.Errorf("no function addresses loaded") + } + i := sort.Search(len(p), func(i int) bool { return p[i].pc > pc }) - 1 + // The search failed if: + // - pc was before the start of any function. + // - The largest function bound not larger than pc was the end of a function, + // not the start of one. + // - The largest function bound not larger than pc was the start of a function + // that we don't know the end of, and the PC is much larger than the start. + if i == -1 || p[i].entry == nil || (i+1 == len(p) && pc-p[i].pc >= 1<<20) { + return nil, 0, fmt.Errorf("no function at %x", pc) + } + return p[i].entry, p[i].pc, nil +} diff --git a/vendor/golang.org/x/debug/dwarf/type.go b/vendor/golang.org/x/debug/dwarf/type.go new file mode 100644 index 0000000..ae1a3f3 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/type.go @@ -0,0 +1,862 @@ +// 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. + +// DWARF type information structures. +// The format is heavily biased toward C, but for simplicity +// the String methods use a pseudo-Go syntax. + +package dwarf + +import ( + "fmt" + "reflect" + "strconv" +) + +// A Type conventionally represents a pointer to any of the +// specific Type structures (CharType, StructType, etc.). +type Type interface { + Common() *CommonType + String() string + Size() int64 +} + +// A CommonType holds fields common to multiple types. +// If a field is not known or not applicable for a given type, +// the zero value is used. +type CommonType struct { + ByteSize int64 // size of value of this type, in bytes + Name string // name that can be used to refer to type + ReflectKind reflect.Kind // the reflect kind of the type. + Offset Offset // the offset at which this type was read +} + +func (c *CommonType) Common() *CommonType { return c } + +func (c *CommonType) Size() int64 { return c.ByteSize } + +// Basic types + +// A BasicType holds fields common to all basic types. +type BasicType struct { + CommonType + BitSize int64 + BitOffset int64 +} + +func (b *BasicType) Basic() *BasicType { return b } + +func (t *BasicType) String() string { + if t.Name != "" { + return t.Name + } + return "?" +} + +// A CharType represents a signed character type. +type CharType struct { + BasicType +} + +// A UcharType represents an unsigned character type. +type UcharType struct { + BasicType +} + +// An IntType represents a signed integer type. +type IntType struct { + BasicType +} + +// A UintType represents an unsigned integer type. +type UintType struct { + BasicType +} + +// A FloatType represents a floating point type. +type FloatType struct { + BasicType +} + +// A ComplexType represents a complex floating point type. +type ComplexType struct { + BasicType +} + +// A BoolType represents a boolean type. +type BoolType struct { + BasicType +} + +// An AddrType represents a machine address type. +type AddrType struct { + BasicType +} + +// An UnspecifiedType represents an implicit, unknown, ambiguous or nonexistent type. +type UnspecifiedType struct { + BasicType +} + +// qualifiers + +// A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier. +type QualType struct { + CommonType + Qual string + Type Type +} + +func (t *QualType) String() string { return t.Qual + " " + t.Type.String() } + +func (t *QualType) Size() int64 { return t.Type.Size() } + +// An ArrayType represents a fixed size array type. +type ArrayType struct { + CommonType + Type Type + StrideBitSize int64 // if > 0, number of bits to hold each element + Count int64 // if == -1, an incomplete array, like char x[]. +} + +func (t *ArrayType) String() string { + return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String() +} + +func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() } + +// A VoidType represents the C void type. +type VoidType struct { + CommonType +} + +func (t *VoidType) String() string { return "void" } + +// A PtrType represents a pointer type. +type PtrType struct { + CommonType + Type Type +} + +func (t *PtrType) String() string { return "*" + t.Type.String() } + +// A StructType represents a struct, union, or C++ class type. +type StructType struct { + CommonType + StructName string + Kind string // "struct", "union", or "class". + Field []*StructField + Incomplete bool // if true, struct, union, class is declared but not defined +} + +// A StructField represents a field in a struct, union, or C++ class type. +type StructField struct { + Name string + Type Type + ByteOffset int64 + ByteSize int64 + BitOffset int64 // within the ByteSize bytes at ByteOffset + BitSize int64 // zero if not a bit field +} + +func (t *StructType) String() string { + if t.StructName != "" { + return t.Kind + " " + t.StructName + } + return t.Defn() +} + +func (t *StructType) Defn() string { + s := t.Kind + if t.StructName != "" { + s += " " + t.StructName + } + if t.Incomplete { + s += " /*incomplete*/" + return s + } + s += " {" + for i, f := range t.Field { + if i > 0 { + s += "; " + } + s += f.Name + " " + f.Type.String() + s += "@" + strconv.FormatInt(f.ByteOffset, 10) + if f.BitSize > 0 { + s += " : " + strconv.FormatInt(f.BitSize, 10) + s += "@" + strconv.FormatInt(f.BitOffset, 10) + } + } + s += "}" + return s +} + +// A SliceType represents a Go slice type. It looks like a StructType, describing +// the runtime-internal structure, with extra fields. +type SliceType struct { + StructType + ElemType Type +} + +func (t *SliceType) String() string { + if t.Name != "" { + return t.Name + } + return "[]" + t.ElemType.String() +} + +// A StringType represents a Go string type. It looks like a StructType, describing +// the runtime-internal structure, but we wrap it for neatness. +type StringType struct { + StructType +} + +func (t *StringType) String() string { + if t.Name != "" { + return t.Name + } + return "string" +} + +// An InterfaceType represents a Go interface. +type InterfaceType struct { + TypedefType +} + +func (t *InterfaceType) String() string { + if t.Name != "" { + return t.Name + } + return "Interface" +} + +// An EnumType represents an enumerated type. +// The only indication of its native integer type is its ByteSize +// (inside CommonType). +type EnumType struct { + CommonType + EnumName string + Val []*EnumValue +} + +// An EnumValue represents a single enumeration value. +type EnumValue struct { + Name string + Val int64 +} + +func (t *EnumType) String() string { + s := "enum" + if t.EnumName != "" { + s += " " + t.EnumName + } + s += " {" + for i, v := range t.Val { + if i > 0 { + s += "; " + } + s += v.Name + "=" + strconv.FormatInt(v.Val, 10) + } + s += "}" + return s +} + +// A FuncType represents a function type. +type FuncType struct { + CommonType + ReturnType Type + ParamType []Type +} + +func (t *FuncType) String() string { + s := "func(" + for i, t := range t.ParamType { + if i > 0 { + s += ", " + } + s += t.String() + } + s += ")" + if t.ReturnType != nil { + s += " " + t.ReturnType.String() + } + return s +} + +// A DotDotDotType represents the variadic ... function parameter. +type DotDotDotType struct { + CommonType +} + +func (t *DotDotDotType) String() string { return "..." } + +// A TypedefType represents a named type. +type TypedefType struct { + CommonType + Type Type +} + +func (t *TypedefType) String() string { return t.Name } + +func (t *TypedefType) Size() int64 { return t.Type.Size() } + +// A MapType represents a Go map type. It looks like a TypedefType, describing +// the runtime-internal structure, with extra fields. +type MapType struct { + TypedefType + KeyType Type + ElemType Type +} + +func (t *MapType) String() string { + if t.Name != "" { + return t.Name + } + return "map[" + t.KeyType.String() + "]" + t.ElemType.String() +} + +// A ChanType represents a Go channel type. +type ChanType struct { + TypedefType + ElemType Type +} + +func (t *ChanType) String() string { + if t.Name != "" { + return t.Name + } + return "chan " + t.ElemType.String() +} + +// typeReader is used to read from either the info section or the +// types section. +type typeReader interface { + Seek(Offset) + Next() (*Entry, error) + clone() typeReader + offset() Offset + // AddressSize returns the size in bytes of addresses in the current + // compilation unit. + AddressSize() int +} + +// Type reads the type at off in the DWARF ``info'' section. +func (d *Data) Type(off Offset) (Type, error) { + return d.readType("info", d.Reader(), off, d.typeCache) +} + +func getKind(e *Entry) reflect.Kind { + integer, _ := e.Val(AttrGoKind).(int64) + return reflect.Kind(integer) +} + +// readType reads a type from r at off of name using and updating a +// type cache. +func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) { + if t, ok := typeCache[off]; ok { + return t, nil + } + r.Seek(off) + e, err := r.Next() + if err != nil { + return nil, err + } + addressSize := r.AddressSize() + if e == nil || e.Offset != off { + return nil, DecodeError{name, off, "no type at offset"} + } + + // Parse type from Entry. + // Must always set typeCache[off] before calling + // d.Type recursively, to handle circular types correctly. + var typ Type + + nextDepth := 0 + + // Get next child; set err if error happens. + next := func() *Entry { + if !e.Children { + return nil + } + // Only return direct children. + // Skip over composite entries that happen to be nested + // inside this one. Most DWARF generators wouldn't generate + // such a thing, but clang does. + // See golang.org/issue/6472. + for { + kid, err1 := r.Next() + if err1 != nil { + err = err1 + return nil + } + if kid == nil { + err = DecodeError{name, r.offset(), "unexpected end of DWARF entries"} + return nil + } + if kid.Tag == 0 { + if nextDepth > 0 { + nextDepth-- + continue + } + return nil + } + if kid.Children { + nextDepth++ + } + if nextDepth > 0 { + continue + } + return kid + } + } + + // Get Type referred to by Entry's attr. + // Set err if error happens. Not having a type is an error. + typeOf := func(e *Entry, attr Attr) Type { + tval := e.Val(attr) + var t Type + switch toff := tval.(type) { + case Offset: + if t, err = d.readType(name, r.clone(), toff, typeCache); err != nil { + return nil + } + case uint64: + if t, err = d.sigToType(toff); err != nil { + return nil + } + default: + // It appears that no Type means "void". + return new(VoidType) + } + return t + } + + switch e.Tag { + case TagArrayType: + // Multi-dimensional array. (DWARF v2 §5.4) + // Attributes: + // AttrType:subtype [required] + // AttrStrideSize: distance in bits between each element of the array + // AttrStride: distance in bytes between each element of the array + // AttrByteSize: size of entire array + // Children: + // TagSubrangeType or TagEnumerationType giving one dimension. + // dimensions are in left to right order. + t := new(ArrayType) + t.Name, _ = e.Val(AttrName).(string) + t.ReflectKind = getKind(e) + typ = t + typeCache[off] = t + if t.Type = typeOf(e, AttrType); err != nil { + goto Error + } + if bytes, ok := e.Val(AttrStride).(int64); ok { + t.StrideBitSize = 8 * bytes + } else if bits, ok := e.Val(AttrStrideSize).(int64); ok { + t.StrideBitSize = bits + } else { + // If there's no stride specified, assume it's the size of the + // array's element type. + t.StrideBitSize = 8 * t.Type.Size() + } + + // Accumulate dimensions, + ndim := 0 + for kid := next(); kid != nil; kid = next() { + // TODO(rsc): Can also be TagEnumerationType + // but haven't seen that in the wild yet. + switch kid.Tag { + case TagSubrangeType: + count, ok := kid.Val(AttrCount).(int64) + if !ok { + // Old binaries may have an upper bound instead. + count, ok = kid.Val(AttrUpperBound).(int64) + if ok { + count++ // Length is one more than upper bound. + } else { + count = -1 // As in x[]. + } + } + if ndim == 0 { + t.Count = count + } else { + // Multidimensional array. + // Create new array type underneath this one. + t.Type = &ArrayType{Type: t.Type, Count: count} + } + ndim++ + case TagEnumerationType: + err = DecodeError{name, kid.Offset, "cannot handle enumeration type as array bound"} + goto Error + } + } + if ndim == 0 { + // LLVM generates this for x[]. + t.Count = -1 + } + + case TagBaseType: + // Basic type. (DWARF v2 §5.1) + // Attributes: + // AttrName: name of base type in programming language of the compilation unit [required] + // AttrEncoding: encoding value for type (encFloat etc) [required] + // AttrByteSize: size of type in bytes [required] + // AttrBitOffset: for sub-byte types, size in bits + // AttrBitSize: for sub-byte types, bit offset of high order bit in the AttrByteSize bytes + name, _ := e.Val(AttrName).(string) + enc, ok := e.Val(AttrEncoding).(int64) + if !ok { + err = DecodeError{name, e.Offset, "missing encoding attribute for " + name} + goto Error + } + switch enc { + default: + err = DecodeError{name, e.Offset, "unrecognized encoding attribute value"} + goto Error + + case encAddress: + typ = new(AddrType) + case encBoolean: + typ = new(BoolType) + case encComplexFloat: + typ = new(ComplexType) + if name == "complex" { + // clang writes out 'complex' instead of 'complex float' or 'complex double'. + // clang also writes out a byte size that we can use to distinguish. + // See issue 8694. + switch byteSize, _ := e.Val(AttrByteSize).(int64); byteSize { + case 8: + name = "complex float" + case 16: + name = "complex double" + } + } + case encFloat: + typ = new(FloatType) + case encSigned: + typ = new(IntType) + case encUnsigned: + typ = new(UintType) + case encSignedChar: + typ = new(CharType) + case encUnsignedChar: + typ = new(UcharType) + } + typeCache[off] = typ + t := typ.(interface { + Basic() *BasicType + }).Basic() + t.Name = name + t.BitSize, _ = e.Val(AttrBitSize).(int64) + t.BitOffset, _ = e.Val(AttrBitOffset).(int64) + t.ReflectKind = getKind(e) + + case TagClassType, TagStructType, TagUnionType: + // Structure, union, or class type. (DWARF v2 §5.5) + // Also Slices and Strings (Go-specific). + // Attributes: + // AttrName: name of struct, union, or class + // AttrByteSize: byte size [required] + // AttrDeclaration: if true, struct/union/class is incomplete + // AttrGoElem: present for slices only. + // Children: + // TagMember to describe one member. + // AttrName: name of member [required] + // AttrType: type of member [required] + // AttrByteSize: size in bytes + // AttrBitOffset: bit offset within bytes for bit fields + // AttrBitSize: bit size for bit fields + // AttrDataMemberLoc: location within struct [required for struct, class] + // There is much more to handle C++, all ignored for now. + t := new(StructType) + t.ReflectKind = getKind(e) + switch t.ReflectKind { + case reflect.Slice: + slice := new(SliceType) + slice.ElemType = typeOf(e, AttrGoElem) + t = &slice.StructType + typ = slice + case reflect.String: + str := new(StringType) + t = &str.StructType + typ = str + default: + typ = t + } + typeCache[off] = typ + switch e.Tag { + case TagClassType: + t.Kind = "class" + case TagStructType: + t.Kind = "struct" + case TagUnionType: + t.Kind = "union" + } + t.Name, _ = e.Val(AttrName).(string) + t.StructName, _ = e.Val(AttrName).(string) + t.Incomplete = e.Val(AttrDeclaration) != nil + t.Field = make([]*StructField, 0, 8) + var lastFieldType Type + var lastFieldBitOffset int64 + for kid := next(); kid != nil; kid = next() { + if kid.Tag == TagMember { + f := new(StructField) + if f.Type = typeOf(kid, AttrType); err != nil { + goto Error + } + switch loc := kid.Val(AttrDataMemberLoc).(type) { + case []byte: + // TODO: Should have original compilation + // unit here, not unknownFormat. + if len(loc) == 0 { + // Empty exprloc. f.ByteOffset=0. + break + } + b := makeBuf(d, unknownFormat{}, "location", 0, loc) + op := b.uint8() + switch op { + case opPlusUconst: + // Handle opcode sequence [DW_OP_plus_uconst ] + f.ByteOffset = int64(b.uint()) + b.assertEmpty() + case opConsts: + // Handle opcode sequence [DW_OP_consts DW_OP_plus] + f.ByteOffset = b.int() + op = b.uint8() + if op != opPlus { + err = DecodeError{name, kid.Offset, fmt.Sprintf("unexpected opcode 0x%x", op)} + goto Error + } + b.assertEmpty() + default: + err = DecodeError{name, kid.Offset, fmt.Sprintf("unexpected opcode 0x%x", op)} + goto Error + } + if b.err != nil { + err = b.err + goto Error + } + case int64: + f.ByteOffset = loc + } + + haveBitOffset := false + f.Name, _ = kid.Val(AttrName).(string) + f.ByteSize, _ = kid.Val(AttrByteSize).(int64) + f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64) + f.BitSize, _ = kid.Val(AttrBitSize).(int64) + t.Field = append(t.Field, f) + + bito := f.BitOffset + if !haveBitOffset { + bito = f.ByteOffset * 8 + } + if bito == lastFieldBitOffset && t.Kind != "union" { + // Last field was zero width. Fix array length. + // (DWARF writes out 0-length arrays as if they were 1-length arrays.) + zeroArray(lastFieldType) + } + lastFieldType = f.Type + lastFieldBitOffset = bito + } + } + if t.Kind != "union" { + b, ok := e.Val(AttrByteSize).(int64) + if ok && b*8 == lastFieldBitOffset { + // Final field must be zero width. Fix array length. + zeroArray(lastFieldType) + } + } + + case TagConstType, TagVolatileType, TagRestrictType: + // Type modifier (DWARF v2 §5.2) + // Attributes: + // AttrType: subtype + t := new(QualType) + t.Name, _ = e.Val(AttrName).(string) + t.ReflectKind = getKind(e) + typ = t + typeCache[off] = t + if t.Type = typeOf(e, AttrType); err != nil { + goto Error + } + switch e.Tag { + case TagConstType: + t.Qual = "const" + case TagRestrictType: + t.Qual = "restrict" + case TagVolatileType: + t.Qual = "volatile" + } + + case TagEnumerationType: + // Enumeration type (DWARF v2 §5.6) + // Attributes: + // AttrName: enum name if any + // AttrByteSize: bytes required to represent largest value + // Children: + // TagEnumerator: + // AttrName: name of constant + // AttrConstValue: value of constant + t := new(EnumType) + t.ReflectKind = getKind(e) + typ = t + typeCache[off] = t + t.Name, _ = e.Val(AttrName).(string) + t.EnumName, _ = e.Val(AttrName).(string) + t.Val = make([]*EnumValue, 0, 8) + for kid := next(); kid != nil; kid = next() { + if kid.Tag == TagEnumerator { + f := new(EnumValue) + f.Name, _ = kid.Val(AttrName).(string) + f.Val, _ = kid.Val(AttrConstValue).(int64) + n := len(t.Val) + if n >= cap(t.Val) { + val := make([]*EnumValue, n, n*2) + copy(val, t.Val) + t.Val = val + } + t.Val = t.Val[0 : n+1] + t.Val[n] = f + } + } + + case TagPointerType: + // Type modifier (DWARF v2 §5.2) + // Attributes: + // AttrType: subtype [not required! void* has no AttrType] + // AttrAddrClass: address class [ignored] + t := new(PtrType) + t.Name, _ = e.Val(AttrName).(string) + t.ReflectKind = getKind(e) + typ = t + typeCache[off] = t + if e.Val(AttrType) == nil { + t.Type = &VoidType{} + break + } + t.Type = typeOf(e, AttrType) + + case TagSubroutineType: + // Subroutine type. (DWARF v2 §5.7) + // Attributes: + // AttrType: type of return value if any + // AttrName: possible name of type [ignored] + // AttrPrototyped: whether used ANSI C prototype [ignored] + // Children: + // TagFormalParameter: typed parameter + // AttrType: type of parameter + // TagUnspecifiedParameter: final ... + t := new(FuncType) + t.Name, _ = e.Val(AttrName).(string) + t.ReflectKind = getKind(e) + typ = t + typeCache[off] = t + if t.ReturnType = typeOf(e, AttrType); err != nil { + goto Error + } + t.ParamType = make([]Type, 0, 8) + for kid := next(); kid != nil; kid = next() { + var tkid Type + switch kid.Tag { + default: + continue + case TagFormalParameter: + if tkid = typeOf(kid, AttrType); err != nil { + goto Error + } + case TagUnspecifiedParameters: + tkid = &DotDotDotType{} + } + t.ParamType = append(t.ParamType, tkid) + } + + case TagTypedef: + // Typedef (DWARF v2 §5.3) + // Also maps and channels (Go-specific). + // Attributes: + // AttrName: name [required] + // AttrType: type definition [required] + // AttrGoKey: present for maps. + // AttrGoElem: present for maps and channels. + t := new(TypedefType) + t.ReflectKind = getKind(e) + switch t.ReflectKind { + case reflect.Map: + m := new(MapType) + m.KeyType = typeOf(e, AttrGoKey) + m.ElemType = typeOf(e, AttrGoElem) + t = &m.TypedefType + typ = m + case reflect.Chan: + c := new(ChanType) + c.ElemType = typeOf(e, AttrGoElem) + t = &c.TypedefType + typ = c + case reflect.Interface: + it := new(InterfaceType) + t = &it.TypedefType + typ = it + default: + typ = t + } + typeCache[off] = typ + t.Name, _ = e.Val(AttrName).(string) + t.Type = typeOf(e, AttrType) + + case TagUnspecifiedType: + // Unspecified type (DWARF v3 §5.2) + // Attributes: + // AttrName: name + t := new(UnspecifiedType) + typ = t + typeCache[off] = t + t.Name, _ = e.Val(AttrName).(string) + } + + if err != nil { + goto Error + } + + typ.Common().Offset = off + + { + b, ok := e.Val(AttrByteSize).(int64) + if !ok { + b = -1 + switch t := typ.(type) { + case *TypedefType: + b = t.Type.Size() + case *MapType: + b = t.Type.Size() + case *ChanType: + b = t.Type.Size() + case *InterfaceType: + b = t.Type.Size() + case *PtrType: + b = int64(addressSize) + } + } + typ.Common().ByteSize = b + } + return typ, nil + +Error: + // If the parse fails, take the type out of the cache + // so that the next call with this offset doesn't hit + // the cache and return success. + delete(typeCache, off) + return nil, err +} + +func zeroArray(t Type) { + for { + at, ok := t.(*ArrayType) + if !ok { + break + } + at.Count = 0 + t = at.Type + } +} diff --git a/vendor/golang.org/x/debug/dwarf/typeunit.go b/vendor/golang.org/x/debug/dwarf/typeunit.go new file mode 100644 index 0000000..d93b9f5 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/typeunit.go @@ -0,0 +1,171 @@ +// 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 dwarf + +import ( + "fmt" + "strconv" +) + +// Parse the type units stored in a DWARF4 .debug_types section. Each +// type unit defines a single primary type and an 8-byte signature. +// Other sections may then use formRefSig8 to refer to the type. + +// The typeUnit format is a single type with a signature. It holds +// the same data as a compilation unit. +type typeUnit struct { + unit + toff Offset // Offset to signature type within data. + name string // Name of .debug_type section. + cache Type // Cache the type, nil to start. +} + +// Parse a .debug_types section. +func (d *Data) parseTypes(name string, types []byte) error { + b := makeBuf(d, unknownFormat{}, name, 0, types) + for len(b.data) > 0 { + base := b.off + dwarf64 := false + n := b.uint32() + if n == 0xffffffff { + n64 := b.uint64() + if n64 != uint64(uint32(n64)) { + b.error("type unit length overflow") + return b.err + } + n = uint32(n64) + dwarf64 = true + } + hdroff := b.off + vers := b.uint16() + if vers != 4 { + b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) + return b.err + } + var ao uint32 + if !dwarf64 { + ao = b.uint32() + } else { + ao64 := b.uint64() + if ao64 != uint64(uint32(ao64)) { + b.error("type unit abbrev offset overflow") + return b.err + } + ao = uint32(ao64) + } + atable, err := d.parseAbbrev(ao) + if err != nil { + return err + } + asize := b.uint8() + sig := b.uint64() + + var toff uint32 + if !dwarf64 { + toff = b.uint32() + } else { + to64 := b.uint64() + if to64 != uint64(uint32(to64)) { + b.error("type unit type offset overflow") + return b.err + } + toff = uint32(to64) + } + + boff := b.off + d.typeSigs[sig] = &typeUnit{ + unit: unit{ + base: base, + off: boff, + data: b.bytes(int(Offset(n) - (b.off - hdroff))), + atable: atable, + asize: int(asize), + vers: int(vers), + is64: dwarf64, + }, + toff: Offset(toff), + name: name, + } + if b.err != nil { + return b.err + } + } + return nil +} + +// Return the type for a type signature. +func (d *Data) sigToType(sig uint64) (Type, error) { + tu := d.typeSigs[sig] + if tu == nil { + return nil, fmt.Errorf("no type unit with signature %v", sig) + } + if tu.cache != nil { + return tu.cache, nil + } + + b := makeBuf(d, tu, tu.name, tu.off, tu.data) + r := &typeUnitReader{d: d, tu: tu, b: b} + t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type)) + if err != nil { + return nil, err + } + + tu.cache = t + return t, nil +} + +// typeUnitReader is a typeReader for a tagTypeUnit. +type typeUnitReader struct { + d *Data + tu *typeUnit + b buf + err error +} + +// Seek to a new position in the type unit. +func (tur *typeUnitReader) Seek(off Offset) { + tur.err = nil + doff := off - tur.tu.off + if doff < 0 || doff >= Offset(len(tur.tu.data)) { + tur.err = fmt.Errorf("%s: offset %d out of range; max %d", tur.tu.name, doff, len(tur.tu.data)) + return + } + tur.b = makeBuf(tur.d, tur.tu, tur.tu.name, off, tur.tu.data[doff:]) +} + +// AddressSize returns the size in bytes of addresses in the current type unit. +func (tur *typeUnitReader) AddressSize() int { + return tur.tu.unit.asize +} + +// Next reads the next Entry from the type unit. +func (tur *typeUnitReader) Next() (*Entry, error) { + if tur.err != nil { + return nil, tur.err + } + if len(tur.tu.data) == 0 { + return nil, nil + } + e := tur.b.entry(tur.tu.atable, tur.tu.base) + if tur.b.err != nil { + tur.err = tur.b.err + return nil, tur.err + } + return e, nil +} + +// clone returns a new reader for the type unit. +func (tur *typeUnitReader) clone() typeReader { + return &typeUnitReader{ + d: tur.d, + tu: tur.tu, + b: makeBuf(tur.d, tur.tu, tur.tu.name, tur.tu.off, tur.tu.data), + } +} + +// offset returns the current offset. +func (tur *typeUnitReader) offset() Offset { + return tur.b.off +} diff --git a/vendor/golang.org/x/debug/dwarf/unit.go b/vendor/golang.org/x/debug/dwarf/unit.go new file mode 100644 index 0000000..0fbc8e0 --- /dev/null +++ b/vendor/golang.org/x/debug/dwarf/unit.go @@ -0,0 +1,90 @@ +// 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 dwarf + +import "strconv" + +// DWARF debug info is split into a sequence of compilation units. +// Each unit has its own abbreviation table and address size. + +type unit struct { + base Offset // byte offset of header within the aggregate info + off Offset // byte offset of data within the aggregate info + data []byte + atable abbrevTable + asize int + vers int + is64 bool // True for 64-bit DWARF format +} + +// Implement the dataFormat interface. + +func (u *unit) version() int { + return u.vers +} + +func (u *unit) dwarf64() (bool, bool) { + return u.is64, true +} + +func (u *unit) addrsize() int { + return u.asize +} + +func (d *Data) parseUnits() ([]unit, error) { + // Count units. + nunit := 0 + b := makeBuf(d, unknownFormat{}, "info", 0, d.info) + for len(b.data) > 0 { + len := b.uint32() + if len == 0xffffffff { + len64 := b.uint64() + if len64 != uint64(uint32(len64)) { + b.error("unit length overflow") + break + } + len = uint32(len64) + } + b.skip(int(len)) + nunit++ + } + if b.err != nil { + return nil, b.err + } + + // Again, this time writing them down. + b = makeBuf(d, unknownFormat{}, "info", 0, d.info) + units := make([]unit, nunit) + for i := range units { + u := &units[i] + u.base = b.off + n := b.uint32() + if n == 0xffffffff { + u.is64 = true + n = uint32(b.uint64()) + } + vers := b.uint16() + if vers != 2 && vers != 3 && vers != 4 { + b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) + break + } + u.vers = int(vers) + atable, err := d.parseAbbrev(b.uint32()) + if err != nil { + if b.err == nil { + b.err = err + } + break + } + u.atable = atable + u.asize = int(b.uint8()) + u.off = b.off + u.data = b.bytes(int(n - (2 + 4 + 1))) + } + if b.err != nil { + return nil, b.err + } + return units, nil +} diff --git a/vendor/golang.org/x/debug/elf/elf.go b/vendor/golang.org/x/debug/elf/elf.go new file mode 100644 index 0000000..03e42b0 --- /dev/null +++ b/vendor/golang.org/x/debug/elf/elf.go @@ -0,0 +1,1521 @@ +/* + * ELF constants and data structures + * + * Derived from: + * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $ + * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $ + * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $ + * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $ + * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $ + * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $ + * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $ + * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $ + * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $ + * + * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. + * Copyright (c) 2001 David E. O'Brien + * Portions Copyright 2009 The Go Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +package elf + +import "strconv" + +/* + * Constants + */ + +// Indexes into the Header.Ident array. +const ( + EI_CLASS = 4 /* Class of machine. */ + EI_DATA = 5 /* Data format. */ + EI_VERSION = 6 /* ELF format version. */ + EI_OSABI = 7 /* Operating system / ABI identification */ + EI_ABIVERSION = 8 /* ABI version */ + EI_PAD = 9 /* Start of padding (per SVR4 ABI). */ + EI_NIDENT = 16 /* Size of e_ident array. */ +) + +// Initial magic number for ELF files. +const ELFMAG = "\177ELF" + +// Version is found in Header.Ident[EI_VERSION] and Header.Version. +type Version byte + +const ( + EV_NONE Version = 0 + EV_CURRENT Version = 1 +) + +var versionStrings = []intName{ + {0, "EV_NONE"}, + {1, "EV_CURRENT"}, +} + +func (i Version) String() string { return stringName(uint32(i), versionStrings, false) } +func (i Version) GoString() string { return stringName(uint32(i), versionStrings, true) } + +// Class is found in Header.Ident[EI_CLASS] and Header.Class. +type Class byte + +const ( + ELFCLASSNONE Class = 0 /* Unknown class. */ + ELFCLASS32 Class = 1 /* 32-bit architecture. */ + ELFCLASS64 Class = 2 /* 64-bit architecture. */ +) + +var classStrings = []intName{ + {0, "ELFCLASSNONE"}, + {1, "ELFCLASS32"}, + {2, "ELFCLASS64"}, +} + +func (i Class) String() string { return stringName(uint32(i), classStrings, false) } +func (i Class) GoString() string { return stringName(uint32(i), classStrings, true) } + +// Data is found in Header.Ident[EI_DATA] and Header.Data. +type Data byte + +const ( + ELFDATANONE Data = 0 /* Unknown data format. */ + ELFDATA2LSB Data = 1 /* 2's complement little-endian. */ + ELFDATA2MSB Data = 2 /* 2's complement big-endian. */ +) + +var dataStrings = []intName{ + {0, "ELFDATANONE"}, + {1, "ELFDATA2LSB"}, + {2, "ELFDATA2MSB"}, +} + +func (i Data) String() string { return stringName(uint32(i), dataStrings, false) } +func (i Data) GoString() string { return stringName(uint32(i), dataStrings, true) } + +// OSABI is found in Header.Ident[EI_OSABI] and Header.OSABI. +type OSABI byte + +const ( + ELFOSABI_NONE OSABI = 0 /* UNIX System V ABI */ + ELFOSABI_HPUX OSABI = 1 /* HP-UX operating system */ + ELFOSABI_NETBSD OSABI = 2 /* NetBSD */ + ELFOSABI_LINUX OSABI = 3 /* GNU/Linux */ + ELFOSABI_HURD OSABI = 4 /* GNU/Hurd */ + ELFOSABI_86OPEN OSABI = 5 /* 86Open common IA32 ABI */ + ELFOSABI_SOLARIS OSABI = 6 /* Solaris */ + ELFOSABI_AIX OSABI = 7 /* AIX */ + ELFOSABI_IRIX OSABI = 8 /* IRIX */ + ELFOSABI_FREEBSD OSABI = 9 /* FreeBSD */ + ELFOSABI_TRU64 OSABI = 10 /* TRU64 UNIX */ + ELFOSABI_MODESTO OSABI = 11 /* Novell Modesto */ + ELFOSABI_OPENBSD OSABI = 12 /* OpenBSD */ + ELFOSABI_OPENVMS OSABI = 13 /* Open VMS */ + ELFOSABI_NSK OSABI = 14 /* HP Non-Stop Kernel */ + ELFOSABI_ARM OSABI = 97 /* ARM */ + ELFOSABI_STANDALONE OSABI = 255 /* Standalone (embedded) application */ +) + +var osabiStrings = []intName{ + {0, "ELFOSABI_NONE"}, + {1, "ELFOSABI_HPUX"}, + {2, "ELFOSABI_NETBSD"}, + {3, "ELFOSABI_LINUX"}, + {4, "ELFOSABI_HURD"}, + {5, "ELFOSABI_86OPEN"}, + {6, "ELFOSABI_SOLARIS"}, + {7, "ELFOSABI_AIX"}, + {8, "ELFOSABI_IRIX"}, + {9, "ELFOSABI_FREEBSD"}, + {10, "ELFOSABI_TRU64"}, + {11, "ELFOSABI_MODESTO"}, + {12, "ELFOSABI_OPENBSD"}, + {13, "ELFOSABI_OPENVMS"}, + {14, "ELFOSABI_NSK"}, + {97, "ELFOSABI_ARM"}, + {255, "ELFOSABI_STANDALONE"}, +} + +func (i OSABI) String() string { return stringName(uint32(i), osabiStrings, false) } +func (i OSABI) GoString() string { return stringName(uint32(i), osabiStrings, true) } + +// Type is found in Header.Type. +type Type uint16 + +const ( + ET_NONE Type = 0 /* Unknown type. */ + ET_REL Type = 1 /* Relocatable. */ + ET_EXEC Type = 2 /* Executable. */ + ET_DYN Type = 3 /* Shared object. */ + ET_CORE Type = 4 /* Core file. */ + ET_LOOS Type = 0xfe00 /* First operating system specific. */ + ET_HIOS Type = 0xfeff /* Last operating system-specific. */ + ET_LOPROC Type = 0xff00 /* First processor-specific. */ + ET_HIPROC Type = 0xffff /* Last processor-specific. */ +) + +var typeStrings = []intName{ + {0, "ET_NONE"}, + {1, "ET_REL"}, + {2, "ET_EXEC"}, + {3, "ET_DYN"}, + {4, "ET_CORE"}, + {0xfe00, "ET_LOOS"}, + {0xfeff, "ET_HIOS"}, + {0xff00, "ET_LOPROC"}, + {0xffff, "ET_HIPROC"}, +} + +func (i Type) String() string { return stringName(uint32(i), typeStrings, false) } +func (i Type) GoString() string { return stringName(uint32(i), typeStrings, true) } + +// Machine is found in Header.Machine. +type Machine uint16 + +const ( + EM_NONE Machine = 0 /* Unknown machine. */ + EM_M32 Machine = 1 /* AT&T WE32100. */ + EM_SPARC Machine = 2 /* Sun SPARC. */ + EM_386 Machine = 3 /* Intel i386. */ + EM_68K Machine = 4 /* Motorola 68000. */ + EM_88K Machine = 5 /* Motorola 88000. */ + EM_860 Machine = 7 /* Intel i860. */ + EM_MIPS Machine = 8 /* MIPS R3000 Big-Endian only. */ + EM_S370 Machine = 9 /* IBM System/370. */ + EM_MIPS_RS3_LE Machine = 10 /* MIPS R3000 Little-Endian. */ + EM_PARISC Machine = 15 /* HP PA-RISC. */ + EM_VPP500 Machine = 17 /* Fujitsu VPP500. */ + EM_SPARC32PLUS Machine = 18 /* SPARC v8plus. */ + EM_960 Machine = 19 /* Intel 80960. */ + EM_PPC Machine = 20 /* PowerPC 32-bit. */ + EM_PPC64 Machine = 21 /* PowerPC 64-bit. */ + EM_S390 Machine = 22 /* IBM System/390. */ + EM_V800 Machine = 36 /* NEC V800. */ + EM_FR20 Machine = 37 /* Fujitsu FR20. */ + EM_RH32 Machine = 38 /* TRW RH-32. */ + EM_RCE Machine = 39 /* Motorola RCE. */ + EM_ARM Machine = 40 /* ARM. */ + EM_SH Machine = 42 /* Hitachi SH. */ + EM_SPARCV9 Machine = 43 /* SPARC v9 64-bit. */ + EM_TRICORE Machine = 44 /* Siemens TriCore embedded processor. */ + EM_ARC Machine = 45 /* Argonaut RISC Core. */ + EM_H8_300 Machine = 46 /* Hitachi H8/300. */ + EM_H8_300H Machine = 47 /* Hitachi H8/300H. */ + EM_H8S Machine = 48 /* Hitachi H8S. */ + EM_H8_500 Machine = 49 /* Hitachi H8/500. */ + EM_IA_64 Machine = 50 /* Intel IA-64 Processor. */ + EM_MIPS_X Machine = 51 /* Stanford MIPS-X. */ + EM_COLDFIRE Machine = 52 /* Motorola ColdFire. */ + EM_68HC12 Machine = 53 /* Motorola M68HC12. */ + EM_MMA Machine = 54 /* Fujitsu MMA. */ + EM_PCP Machine = 55 /* Siemens PCP. */ + EM_NCPU Machine = 56 /* Sony nCPU. */ + EM_NDR1 Machine = 57 /* Denso NDR1 microprocessor. */ + EM_STARCORE Machine = 58 /* Motorola Star*Core processor. */ + EM_ME16 Machine = 59 /* Toyota ME16 processor. */ + EM_ST100 Machine = 60 /* STMicroelectronics ST100 processor. */ + EM_TINYJ Machine = 61 /* Advanced Logic Corp. TinyJ processor. */ + EM_X86_64 Machine = 62 /* Advanced Micro Devices x86-64 */ + + /* Non-standard or deprecated. */ + EM_486 Machine = 6 /* Intel i486. */ + EM_MIPS_RS4_BE Machine = 10 /* MIPS R4000 Big-Endian */ + EM_ALPHA_STD Machine = 41 /* Digital Alpha (standard value). */ + EM_ALPHA Machine = 0x9026 /* Alpha (written in the absence of an ABI) */ +) + +var machineStrings = []intName{ + {0, "EM_NONE"}, + {1, "EM_M32"}, + {2, "EM_SPARC"}, + {3, "EM_386"}, + {4, "EM_68K"}, + {5, "EM_88K"}, + {7, "EM_860"}, + {8, "EM_MIPS"}, + {9, "EM_S370"}, + {10, "EM_MIPS_RS3_LE"}, + {15, "EM_PARISC"}, + {17, "EM_VPP500"}, + {18, "EM_SPARC32PLUS"}, + {19, "EM_960"}, + {20, "EM_PPC"}, + {21, "EM_PPC64"}, + {22, "EM_S390"}, + {36, "EM_V800"}, + {37, "EM_FR20"}, + {38, "EM_RH32"}, + {39, "EM_RCE"}, + {40, "EM_ARM"}, + {42, "EM_SH"}, + {43, "EM_SPARCV9"}, + {44, "EM_TRICORE"}, + {45, "EM_ARC"}, + {46, "EM_H8_300"}, + {47, "EM_H8_300H"}, + {48, "EM_H8S"}, + {49, "EM_H8_500"}, + {50, "EM_IA_64"}, + {51, "EM_MIPS_X"}, + {52, "EM_COLDFIRE"}, + {53, "EM_68HC12"}, + {54, "EM_MMA"}, + {55, "EM_PCP"}, + {56, "EM_NCPU"}, + {57, "EM_NDR1"}, + {58, "EM_STARCORE"}, + {59, "EM_ME16"}, + {60, "EM_ST100"}, + {61, "EM_TINYJ"}, + {62, "EM_X86_64"}, + + /* Non-standard or deprecated. */ + {6, "EM_486"}, + {10, "EM_MIPS_RS4_BE"}, + {41, "EM_ALPHA_STD"}, + {0x9026, "EM_ALPHA"}, +} + +func (i Machine) String() string { return stringName(uint32(i), machineStrings, false) } +func (i Machine) GoString() string { return stringName(uint32(i), machineStrings, true) } + +// Special section indices. +type SectionIndex int + +const ( + SHN_UNDEF SectionIndex = 0 /* Undefined, missing, irrelevant. */ + SHN_LORESERVE SectionIndex = 0xff00 /* First of reserved range. */ + SHN_LOPROC SectionIndex = 0xff00 /* First processor-specific. */ + SHN_HIPROC SectionIndex = 0xff1f /* Last processor-specific. */ + SHN_LOOS SectionIndex = 0xff20 /* First operating system-specific. */ + SHN_HIOS SectionIndex = 0xff3f /* Last operating system-specific. */ + SHN_ABS SectionIndex = 0xfff1 /* Absolute values. */ + SHN_COMMON SectionIndex = 0xfff2 /* Common data. */ + SHN_XINDEX SectionIndex = 0xffff /* Escape -- index stored elsewhere. */ + SHN_HIRESERVE SectionIndex = 0xffff /* Last of reserved range. */ +) + +var shnStrings = []intName{ + {0, "SHN_UNDEF"}, + {0xff00, "SHN_LOPROC"}, + {0xff20, "SHN_LOOS"}, + {0xfff1, "SHN_ABS"}, + {0xfff2, "SHN_COMMON"}, + {0xffff, "SHN_XINDEX"}, +} + +func (i SectionIndex) String() string { return stringName(uint32(i), shnStrings, false) } +func (i SectionIndex) GoString() string { return stringName(uint32(i), shnStrings, true) } + +// Section type. +type SectionType uint32 + +const ( + SHT_NULL SectionType = 0 /* inactive */ + SHT_PROGBITS SectionType = 1 /* program defined information */ + SHT_SYMTAB SectionType = 2 /* symbol table section */ + SHT_STRTAB SectionType = 3 /* string table section */ + SHT_RELA SectionType = 4 /* relocation section with addends */ + SHT_HASH SectionType = 5 /* symbol hash table section */ + SHT_DYNAMIC SectionType = 6 /* dynamic section */ + SHT_NOTE SectionType = 7 /* note section */ + SHT_NOBITS SectionType = 8 /* no space section */ + SHT_REL SectionType = 9 /* relocation section - no addends */ + SHT_SHLIB SectionType = 10 /* reserved - purpose unknown */ + SHT_DYNSYM SectionType = 11 /* dynamic symbol table section */ + SHT_INIT_ARRAY SectionType = 14 /* Initialization function pointers. */ + SHT_FINI_ARRAY SectionType = 15 /* Termination function pointers. */ + SHT_PREINIT_ARRAY SectionType = 16 /* Pre-initialization function ptrs. */ + SHT_GROUP SectionType = 17 /* Section group. */ + SHT_SYMTAB_SHNDX SectionType = 18 /* Section indexes (see SHN_XINDEX). */ + SHT_LOOS SectionType = 0x60000000 /* First of OS specific semantics */ + SHT_GNU_ATTRIBUTES SectionType = 0x6ffffff5 /* GNU object attributes */ + SHT_GNU_HASH SectionType = 0x6ffffff6 /* GNU hash table */ + SHT_GNU_LIBLIST SectionType = 0x6ffffff7 /* GNU prelink library list */ + SHT_GNU_VERDEF SectionType = 0x6ffffffd /* GNU version definition section */ + SHT_GNU_VERNEED SectionType = 0x6ffffffe /* GNU version needs section */ + SHT_GNU_VERSYM SectionType = 0x6fffffff /* GNU version symbol table */ + SHT_HIOS SectionType = 0x6fffffff /* Last of OS specific semantics */ + SHT_LOPROC SectionType = 0x70000000 /* reserved range for processor */ + SHT_HIPROC SectionType = 0x7fffffff /* specific section header types */ + SHT_LOUSER SectionType = 0x80000000 /* reserved range for application */ + SHT_HIUSER SectionType = 0xffffffff /* specific indexes */ +) + +var shtStrings = []intName{ + {0, "SHT_NULL"}, + {1, "SHT_PROGBITS"}, + {2, "SHT_SYMTAB"}, + {3, "SHT_STRTAB"}, + {4, "SHT_RELA"}, + {5, "SHT_HASH"}, + {6, "SHT_DYNAMIC"}, + {7, "SHT_NOTE"}, + {8, "SHT_NOBITS"}, + {9, "SHT_REL"}, + {10, "SHT_SHLIB"}, + {11, "SHT_DYNSYM"}, + {14, "SHT_INIT_ARRAY"}, + {15, "SHT_FINI_ARRAY"}, + {16, "SHT_PREINIT_ARRAY"}, + {17, "SHT_GROUP"}, + {18, "SHT_SYMTAB_SHNDX"}, + {0x60000000, "SHT_LOOS"}, + {0x6ffffff5, "SHT_GNU_ATTRIBUTES"}, + {0x6ffffff6, "SHT_GNU_HASH"}, + {0x6ffffff7, "SHT_GNU_LIBLIST"}, + {0x6ffffffd, "SHT_GNU_VERDEF"}, + {0x6ffffffe, "SHT_GNU_VERNEED"}, + {0x6fffffff, "SHT_GNU_VERSYM"}, + {0x70000000, "SHT_LOPROC"}, + {0x7fffffff, "SHT_HIPROC"}, + {0x80000000, "SHT_LOUSER"}, + {0xffffffff, "SHT_HIUSER"}, +} + +func (i SectionType) String() string { return stringName(uint32(i), shtStrings, false) } +func (i SectionType) GoString() string { return stringName(uint32(i), shtStrings, true) } + +// Section flags. +type SectionFlag uint32 + +const ( + SHF_WRITE SectionFlag = 0x1 /* Section contains writable data. */ + SHF_ALLOC SectionFlag = 0x2 /* Section occupies memory. */ + SHF_EXECINSTR SectionFlag = 0x4 /* Section contains instructions. */ + SHF_MERGE SectionFlag = 0x10 /* Section may be merged. */ + SHF_STRINGS SectionFlag = 0x20 /* Section contains strings. */ + SHF_INFO_LINK SectionFlag = 0x40 /* sh_info holds section index. */ + SHF_LINK_ORDER SectionFlag = 0x80 /* Special ordering requirements. */ + SHF_OS_NONCONFORMING SectionFlag = 0x100 /* OS-specific processing required. */ + SHF_GROUP SectionFlag = 0x200 /* Member of section group. */ + SHF_TLS SectionFlag = 0x400 /* Section contains TLS data. */ + SHF_MASKOS SectionFlag = 0x0ff00000 /* OS-specific semantics. */ + SHF_MASKPROC SectionFlag = 0xf0000000 /* Processor-specific semantics. */ +) + +var shfStrings = []intName{ + {0x1, "SHF_WRITE"}, + {0x2, "SHF_ALLOC"}, + {0x4, "SHF_EXECINSTR"}, + {0x10, "SHF_MERGE"}, + {0x20, "SHF_STRINGS"}, + {0x40, "SHF_INFO_LINK"}, + {0x80, "SHF_LINK_ORDER"}, + {0x100, "SHF_OS_NONCONFORMING"}, + {0x200, "SHF_GROUP"}, + {0x400, "SHF_TLS"}, +} + +func (i SectionFlag) String() string { return flagName(uint32(i), shfStrings, false) } +func (i SectionFlag) GoString() string { return flagName(uint32(i), shfStrings, true) } + +// Prog.Type +type ProgType int + +const ( + PT_NULL ProgType = 0 /* Unused entry. */ + PT_LOAD ProgType = 1 /* Loadable segment. */ + PT_DYNAMIC ProgType = 2 /* Dynamic linking information segment. */ + PT_INTERP ProgType = 3 /* Pathname of interpreter. */ + PT_NOTE ProgType = 4 /* Auxiliary information. */ + PT_SHLIB ProgType = 5 /* Reserved (not used). */ + PT_PHDR ProgType = 6 /* Location of program header itself. */ + PT_TLS ProgType = 7 /* Thread local storage segment */ + PT_LOOS ProgType = 0x60000000 /* First OS-specific. */ + PT_HIOS ProgType = 0x6fffffff /* Last OS-specific. */ + PT_LOPROC ProgType = 0x70000000 /* First processor-specific type. */ + PT_HIPROC ProgType = 0x7fffffff /* Last processor-specific type. */ +) + +var ptStrings = []intName{ + {0, "PT_NULL"}, + {1, "PT_LOAD"}, + {2, "PT_DYNAMIC"}, + {3, "PT_INTERP"}, + {4, "PT_NOTE"}, + {5, "PT_SHLIB"}, + {6, "PT_PHDR"}, + {7, "PT_TLS"}, + {0x60000000, "PT_LOOS"}, + {0x6fffffff, "PT_HIOS"}, + {0x70000000, "PT_LOPROC"}, + {0x7fffffff, "PT_HIPROC"}, +} + +func (i ProgType) String() string { return stringName(uint32(i), ptStrings, false) } +func (i ProgType) GoString() string { return stringName(uint32(i), ptStrings, true) } + +// Prog.Flag +type ProgFlag uint32 + +const ( + PF_X ProgFlag = 0x1 /* Executable. */ + PF_W ProgFlag = 0x2 /* Writable. */ + PF_R ProgFlag = 0x4 /* Readable. */ + PF_MASKOS ProgFlag = 0x0ff00000 /* Operating system-specific. */ + PF_MASKPROC ProgFlag = 0xf0000000 /* Processor-specific. */ +) + +var pfStrings = []intName{ + {0x1, "PF_X"}, + {0x2, "PF_W"}, + {0x4, "PF_R"}, +} + +func (i ProgFlag) String() string { return flagName(uint32(i), pfStrings, false) } +func (i ProgFlag) GoString() string { return flagName(uint32(i), pfStrings, true) } + +// Dyn.Tag +type DynTag int + +const ( + DT_NULL DynTag = 0 /* Terminating entry. */ + DT_NEEDED DynTag = 1 /* String table offset of a needed shared library. */ + DT_PLTRELSZ DynTag = 2 /* Total size in bytes of PLT relocations. */ + DT_PLTGOT DynTag = 3 /* Processor-dependent address. */ + DT_HASH DynTag = 4 /* Address of symbol hash table. */ + DT_STRTAB DynTag = 5 /* Address of string table. */ + DT_SYMTAB DynTag = 6 /* Address of symbol table. */ + DT_RELA DynTag = 7 /* Address of ElfNN_Rela relocations. */ + DT_RELASZ DynTag = 8 /* Total size of ElfNN_Rela relocations. */ + DT_RELAENT DynTag = 9 /* Size of each ElfNN_Rela relocation entry. */ + DT_STRSZ DynTag = 10 /* Size of string table. */ + DT_SYMENT DynTag = 11 /* Size of each symbol table entry. */ + DT_INIT DynTag = 12 /* Address of initialization function. */ + DT_FINI DynTag = 13 /* Address of finalization function. */ + DT_SONAME DynTag = 14 /* String table offset of shared object name. */ + DT_RPATH DynTag = 15 /* String table offset of library path. [sup] */ + DT_SYMBOLIC DynTag = 16 /* Indicates "symbolic" linking. [sup] */ + DT_REL DynTag = 17 /* Address of ElfNN_Rel relocations. */ + DT_RELSZ DynTag = 18 /* Total size of ElfNN_Rel relocations. */ + DT_RELENT DynTag = 19 /* Size of each ElfNN_Rel relocation. */ + DT_PLTREL DynTag = 20 /* Type of relocation used for PLT. */ + DT_DEBUG DynTag = 21 /* Reserved (not used). */ + DT_TEXTREL DynTag = 22 /* Indicates there may be relocations in non-writable segments. [sup] */ + DT_JMPREL DynTag = 23 /* Address of PLT relocations. */ + DT_BIND_NOW DynTag = 24 /* [sup] */ + DT_INIT_ARRAY DynTag = 25 /* Address of the array of pointers to initialization functions */ + DT_FINI_ARRAY DynTag = 26 /* Address of the array of pointers to termination functions */ + DT_INIT_ARRAYSZ DynTag = 27 /* Size in bytes of the array of initialization functions. */ + DT_FINI_ARRAYSZ DynTag = 28 /* Size in bytes of the array of terminationfunctions. */ + DT_RUNPATH DynTag = 29 /* String table offset of a null-terminated library search path string. */ + DT_FLAGS DynTag = 30 /* Object specific flag values. */ + DT_ENCODING DynTag = 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', even == 'd_val' + or none */ + DT_PREINIT_ARRAY DynTag = 32 /* Address of the array of pointers to pre-initialization functions. */ + DT_PREINIT_ARRAYSZ DynTag = 33 /* Size in bytes of the array of pre-initialization functions. */ + DT_LOOS DynTag = 0x6000000d /* First OS-specific */ + DT_HIOS DynTag = 0x6ffff000 /* Last OS-specific */ + DT_VERSYM DynTag = 0x6ffffff0 + DT_VERNEED DynTag = 0x6ffffffe + DT_VERNEEDNUM DynTag = 0x6fffffff + DT_LOPROC DynTag = 0x70000000 /* First processor-specific type. */ + DT_HIPROC DynTag = 0x7fffffff /* Last processor-specific type. */ +) + +var dtStrings = []intName{ + {0, "DT_NULL"}, + {1, "DT_NEEDED"}, + {2, "DT_PLTRELSZ"}, + {3, "DT_PLTGOT"}, + {4, "DT_HASH"}, + {5, "DT_STRTAB"}, + {6, "DT_SYMTAB"}, + {7, "DT_RELA"}, + {8, "DT_RELASZ"}, + {9, "DT_RELAENT"}, + {10, "DT_STRSZ"}, + {11, "DT_SYMENT"}, + {12, "DT_INIT"}, + {13, "DT_FINI"}, + {14, "DT_SONAME"}, + {15, "DT_RPATH"}, + {16, "DT_SYMBOLIC"}, + {17, "DT_REL"}, + {18, "DT_RELSZ"}, + {19, "DT_RELENT"}, + {20, "DT_PLTREL"}, + {21, "DT_DEBUG"}, + {22, "DT_TEXTREL"}, + {23, "DT_JMPREL"}, + {24, "DT_BIND_NOW"}, + {25, "DT_INIT_ARRAY"}, + {26, "DT_FINI_ARRAY"}, + {27, "DT_INIT_ARRAYSZ"}, + {28, "DT_FINI_ARRAYSZ"}, + {29, "DT_RUNPATH"}, + {30, "DT_FLAGS"}, + {32, "DT_ENCODING"}, + {32, "DT_PREINIT_ARRAY"}, + {33, "DT_PREINIT_ARRAYSZ"}, + {0x6000000d, "DT_LOOS"}, + {0x6ffff000, "DT_HIOS"}, + {0x6ffffff0, "DT_VERSYM"}, + {0x6ffffffe, "DT_VERNEED"}, + {0x6fffffff, "DT_VERNEEDNUM"}, + {0x70000000, "DT_LOPROC"}, + {0x7fffffff, "DT_HIPROC"}, +} + +func (i DynTag) String() string { return stringName(uint32(i), dtStrings, false) } +func (i DynTag) GoString() string { return stringName(uint32(i), dtStrings, true) } + +// DT_FLAGS values. +type DynFlag int + +const ( + DF_ORIGIN DynFlag = 0x0001 /* Indicates that the object being loaded may + make reference to the + $ORIGIN substitution string */ + DF_SYMBOLIC DynFlag = 0x0002 /* Indicates "symbolic" linking. */ + DF_TEXTREL DynFlag = 0x0004 /* Indicates there may be relocations in non-writable segments. */ + DF_BIND_NOW DynFlag = 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ + DF_STATIC_TLS DynFlag = 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ +) + +var dflagStrings = []intName{ + {0x0001, "DF_ORIGIN"}, + {0x0002, "DF_SYMBOLIC"}, + {0x0004, "DF_TEXTREL"}, + {0x0008, "DF_BIND_NOW"}, + {0x0010, "DF_STATIC_TLS"}, +} + +func (i DynFlag) String() string { return flagName(uint32(i), dflagStrings, false) } +func (i DynFlag) GoString() string { return flagName(uint32(i), dflagStrings, true) } + +// NType values; used in core files. +type NType int + +const ( + NT_PRSTATUS NType = 1 /* Process status. */ + NT_FPREGSET NType = 2 /* Floating point registers. */ + NT_PRPSINFO NType = 3 /* Process state info. */ +) + +var ntypeStrings = []intName{ + {1, "NT_PRSTATUS"}, + {2, "NT_FPREGSET"}, + {3, "NT_PRPSINFO"}, +} + +func (i NType) String() string { return stringName(uint32(i), ntypeStrings, false) } +func (i NType) GoString() string { return stringName(uint32(i), ntypeStrings, true) } + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +type SymBind int + +const ( + STB_LOCAL SymBind = 0 /* Local symbol */ + STB_GLOBAL SymBind = 1 /* Global symbol */ + STB_WEAK SymBind = 2 /* like global - lower precedence */ + STB_LOOS SymBind = 10 /* Reserved range for operating system */ + STB_HIOS SymBind = 12 /* specific semantics. */ + STB_LOPROC SymBind = 13 /* reserved range for processor */ + STB_HIPROC SymBind = 15 /* specific semantics. */ +) + +var stbStrings = []intName{ + {0, "STB_LOCAL"}, + {1, "STB_GLOBAL"}, + {2, "STB_WEAK"}, + {10, "STB_LOOS"}, + {12, "STB_HIOS"}, + {13, "STB_LOPROC"}, + {15, "STB_HIPROC"}, +} + +func (i SymBind) String() string { return stringName(uint32(i), stbStrings, false) } +func (i SymBind) GoString() string { return stringName(uint32(i), stbStrings, true) } + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +type SymType int + +const ( + STT_NOTYPE SymType = 0 /* Unspecified type. */ + STT_OBJECT SymType = 1 /* Data object. */ + STT_FUNC SymType = 2 /* Function. */ + STT_SECTION SymType = 3 /* Section. */ + STT_FILE SymType = 4 /* Source file. */ + STT_COMMON SymType = 5 /* Uninitialized common block. */ + STT_TLS SymType = 6 /* TLS object. */ + STT_LOOS SymType = 10 /* Reserved range for operating system */ + STT_HIOS SymType = 12 /* specific semantics. */ + STT_LOPROC SymType = 13 /* reserved range for processor */ + STT_HIPROC SymType = 15 /* specific semantics. */ +) + +var sttStrings = []intName{ + {0, "STT_NOTYPE"}, + {1, "STT_OBJECT"}, + {2, "STT_FUNC"}, + {3, "STT_SECTION"}, + {4, "STT_FILE"}, + {5, "STT_COMMON"}, + {6, "STT_TLS"}, + {10, "STT_LOOS"}, + {12, "STT_HIOS"}, + {13, "STT_LOPROC"}, + {15, "STT_HIPROC"}, +} + +func (i SymType) String() string { return stringName(uint32(i), sttStrings, false) } +func (i SymType) GoString() string { return stringName(uint32(i), sttStrings, true) } + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +type SymVis int + +const ( + STV_DEFAULT SymVis = 0x0 /* Default visibility (see binding). */ + STV_INTERNAL SymVis = 0x1 /* Special meaning in relocatable objects. */ + STV_HIDDEN SymVis = 0x2 /* Not visible. */ + STV_PROTECTED SymVis = 0x3 /* Visible but not preemptible. */ +) + +var stvStrings = []intName{ + {0x0, "STV_DEFAULT"}, + {0x1, "STV_INTERNAL"}, + {0x2, "STV_HIDDEN"}, + {0x3, "STV_PROTECTED"}, +} + +func (i SymVis) String() string { return stringName(uint32(i), stvStrings, false) } +func (i SymVis) GoString() string { return stringName(uint32(i), stvStrings, true) } + +/* + * Relocation types. + */ + +// Relocation types for x86-64. +type R_X86_64 int + +const ( + R_X86_64_NONE R_X86_64 = 0 /* No relocation. */ + R_X86_64_64 R_X86_64 = 1 /* Add 64 bit symbol value. */ + R_X86_64_PC32 R_X86_64 = 2 /* PC-relative 32 bit signed sym value. */ + R_X86_64_GOT32 R_X86_64 = 3 /* PC-relative 32 bit GOT offset. */ + R_X86_64_PLT32 R_X86_64 = 4 /* PC-relative 32 bit PLT offset. */ + R_X86_64_COPY R_X86_64 = 5 /* Copy data from shared object. */ + R_X86_64_GLOB_DAT R_X86_64 = 6 /* Set GOT entry to data address. */ + R_X86_64_JMP_SLOT R_X86_64 = 7 /* Set GOT entry to code address. */ + R_X86_64_RELATIVE R_X86_64 = 8 /* Add load address of shared object. */ + R_X86_64_GOTPCREL R_X86_64 = 9 /* Add 32 bit signed pcrel offset to GOT. */ + R_X86_64_32 R_X86_64 = 10 /* Add 32 bit zero extended symbol value */ + R_X86_64_32S R_X86_64 = 11 /* Add 32 bit sign extended symbol value */ + R_X86_64_16 R_X86_64 = 12 /* Add 16 bit zero extended symbol value */ + R_X86_64_PC16 R_X86_64 = 13 /* Add 16 bit signed extended pc relative symbol value */ + R_X86_64_8 R_X86_64 = 14 /* Add 8 bit zero extended symbol value */ + R_X86_64_PC8 R_X86_64 = 15 /* Add 8 bit signed extended pc relative symbol value */ + R_X86_64_DTPMOD64 R_X86_64 = 16 /* ID of module containing symbol */ + R_X86_64_DTPOFF64 R_X86_64 = 17 /* Offset in TLS block */ + R_X86_64_TPOFF64 R_X86_64 = 18 /* Offset in static TLS block */ + R_X86_64_TLSGD R_X86_64 = 19 /* PC relative offset to GD GOT entry */ + R_X86_64_TLSLD R_X86_64 = 20 /* PC relative offset to LD GOT entry */ + R_X86_64_DTPOFF32 R_X86_64 = 21 /* Offset in TLS block */ + R_X86_64_GOTTPOFF R_X86_64 = 22 /* PC relative offset to IE GOT entry */ + R_X86_64_TPOFF32 R_X86_64 = 23 /* Offset in static TLS block */ +) + +var rx86_64Strings = []intName{ + {0, "R_X86_64_NONE"}, + {1, "R_X86_64_64"}, + {2, "R_X86_64_PC32"}, + {3, "R_X86_64_GOT32"}, + {4, "R_X86_64_PLT32"}, + {5, "R_X86_64_COPY"}, + {6, "R_X86_64_GLOB_DAT"}, + {7, "R_X86_64_JMP_SLOT"}, + {8, "R_X86_64_RELATIVE"}, + {9, "R_X86_64_GOTPCREL"}, + {10, "R_X86_64_32"}, + {11, "R_X86_64_32S"}, + {12, "R_X86_64_16"}, + {13, "R_X86_64_PC16"}, + {14, "R_X86_64_8"}, + {15, "R_X86_64_PC8"}, + {16, "R_X86_64_DTPMOD64"}, + {17, "R_X86_64_DTPOFF64"}, + {18, "R_X86_64_TPOFF64"}, + {19, "R_X86_64_TLSGD"}, + {20, "R_X86_64_TLSLD"}, + {21, "R_X86_64_DTPOFF32"}, + {22, "R_X86_64_GOTTPOFF"}, + {23, "R_X86_64_TPOFF32"}, +} + +func (i R_X86_64) String() string { return stringName(uint32(i), rx86_64Strings, false) } +func (i R_X86_64) GoString() string { return stringName(uint32(i), rx86_64Strings, true) } + +// Relocation types for Alpha. +type R_ALPHA int + +const ( + R_ALPHA_NONE R_ALPHA = 0 /* No reloc */ + R_ALPHA_REFLONG R_ALPHA = 1 /* Direct 32 bit */ + R_ALPHA_REFQUAD R_ALPHA = 2 /* Direct 64 bit */ + R_ALPHA_GPREL32 R_ALPHA = 3 /* GP relative 32 bit */ + R_ALPHA_LITERAL R_ALPHA = 4 /* GP relative 16 bit w/optimization */ + R_ALPHA_LITUSE R_ALPHA = 5 /* Optimization hint for LITERAL */ + R_ALPHA_GPDISP R_ALPHA = 6 /* Add displacement to GP */ + R_ALPHA_BRADDR R_ALPHA = 7 /* PC+4 relative 23 bit shifted */ + R_ALPHA_HINT R_ALPHA = 8 /* PC+4 relative 16 bit shifted */ + R_ALPHA_SREL16 R_ALPHA = 9 /* PC relative 16 bit */ + R_ALPHA_SREL32 R_ALPHA = 10 /* PC relative 32 bit */ + R_ALPHA_SREL64 R_ALPHA = 11 /* PC relative 64 bit */ + R_ALPHA_OP_PUSH R_ALPHA = 12 /* OP stack push */ + R_ALPHA_OP_STORE R_ALPHA = 13 /* OP stack pop and store */ + R_ALPHA_OP_PSUB R_ALPHA = 14 /* OP stack subtract */ + R_ALPHA_OP_PRSHIFT R_ALPHA = 15 /* OP stack right shift */ + R_ALPHA_GPVALUE R_ALPHA = 16 + R_ALPHA_GPRELHIGH R_ALPHA = 17 + R_ALPHA_GPRELLOW R_ALPHA = 18 + R_ALPHA_IMMED_GP_16 R_ALPHA = 19 + R_ALPHA_IMMED_GP_HI32 R_ALPHA = 20 + R_ALPHA_IMMED_SCN_HI32 R_ALPHA = 21 + R_ALPHA_IMMED_BR_HI32 R_ALPHA = 22 + R_ALPHA_IMMED_LO32 R_ALPHA = 23 + R_ALPHA_COPY R_ALPHA = 24 /* Copy symbol at runtime */ + R_ALPHA_GLOB_DAT R_ALPHA = 25 /* Create GOT entry */ + R_ALPHA_JMP_SLOT R_ALPHA = 26 /* Create PLT entry */ + R_ALPHA_RELATIVE R_ALPHA = 27 /* Adjust by program base */ +) + +var ralphaStrings = []intName{ + {0, "R_ALPHA_NONE"}, + {1, "R_ALPHA_REFLONG"}, + {2, "R_ALPHA_REFQUAD"}, + {3, "R_ALPHA_GPREL32"}, + {4, "R_ALPHA_LITERAL"}, + {5, "R_ALPHA_LITUSE"}, + {6, "R_ALPHA_GPDISP"}, + {7, "R_ALPHA_BRADDR"}, + {8, "R_ALPHA_HINT"}, + {9, "R_ALPHA_SREL16"}, + {10, "R_ALPHA_SREL32"}, + {11, "R_ALPHA_SREL64"}, + {12, "R_ALPHA_OP_PUSH"}, + {13, "R_ALPHA_OP_STORE"}, + {14, "R_ALPHA_OP_PSUB"}, + {15, "R_ALPHA_OP_PRSHIFT"}, + {16, "R_ALPHA_GPVALUE"}, + {17, "R_ALPHA_GPRELHIGH"}, + {18, "R_ALPHA_GPRELLOW"}, + {19, "R_ALPHA_IMMED_GP_16"}, + {20, "R_ALPHA_IMMED_GP_HI32"}, + {21, "R_ALPHA_IMMED_SCN_HI32"}, + {22, "R_ALPHA_IMMED_BR_HI32"}, + {23, "R_ALPHA_IMMED_LO32"}, + {24, "R_ALPHA_COPY"}, + {25, "R_ALPHA_GLOB_DAT"}, + {26, "R_ALPHA_JMP_SLOT"}, + {27, "R_ALPHA_RELATIVE"}, +} + +func (i R_ALPHA) String() string { return stringName(uint32(i), ralphaStrings, false) } +func (i R_ALPHA) GoString() string { return stringName(uint32(i), ralphaStrings, true) } + +// Relocation types for ARM. +type R_ARM int + +const ( + R_ARM_NONE R_ARM = 0 /* No relocation. */ + R_ARM_PC24 R_ARM = 1 + R_ARM_ABS32 R_ARM = 2 + R_ARM_REL32 R_ARM = 3 + R_ARM_PC13 R_ARM = 4 + R_ARM_ABS16 R_ARM = 5 + R_ARM_ABS12 R_ARM = 6 + R_ARM_THM_ABS5 R_ARM = 7 + R_ARM_ABS8 R_ARM = 8 + R_ARM_SBREL32 R_ARM = 9 + R_ARM_THM_PC22 R_ARM = 10 + R_ARM_THM_PC8 R_ARM = 11 + R_ARM_AMP_VCALL9 R_ARM = 12 + R_ARM_SWI24 R_ARM = 13 + R_ARM_THM_SWI8 R_ARM = 14 + R_ARM_XPC25 R_ARM = 15 + R_ARM_THM_XPC22 R_ARM = 16 + R_ARM_COPY R_ARM = 20 /* Copy data from shared object. */ + R_ARM_GLOB_DAT R_ARM = 21 /* Set GOT entry to data address. */ + R_ARM_JUMP_SLOT R_ARM = 22 /* Set GOT entry to code address. */ + R_ARM_RELATIVE R_ARM = 23 /* Add load address of shared object. */ + R_ARM_GOTOFF R_ARM = 24 /* Add GOT-relative symbol address. */ + R_ARM_GOTPC R_ARM = 25 /* Add PC-relative GOT table address. */ + R_ARM_GOT32 R_ARM = 26 /* Add PC-relative GOT offset. */ + R_ARM_PLT32 R_ARM = 27 /* Add PC-relative PLT offset. */ + R_ARM_GNU_VTENTRY R_ARM = 100 + R_ARM_GNU_VTINHERIT R_ARM = 101 + R_ARM_RSBREL32 R_ARM = 250 + R_ARM_THM_RPC22 R_ARM = 251 + R_ARM_RREL32 R_ARM = 252 + R_ARM_RABS32 R_ARM = 253 + R_ARM_RPC24 R_ARM = 254 + R_ARM_RBASE R_ARM = 255 +) + +var rarmStrings = []intName{ + {0, "R_ARM_NONE"}, + {1, "R_ARM_PC24"}, + {2, "R_ARM_ABS32"}, + {3, "R_ARM_REL32"}, + {4, "R_ARM_PC13"}, + {5, "R_ARM_ABS16"}, + {6, "R_ARM_ABS12"}, + {7, "R_ARM_THM_ABS5"}, + {8, "R_ARM_ABS8"}, + {9, "R_ARM_SBREL32"}, + {10, "R_ARM_THM_PC22"}, + {11, "R_ARM_THM_PC8"}, + {12, "R_ARM_AMP_VCALL9"}, + {13, "R_ARM_SWI24"}, + {14, "R_ARM_THM_SWI8"}, + {15, "R_ARM_XPC25"}, + {16, "R_ARM_THM_XPC22"}, + {20, "R_ARM_COPY"}, + {21, "R_ARM_GLOB_DAT"}, + {22, "R_ARM_JUMP_SLOT"}, + {23, "R_ARM_RELATIVE"}, + {24, "R_ARM_GOTOFF"}, + {25, "R_ARM_GOTPC"}, + {26, "R_ARM_GOT32"}, + {27, "R_ARM_PLT32"}, + {100, "R_ARM_GNU_VTENTRY"}, + {101, "R_ARM_GNU_VTINHERIT"}, + {250, "R_ARM_RSBREL32"}, + {251, "R_ARM_THM_RPC22"}, + {252, "R_ARM_RREL32"}, + {253, "R_ARM_RABS32"}, + {254, "R_ARM_RPC24"}, + {255, "R_ARM_RBASE"}, +} + +func (i R_ARM) String() string { return stringName(uint32(i), rarmStrings, false) } +func (i R_ARM) GoString() string { return stringName(uint32(i), rarmStrings, true) } + +// Relocation types for 386. +type R_386 int + +const ( + R_386_NONE R_386 = 0 /* No relocation. */ + R_386_32 R_386 = 1 /* Add symbol value. */ + R_386_PC32 R_386 = 2 /* Add PC-relative symbol value. */ + R_386_GOT32 R_386 = 3 /* Add PC-relative GOT offset. */ + R_386_PLT32 R_386 = 4 /* Add PC-relative PLT offset. */ + R_386_COPY R_386 = 5 /* Copy data from shared object. */ + R_386_GLOB_DAT R_386 = 6 /* Set GOT entry to data address. */ + R_386_JMP_SLOT R_386 = 7 /* Set GOT entry to code address. */ + R_386_RELATIVE R_386 = 8 /* Add load address of shared object. */ + R_386_GOTOFF R_386 = 9 /* Add GOT-relative symbol address. */ + R_386_GOTPC R_386 = 10 /* Add PC-relative GOT table address. */ + R_386_TLS_TPOFF R_386 = 14 /* Negative offset in static TLS block */ + R_386_TLS_IE R_386 = 15 /* Absolute address of GOT for -ve static TLS */ + R_386_TLS_GOTIE R_386 = 16 /* GOT entry for negative static TLS block */ + R_386_TLS_LE R_386 = 17 /* Negative offset relative to static TLS */ + R_386_TLS_GD R_386 = 18 /* 32 bit offset to GOT (index,off) pair */ + R_386_TLS_LDM R_386 = 19 /* 32 bit offset to GOT (index,zero) pair */ + R_386_TLS_GD_32 R_386 = 24 /* 32 bit offset to GOT (index,off) pair */ + R_386_TLS_GD_PUSH R_386 = 25 /* pushl instruction for Sun ABI GD sequence */ + R_386_TLS_GD_CALL R_386 = 26 /* call instruction for Sun ABI GD sequence */ + R_386_TLS_GD_POP R_386 = 27 /* popl instruction for Sun ABI GD sequence */ + R_386_TLS_LDM_32 R_386 = 28 /* 32 bit offset to GOT (index,zero) pair */ + R_386_TLS_LDM_PUSH R_386 = 29 /* pushl instruction for Sun ABI LD sequence */ + R_386_TLS_LDM_CALL R_386 = 30 /* call instruction for Sun ABI LD sequence */ + R_386_TLS_LDM_POP R_386 = 31 /* popl instruction for Sun ABI LD sequence */ + R_386_TLS_LDO_32 R_386 = 32 /* 32 bit offset from start of TLS block */ + R_386_TLS_IE_32 R_386 = 33 /* 32 bit offset to GOT static TLS offset entry */ + R_386_TLS_LE_32 R_386 = 34 /* 32 bit offset within static TLS block */ + R_386_TLS_DTPMOD32 R_386 = 35 /* GOT entry containing TLS index */ + R_386_TLS_DTPOFF32 R_386 = 36 /* GOT entry containing TLS offset */ + R_386_TLS_TPOFF32 R_386 = 37 /* GOT entry of -ve static TLS offset */ +) + +var r386Strings = []intName{ + {0, "R_386_NONE"}, + {1, "R_386_32"}, + {2, "R_386_PC32"}, + {3, "R_386_GOT32"}, + {4, "R_386_PLT32"}, + {5, "R_386_COPY"}, + {6, "R_386_GLOB_DAT"}, + {7, "R_386_JMP_SLOT"}, + {8, "R_386_RELATIVE"}, + {9, "R_386_GOTOFF"}, + {10, "R_386_GOTPC"}, + {14, "R_386_TLS_TPOFF"}, + {15, "R_386_TLS_IE"}, + {16, "R_386_TLS_GOTIE"}, + {17, "R_386_TLS_LE"}, + {18, "R_386_TLS_GD"}, + {19, "R_386_TLS_LDM"}, + {24, "R_386_TLS_GD_32"}, + {25, "R_386_TLS_GD_PUSH"}, + {26, "R_386_TLS_GD_CALL"}, + {27, "R_386_TLS_GD_POP"}, + {28, "R_386_TLS_LDM_32"}, + {29, "R_386_TLS_LDM_PUSH"}, + {30, "R_386_TLS_LDM_CALL"}, + {31, "R_386_TLS_LDM_POP"}, + {32, "R_386_TLS_LDO_32"}, + {33, "R_386_TLS_IE_32"}, + {34, "R_386_TLS_LE_32"}, + {35, "R_386_TLS_DTPMOD32"}, + {36, "R_386_TLS_DTPOFF32"}, + {37, "R_386_TLS_TPOFF32"}, +} + +func (i R_386) String() string { return stringName(uint32(i), r386Strings, false) } +func (i R_386) GoString() string { return stringName(uint32(i), r386Strings, true) } + +// Relocation types for PowerPC. +type R_PPC int + +const ( + R_PPC_NONE R_PPC = 0 /* No relocation. */ + R_PPC_ADDR32 R_PPC = 1 + R_PPC_ADDR24 R_PPC = 2 + R_PPC_ADDR16 R_PPC = 3 + R_PPC_ADDR16_LO R_PPC = 4 + R_PPC_ADDR16_HI R_PPC = 5 + R_PPC_ADDR16_HA R_PPC = 6 + R_PPC_ADDR14 R_PPC = 7 + R_PPC_ADDR14_BRTAKEN R_PPC = 8 + R_PPC_ADDR14_BRNTAKEN R_PPC = 9 + R_PPC_REL24 R_PPC = 10 + R_PPC_REL14 R_PPC = 11 + R_PPC_REL14_BRTAKEN R_PPC = 12 + R_PPC_REL14_BRNTAKEN R_PPC = 13 + R_PPC_GOT16 R_PPC = 14 + R_PPC_GOT16_LO R_PPC = 15 + R_PPC_GOT16_HI R_PPC = 16 + R_PPC_GOT16_HA R_PPC = 17 + R_PPC_PLTREL24 R_PPC = 18 + R_PPC_COPY R_PPC = 19 + R_PPC_GLOB_DAT R_PPC = 20 + R_PPC_JMP_SLOT R_PPC = 21 + R_PPC_RELATIVE R_PPC = 22 + R_PPC_LOCAL24PC R_PPC = 23 + R_PPC_UADDR32 R_PPC = 24 + R_PPC_UADDR16 R_PPC = 25 + R_PPC_REL32 R_PPC = 26 + R_PPC_PLT32 R_PPC = 27 + R_PPC_PLTREL32 R_PPC = 28 + R_PPC_PLT16_LO R_PPC = 29 + R_PPC_PLT16_HI R_PPC = 30 + R_PPC_PLT16_HA R_PPC = 31 + R_PPC_SDAREL16 R_PPC = 32 + R_PPC_SECTOFF R_PPC = 33 + R_PPC_SECTOFF_LO R_PPC = 34 + R_PPC_SECTOFF_HI R_PPC = 35 + R_PPC_SECTOFF_HA R_PPC = 36 + R_PPC_TLS R_PPC = 67 + R_PPC_DTPMOD32 R_PPC = 68 + R_PPC_TPREL16 R_PPC = 69 + R_PPC_TPREL16_LO R_PPC = 70 + R_PPC_TPREL16_HI R_PPC = 71 + R_PPC_TPREL16_HA R_PPC = 72 + R_PPC_TPREL32 R_PPC = 73 + R_PPC_DTPREL16 R_PPC = 74 + R_PPC_DTPREL16_LO R_PPC = 75 + R_PPC_DTPREL16_HI R_PPC = 76 + R_PPC_DTPREL16_HA R_PPC = 77 + R_PPC_DTPREL32 R_PPC = 78 + R_PPC_GOT_TLSGD16 R_PPC = 79 + R_PPC_GOT_TLSGD16_LO R_PPC = 80 + R_PPC_GOT_TLSGD16_HI R_PPC = 81 + R_PPC_GOT_TLSGD16_HA R_PPC = 82 + R_PPC_GOT_TLSLD16 R_PPC = 83 + R_PPC_GOT_TLSLD16_LO R_PPC = 84 + R_PPC_GOT_TLSLD16_HI R_PPC = 85 + R_PPC_GOT_TLSLD16_HA R_PPC = 86 + R_PPC_GOT_TPREL16 R_PPC = 87 + R_PPC_GOT_TPREL16_LO R_PPC = 88 + R_PPC_GOT_TPREL16_HI R_PPC = 89 + R_PPC_GOT_TPREL16_HA R_PPC = 90 + R_PPC_EMB_NADDR32 R_PPC = 101 + R_PPC_EMB_NADDR16 R_PPC = 102 + R_PPC_EMB_NADDR16_LO R_PPC = 103 + R_PPC_EMB_NADDR16_HI R_PPC = 104 + R_PPC_EMB_NADDR16_HA R_PPC = 105 + R_PPC_EMB_SDAI16 R_PPC = 106 + R_PPC_EMB_SDA2I16 R_PPC = 107 + R_PPC_EMB_SDA2REL R_PPC = 108 + R_PPC_EMB_SDA21 R_PPC = 109 + R_PPC_EMB_MRKREF R_PPC = 110 + R_PPC_EMB_RELSEC16 R_PPC = 111 + R_PPC_EMB_RELST_LO R_PPC = 112 + R_PPC_EMB_RELST_HI R_PPC = 113 + R_PPC_EMB_RELST_HA R_PPC = 114 + R_PPC_EMB_BIT_FLD R_PPC = 115 + R_PPC_EMB_RELSDA R_PPC = 116 +) + +var rppcStrings = []intName{ + {0, "R_PPC_NONE"}, + {1, "R_PPC_ADDR32"}, + {2, "R_PPC_ADDR24"}, + {3, "R_PPC_ADDR16"}, + {4, "R_PPC_ADDR16_LO"}, + {5, "R_PPC_ADDR16_HI"}, + {6, "R_PPC_ADDR16_HA"}, + {7, "R_PPC_ADDR14"}, + {8, "R_PPC_ADDR14_BRTAKEN"}, + {9, "R_PPC_ADDR14_BRNTAKEN"}, + {10, "R_PPC_REL24"}, + {11, "R_PPC_REL14"}, + {12, "R_PPC_REL14_BRTAKEN"}, + {13, "R_PPC_REL14_BRNTAKEN"}, + {14, "R_PPC_GOT16"}, + {15, "R_PPC_GOT16_LO"}, + {16, "R_PPC_GOT16_HI"}, + {17, "R_PPC_GOT16_HA"}, + {18, "R_PPC_PLTREL24"}, + {19, "R_PPC_COPY"}, + {20, "R_PPC_GLOB_DAT"}, + {21, "R_PPC_JMP_SLOT"}, + {22, "R_PPC_RELATIVE"}, + {23, "R_PPC_LOCAL24PC"}, + {24, "R_PPC_UADDR32"}, + {25, "R_PPC_UADDR16"}, + {26, "R_PPC_REL32"}, + {27, "R_PPC_PLT32"}, + {28, "R_PPC_PLTREL32"}, + {29, "R_PPC_PLT16_LO"}, + {30, "R_PPC_PLT16_HI"}, + {31, "R_PPC_PLT16_HA"}, + {32, "R_PPC_SDAREL16"}, + {33, "R_PPC_SECTOFF"}, + {34, "R_PPC_SECTOFF_LO"}, + {35, "R_PPC_SECTOFF_HI"}, + {36, "R_PPC_SECTOFF_HA"}, + + {67, "R_PPC_TLS"}, + {68, "R_PPC_DTPMOD32"}, + {69, "R_PPC_TPREL16"}, + {70, "R_PPC_TPREL16_LO"}, + {71, "R_PPC_TPREL16_HI"}, + {72, "R_PPC_TPREL16_HA"}, + {73, "R_PPC_TPREL32"}, + {74, "R_PPC_DTPREL16"}, + {75, "R_PPC_DTPREL16_LO"}, + {76, "R_PPC_DTPREL16_HI"}, + {77, "R_PPC_DTPREL16_HA"}, + {78, "R_PPC_DTPREL32"}, + {79, "R_PPC_GOT_TLSGD16"}, + {80, "R_PPC_GOT_TLSGD16_LO"}, + {81, "R_PPC_GOT_TLSGD16_HI"}, + {82, "R_PPC_GOT_TLSGD16_HA"}, + {83, "R_PPC_GOT_TLSLD16"}, + {84, "R_PPC_GOT_TLSLD16_LO"}, + {85, "R_PPC_GOT_TLSLD16_HI"}, + {86, "R_PPC_GOT_TLSLD16_HA"}, + {87, "R_PPC_GOT_TPREL16"}, + {88, "R_PPC_GOT_TPREL16_LO"}, + {89, "R_PPC_GOT_TPREL16_HI"}, + {90, "R_PPC_GOT_TPREL16_HA"}, + + {101, "R_PPC_EMB_NADDR32"}, + {102, "R_PPC_EMB_NADDR16"}, + {103, "R_PPC_EMB_NADDR16_LO"}, + {104, "R_PPC_EMB_NADDR16_HI"}, + {105, "R_PPC_EMB_NADDR16_HA"}, + {106, "R_PPC_EMB_SDAI16"}, + {107, "R_PPC_EMB_SDA2I16"}, + {108, "R_PPC_EMB_SDA2REL"}, + {109, "R_PPC_EMB_SDA21"}, + {110, "R_PPC_EMB_MRKREF"}, + {111, "R_PPC_EMB_RELSEC16"}, + {112, "R_PPC_EMB_RELST_LO"}, + {113, "R_PPC_EMB_RELST_HI"}, + {114, "R_PPC_EMB_RELST_HA"}, + {115, "R_PPC_EMB_BIT_FLD"}, + {116, "R_PPC_EMB_RELSDA"}, +} + +func (i R_PPC) String() string { return stringName(uint32(i), rppcStrings, false) } +func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) } + +// Relocation types for SPARC. +type R_SPARC int + +const ( + R_SPARC_NONE R_SPARC = 0 + R_SPARC_8 R_SPARC = 1 + R_SPARC_16 R_SPARC = 2 + R_SPARC_32 R_SPARC = 3 + R_SPARC_DISP8 R_SPARC = 4 + R_SPARC_DISP16 R_SPARC = 5 + R_SPARC_DISP32 R_SPARC = 6 + R_SPARC_WDISP30 R_SPARC = 7 + R_SPARC_WDISP22 R_SPARC = 8 + R_SPARC_HI22 R_SPARC = 9 + R_SPARC_22 R_SPARC = 10 + R_SPARC_13 R_SPARC = 11 + R_SPARC_LO10 R_SPARC = 12 + R_SPARC_GOT10 R_SPARC = 13 + R_SPARC_GOT13 R_SPARC = 14 + R_SPARC_GOT22 R_SPARC = 15 + R_SPARC_PC10 R_SPARC = 16 + R_SPARC_PC22 R_SPARC = 17 + R_SPARC_WPLT30 R_SPARC = 18 + R_SPARC_COPY R_SPARC = 19 + R_SPARC_GLOB_DAT R_SPARC = 20 + R_SPARC_JMP_SLOT R_SPARC = 21 + R_SPARC_RELATIVE R_SPARC = 22 + R_SPARC_UA32 R_SPARC = 23 + R_SPARC_PLT32 R_SPARC = 24 + R_SPARC_HIPLT22 R_SPARC = 25 + R_SPARC_LOPLT10 R_SPARC = 26 + R_SPARC_PCPLT32 R_SPARC = 27 + R_SPARC_PCPLT22 R_SPARC = 28 + R_SPARC_PCPLT10 R_SPARC = 29 + R_SPARC_10 R_SPARC = 30 + R_SPARC_11 R_SPARC = 31 + R_SPARC_64 R_SPARC = 32 + R_SPARC_OLO10 R_SPARC = 33 + R_SPARC_HH22 R_SPARC = 34 + R_SPARC_HM10 R_SPARC = 35 + R_SPARC_LM22 R_SPARC = 36 + R_SPARC_PC_HH22 R_SPARC = 37 + R_SPARC_PC_HM10 R_SPARC = 38 + R_SPARC_PC_LM22 R_SPARC = 39 + R_SPARC_WDISP16 R_SPARC = 40 + R_SPARC_WDISP19 R_SPARC = 41 + R_SPARC_GLOB_JMP R_SPARC = 42 + R_SPARC_7 R_SPARC = 43 + R_SPARC_5 R_SPARC = 44 + R_SPARC_6 R_SPARC = 45 + R_SPARC_DISP64 R_SPARC = 46 + R_SPARC_PLT64 R_SPARC = 47 + R_SPARC_HIX22 R_SPARC = 48 + R_SPARC_LOX10 R_SPARC = 49 + R_SPARC_H44 R_SPARC = 50 + R_SPARC_M44 R_SPARC = 51 + R_SPARC_L44 R_SPARC = 52 + R_SPARC_REGISTER R_SPARC = 53 + R_SPARC_UA64 R_SPARC = 54 + R_SPARC_UA16 R_SPARC = 55 +) + +var rsparcStrings = []intName{ + {0, "R_SPARC_NONE"}, + {1, "R_SPARC_8"}, + {2, "R_SPARC_16"}, + {3, "R_SPARC_32"}, + {4, "R_SPARC_DISP8"}, + {5, "R_SPARC_DISP16"}, + {6, "R_SPARC_DISP32"}, + {7, "R_SPARC_WDISP30"}, + {8, "R_SPARC_WDISP22"}, + {9, "R_SPARC_HI22"}, + {10, "R_SPARC_22"}, + {11, "R_SPARC_13"}, + {12, "R_SPARC_LO10"}, + {13, "R_SPARC_GOT10"}, + {14, "R_SPARC_GOT13"}, + {15, "R_SPARC_GOT22"}, + {16, "R_SPARC_PC10"}, + {17, "R_SPARC_PC22"}, + {18, "R_SPARC_WPLT30"}, + {19, "R_SPARC_COPY"}, + {20, "R_SPARC_GLOB_DAT"}, + {21, "R_SPARC_JMP_SLOT"}, + {22, "R_SPARC_RELATIVE"}, + {23, "R_SPARC_UA32"}, + {24, "R_SPARC_PLT32"}, + {25, "R_SPARC_HIPLT22"}, + {26, "R_SPARC_LOPLT10"}, + {27, "R_SPARC_PCPLT32"}, + {28, "R_SPARC_PCPLT22"}, + {29, "R_SPARC_PCPLT10"}, + {30, "R_SPARC_10"}, + {31, "R_SPARC_11"}, + {32, "R_SPARC_64"}, + {33, "R_SPARC_OLO10"}, + {34, "R_SPARC_HH22"}, + {35, "R_SPARC_HM10"}, + {36, "R_SPARC_LM22"}, + {37, "R_SPARC_PC_HH22"}, + {38, "R_SPARC_PC_HM10"}, + {39, "R_SPARC_PC_LM22"}, + {40, "R_SPARC_WDISP16"}, + {41, "R_SPARC_WDISP19"}, + {42, "R_SPARC_GLOB_JMP"}, + {43, "R_SPARC_7"}, + {44, "R_SPARC_5"}, + {45, "R_SPARC_6"}, + {46, "R_SPARC_DISP64"}, + {47, "R_SPARC_PLT64"}, + {48, "R_SPARC_HIX22"}, + {49, "R_SPARC_LOX10"}, + {50, "R_SPARC_H44"}, + {51, "R_SPARC_M44"}, + {52, "R_SPARC_L44"}, + {53, "R_SPARC_REGISTER"}, + {54, "R_SPARC_UA64"}, + {55, "R_SPARC_UA16"}, +} + +func (i R_SPARC) String() string { return stringName(uint32(i), rsparcStrings, false) } +func (i R_SPARC) GoString() string { return stringName(uint32(i), rsparcStrings, true) } + +// Magic number for the elf trampoline, chosen wisely to be an immediate value. +const ARM_MAGIC_TRAMP_NUMBER = 0x5c000003 + +// ELF32 File header. +type Header32 struct { + Ident [EI_NIDENT]byte /* File identification. */ + Type uint16 /* File type. */ + Machine uint16 /* Machine architecture. */ + Version uint32 /* ELF format version. */ + Entry uint32 /* Entry point. */ + Phoff uint32 /* Program header file offset. */ + Shoff uint32 /* Section header file offset. */ + Flags uint32 /* Architecture-specific flags. */ + Ehsize uint16 /* Size of ELF header in bytes. */ + Phentsize uint16 /* Size of program header entry. */ + Phnum uint16 /* Number of program header entries. */ + Shentsize uint16 /* Size of section header entry. */ + Shnum uint16 /* Number of section header entries. */ + Shstrndx uint16 /* Section name strings section. */ +} + +// ELF32 Section header. +type Section32 struct { + Name uint32 /* Section name (index into the section header string table). */ + Type uint32 /* Section type. */ + Flags uint32 /* Section flags. */ + Addr uint32 /* Address in memory image. */ + Off uint32 /* Offset in file. */ + Size uint32 /* Size in bytes. */ + Link uint32 /* Index of a related section. */ + Info uint32 /* Depends on section type. */ + Addralign uint32 /* Alignment in bytes. */ + Entsize uint32 /* Size of each entry in section. */ +} + +// ELF32 Program header. +type Prog32 struct { + Type uint32 /* Entry type. */ + Off uint32 /* File offset of contents. */ + Vaddr uint32 /* Virtual address in memory image. */ + Paddr uint32 /* Physical address (not used). */ + Filesz uint32 /* Size of contents in file. */ + Memsz uint32 /* Size of contents in memory. */ + Flags uint32 /* Access permission flags. */ + Align uint32 /* Alignment in memory and file. */ +} + +// ELF32 Dynamic structure. The ".dynamic" section contains an array of them. +type Dyn32 struct { + Tag int32 /* Entry type. */ + Val uint32 /* Integer/Address value. */ +} + +/* + * Relocation entries. + */ + +// ELF32 Relocations that don't need an addend field. +type Rel32 struct { + Off uint32 /* Location to be relocated. */ + Info uint32 /* Relocation type and symbol index. */ +} + +// ELF32 Relocations that need an addend field. +type Rela32 struct { + Off uint32 /* Location to be relocated. */ + Info uint32 /* Relocation type and symbol index. */ + Addend int32 /* Addend. */ +} + +func R_SYM32(info uint32) uint32 { return uint32(info >> 8) } +func R_TYPE32(info uint32) uint32 { return uint32(info & 0xff) } +func R_INFO32(sym, typ uint32) uint32 { return sym<<8 | typ } + +// ELF32 Symbol. +type Sym32 struct { + Name uint32 + Value uint32 + Size uint32 + Info uint8 + Other uint8 + Shndx uint16 +} + +const Sym32Size = 16 + +func ST_BIND(info uint8) SymBind { return SymBind(info >> 4) } +func ST_TYPE(info uint8) SymType { return SymType(info & 0xF) } +func ST_INFO(bind SymBind, typ SymType) uint8 { + return uint8(bind)<<4 | uint8(typ)&0xf +} +func ST_VISIBILITY(other uint8) SymVis { return SymVis(other & 3) } + +/* + * ELF64 + */ + +// ELF64 file header. +type Header64 struct { + Ident [EI_NIDENT]byte /* File identification. */ + Type uint16 /* File type. */ + Machine uint16 /* Machine architecture. */ + Version uint32 /* ELF format version. */ + Entry uint64 /* Entry point. */ + Phoff uint64 /* Program header file offset. */ + Shoff uint64 /* Section header file offset. */ + Flags uint32 /* Architecture-specific flags. */ + Ehsize uint16 /* Size of ELF header in bytes. */ + Phentsize uint16 /* Size of program header entry. */ + Phnum uint16 /* Number of program header entries. */ + Shentsize uint16 /* Size of section header entry. */ + Shnum uint16 /* Number of section header entries. */ + Shstrndx uint16 /* Section name strings section. */ +} + +// ELF64 Section header. +type Section64 struct { + Name uint32 /* Section name (index into the section header string table). */ + Type uint32 /* Section type. */ + Flags uint64 /* Section flags. */ + Addr uint64 /* Address in memory image. */ + Off uint64 /* Offset in file. */ + Size uint64 /* Size in bytes. */ + Link uint32 /* Index of a related section. */ + Info uint32 /* Depends on section type. */ + Addralign uint64 /* Alignment in bytes. */ + Entsize uint64 /* Size of each entry in section. */ +} + +// ELF64 Program header. +type Prog64 struct { + Type uint32 /* Entry type. */ + Flags uint32 /* Access permission flags. */ + Off uint64 /* File offset of contents. */ + Vaddr uint64 /* Virtual address in memory image. */ + Paddr uint64 /* Physical address (not used). */ + Filesz uint64 /* Size of contents in file. */ + Memsz uint64 /* Size of contents in memory. */ + Align uint64 /* Alignment in memory and file. */ +} + +// ELF64 Dynamic structure. The ".dynamic" section contains an array of them. +type Dyn64 struct { + Tag int64 /* Entry type. */ + Val uint64 /* Integer/address value */ +} + +/* + * Relocation entries. + */ + +/* ELF64 relocations that don't need an addend field. */ +type Rel64 struct { + Off uint64 /* Location to be relocated. */ + Info uint64 /* Relocation type and symbol index. */ +} + +/* ELF64 relocations that need an addend field. */ +type Rela64 struct { + Off uint64 /* Location to be relocated. */ + Info uint64 /* Relocation type and symbol index. */ + Addend int64 /* Addend. */ +} + +func R_SYM64(info uint64) uint32 { return uint32(info >> 32) } +func R_TYPE64(info uint64) uint32 { return uint32(info) } +func R_INFO(sym, typ uint32) uint64 { return uint64(sym)<<32 | uint64(typ) } + +// ELF64 symbol table entries. +type Sym64 struct { + Name uint32 /* String table index of name. */ + Info uint8 /* Type and binding information. */ + Other uint8 /* Reserved (not used). */ + Shndx uint16 /* Section index of symbol. */ + Value uint64 /* Symbol value. */ + Size uint64 /* Size of associated object. */ +} + +const Sym64Size = 24 + +type intName struct { + i uint32 + s string +} + +func stringName(i uint32, names []intName, goSyntax bool) string { + for _, n := range names { + if n.i == i { + if goSyntax { + return "elf." + n.s + } + return n.s + } + } + + // second pass - look for smaller to add with. + // assume sorted already + for j := len(names) - 1; j >= 0; j-- { + n := names[j] + if n.i < i { + s := n.s + if goSyntax { + s = "elf." + s + } + return s + "+" + strconv.FormatUint(uint64(i-n.i), 10) + } + } + + return strconv.FormatUint(uint64(i), 10) +} + +func flagName(i uint32, names []intName, goSyntax bool) string { + s := "" + for _, n := range names { + if n.i&i == n.i { + if len(s) > 0 { + s += "+" + } + if goSyntax { + s += "elf." + } + s += n.s + i -= n.i + } + } + if len(s) == 0 { + return "0x" + strconv.FormatUint(uint64(i), 16) + } + if i != 0 { + s += "+0x" + strconv.FormatUint(uint64(i), 16) + } + return s +} diff --git a/vendor/golang.org/x/debug/elf/file.go b/vendor/golang.org/x/debug/elf/file.go new file mode 100644 index 0000000..6946550 --- /dev/null +++ b/vendor/golang.org/x/debug/elf/file.go @@ -0,0 +1,829 @@ +// 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 elf implements access to ELF object files. +package elf + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "os" + + "golang.org/x/debug/dwarf" +) + +// TODO: error reporting detail + +/* + * Internal ELF representation + */ + +// A FileHeader represents an ELF file header. +type FileHeader struct { + Class Class + Data Data + Version Version + OSABI OSABI + ABIVersion uint8 + ByteOrder binary.ByteOrder + Type Type + Machine Machine + Entry uint64 +} + +// A File represents an open ELF file. +type File struct { + FileHeader + Sections []*Section + Progs []*Prog + closer io.Closer + gnuNeed []verneed + gnuVersym []byte +} + +// A SectionHeader represents a single ELF section header. +type SectionHeader struct { + Name string + Type SectionType + Flags SectionFlag + Addr uint64 + Offset uint64 + Size uint64 + Link uint32 + Info uint32 + Addralign uint64 + Entsize uint64 +} + +// A Section represents a single section in an ELF file. +type Section struct { + SectionHeader + + // Embed ReaderAt for ReadAt method. + // Do not embed SectionReader directly + // to avoid having Read and Seek. + // If a client wants Read and Seek it must use + // Open() to avoid fighting over the seek offset + // with other clients. + io.ReaderAt + sr *io.SectionReader +} + +// Data reads and returns the contents of the ELF section. +func (s *Section) Data() ([]byte, error) { + dat := make([]byte, s.sr.Size()) + n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } + return dat[0:n], err +} + +// stringTable reads and returns the string table given by the +// specified link value. +func (f *File) stringTable(link uint32) ([]byte, error) { + if link <= 0 || link >= uint32(len(f.Sections)) { + return nil, errors.New("section has invalid string table link") + } + return f.Sections[link].Data() +} + +// Open returns a new ReadSeeker reading the ELF section. +func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } + +// A ProgHeader represents a single ELF program header. +type ProgHeader struct { + Type ProgType + Flags ProgFlag + Off uint64 + Vaddr uint64 + Paddr uint64 + Filesz uint64 + Memsz uint64 + Align uint64 +} + +// A Prog represents a single ELF program header in an ELF binary. +type Prog struct { + ProgHeader + + // Embed ReaderAt for ReadAt method. + // Do not embed SectionReader directly + // to avoid having Read and Seek. + // If a client wants Read and Seek it must use + // Open() to avoid fighting over the seek offset + // with other clients. + io.ReaderAt + sr *io.SectionReader +} + +// Open returns a new ReadSeeker reading the ELF program body. +func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) } + +// A Symbol represents an entry in an ELF symbol table section. +type Symbol struct { + Name string + Info, Other byte + Section SectionIndex + Value, Size uint64 +} + +/* + * ELF reader + */ + +type FormatError struct { + off int64 + msg string + val interface{} +} + +func (e *FormatError) Error() string { + msg := e.msg + if e.val != nil { + msg += fmt.Sprintf(" '%v' ", e.val) + } + msg += fmt.Sprintf("in record at byte %#x", e.off) + return msg +} + +// Open opens the named file using os.Open and prepares it for use as an ELF binary. +func Open(name string) (*File, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + ff, err := NewFile(f) + if err != nil { + f.Close() + return nil, err + } + ff.closer = f + return ff, nil +} + +// Close closes the File. +// If the File was created using NewFile directly instead of Open, +// Close has no effect. +func (f *File) Close() error { + var err error + if f.closer != nil { + err = f.closer.Close() + f.closer = nil + } + return err +} + +// SectionByType returns the first section in f with the +// given type, or nil if there is no such section. +func (f *File) SectionByType(typ SectionType) *Section { + for _, s := range f.Sections { + if s.Type == typ { + return s + } + } + return nil +} + +// NewFile creates a new File for accessing an ELF binary in an underlying reader. +// The ELF binary is expected to start at position 0 in the ReaderAt. +func NewFile(r io.ReaderAt) (*File, error) { + sr := io.NewSectionReader(r, 0, 1<<63-1) + // Read and decode ELF identifier + var ident [16]uint8 + if _, err := r.ReadAt(ident[0:], 0); err != nil { + return nil, err + } + if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' { + return nil, &FormatError{0, "bad magic number", ident[0:4]} + } + + f := new(File) + f.Class = Class(ident[EI_CLASS]) + switch f.Class { + case ELFCLASS32: + case ELFCLASS64: + // ok + default: + return nil, &FormatError{0, "unknown ELF class", f.Class} + } + + f.Data = Data(ident[EI_DATA]) + switch f.Data { + case ELFDATA2LSB: + f.ByteOrder = binary.LittleEndian + case ELFDATA2MSB: + f.ByteOrder = binary.BigEndian + default: + return nil, &FormatError{0, "unknown ELF data encoding", f.Data} + } + + f.Version = Version(ident[EI_VERSION]) + if f.Version != EV_CURRENT { + return nil, &FormatError{0, "unknown ELF version", f.Version} + } + + f.OSABI = OSABI(ident[EI_OSABI]) + f.ABIVersion = ident[EI_ABIVERSION] + + // Read ELF file header + var phoff int64 + var phentsize, phnum int + var shoff int64 + var shentsize, shnum, shstrndx int + shstrndx = -1 + switch f.Class { + case ELFCLASS32: + hdr := new(Header32) + sr.Seek(0, os.SEEK_SET) + if err := binary.Read(sr, f.ByteOrder, hdr); err != nil { + return nil, err + } + f.Type = Type(hdr.Type) + f.Machine = Machine(hdr.Machine) + f.Entry = uint64(hdr.Entry) + if v := Version(hdr.Version); v != f.Version { + return nil, &FormatError{0, "mismatched ELF version", v} + } + phoff = int64(hdr.Phoff) + phentsize = int(hdr.Phentsize) + phnum = int(hdr.Phnum) + shoff = int64(hdr.Shoff) + shentsize = int(hdr.Shentsize) + shnum = int(hdr.Shnum) + shstrndx = int(hdr.Shstrndx) + case ELFCLASS64: + hdr := new(Header64) + sr.Seek(0, os.SEEK_SET) + if err := binary.Read(sr, f.ByteOrder, hdr); err != nil { + return nil, err + } + f.Type = Type(hdr.Type) + f.Machine = Machine(hdr.Machine) + f.Entry = uint64(hdr.Entry) + if v := Version(hdr.Version); v != f.Version { + return nil, &FormatError{0, "mismatched ELF version", v} + } + phoff = int64(hdr.Phoff) + phentsize = int(hdr.Phentsize) + phnum = int(hdr.Phnum) + shoff = int64(hdr.Shoff) + shentsize = int(hdr.Shentsize) + shnum = int(hdr.Shnum) + shstrndx = int(hdr.Shstrndx) + } + + if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) { + return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx} + } + + // Read program headers + f.Progs = make([]*Prog, phnum) + for i := 0; i < phnum; i++ { + off := phoff + int64(i)*int64(phentsize) + sr.Seek(off, os.SEEK_SET) + p := new(Prog) + switch f.Class { + case ELFCLASS32: + ph := new(Prog32) + if err := binary.Read(sr, f.ByteOrder, ph); err != nil { + return nil, err + } + p.ProgHeader = ProgHeader{ + Type: ProgType(ph.Type), + Flags: ProgFlag(ph.Flags), + Off: uint64(ph.Off), + Vaddr: uint64(ph.Vaddr), + Paddr: uint64(ph.Paddr), + Filesz: uint64(ph.Filesz), + Memsz: uint64(ph.Memsz), + Align: uint64(ph.Align), + } + case ELFCLASS64: + ph := new(Prog64) + if err := binary.Read(sr, f.ByteOrder, ph); err != nil { + return nil, err + } + p.ProgHeader = ProgHeader{ + Type: ProgType(ph.Type), + Flags: ProgFlag(ph.Flags), + Off: uint64(ph.Off), + Vaddr: uint64(ph.Vaddr), + Paddr: uint64(ph.Paddr), + Filesz: uint64(ph.Filesz), + Memsz: uint64(ph.Memsz), + Align: uint64(ph.Align), + } + } + p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz)) + p.ReaderAt = p.sr + f.Progs[i] = p + } + + // Read section headers + f.Sections = make([]*Section, shnum) + names := make([]uint32, shnum) + for i := 0; i < shnum; i++ { + off := shoff + int64(i)*int64(shentsize) + sr.Seek(off, os.SEEK_SET) + s := new(Section) + switch f.Class { + case ELFCLASS32: + sh := new(Section32) + if err := binary.Read(sr, f.ByteOrder, sh); err != nil { + return nil, err + } + names[i] = sh.Name + s.SectionHeader = SectionHeader{ + Type: SectionType(sh.Type), + Flags: SectionFlag(sh.Flags), + Addr: uint64(sh.Addr), + Offset: uint64(sh.Off), + Size: uint64(sh.Size), + Link: uint32(sh.Link), + Info: uint32(sh.Info), + Addralign: uint64(sh.Addralign), + Entsize: uint64(sh.Entsize), + } + case ELFCLASS64: + sh := new(Section64) + if err := binary.Read(sr, f.ByteOrder, sh); err != nil { + return nil, err + } + names[i] = sh.Name + s.SectionHeader = SectionHeader{ + Type: SectionType(sh.Type), + Flags: SectionFlag(sh.Flags), + Offset: uint64(sh.Off), + Size: uint64(sh.Size), + Addr: uint64(sh.Addr), + Link: uint32(sh.Link), + Info: uint32(sh.Info), + Addralign: uint64(sh.Addralign), + Entsize: uint64(sh.Entsize), + } + } + s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size)) + s.ReaderAt = s.sr + f.Sections[i] = s + } + + if len(f.Sections) == 0 { + return f, nil + } + + // Load section header string table. + shstrtab, err := f.Sections[shstrndx].Data() + if err != nil { + return nil, err + } + for i, s := range f.Sections { + var ok bool + s.Name, ok = getString(shstrtab, int(names[i])) + if !ok { + return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]} + } + } + + return f, nil +} + +// getSymbols returns a slice of Symbols from parsing the symbol table +// with the given type, along with the associated string table. +func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) { + switch f.Class { + case ELFCLASS64: + return f.getSymbols64(typ) + + case ELFCLASS32: + return f.getSymbols32(typ) + } + + return nil, nil, errors.New("not implemented") +} + +func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { + symtabSection := f.SectionByType(typ) + if symtabSection == nil { + return nil, nil, errors.New("no symbol section") + } + + data, err := symtabSection.Data() + if err != nil { + return nil, nil, errors.New("cannot load symbol section") + } + symtab := bytes.NewReader(data) + if symtab.Len()%Sym32Size != 0 { + return nil, nil, errors.New("length of symbol section is not a multiple of SymSize") + } + + strdata, err := f.stringTable(symtabSection.Link) + if err != nil { + return nil, nil, errors.New("cannot load string table section") + } + + // The first entry is all zeros. + var skip [Sym32Size]byte + symtab.Read(skip[:]) + + symbols := make([]Symbol, symtab.Len()/Sym32Size) + + i := 0 + var sym Sym32 + for symtab.Len() > 0 { + binary.Read(symtab, f.ByteOrder, &sym) + str, _ := getString(strdata, int(sym.Name)) + symbols[i].Name = str + symbols[i].Info = sym.Info + symbols[i].Other = sym.Other + symbols[i].Section = SectionIndex(sym.Shndx) + symbols[i].Value = uint64(sym.Value) + symbols[i].Size = uint64(sym.Size) + i++ + } + + return symbols, strdata, nil +} + +func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { + symtabSection := f.SectionByType(typ) + if symtabSection == nil { + return nil, nil, errors.New("no symbol section") + } + + data, err := symtabSection.Data() + if err != nil { + return nil, nil, errors.New("cannot load symbol section") + } + symtab := bytes.NewReader(data) + if symtab.Len()%Sym64Size != 0 { + return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size") + } + + strdata, err := f.stringTable(symtabSection.Link) + if err != nil { + return nil, nil, errors.New("cannot load string table section") + } + + // The first entry is all zeros. + var skip [Sym64Size]byte + symtab.Read(skip[:]) + + symbols := make([]Symbol, symtab.Len()/Sym64Size) + + i := 0 + var sym Sym64 + for symtab.Len() > 0 { + binary.Read(symtab, f.ByteOrder, &sym) + str, _ := getString(strdata, int(sym.Name)) + symbols[i].Name = str + symbols[i].Info = sym.Info + symbols[i].Other = sym.Other + symbols[i].Section = SectionIndex(sym.Shndx) + symbols[i].Value = sym.Value + symbols[i].Size = sym.Size + i++ + } + + return symbols, strdata, nil +} + +// getString extracts a string from an ELF string table. +func getString(section []byte, start int) (string, bool) { + if start < 0 || start >= len(section) { + return "", false + } + + for end := start; end < len(section); end++ { + if section[end] == 0 { + return string(section[start:end]), true + } + } + return "", false +} + +// Section returns a section with the given name, or nil if no such +// section exists. +func (f *File) Section(name string) *Section { + for _, s := range f.Sections { + if s.Name == name { + return s + } + } + return nil +} + +// applyRelocations applies relocations to dst. rels is a relocations section +// in RELA format. +func (f *File) applyRelocations(dst []byte, rels []byte) error { + if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 { + return f.applyRelocationsAMD64(dst, rels) + } + + return errors.New("not implemented") +} + +func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { + if len(rels)%Sym64Size != 0 { + return errors.New("length of relocation section is not a multiple of Sym64Size") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewReader(rels) + var rela Rela64 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rela) + symNo := rela.Info >> 32 + t := R_X86_64(rela.Info & 0xffff) + + if symNo == 0 || symNo > uint64(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + if SymType(sym.Info&0xf) != STT_SECTION { + // We don't handle non-section relocations for now. + continue + } + + switch t { + case R_X86_64_64: + if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) + case R_X86_64_32: + if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) + } + } + + return nil +} + +func (f *File) DWARF() (*dwarf.Data, error) { + // There are many other DWARF sections, but these + // are the required ones, and the debug/dwarf package + // does not use the others, so don't bother loading them. + // r: added line. + var names = [...]string{"abbrev", "frame", "info", "line", "str"} + var dat [len(names)][]byte + for i, name := range names { + name = ".debug_" + name + s := f.Section(name) + if s == nil { + continue + } + b, err := s.Data() + if err != nil && uint64(len(b)) < s.Size { + return nil, err + } + dat[i] = b + } + + // If there's a relocation table for .debug_info, we have to process it + // now otherwise the data in .debug_info is invalid for x86-64 objects. + rela := f.Section(".rela.debug_info") + if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 { + data, err := rela.Data() + if err != nil { + return nil, err + } + err = f.applyRelocations(dat[2], data) + if err != nil { + return nil, err + } + } + + abbrev, frame, info, line, str := dat[0], dat[1], dat[2], dat[3], dat[4] + d, err := dwarf.New(abbrev, nil, frame, info, line, nil, nil, str) + if err != nil { + return nil, err + } + + // Look for DWARF4 .debug_types sections. + for i, s := range f.Sections { + if s.Name == ".debug_types" { + b, err := s.Data() + if err != nil && uint64(len(b)) < s.Size { + return nil, err + } + + for _, r := range f.Sections { + if r.Type != SHT_RELA && r.Type != SHT_REL { + continue + } + if int(r.Info) != i { + continue + } + rd, err := r.Data() + if err != nil { + return nil, err + } + err = f.applyRelocations(b, rd) + if err != nil { + return nil, err + } + } + + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if err != nil { + return nil, err + } + } + } + + return d, nil +} + +// Symbols returns the symbol table for f. +// +// For compatibility with Go 1.0, Symbols omits the null symbol at index 0. +// After retrieving the symbols as symtab, an externally supplied index x +// corresponds to symtab[x-1], not symtab[x]. +func (f *File) Symbols() ([]Symbol, error) { + sym, _, err := f.getSymbols(SHT_SYMTAB) + return sym, err +} + +type ImportedSymbol struct { + Name string + Version string + Library string +} + +// ImportedSymbols returns the names of all symbols +// referred to by the binary f that are expected to be +// satisfied by other libraries at dynamic load time. +// It does not return weak symbols. +func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { + sym, str, err := f.getSymbols(SHT_DYNSYM) + if err != nil { + return nil, err + } + f.gnuVersionInit(str) + var all []ImportedSymbol + for i, s := range sym { + if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF { + all = append(all, ImportedSymbol{Name: s.Name}) + f.gnuVersion(i, &all[len(all)-1]) + } + } + return all, nil +} + +type verneed struct { + File string + Name string +} + +// gnuVersionInit parses the GNU version tables +// for use by calls to gnuVersion. +func (f *File) gnuVersionInit(str []byte) { + // Accumulate verneed information. + vn := f.SectionByType(SHT_GNU_VERNEED) + if vn == nil { + return + } + d, _ := vn.Data() + + var need []verneed + i := 0 + for { + if i+16 > len(d) { + break + } + vers := f.ByteOrder.Uint16(d[i : i+2]) + if vers != 1 { + break + } + cnt := f.ByteOrder.Uint16(d[i+2 : i+4]) + fileoff := f.ByteOrder.Uint32(d[i+4 : i+8]) + aux := f.ByteOrder.Uint32(d[i+8 : i+12]) + next := f.ByteOrder.Uint32(d[i+12 : i+16]) + file, _ := getString(str, int(fileoff)) + + var name string + j := i + int(aux) + for c := 0; c < int(cnt); c++ { + if j+16 > len(d) { + break + } + // hash := f.ByteOrder.Uint32(d[j:j+4]) + // flags := f.ByteOrder.Uint16(d[j+4:j+6]) + other := f.ByteOrder.Uint16(d[j+6 : j+8]) + nameoff := f.ByteOrder.Uint32(d[j+8 : j+12]) + next := f.ByteOrder.Uint32(d[j+12 : j+16]) + name, _ = getString(str, int(nameoff)) + ndx := int(other) + if ndx >= len(need) { + a := make([]verneed, 2*(ndx+1)) + copy(a, need) + need = a + } + + need[ndx] = verneed{file, name} + if next == 0 { + break + } + j += int(next) + } + + if next == 0 { + break + } + i += int(next) + } + + // Versym parallels symbol table, indexing into verneed. + vs := f.SectionByType(SHT_GNU_VERSYM) + if vs == nil { + return + } + d, _ = vs.Data() + + f.gnuNeed = need + f.gnuVersym = d +} + +// gnuVersion adds Library and Version information to sym, +// which came from offset i of the symbol table. +func (f *File) gnuVersion(i int, sym *ImportedSymbol) { + // Each entry is two bytes. + i = (i + 1) * 2 + if i >= len(f.gnuVersym) { + return + } + j := int(f.ByteOrder.Uint16(f.gnuVersym[i:])) + if j < 2 || j >= len(f.gnuNeed) { + return + } + n := &f.gnuNeed[j] + sym.Library = n.File + sym.Version = n.Name +} + +// ImportedLibraries returns the names of all libraries +// referred to by the binary f that are expected to be +// linked with the binary at dynamic link time. +func (f *File) ImportedLibraries() ([]string, error) { + return f.DynString(DT_NEEDED) +} + +// DynString returns the strings listed for the given tag in the file's dynamic +// section. +// +// The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or +// DT_RUNPATH. +func (f *File) DynString(tag DynTag) ([]string, error) { + switch tag { + case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH: + default: + return nil, fmt.Errorf("non-string-valued tag %v", tag) + } + ds := f.SectionByType(SHT_DYNAMIC) + if ds == nil { + // not dynamic, so no libraries + return nil, nil + } + d, err := ds.Data() + if err != nil { + return nil, err + } + str, err := f.stringTable(ds.Link) + if err != nil { + return nil, err + } + var all []string + for len(d) > 0 { + var t DynTag + var v uint64 + switch f.Class { + case ELFCLASS32: + t = DynTag(f.ByteOrder.Uint32(d[0:4])) + v = uint64(f.ByteOrder.Uint32(d[4:8])) + d = d[8:] + case ELFCLASS64: + t = DynTag(f.ByteOrder.Uint64(d[0:8])) + v = f.ByteOrder.Uint64(d[8:16]) + d = d[16:] + } + if t == tag { + s, ok := getString(str, int(v)) + if ok { + all = append(all, s) + } + } + } + return all, nil +} diff --git a/vendor/golang.org/x/debug/macho/fat.go b/vendor/golang.org/x/debug/macho/fat.go new file mode 100644 index 0000000..93b8315 --- /dev/null +++ b/vendor/golang.org/x/debug/macho/fat.go @@ -0,0 +1,146 @@ +// Copyright 2014 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 macho + +import ( + "encoding/binary" + "fmt" + "io" + "os" +) + +// A FatFile is a Mach-O universal binary that contains at least one architecture. +type FatFile struct { + Magic uint32 + Arches []FatArch + closer io.Closer +} + +// A FatArchHeader represents a fat header for a specific image architecture. +type FatArchHeader struct { + Cpu Cpu + SubCpu uint32 + Offset uint32 + Size uint32 + Align uint32 +} + +const fatArchHeaderSize = 5 * 4 + +// A FatArch is a Mach-O File inside a FatFile. +type FatArch struct { + FatArchHeader + *File +} + +// ErrNotFat is returned from NewFatFile or OpenFat when the file is not a +// universal binary but may be a thin binary, based on its magic number. +var ErrNotFat = &FormatError{0, "not a fat Mach-O file", nil} + +// NewFatFile creates a new FatFile for accessing all the Mach-O images in a +// universal binary. The Mach-O binary is expected to start at position 0 in +// the ReaderAt. +func NewFatFile(r io.ReaderAt) (*FatFile, error) { + var ff FatFile + sr := io.NewSectionReader(r, 0, 1<<63-1) + + // Read the fat_header struct, which is always in big endian. + // Start with the magic number. + err := binary.Read(sr, binary.BigEndian, &ff.Magic) + if err != nil { + return nil, &FormatError{0, "error reading magic number", nil} + } else if ff.Magic != MagicFat { + // See if this is a Mach-O file via its magic number. The magic + // must be converted to little endian first though. + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], ff.Magic) + leMagic := binary.LittleEndian.Uint32(buf[:]) + if leMagic == Magic32 || leMagic == Magic64 { + return nil, ErrNotFat + } else { + return nil, &FormatError{0, "invalid magic number", nil} + } + } + offset := int64(4) + + // Read the number of FatArchHeaders that come after the fat_header. + var narch uint32 + err = binary.Read(sr, binary.BigEndian, &narch) + if err != nil { + return nil, &FormatError{offset, "invalid fat_header", nil} + } + offset += 4 + + if narch < 1 { + return nil, &FormatError{offset, "file contains no images", nil} + } + + // Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure + // there are not duplicate architectures. + seenArches := make(map[uint64]bool, narch) + // Make sure that all images are for the same MH_ type. + var machoType Type + + // Following the fat_header comes narch fat_arch structs that index + // Mach-O images further in the file. + ff.Arches = make([]FatArch, narch) + for i := uint32(0); i < narch; i++ { + fa := &ff.Arches[i] + err = binary.Read(sr, binary.BigEndian, &fa.FatArchHeader) + if err != nil { + return nil, &FormatError{offset, "invalid fat_arch header", nil} + } + offset += fatArchHeaderSize + + fr := io.NewSectionReader(r, int64(fa.Offset), int64(fa.Size)) + fa.File, err = NewFile(fr) + if err != nil { + return nil, err + } + + // Make sure the architecture for this image is not duplicate. + seenArch := (uint64(fa.Cpu) << 32) | uint64(fa.SubCpu) + if o, k := seenArches[seenArch]; o || k { + return nil, &FormatError{offset, fmt.Sprintf("duplicate architecture cpu=%v, subcpu=%#x", fa.Cpu, fa.SubCpu), nil} + } + seenArches[seenArch] = true + + // Make sure the Mach-O type matches that of the first image. + if i == 0 { + machoType = fa.Type + } else { + if fa.Type != machoType { + return nil, &FormatError{offset, fmt.Sprintf("Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)", i, fa.Type, machoType), nil} + } + } + } + + return &ff, nil +} + +// OpenFat opens the named file using os.Open and prepares it for use as a Mach-O +// universal binary. +func OpenFat(name string) (ff *FatFile, err error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + ff, err = NewFatFile(f) + if err != nil { + f.Close() + return nil, err + } + ff.closer = f + return +} + +func (ff *FatFile) Close() error { + var err error + if ff.closer != nil { + err = ff.closer.Close() + ff.closer = nil + } + return err +} diff --git a/vendor/golang.org/x/debug/macho/file.go b/vendor/golang.org/x/debug/macho/file.go new file mode 100644 index 0000000..7f59901 --- /dev/null +++ b/vendor/golang.org/x/debug/macho/file.go @@ -0,0 +1,525 @@ +// 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 macho implements access to Mach-O object files. +package macho + +// High level access to low level data structures. + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "os" + + "golang.org/x/debug/dwarf" +) + +// A File represents an open Mach-O file. +type File struct { + FileHeader + ByteOrder binary.ByteOrder + Loads []Load + Sections []*Section + + Symtab *Symtab + Dysymtab *Dysymtab + + closer io.Closer +} + +// A Load represents any Mach-O load command. +type Load interface { + Raw() []byte +} + +// A LoadBytes is the uninterpreted bytes of a Mach-O load command. +type LoadBytes []byte + +func (b LoadBytes) Raw() []byte { return b } + +// A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command. +type SegmentHeader struct { + Cmd LoadCmd + Len uint32 + Name string + Addr uint64 + Memsz uint64 + Offset uint64 + Filesz uint64 + Maxprot uint32 + Prot uint32 + Nsect uint32 + Flag uint32 +} + +// A Segment represents a Mach-O 32-bit or 64-bit load segment command. +type Segment struct { + LoadBytes + SegmentHeader + + // Embed ReaderAt for ReadAt method. + // Do not embed SectionReader directly + // to avoid having Read and Seek. + // If a client wants Read and Seek it must use + // Open() to avoid fighting over the seek offset + // with other clients. + io.ReaderAt + sr *io.SectionReader +} + +// Data reads and returns the contents of the segment. +func (s *Segment) Data() ([]byte, error) { + dat := make([]byte, s.sr.Size()) + n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } + return dat[0:n], err +} + +// Open returns a new ReadSeeker reading the segment. +func (s *Segment) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } + +type SectionHeader struct { + Name string + Seg string + Addr uint64 + Size uint64 + Offset uint32 + Align uint32 + Reloff uint32 + Nreloc uint32 + Flags uint32 +} + +type Section struct { + SectionHeader + + // Embed ReaderAt for ReadAt method. + // Do not embed SectionReader directly + // to avoid having Read and Seek. + // If a client wants Read and Seek it must use + // Open() to avoid fighting over the seek offset + // with other clients. + io.ReaderAt + sr *io.SectionReader +} + +// Data reads and returns the contents of the Mach-O section. +func (s *Section) Data() ([]byte, error) { + dat := make([]byte, s.sr.Size()) + n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } + return dat[0:n], err +} + +// Open returns a new ReadSeeker reading the Mach-O section. +func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } + +// A Dylib represents a Mach-O load dynamic library command. +type Dylib struct { + LoadBytes + Name string + Time uint32 + CurrentVersion uint32 + CompatVersion uint32 +} + +// A Symtab represents a Mach-O symbol table command. +type Symtab struct { + LoadBytes + SymtabCmd + Syms []Symbol +} + +// A Dysymtab represents a Mach-O dynamic symbol table command. +type Dysymtab struct { + LoadBytes + DysymtabCmd + IndirectSyms []uint32 // indices into Symtab.Syms +} + +/* + * Mach-O reader + */ + +// FormatError is returned by some operations if the data does +// not have the correct format for an object file. +type FormatError struct { + off int64 + msg string + val interface{} +} + +func (e *FormatError) Error() string { + msg := e.msg + if e.val != nil { + msg += fmt.Sprintf(" '%v'", e.val) + } + msg += fmt.Sprintf(" in record at byte %#x", e.off) + return msg +} + +// Open opens the named file using os.Open and prepares it for use as a Mach-O binary. +func Open(name string) (*File, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + ff, err := NewFile(f) + if err != nil { + f.Close() + return nil, err + } + ff.closer = f + return ff, nil +} + +// Close closes the File. +// If the File was created using NewFile directly instead of Open, +// Close has no effect. +func (f *File) Close() error { + var err error + if f.closer != nil { + err = f.closer.Close() + f.closer = nil + } + return err +} + +// NewFile creates a new File for accessing a Mach-O binary in an underlying reader. +// The Mach-O binary is expected to start at position 0 in the ReaderAt. +func NewFile(r io.ReaderAt) (*File, error) { + f := new(File) + sr := io.NewSectionReader(r, 0, 1<<63-1) + + // Read and decode Mach magic to determine byte order, size. + // Magic32 and Magic64 differ only in the bottom bit. + var ident [4]byte + if _, err := r.ReadAt(ident[0:], 0); err != nil { + return nil, err + } + be := binary.BigEndian.Uint32(ident[0:]) + le := binary.LittleEndian.Uint32(ident[0:]) + switch Magic32 &^ 1 { + case be &^ 1: + f.ByteOrder = binary.BigEndian + f.Magic = be + case le &^ 1: + f.ByteOrder = binary.LittleEndian + f.Magic = le + default: + return nil, &FormatError{0, "invalid magic number", nil} + } + + // Read entire file header. + if err := binary.Read(sr, f.ByteOrder, &f.FileHeader); err != nil { + return nil, err + } + + // Then load commands. + offset := int64(fileHeaderSize32) + if f.Magic == Magic64 { + offset = fileHeaderSize64 + } + dat := make([]byte, f.Cmdsz) + if _, err := r.ReadAt(dat, offset); err != nil { + return nil, err + } + f.Loads = make([]Load, f.Ncmd) + bo := f.ByteOrder + for i := range f.Loads { + // Each load command begins with uint32 command and length. + if len(dat) < 8 { + return nil, &FormatError{offset, "command block too small", nil} + } + cmd, siz := LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8]) + if siz < 8 || siz > uint32(len(dat)) { + return nil, &FormatError{offset, "invalid command block size", nil} + } + var cmddat []byte + cmddat, dat = dat[0:siz], dat[siz:] + offset += int64(siz) + var s *Segment + switch cmd { + default: + f.Loads[i] = LoadBytes(cmddat) + + case LoadCmdDylib: + var hdr DylibCmd + b := bytes.NewReader(cmddat) + if err := binary.Read(b, bo, &hdr); err != nil { + return nil, err + } + l := new(Dylib) + if hdr.Name >= uint32(len(cmddat)) { + return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name} + } + l.Name = cstring(cmddat[hdr.Name:]) + l.Time = hdr.Time + l.CurrentVersion = hdr.CurrentVersion + l.CompatVersion = hdr.CompatVersion + l.LoadBytes = LoadBytes(cmddat) + f.Loads[i] = l + + case LoadCmdSymtab: + var hdr SymtabCmd + b := bytes.NewReader(cmddat) + if err := binary.Read(b, bo, &hdr); err != nil { + return nil, err + } + strtab := make([]byte, hdr.Strsize) + if _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil { + return nil, err + } + var symsz int + if f.Magic == Magic64 { + symsz = 16 + } else { + symsz = 12 + } + symdat := make([]byte, int(hdr.Nsyms)*symsz) + if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil { + return nil, err + } + st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset) + if err != nil { + return nil, err + } + f.Loads[i] = st + f.Symtab = st + + case LoadCmdDysymtab: + var hdr DysymtabCmd + b := bytes.NewReader(cmddat) + if err := binary.Read(b, bo, &hdr); err != nil { + return nil, err + } + dat := make([]byte, hdr.Nindirectsyms*4) + if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil { + return nil, err + } + x := make([]uint32, hdr.Nindirectsyms) + if err := binary.Read(bytes.NewReader(dat), bo, x); err != nil { + return nil, err + } + st := new(Dysymtab) + st.LoadBytes = LoadBytes(cmddat) + st.DysymtabCmd = hdr + st.IndirectSyms = x + f.Loads[i] = st + f.Dysymtab = st + + case LoadCmdSegment: + var seg32 Segment32 + b := bytes.NewReader(cmddat) + if err := binary.Read(b, bo, &seg32); err != nil { + return nil, err + } + s = new(Segment) + s.LoadBytes = cmddat + s.Cmd = cmd + s.Len = siz + s.Name = cstring(seg32.Name[0:]) + s.Addr = uint64(seg32.Addr) + s.Memsz = uint64(seg32.Memsz) + s.Offset = uint64(seg32.Offset) + s.Filesz = uint64(seg32.Filesz) + s.Maxprot = seg32.Maxprot + s.Prot = seg32.Prot + s.Nsect = seg32.Nsect + s.Flag = seg32.Flag + f.Loads[i] = s + for i := 0; i < int(s.Nsect); i++ { + var sh32 Section32 + if err := binary.Read(b, bo, &sh32); err != nil { + return nil, err + } + sh := new(Section) + sh.Name = cstring(sh32.Name[0:]) + sh.Seg = cstring(sh32.Seg[0:]) + sh.Addr = uint64(sh32.Addr) + sh.Size = uint64(sh32.Size) + sh.Offset = sh32.Offset + sh.Align = sh32.Align + sh.Reloff = sh32.Reloff + sh.Nreloc = sh32.Nreloc + sh.Flags = sh32.Flags + f.pushSection(sh, r) + } + + case LoadCmdSegment64: + var seg64 Segment64 + b := bytes.NewReader(cmddat) + if err := binary.Read(b, bo, &seg64); err != nil { + return nil, err + } + s = new(Segment) + s.LoadBytes = cmddat + s.Cmd = cmd + s.Len = siz + s.Name = cstring(seg64.Name[0:]) + s.Addr = seg64.Addr + s.Memsz = seg64.Memsz + s.Offset = seg64.Offset + s.Filesz = seg64.Filesz + s.Maxprot = seg64.Maxprot + s.Prot = seg64.Prot + s.Nsect = seg64.Nsect + s.Flag = seg64.Flag + f.Loads[i] = s + for i := 0; i < int(s.Nsect); i++ { + var sh64 Section64 + if err := binary.Read(b, bo, &sh64); err != nil { + return nil, err + } + sh := new(Section) + sh.Name = cstring(sh64.Name[0:]) + sh.Seg = cstring(sh64.Seg[0:]) + sh.Addr = sh64.Addr + sh.Size = sh64.Size + sh.Offset = sh64.Offset + sh.Align = sh64.Align + sh.Reloff = sh64.Reloff + sh.Nreloc = sh64.Nreloc + sh.Flags = sh64.Flags + f.pushSection(sh, r) + } + } + if s != nil { + s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz)) + s.ReaderAt = s.sr + } + } + return f, nil +} + +func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) { + bo := f.ByteOrder + symtab := make([]Symbol, hdr.Nsyms) + b := bytes.NewReader(symdat) + for i := range symtab { + var n Nlist64 + if f.Magic == Magic64 { + if err := binary.Read(b, bo, &n); err != nil { + return nil, err + } + } else { + var n32 Nlist32 + if err := binary.Read(b, bo, &n32); err != nil { + return nil, err + } + n.Name = n32.Name + n.Type = n32.Type + n.Sect = n32.Sect + n.Desc = n32.Desc + n.Value = uint64(n32.Value) + } + sym := &symtab[i] + if n.Name >= uint32(len(strtab)) { + return nil, &FormatError{offset, "invalid name in symbol table", n.Name} + } + sym.Name = cstring(strtab[n.Name:]) + sym.Type = n.Type + sym.Sect = n.Sect + sym.Desc = n.Desc + sym.Value = n.Value + } + st := new(Symtab) + st.LoadBytes = LoadBytes(cmddat) + st.Syms = symtab + return st, nil +} + +func (f *File) pushSection(sh *Section, r io.ReaderAt) { + f.Sections = append(f.Sections, sh) + sh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size)) + sh.ReaderAt = sh.sr +} + +func cstring(b []byte) string { + var i int + for i = 0; i < len(b) && b[i] != 0; i++ { + } + return string(b[0:i]) +} + +// Segment returns the first Segment with the given name, or nil if no such segment exists. +func (f *File) Segment(name string) *Segment { + for _, l := range f.Loads { + if s, ok := l.(*Segment); ok && s.Name == name { + return s + } + } + return nil +} + +// Section returns the first section with the given name, or nil if no such +// section exists. +func (f *File) Section(name string) *Section { + for _, s := range f.Sections { + if s.Name == name { + return s + } + } + return nil +} + +// DWARF returns the DWARF debug information for the Mach-O file. +func (f *File) DWARF() (*dwarf.Data, error) { + // There are many other DWARF sections, but these + // are the required ones, and the debug/dwarf package + // does not use the others, so don't bother loading them. + var names = [...]string{"abbrev", "frame", "info", "line", "str"} + var dat [len(names)][]byte + for i, name := range names { + name = "__debug_" + name + s := f.Section(name) + if s == nil { + continue + } + b, err := s.Data() + if err != nil && uint64(len(b)) < s.Size { + return nil, err + } + dat[i] = b + } + + abbrev, frame, info, line, str := dat[0], dat[1], dat[2], dat[3], dat[4] + return dwarf.New(abbrev, nil, frame, info, line, nil, nil, str) +} + +// ImportedSymbols returns the names of all symbols +// referred to by the binary f that are expected to be +// satisfied by other libraries at dynamic load time. +func (f *File) ImportedSymbols() ([]string, error) { + if f.Dysymtab == nil || f.Symtab == nil { + return nil, &FormatError{0, "missing symbol table", nil} + } + + st := f.Symtab + dt := f.Dysymtab + var all []string + for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] { + all = append(all, s.Name) + } + return all, nil +} + +// ImportedLibraries returns the paths of all libraries +// referred to by the binary f that are expected to be +// linked with the binary at dynamic link time. +func (f *File) ImportedLibraries() ([]string, error) { + var all []string + for _, l := range f.Loads { + if lib, ok := l.(*Dylib); ok { + all = append(all, lib.Name) + } + } + return all, nil +} diff --git a/vendor/golang.org/x/debug/macho/macho.go b/vendor/golang.org/x/debug/macho/macho.go new file mode 100644 index 0000000..d9678c8 --- /dev/null +++ b/vendor/golang.org/x/debug/macho/macho.go @@ -0,0 +1,316 @@ +// 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. + +// Mach-O header data structures +// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html + +package macho + +import "strconv" + +// A FileHeader represents a Mach-O file header. +type FileHeader struct { + Magic uint32 + Cpu Cpu + SubCpu uint32 + Type Type + Ncmd uint32 + Cmdsz uint32 + Flags uint32 +} + +const ( + fileHeaderSize32 = 7 * 4 + fileHeaderSize64 = 8 * 4 +) + +const ( + Magic32 uint32 = 0xfeedface + Magic64 uint32 = 0xfeedfacf + MagicFat uint32 = 0xcafebabe +) + +// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library. +type Type uint32 + +const ( + TypeObj Type = 1 + TypeExec Type = 2 + TypeDylib Type = 6 + TypeBundle Type = 8 +) + +// A Cpu is a Mach-O cpu type. +type Cpu uint32 + +const cpuArch64 = 0x01000000 + +const ( + Cpu386 Cpu = 7 + CpuAmd64 Cpu = Cpu386 | cpuArch64 + CpuArm Cpu = 12 + CpuPpc Cpu = 18 + CpuPpc64 Cpu = CpuPpc | cpuArch64 +) + +var cpuStrings = []intName{ + {uint32(Cpu386), "Cpu386"}, + {uint32(CpuAmd64), "CpuAmd64"}, + {uint32(CpuArm), "CpuArm"}, + {uint32(CpuPpc), "CpuPpc"}, + {uint32(CpuPpc64), "CpuPpc64"}, +} + +func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) } +func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) } + +// A LoadCmd is a Mach-O load command. +type LoadCmd uint32 + +const ( + LoadCmdSegment LoadCmd = 1 + LoadCmdSymtab LoadCmd = 2 + LoadCmdThread LoadCmd = 4 + LoadCmdUnixThread LoadCmd = 5 // thread+stack + LoadCmdDysymtab LoadCmd = 11 + LoadCmdDylib LoadCmd = 12 + LoadCmdDylinker LoadCmd = 15 + LoadCmdSegment64 LoadCmd = 25 +) + +var cmdStrings = []intName{ + {uint32(LoadCmdSegment), "LoadCmdSegment"}, + {uint32(LoadCmdThread), "LoadCmdThread"}, + {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"}, + {uint32(LoadCmdDylib), "LoadCmdDylib"}, + {uint32(LoadCmdSegment64), "LoadCmdSegment64"}, +} + +func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) } +func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) } + +// A Segment64 is a 64-bit Mach-O segment load command. +type Segment64 struct { + Cmd LoadCmd + Len uint32 + Name [16]byte + Addr uint64 + Memsz uint64 + Offset uint64 + Filesz uint64 + Maxprot uint32 + Prot uint32 + Nsect uint32 + Flag uint32 +} + +// A Segment32 is a 32-bit Mach-O segment load command. +type Segment32 struct { + Cmd LoadCmd + Len uint32 + Name [16]byte + Addr uint32 + Memsz uint32 + Offset uint32 + Filesz uint32 + Maxprot uint32 + Prot uint32 + Nsect uint32 + Flag uint32 +} + +// A DylibCmd is a Mach-O load dynamic library command. +type DylibCmd struct { + Cmd LoadCmd + Len uint32 + Name uint32 + Time uint32 + CurrentVersion uint32 + CompatVersion uint32 +} + +// A Section32 is a 32-bit Mach-O section header. +type Section32 struct { + Name [16]byte + Seg [16]byte + Addr uint32 + Size uint32 + Offset uint32 + Align uint32 + Reloff uint32 + Nreloc uint32 + Flags uint32 + Reserve1 uint32 + Reserve2 uint32 +} + +// A Section32 is a 64-bit Mach-O section header. +type Section64 struct { + Name [16]byte + Seg [16]byte + Addr uint64 + Size uint64 + Offset uint32 + Align uint32 + Reloff uint32 + Nreloc uint32 + Flags uint32 + Reserve1 uint32 + Reserve2 uint32 + Reserve3 uint32 +} + +// A SymtabCmd is a Mach-O symbol table command. +type SymtabCmd struct { + Cmd LoadCmd + Len uint32 + Symoff uint32 + Nsyms uint32 + Stroff uint32 + Strsize uint32 +} + +// A DysymtabCmd is a Mach-O dynamic symbol table command. +type DysymtabCmd struct { + Cmd LoadCmd + Len uint32 + Ilocalsym uint32 + Nlocalsym uint32 + Iextdefsym uint32 + Nextdefsym uint32 + Iundefsym uint32 + Nundefsym uint32 + Tocoffset uint32 + Ntoc uint32 + Modtaboff uint32 + Nmodtab uint32 + Extrefsymoff uint32 + Nextrefsyms uint32 + Indirectsymoff uint32 + Nindirectsyms uint32 + Extreloff uint32 + Nextrel uint32 + Locreloff uint32 + Nlocrel uint32 +} + +// An Nlist32 is a Mach-O 32-bit symbol table entry. +type Nlist32 struct { + Name uint32 + Type uint8 + Sect uint8 + Desc uint16 + Value uint32 +} + +// An Nlist64 is a Mach-O 64-bit symbol table entry. +type Nlist64 struct { + Name uint32 + Type uint8 + Sect uint8 + Desc uint16 + Value uint64 +} + +// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry. +type Symbol struct { + Name string + Type uint8 + Sect uint8 + Desc uint16 + Value uint64 +} + +// A Thread is a Mach-O thread state command. +type Thread struct { + Cmd LoadCmd + Len uint32 + Type uint32 + Data []uint32 +} + +// Regs386 is the Mach-O 386 register structure. +type Regs386 struct { + AX uint32 + BX uint32 + CX uint32 + DX uint32 + DI uint32 + SI uint32 + BP uint32 + SP uint32 + SS uint32 + FLAGS uint32 + IP uint32 + CS uint32 + DS uint32 + ES uint32 + FS uint32 + GS uint32 +} + +// RegsAMD64 is the Mach-O AMD64 register structure. +type RegsAMD64 struct { + AX uint64 + BX uint64 + CX uint64 + DX uint64 + DI uint64 + SI uint64 + BP uint64 + SP uint64 + R8 uint64 + R9 uint64 + R10 uint64 + R11 uint64 + R12 uint64 + R13 uint64 + R14 uint64 + R15 uint64 + IP uint64 + FLAGS uint64 + CS uint64 + FS uint64 + GS uint64 +} + +type intName struct { + i uint32 + s string +} + +func stringName(i uint32, names []intName, goSyntax bool) string { + for _, n := range names { + if n.i == i { + if goSyntax { + return "macho." + n.s + } + return n.s + } + } + return strconv.FormatUint(uint64(i), 10) +} + +func flagName(i uint32, names []intName, goSyntax bool) string { + s := "" + for _, n := range names { + if n.i&i == n.i { + if len(s) > 0 { + s += "+" + } + if goSyntax { + s += "macho." + } + s += n.s + i -= n.i + } + } + if len(s) == 0 { + return "0x" + strconv.FormatUint(uint64(i), 16) + } + if i != 0 { + s += "+0x" + strconv.FormatUint(uint64(i), 16) + } + return s +} diff --git a/vendor/golang.org/x/sys/windows/asm.s b/vendor/golang.org/x/sys/windows/asm.s new file mode 100644 index 0000000..d4ca868 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/asm.s @@ -0,0 +1,8 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +TEXT ·use(SB),NOSPLIT,$0 + RET diff --git a/vendor/golang.org/x/sys/windows/asm_windows_386.s b/vendor/golang.org/x/sys/windows/asm_windows_386.s new file mode 100644 index 0000000..1c20dd2 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/asm_windows_386.s @@ -0,0 +1,13 @@ +// 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. + +// +// System calls for 386, Windows are implemented in runtime/syscall_windows.goc +// + +TEXT ·getprocaddress(SB), 7, $0-8 + JMP syscall·getprocaddress(SB) + +TEXT ·loadlibrary(SB), 7, $0-4 + JMP syscall·loadlibrary(SB) diff --git a/vendor/golang.org/x/sys/windows/asm_windows_amd64.s b/vendor/golang.org/x/sys/windows/asm_windows_amd64.s new file mode 100644 index 0000000..4d025ab --- /dev/null +++ b/vendor/golang.org/x/sys/windows/asm_windows_amd64.s @@ -0,0 +1,13 @@ +// 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. + +// +// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc +// + +TEXT ·getprocaddress(SB), 7, $0-32 + JMP syscall·getprocaddress(SB) + +TEXT ·loadlibrary(SB), 7, $0-8 + JMP syscall·loadlibrary(SB) diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go new file mode 100644 index 0000000..7f9f05f --- /dev/null +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -0,0 +1,275 @@ +// 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 windows + +import ( + "sync" + "sync/atomic" + "syscall" + "unsafe" +) + +// DLLError describes reasons for DLL load failures. +type DLLError struct { + Err error + ObjName string + Msg string +} + +func (e *DLLError) Error() string { return e.Msg } + +// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file. +func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno) +func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno) + +// A DLL implements access to a single DLL. +type DLL struct { + Name string + Handle Handle +} + +// LoadDLL loads DLL file into memory. +func LoadDLL(name string) (dll *DLL, err error) { + namep, err := UTF16PtrFromString(name) + if err != nil { + return nil, err + } + h, e := loadlibrary(namep) + if e != 0 { + return nil, &DLLError{ + Err: e, + ObjName: name, + Msg: "Failed to load " + name + ": " + e.Error(), + } + } + d := &DLL{ + Name: name, + Handle: Handle(h), + } + return d, nil +} + +// MustLoadDLL is like LoadDLL but panics if load operation failes. +func MustLoadDLL(name string) *DLL { + d, e := LoadDLL(name) + if e != nil { + panic(e) + } + return d +} + +// FindProc searches DLL d for procedure named name and returns *Proc +// if found. It returns an error if search fails. +func (d *DLL) FindProc(name string) (proc *Proc, err error) { + namep, err := BytePtrFromString(name) + if err != nil { + return nil, err + } + a, e := getprocaddress(uintptr(d.Handle), namep) + if e != 0 { + return nil, &DLLError{ + Err: e, + ObjName: name, + Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(), + } + } + p := &Proc{ + Dll: d, + Name: name, + addr: a, + } + return p, nil +} + +// MustFindProc is like FindProc but panics if search fails. +func (d *DLL) MustFindProc(name string) *Proc { + p, e := d.FindProc(name) + if e != nil { + panic(e) + } + return p +} + +// Release unloads DLL d from memory. +func (d *DLL) Release() (err error) { + return FreeLibrary(d.Handle) +} + +// A Proc implements access to a procedure inside a DLL. +type Proc struct { + Dll *DLL + Name string + addr uintptr +} + +// Addr returns the address of the procedure represented by p. +// The return value can be passed to Syscall to run the procedure. +func (p *Proc) Addr() uintptr { + return p.addr +} + +// Call executes procedure p with arguments a. It will panic, if more then 15 arguments +// are supplied. +// +// The returned error is always non-nil, constructed from the result of GetLastError. +// Callers must inspect the primary return value to decide whether an error occurred +// (according to the semantics of the specific function being called) before consulting +// the error. The error will be guaranteed to contain windows.Errno. +func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) { + switch len(a) { + case 0: + return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0) + case 1: + return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0) + case 2: + return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0) + case 3: + return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2]) + case 4: + return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0) + case 5: + return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0) + case 6: + return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5]) + case 7: + return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0) + case 8: + return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0) + case 9: + return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]) + case 10: + return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0) + case 11: + return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0) + case 12: + return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]) + case 13: + return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0) + case 14: + return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0) + case 15: + return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14]) + default: + panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".") + } + return +} + +// A LazyDLL implements access to a single DLL. +// It will delay the load of the DLL until the first +// call to its Handle method or to one of its +// LazyProc's Addr method. +type LazyDLL struct { + mu sync.Mutex + dll *DLL // non nil once DLL is loaded + Name string +} + +// Load loads DLL file d.Name into memory. It returns an error if fails. +// Load will not try to load DLL, if it is already loaded into memory. +func (d *LazyDLL) Load() error { + // Non-racy version of: + // if d.dll == nil { + if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) == nil { + d.mu.Lock() + defer d.mu.Unlock() + if d.dll == nil { + dll, e := LoadDLL(d.Name) + if e != nil { + return e + } + // Non-racy version of: + // d.dll = dll + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll)) + } + } + return nil +} + +// mustLoad is like Load but panics if search fails. +func (d *LazyDLL) mustLoad() { + e := d.Load() + if e != nil { + panic(e) + } +} + +// Handle returns d's module handle. +func (d *LazyDLL) Handle() uintptr { + d.mustLoad() + return uintptr(d.dll.Handle) +} + +// NewProc returns a LazyProc for accessing the named procedure in the DLL d. +func (d *LazyDLL) NewProc(name string) *LazyProc { + return &LazyProc{l: d, Name: name} +} + +// NewLazyDLL creates new LazyDLL associated with DLL file. +func NewLazyDLL(name string) *LazyDLL { + return &LazyDLL{Name: name} +} + +// A LazyProc implements access to a procedure inside a LazyDLL. +// It delays the lookup until the Addr method is called. +type LazyProc struct { + mu sync.Mutex + Name string + l *LazyDLL + proc *Proc +} + +// Find searches DLL for procedure named p.Name. It returns +// an error if search fails. Find will not search procedure, +// if it is already found and loaded into memory. +func (p *LazyProc) Find() error { + // Non-racy version of: + // if p.proc == nil { + if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil { + p.mu.Lock() + defer p.mu.Unlock() + if p.proc == nil { + e := p.l.Load() + if e != nil { + return e + } + proc, e := p.l.dll.FindProc(p.Name) + if e != nil { + return e + } + // Non-racy version of: + // p.proc = proc + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc)) + } + } + return nil +} + +// mustFind is like Find but panics if search fails. +func (p *LazyProc) mustFind() { + e := p.Find() + if e != nil { + panic(e) + } +} + +// Addr returns the address of the procedure represented by p. +// The return value can be passed to Syscall to run the procedure. +func (p *LazyProc) Addr() uintptr { + p.mustFind() + return p.proc.Addr() +} + +// Call executes procedure p with arguments a. It will panic, if more then 15 arguments +// are supplied. +// +// The returned error is always non-nil, constructed from the result of GetLastError. +// Callers must inspect the primary return value to decide whether an error occurred +// (according to the semantics of the specific function being called) before consulting +// the error. The error will be guaranteed to contain windows.Errno. +func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) { + p.mustFind() + return p.proc.Call(a...) +} diff --git a/vendor/golang.org/x/sys/windows/env_unset.go b/vendor/golang.org/x/sys/windows/env_unset.go new file mode 100644 index 0000000..999ffac --- /dev/null +++ b/vendor/golang.org/x/sys/windows/env_unset.go @@ -0,0 +1,14 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.4 + +package windows + +import "syscall" + +func Unsetenv(key string) error { + // This was added in Go 1.4. + return syscall.Unsetenv(key) +} diff --git a/vendor/golang.org/x/sys/windows/env_windows.go b/vendor/golang.org/x/sys/windows/env_windows.go new file mode 100644 index 0000000..a9d8ef4 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/env_windows.go @@ -0,0 +1,25 @@ +// Copyright 2010 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. + +// Windows environment variables. + +package windows + +import "syscall" + +func Getenv(key string) (value string, found bool) { + return syscall.Getenv(key) +} + +func Setenv(key, value string) error { + return syscall.Setenv(key, value) +} + +func Clearenv() { + syscall.Clearenv() +} + +func Environ() []string { + return syscall.Environ() +} diff --git a/vendor/golang.org/x/sys/windows/eventlog.go b/vendor/golang.org/x/sys/windows/eventlog.go new file mode 100644 index 0000000..40af946 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/eventlog.go @@ -0,0 +1,20 @@ +// 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. + +// +build windows + +package windows + +const ( + EVENTLOG_SUCCESS = 0 + EVENTLOG_ERROR_TYPE = 1 + EVENTLOG_WARNING_TYPE = 2 + EVENTLOG_INFORMATION_TYPE = 4 + EVENTLOG_AUDIT_SUCCESS = 8 + EVENTLOG_AUDIT_FAILURE = 16 +) + +//sys RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) [failretval==0] = advapi32.RegisterEventSourceW +//sys DeregisterEventSource(handle Handle) (err error) = advapi32.DeregisterEventSource +//sys ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) = advapi32.ReportEventW diff --git a/vendor/golang.org/x/sys/windows/exec_windows.go b/vendor/golang.org/x/sys/windows/exec_windows.go new file mode 100644 index 0000000..3606c3a --- /dev/null +++ b/vendor/golang.org/x/sys/windows/exec_windows.go @@ -0,0 +1,97 @@ +// 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. + +// Fork, exec, wait, etc. + +package windows + +// EscapeArg rewrites command line argument s as prescribed +// in http://msdn.microsoft.com/en-us/library/ms880421. +// This function returns "" (2 double quotes) if s is empty. +// Alternatively, these transformations are done: +// - every back slash (\) is doubled, but only if immediately +// followed by double quote ("); +// - every double quote (") is escaped by back slash (\); +// - finally, s is wrapped with double quotes (arg -> "arg"), +// but only if there is space or tab inside s. +func EscapeArg(s string) string { + if len(s) == 0 { + return "\"\"" + } + n := len(s) + hasSpace := false + for i := 0; i < len(s); i++ { + switch s[i] { + case '"', '\\': + n++ + case ' ', '\t': + hasSpace = true + } + } + if hasSpace { + n += 2 + } + if n == len(s) { + return s + } + + qs := make([]byte, n) + j := 0 + if hasSpace { + qs[j] = '"' + j++ + } + slashes := 0 + for i := 0; i < len(s); i++ { + switch s[i] { + default: + slashes = 0 + qs[j] = s[i] + case '\\': + slashes++ + qs[j] = s[i] + case '"': + for ; slashes > 0; slashes-- { + qs[j] = '\\' + j++ + } + qs[j] = '\\' + j++ + qs[j] = s[i] + } + j++ + } + if hasSpace { + for ; slashes > 0; slashes-- { + qs[j] = '\\' + j++ + } + qs[j] = '"' + j++ + } + return string(qs[:j]) +} + +func CloseOnExec(fd Handle) { + SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0) +} + +// FullPath retrieves the full path of the specified file. +func FullPath(name string) (path string, err error) { + p, err := UTF16PtrFromString(name) + if err != nil { + return "", err + } + n := uint32(100) + for { + buf := make([]uint16, n) + n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil) + if err != nil { + return "", err + } + if n <= uint32(len(buf)) { + return UTF16ToString(buf[:n]), nil + } + } +} diff --git a/vendor/golang.org/x/sys/windows/race.go b/vendor/golang.org/x/sys/windows/race.go new file mode 100644 index 0000000..343e18a --- /dev/null +++ b/vendor/golang.org/x/sys/windows/race.go @@ -0,0 +1,30 @@ +// 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. + +// +build windows,race + +package windows + +import ( + "runtime" + "unsafe" +) + +const raceenabled = true + +func raceAcquire(addr unsafe.Pointer) { + runtime.RaceAcquire(addr) +} + +func raceReleaseMerge(addr unsafe.Pointer) { + runtime.RaceReleaseMerge(addr) +} + +func raceReadRange(addr unsafe.Pointer, len int) { + runtime.RaceReadRange(addr, len) +} + +func raceWriteRange(addr unsafe.Pointer, len int) { + runtime.RaceWriteRange(addr, len) +} diff --git a/vendor/golang.org/x/sys/windows/race0.go b/vendor/golang.org/x/sys/windows/race0.go new file mode 100644 index 0000000..17af843 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/race0.go @@ -0,0 +1,25 @@ +// 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. + +// +build windows,!race + +package windows + +import ( + "unsafe" +) + +const raceenabled = false + +func raceAcquire(addr unsafe.Pointer) { +} + +func raceReleaseMerge(addr unsafe.Pointer) { +} + +func raceReadRange(addr unsafe.Pointer, len int) { +} + +func raceWriteRange(addr unsafe.Pointer, len int) { +} diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go new file mode 100644 index 0000000..ca09bdd --- /dev/null +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -0,0 +1,435 @@ +// 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 windows + +import ( + "syscall" + "unsafe" +) + +const ( + STANDARD_RIGHTS_REQUIRED = 0xf0000 + STANDARD_RIGHTS_READ = 0x20000 + STANDARD_RIGHTS_WRITE = 0x20000 + STANDARD_RIGHTS_EXECUTE = 0x20000 + STANDARD_RIGHTS_ALL = 0x1F0000 +) + +const ( + NameUnknown = 0 + NameFullyQualifiedDN = 1 + NameSamCompatible = 2 + NameDisplay = 3 + NameUniqueId = 6 + NameCanonical = 7 + NameUserPrincipal = 8 + NameCanonicalEx = 9 + NameServicePrincipal = 10 + NameDnsDomain = 12 +) + +// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. +// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx +//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW +//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW + +// TranslateAccountName converts a directory service +// object name from one format to another. +func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) { + u, e := UTF16PtrFromString(username) + if e != nil { + return "", e + } + n := uint32(50) + for { + b := make([]uint16, n) + e = TranslateName(u, from, to, &b[0], &n) + if e == nil { + return UTF16ToString(b[:n]), nil + } + if e != ERROR_INSUFFICIENT_BUFFER { + return "", e + } + if n <= uint32(len(b)) { + return "", e + } + } +} + +const ( + // do not reorder + NetSetupUnknownStatus = iota + NetSetupUnjoined + NetSetupWorkgroupName + NetSetupDomainName +) + +type UserInfo10 struct { + Name *uint16 + Comment *uint16 + UsrComment *uint16 + FullName *uint16 +} + +//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo +//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation +//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree + +const ( + // do not reorder + SidTypeUser = 1 + iota + SidTypeGroup + SidTypeDomain + SidTypeAlias + SidTypeWellKnownGroup + SidTypeDeletedAccount + SidTypeInvalid + SidTypeUnknown + SidTypeComputer + SidTypeLabel +) + +type SidIdentifierAuthority struct { + Value [6]byte +} + +var ( + SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}} + SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}} + SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}} + SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}} + SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}} + SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}} + SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}} +) + +const ( + SECURITY_NULL_RID = 0 + SECURITY_WORLD_RID = 0 + SECURITY_LOCAL_RID = 0 + SECURITY_CREATOR_OWNER_RID = 0 + SECURITY_CREATOR_GROUP_RID = 1 + SECURITY_DIALUP_RID = 1 + SECURITY_NETWORK_RID = 2 + SECURITY_BATCH_RID = 3 + SECURITY_INTERACTIVE_RID = 4 + SECURITY_LOGON_IDS_RID = 5 + SECURITY_SERVICE_RID = 6 + SECURITY_LOCAL_SYSTEM_RID = 18 + SECURITY_BUILTIN_DOMAIN_RID = 32 + SECURITY_PRINCIPAL_SELF_RID = 10 + SECURITY_CREATOR_OWNER_SERVER_RID = 0x2 + SECURITY_CREATOR_GROUP_SERVER_RID = 0x3 + SECURITY_LOGON_IDS_RID_COUNT = 0x3 + SECURITY_ANONYMOUS_LOGON_RID = 0x7 + SECURITY_PROXY_RID = 0x8 + SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9 + SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID + SECURITY_AUTHENTICATED_USER_RID = 0xb + SECURITY_RESTRICTED_CODE_RID = 0xc + SECURITY_NT_NON_UNIQUE_RID = 0x15 +) + +//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW +//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW +//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW +//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW +//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid +//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid +//sys AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid +//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid +//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid + +// The security identifier (SID) structure is a variable-length +// structure used to uniquely identify users or groups. +type SID struct{} + +// StringToSid converts a string-format security identifier +// sid into a valid, functional sid. +func StringToSid(s string) (*SID, error) { + var sid *SID + p, e := UTF16PtrFromString(s) + if e != nil { + return nil, e + } + e = ConvertStringSidToSid(p, &sid) + if e != nil { + return nil, e + } + defer LocalFree((Handle)(unsafe.Pointer(sid))) + return sid.Copy() +} + +// LookupSID retrieves a security identifier sid for the account +// and the name of the domain on which the account was found. +// System specify target computer to search. +func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) { + if len(account) == 0 { + return nil, "", 0, syscall.EINVAL + } + acc, e := UTF16PtrFromString(account) + if e != nil { + return nil, "", 0, e + } + var sys *uint16 + if len(system) > 0 { + sys, e = UTF16PtrFromString(system) + if e != nil { + return nil, "", 0, e + } + } + n := uint32(50) + dn := uint32(50) + for { + b := make([]byte, n) + db := make([]uint16, dn) + sid = (*SID)(unsafe.Pointer(&b[0])) + e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType) + if e == nil { + return sid, UTF16ToString(db), accType, nil + } + if e != ERROR_INSUFFICIENT_BUFFER { + return nil, "", 0, e + } + if n <= uint32(len(b)) { + return nil, "", 0, e + } + } +} + +// String converts sid to a string format +// suitable for display, storage, or transmission. +func (sid *SID) String() (string, error) { + var s *uint16 + e := ConvertSidToStringSid(sid, &s) + if e != nil { + return "", e + } + defer LocalFree((Handle)(unsafe.Pointer(s))) + return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil +} + +// Len returns the length, in bytes, of a valid security identifier sid. +func (sid *SID) Len() int { + return int(GetLengthSid(sid)) +} + +// Copy creates a duplicate of security identifier sid. +func (sid *SID) Copy() (*SID, error) { + b := make([]byte, sid.Len()) + sid2 := (*SID)(unsafe.Pointer(&b[0])) + e := CopySid(uint32(len(b)), sid2, sid) + if e != nil { + return nil, e + } + return sid2, nil +} + +// LookupAccount retrieves the name of the account for this sid +// and the name of the first domain on which this sid is found. +// System specify target computer to search for. +func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) { + var sys *uint16 + if len(system) > 0 { + sys, err = UTF16PtrFromString(system) + if err != nil { + return "", "", 0, err + } + } + n := uint32(50) + dn := uint32(50) + for { + b := make([]uint16, n) + db := make([]uint16, dn) + e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType) + if e == nil { + return UTF16ToString(b), UTF16ToString(db), accType, nil + } + if e != ERROR_INSUFFICIENT_BUFFER { + return "", "", 0, e + } + if n <= uint32(len(b)) { + return "", "", 0, e + } + } +} + +const ( + // do not reorder + TOKEN_ASSIGN_PRIMARY = 1 << iota + TOKEN_DUPLICATE + TOKEN_IMPERSONATE + TOKEN_QUERY + TOKEN_QUERY_SOURCE + TOKEN_ADJUST_PRIVILEGES + TOKEN_ADJUST_GROUPS + TOKEN_ADJUST_DEFAULT + + TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | + TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | + TOKEN_IMPERSONATE | + TOKEN_QUERY | + TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | + TOKEN_ADJUST_GROUPS | + TOKEN_ADJUST_DEFAULT + TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY + TOKEN_WRITE = STANDARD_RIGHTS_WRITE | + TOKEN_ADJUST_PRIVILEGES | + TOKEN_ADJUST_GROUPS | + TOKEN_ADJUST_DEFAULT + TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE +) + +const ( + // do not reorder + TokenUser = 1 + iota + TokenGroups + TokenPrivileges + TokenOwner + TokenPrimaryGroup + TokenDefaultDacl + TokenSource + TokenType + TokenImpersonationLevel + TokenStatistics + TokenRestrictedSids + TokenSessionId + TokenGroupsAndPrivileges + TokenSessionReference + TokenSandBoxInert + TokenAuditPolicy + TokenOrigin + TokenElevationType + TokenLinkedToken + TokenElevation + TokenHasRestrictions + TokenAccessInformation + TokenVirtualizationAllowed + TokenVirtualizationEnabled + TokenIntegrityLevel + TokenUIAccess + TokenMandatoryPolicy + TokenLogonSid + MaxTokenInfoClass +) + +type SIDAndAttributes struct { + Sid *SID + Attributes uint32 +} + +type Tokenuser struct { + User SIDAndAttributes +} + +type Tokenprimarygroup struct { + PrimaryGroup *SID +} + +type Tokengroups struct { + GroupCount uint32 + Groups [1]SIDAndAttributes +} + +//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken +//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation +//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW + +// An access token contains the security information for a logon session. +// The system creates an access token when a user logs on, and every +// process executed on behalf of the user has a copy of the token. +// The token identifies the user, the user's groups, and the user's +// privileges. The system uses the token to control access to securable +// objects and to control the ability of the user to perform various +// system-related operations on the local computer. +type Token Handle + +// OpenCurrentProcessToken opens the access token +// associated with current process. +func OpenCurrentProcessToken() (Token, error) { + p, e := GetCurrentProcess() + if e != nil { + return 0, e + } + var t Token + e = OpenProcessToken(p, TOKEN_QUERY, &t) + if e != nil { + return 0, e + } + return t, nil +} + +// Close releases access to access token. +func (t Token) Close() error { + return CloseHandle(Handle(t)) +} + +// getInfo retrieves a specified type of information about an access token. +func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) { + n := uint32(initSize) + for { + b := make([]byte, n) + e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) + if e == nil { + return unsafe.Pointer(&b[0]), nil + } + if e != ERROR_INSUFFICIENT_BUFFER { + return nil, e + } + if n <= uint32(len(b)) { + return nil, e + } + } +} + +// GetTokenUser retrieves access token t user account information. +func (t Token) GetTokenUser() (*Tokenuser, error) { + i, e := t.getInfo(TokenUser, 50) + if e != nil { + return nil, e + } + return (*Tokenuser)(i), nil +} + +// GetTokenGroups retrieves group accounts associated with access token t. +func (t Token) GetTokenGroups() (*Tokengroups, error) { + i, e := t.getInfo(TokenGroups, 50) + if e != nil { + return nil, e + } + return (*Tokengroups)(i), nil +} + +// GetTokenPrimaryGroup retrieves access token t primary group information. +// A pointer to a SID structure representing a group that will become +// the primary group of any objects created by a process using this access token. +func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) { + i, e := t.getInfo(TokenPrimaryGroup, 50) + if e != nil { + return nil, e + } + return (*Tokenprimarygroup)(i), nil +} + +// GetUserProfileDirectory retrieves path to the +// root directory of the access token t user's profile. +func (t Token) GetUserProfileDirectory() (string, error) { + n := uint32(100) + for { + b := make([]uint16, n) + e := GetUserProfileDirectory(t, &b[0], &n) + if e == nil { + return UTF16ToString(b), nil + } + if e != ERROR_INSUFFICIENT_BUFFER { + return "", e + } + if n <= uint32(len(b)) { + return "", e + } + } +} diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go new file mode 100644 index 0000000..1c11d39 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/service.go @@ -0,0 +1,143 @@ +// 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. + +// +build windows + +package windows + +const ( + SC_MANAGER_CONNECT = 1 + SC_MANAGER_CREATE_SERVICE = 2 + SC_MANAGER_ENUMERATE_SERVICE = 4 + SC_MANAGER_LOCK = 8 + SC_MANAGER_QUERY_LOCK_STATUS = 16 + SC_MANAGER_MODIFY_BOOT_CONFIG = 32 + SC_MANAGER_ALL_ACCESS = 0xf003f +) + +//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW + +const ( + SERVICE_KERNEL_DRIVER = 1 + SERVICE_FILE_SYSTEM_DRIVER = 2 + SERVICE_ADAPTER = 4 + SERVICE_RECOGNIZER_DRIVER = 8 + SERVICE_WIN32_OWN_PROCESS = 16 + SERVICE_WIN32_SHARE_PROCESS = 32 + SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS + SERVICE_INTERACTIVE_PROCESS = 256 + SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER + SERVICE_TYPE_ALL = SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS + + SERVICE_BOOT_START = 0 + SERVICE_SYSTEM_START = 1 + SERVICE_AUTO_START = 2 + SERVICE_DEMAND_START = 3 + SERVICE_DISABLED = 4 + + SERVICE_ERROR_IGNORE = 0 + SERVICE_ERROR_NORMAL = 1 + SERVICE_ERROR_SEVERE = 2 + SERVICE_ERROR_CRITICAL = 3 + + SC_STATUS_PROCESS_INFO = 0 + + SERVICE_STOPPED = 1 + SERVICE_START_PENDING = 2 + SERVICE_STOP_PENDING = 3 + SERVICE_RUNNING = 4 + SERVICE_CONTINUE_PENDING = 5 + SERVICE_PAUSE_PENDING = 6 + SERVICE_PAUSED = 7 + SERVICE_NO_CHANGE = 0xffffffff + + SERVICE_ACCEPT_STOP = 1 + SERVICE_ACCEPT_PAUSE_CONTINUE = 2 + SERVICE_ACCEPT_SHUTDOWN = 4 + SERVICE_ACCEPT_PARAMCHANGE = 8 + SERVICE_ACCEPT_NETBINDCHANGE = 16 + SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32 + SERVICE_ACCEPT_POWEREVENT = 64 + SERVICE_ACCEPT_SESSIONCHANGE = 128 + + SERVICE_CONTROL_STOP = 1 + SERVICE_CONTROL_PAUSE = 2 + SERVICE_CONTROL_CONTINUE = 3 + SERVICE_CONTROL_INTERROGATE = 4 + SERVICE_CONTROL_SHUTDOWN = 5 + SERVICE_CONTROL_PARAMCHANGE = 6 + SERVICE_CONTROL_NETBINDADD = 7 + SERVICE_CONTROL_NETBINDREMOVE = 8 + SERVICE_CONTROL_NETBINDENABLE = 9 + SERVICE_CONTROL_NETBINDDISABLE = 10 + SERVICE_CONTROL_DEVICEEVENT = 11 + SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12 + SERVICE_CONTROL_POWEREVENT = 13 + SERVICE_CONTROL_SESSIONCHANGE = 14 + + SERVICE_ACTIVE = 1 + SERVICE_INACTIVE = 2 + SERVICE_STATE_ALL = 3 + + SERVICE_QUERY_CONFIG = 1 + SERVICE_CHANGE_CONFIG = 2 + SERVICE_QUERY_STATUS = 4 + SERVICE_ENUMERATE_DEPENDENTS = 8 + SERVICE_START = 16 + SERVICE_STOP = 32 + SERVICE_PAUSE_CONTINUE = 64 + SERVICE_INTERROGATE = 128 + SERVICE_USER_DEFINED_CONTROL = 256 + SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL + SERVICE_RUNS_IN_SYSTEM_PROCESS = 1 + SERVICE_CONFIG_DESCRIPTION = 1 + SERVICE_CONFIG_FAILURE_ACTIONS = 2 + + NO_ERROR = 0 +) + +type SERVICE_STATUS struct { + ServiceType uint32 + CurrentState uint32 + ControlsAccepted uint32 + Win32ExitCode uint32 + ServiceSpecificExitCode uint32 + CheckPoint uint32 + WaitHint uint32 +} + +type SERVICE_TABLE_ENTRY struct { + ServiceName *uint16 + ServiceProc uintptr +} + +type QUERY_SERVICE_CONFIG struct { + ServiceType uint32 + StartType uint32 + ErrorControl uint32 + BinaryPathName *uint16 + LoadOrderGroup *uint16 + TagId uint32 + Dependencies *uint16 + ServiceStartName *uint16 + DisplayName *uint16 +} + +type SERVICE_DESCRIPTION struct { + Description *uint16 +} + +//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle +//sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW +//sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW +//sys DeleteService(service Handle) (err error) = advapi32.DeleteService +//sys StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) = advapi32.StartServiceW +//sys QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus +//sys ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) = advapi32.ControlService +//sys StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) = advapi32.StartServiceCtrlDispatcherW +//sys SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) = advapi32.SetServiceStatus +//sys ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) = advapi32.ChangeServiceConfigW +//sys QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfigW +//sys ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) = advapi32.ChangeServiceConfig2W +//sys QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfig2W diff --git a/vendor/golang.org/x/sys/windows/str.go b/vendor/golang.org/x/sys/windows/str.go new file mode 100644 index 0000000..917cc2a --- /dev/null +++ b/vendor/golang.org/x/sys/windows/str.go @@ -0,0 +1,22 @@ +// 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. + +// +build windows + +package windows + +func itoa(val int) string { // do it here rather than with fmt to avoid dependency + if val < 0 { + return "-" + itoa(-val) + } + var buf [32]byte // big enough for int64 + i := len(buf) - 1 + for val >= 10 { + buf[i] = byte(val%10 + '0') + i-- + val /= 10 + } + buf[i] = byte(val + '0') + return string(buf[i:]) +} diff --git a/vendor/golang.org/x/sys/windows/syscall.go b/vendor/golang.org/x/sys/windows/syscall.go new file mode 100644 index 0000000..281cd66 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/syscall.go @@ -0,0 +1,77 @@ +// 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. + +// +build windows + +// Package windows contains an interface to the low-level operating system +// primitives. OS details vary depending on the underlying system, and +// by default, godoc will display the OS-specific documentation for the current +// system. If you want godoc to display syscall documentation for another +// system, set $GOOS and $GOARCH to the desired system. For example, if +// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS +// to freebsd and $GOARCH to arm. +// The primary use of this package is inside other packages that provide a more +// portable interface to the system, such as "os", "time" and "net". Use +// those packages rather than this one if you can. +// For details of the functions and data types in this package consult +// the manuals for the appropriate operating system. +// These calls return err == nil to indicate success; otherwise +// err represents an operating system error describing the failure and +// holds a value of type syscall.Errno. +package windows + +import ( + "syscall" + "unsafe" +) + +// ByteSliceFromString returns a NUL-terminated slice of bytes +// containing the text of s. If s contains a NUL byte at any +// location, it returns (nil, syscall.EINVAL). +func ByteSliceFromString(s string) ([]byte, error) { + for i := 0; i < len(s); i++ { + if s[i] == 0 { + return nil, syscall.EINVAL + } + } + a := make([]byte, len(s)+1) + copy(a, s) + return a, nil +} + +// BytePtrFromString returns a pointer to a NUL-terminated array of +// bytes containing the text of s. If s contains a NUL byte at any +// location, it returns (nil, syscall.EINVAL). +func BytePtrFromString(s string) (*byte, error) { + a, err := ByteSliceFromString(s) + if err != nil { + return nil, err + } + return &a[0], nil +} + +// Single-word zero for use when we need a valid pointer to 0 bytes. +// See mksyscall.pl. +var _zero uintptr + +func (ts *Timespec) Unix() (sec int64, nsec int64) { + return int64(ts.Sec), int64(ts.Nsec) +} + +func (tv *Timeval) Unix() (sec int64, nsec int64) { + return int64(tv.Sec), int64(tv.Usec) * 1000 +} + +func (ts *Timespec) Nano() int64 { + return int64(ts.Sec)*1e9 + int64(ts.Nsec) +} + +func (tv *Timeval) Nano() int64 { + return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 +} + +// use is a no-op, but the compiler cannot see that it is. +// Calling use(p) ensures that p is kept live until that point. +//go:noescape +func use(p unsafe.Pointer) diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go new file mode 100644 index 0000000..75def60 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -0,0 +1,990 @@ +// 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. + +// Windows system calls. + +package windows + +import ( + errorspkg "errors" + "sync" + "syscall" + "unicode/utf16" + "unsafe" +) + +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go + +type Handle uintptr + +const InvalidHandle = ^Handle(0) + +// StringToUTF16 is deprecated. Use UTF16FromString instead. +// If s contains a NUL byte this function panics instead of +// returning an error. +func StringToUTF16(s string) []uint16 { + a, err := UTF16FromString(s) + if err != nil { + panic("windows: string with NUL passed to StringToUTF16") + } + return a +} + +// UTF16FromString returns the UTF-16 encoding of the UTF-8 string +// s, with a terminating NUL added. If s contains a NUL byte at any +// location, it returns (nil, syscall.EINVAL). +func UTF16FromString(s string) ([]uint16, error) { + for i := 0; i < len(s); i++ { + if s[i] == 0 { + return nil, syscall.EINVAL + } + } + return utf16.Encode([]rune(s + "\x00")), nil +} + +// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, +// with a terminating NUL removed. +func UTF16ToString(s []uint16) string { + for i, v := range s { + if v == 0 { + s = s[0:i] + break + } + } + return string(utf16.Decode(s)) +} + +// StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead. +// If s contains a NUL byte this function panics instead of +// returning an error. +func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } + +// UTF16PtrFromString returns pointer to the UTF-16 encoding of +// the UTF-8 string s, with a terminating NUL added. If s +// contains a NUL byte at any location, it returns (nil, syscall.EINVAL). +func UTF16PtrFromString(s string) (*uint16, error) { + a, err := UTF16FromString(s) + if err != nil { + return nil, err + } + return &a[0], nil +} + +func Getpagesize() int { return 4096 } + +// Converts a Go function to a function pointer conforming +// to the stdcall or cdecl calling convention. This is useful when +// interoperating with Windows code requiring callbacks. +// Implemented in runtime/syscall_windows.goc +func NewCallback(fn interface{}) uintptr +func NewCallbackCDecl(fn interface{}) uintptr + +// windows api calls + +//sys GetLastError() (lasterr error) +//sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW +//sys FreeLibrary(handle Handle) (err error) +//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) +//sys GetVersion() (ver uint32, err error) +//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW +//sys ExitProcess(exitcode uint32) +//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW +//sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) +//sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) +//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff] +//sys CloseHandle(handle Handle) (err error) +//sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle] +//sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW +//sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW +//sys FindClose(handle Handle) (err error) +//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) +//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW +//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW +//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW +//sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW +//sys DeleteFile(path *uint16) (err error) = DeleteFileW +//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW +//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW +//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW +//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW +//sys SetEndOfFile(handle Handle) (err error) +//sys GetSystemTimeAsFileTime(time *Filetime) +//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] +//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) +//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) +//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) +//sys CancelIo(s Handle) (err error) +//sys CancelIoEx(s Handle, o *Overlapped) (err error) +//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW +//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) +//sys TerminateProcess(handle Handle, exitcode uint32) (err error) +//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) +//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW +//sys GetCurrentProcess() (pseudoHandle Handle, err error) +//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) +//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) +//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] +//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW +//sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) +//sys GetFileType(filehandle Handle) (n uint32, err error) +//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW +//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext +//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom +//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW +//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW +//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW +//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW +//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) +//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW +//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW +//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW +//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW +//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW +//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0] +//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) +//sys FlushFileBuffers(handle Handle) (err error) +//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW +//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW +//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW +//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW +//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) +//sys UnmapViewOfFile(addr uintptr) (err error) +//sys FlushViewOfFile(addr uintptr, length uintptr) (err error) +//sys VirtualLock(addr uintptr, length uintptr) (err error) +//sys VirtualUnlock(addr uintptr, length uintptr) (err error) +//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile +//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW +//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW +//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore +//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore +//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore +//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore +//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain +//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain +//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext +//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext +//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy +//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW +//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey +//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW +//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW +//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW +//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId +//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode +//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW +//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW +//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot +//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW +//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW +//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) +// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. +//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW +//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW +//sys GetCurrentThreadId() (id uint32) +//sys CreateEvent(eventAttrs *syscall.SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) = kernel32.CreateEventW +//sys SetEvent(event Handle) (err error) = kernel32.SetEvent + +// syscall interface implementation for other packages + +func Exit(code int) { ExitProcess(uint32(code)) } + +func makeInheritSa() *SecurityAttributes { + var sa SecurityAttributes + sa.Length = uint32(unsafe.Sizeof(sa)) + sa.InheritHandle = 1 + return &sa +} + +func Open(path string, mode int, perm uint32) (fd Handle, err error) { + if len(path) == 0 { + return InvalidHandle, ERROR_FILE_NOT_FOUND + } + pathp, err := UTF16PtrFromString(path) + if err != nil { + return InvalidHandle, err + } + var access uint32 + switch mode & (O_RDONLY | O_WRONLY | O_RDWR) { + case O_RDONLY: + access = GENERIC_READ + case O_WRONLY: + access = GENERIC_WRITE + case O_RDWR: + access = GENERIC_READ | GENERIC_WRITE + } + if mode&O_CREAT != 0 { + access |= GENERIC_WRITE + } + if mode&O_APPEND != 0 { + access &^= GENERIC_WRITE + access |= FILE_APPEND_DATA + } + sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE) + var sa *SecurityAttributes + if mode&O_CLOEXEC == 0 { + sa = makeInheritSa() + } + var createmode uint32 + switch { + case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): + createmode = CREATE_NEW + case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): + createmode = CREATE_ALWAYS + case mode&O_CREAT == O_CREAT: + createmode = OPEN_ALWAYS + case mode&O_TRUNC == O_TRUNC: + createmode = TRUNCATE_EXISTING + default: + createmode = OPEN_EXISTING + } + h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0) + return h, e +} + +func Read(fd Handle, p []byte) (n int, err error) { + var done uint32 + e := ReadFile(fd, p, &done, nil) + if e != nil { + if e == ERROR_BROKEN_PIPE { + // NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin + return 0, nil + } + return 0, e + } + if raceenabled { + if done > 0 { + raceWriteRange(unsafe.Pointer(&p[0]), int(done)) + } + raceAcquire(unsafe.Pointer(&ioSync)) + } + return int(done), nil +} + +func Write(fd Handle, p []byte) (n int, err error) { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + var done uint32 + e := WriteFile(fd, p, &done, nil) + if e != nil { + return 0, e + } + if raceenabled && done > 0 { + raceReadRange(unsafe.Pointer(&p[0]), int(done)) + } + return int(done), nil +} + +var ioSync int64 + +func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) { + var w uint32 + switch whence { + case 0: + w = FILE_BEGIN + case 1: + w = FILE_CURRENT + case 2: + w = FILE_END + } + hi := int32(offset >> 32) + lo := int32(offset) + // use GetFileType to check pipe, pipe can't do seek + ft, _ := GetFileType(fd) + if ft == FILE_TYPE_PIPE { + return 0, syscall.EPIPE + } + rlo, e := SetFilePointer(fd, lo, &hi, w) + if e != nil { + return 0, e + } + return int64(hi)<<32 + int64(rlo), nil +} + +func Close(fd Handle) (err error) { + return CloseHandle(fd) +} + +var ( + Stdin = getStdHandle(STD_INPUT_HANDLE) + Stdout = getStdHandle(STD_OUTPUT_HANDLE) + Stderr = getStdHandle(STD_ERROR_HANDLE) +) + +func getStdHandle(h int) (fd Handle) { + r, _ := GetStdHandle(h) + CloseOnExec(r) + return r +} + +const ImplementsGetwd = true + +func Getwd() (wd string, err error) { + b := make([]uint16, 300) + n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) + if e != nil { + return "", e + } + return string(utf16.Decode(b[0:n])), nil +} + +func Chdir(path string) (err error) { + pathp, err := UTF16PtrFromString(path) + if err != nil { + return err + } + return SetCurrentDirectory(pathp) +} + +func Mkdir(path string, mode uint32) (err error) { + pathp, err := UTF16PtrFromString(path) + if err != nil { + return err + } + return CreateDirectory(pathp, nil) +} + +func Rmdir(path string) (err error) { + pathp, err := UTF16PtrFromString(path) + if err != nil { + return err + } + return RemoveDirectory(pathp) +} + +func Unlink(path string) (err error) { + pathp, err := UTF16PtrFromString(path) + if err != nil { + return err + } + return DeleteFile(pathp) +} + +func Rename(oldpath, newpath string) (err error) { + from, err := UTF16PtrFromString(oldpath) + if err != nil { + return err + } + to, err := UTF16PtrFromString(newpath) + if err != nil { + return err + } + return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) +} + +func ComputerName() (name string, err error) { + var n uint32 = MAX_COMPUTERNAME_LENGTH + 1 + b := make([]uint16, n) + e := GetComputerName(&b[0], &n) + if e != nil { + return "", e + } + return string(utf16.Decode(b[0:n])), nil +} + +func Ftruncate(fd Handle, length int64) (err error) { + curoffset, e := Seek(fd, 0, 1) + if e != nil { + return e + } + defer Seek(fd, curoffset, 0) + _, e = Seek(fd, length, 0) + if e != nil { + return e + } + e = SetEndOfFile(fd) + if e != nil { + return e + } + return nil +} + +func Gettimeofday(tv *Timeval) (err error) { + var ft Filetime + GetSystemTimeAsFileTime(&ft) + *tv = NsecToTimeval(ft.Nanoseconds()) + return nil +} + +func Pipe(p []Handle) (err error) { + if len(p) != 2 { + return syscall.EINVAL + } + var r, w Handle + e := CreatePipe(&r, &w, makeInheritSa(), 0) + if e != nil { + return e + } + p[0] = r + p[1] = w + return nil +} + +func Utimes(path string, tv []Timeval) (err error) { + if len(tv) != 2 { + return syscall.EINVAL + } + pathp, e := UTF16PtrFromString(path) + if e != nil { + return e + } + h, e := CreateFile(pathp, + FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) + if e != nil { + return e + } + defer Close(h) + a := NsecToFiletime(tv[0].Nanoseconds()) + w := NsecToFiletime(tv[1].Nanoseconds()) + return SetFileTime(h, nil, &a, &w) +} + +func UtimesNano(path string, ts []Timespec) (err error) { + if len(ts) != 2 { + return syscall.EINVAL + } + pathp, e := UTF16PtrFromString(path) + if e != nil { + return e + } + h, e := CreateFile(pathp, + FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) + if e != nil { + return e + } + defer Close(h) + a := NsecToFiletime(TimespecToNsec(ts[0])) + w := NsecToFiletime(TimespecToNsec(ts[1])) + return SetFileTime(h, nil, &a, &w) +} + +func Fsync(fd Handle) (err error) { + return FlushFileBuffers(fd) +} + +func Chmod(path string, mode uint32) (err error) { + if mode == 0 { + return syscall.EINVAL + } + p, e := UTF16PtrFromString(path) + if e != nil { + return e + } + attrs, e := GetFileAttributes(p) + if e != nil { + return e + } + if mode&S_IWRITE != 0 { + attrs &^= FILE_ATTRIBUTE_READONLY + } else { + attrs |= FILE_ATTRIBUTE_READONLY + } + return SetFileAttributes(p, attrs) +} + +func LoadCancelIoEx() error { + return procCancelIoEx.Find() +} + +func LoadSetFileCompletionNotificationModes() error { + return procSetFileCompletionNotificationModes.Find() +} + +// net api calls + +const socket_error = uintptr(^uint32(0)) + +//sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup +//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup +//sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl +//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket +//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt +//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt +//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind +//sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect +//sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname +//sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername +//sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen +//sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown +//sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket +//sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx +//sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs +//sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv +//sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend +//sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom +//sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo +//sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname +//sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname +//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs +//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname +//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W +//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree +//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W +//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW +//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW +//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry +//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo +//sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes +//sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW +//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses +//sys GetACP() (acp uint32) = kernel32.GetACP +//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar + +// For testing: clients can set this flag to force +// creation of IPv6 sockets to return EAFNOSUPPORT. +var SocketDisableIPv6 bool + +type RawSockaddrInet4 struct { + Family uint16 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]uint8 +} + +type RawSockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddr struct { + Family uint16 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [96]int8 +} + +type Sockaddr interface { + sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs +} + +type SockaddrInet4 struct { + Port int + Addr [4]byte + raw RawSockaddrInet4 +} + +func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { + if sa.Port < 0 || sa.Port > 0xFFFF { + return nil, 0, syscall.EINVAL + } + sa.raw.Family = AF_INET + p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } + return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil +} + +type SockaddrInet6 struct { + Port int + ZoneId uint32 + Addr [16]byte + raw RawSockaddrInet6 +} + +func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { + if sa.Port < 0 || sa.Port > 0xFFFF { + return nil, 0, syscall.EINVAL + } + sa.raw.Family = AF_INET6 + p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + sa.raw.Scope_id = sa.ZoneId + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } + return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil +} + +type SockaddrUnix struct { + Name string +} + +func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { + // TODO(brainman): implement SockaddrUnix.sockaddr() + return nil, 0, syscall.EWINDOWS +} + +func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { + switch rsa.Addr.Family { + case AF_UNIX: + return nil, syscall.EWINDOWS + + case AF_INET: + pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) + sa := new(SockaddrInet4) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } + return sa, nil + + case AF_INET6: + pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) + sa := new(SockaddrInet6) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.ZoneId = pp.Scope_id + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } + return sa, nil + } + return nil, syscall.EAFNOSUPPORT +} + +func Socket(domain, typ, proto int) (fd Handle, err error) { + if domain == AF_INET6 && SocketDisableIPv6 { + return InvalidHandle, syscall.EAFNOSUPPORT + } + return socket(int32(domain), int32(typ), int32(proto)) +} + +func SetsockoptInt(fd Handle, level, opt int, value int) (err error) { + v := int32(value) + return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v))) +} + +func Bind(fd Handle, sa Sockaddr) (err error) { + ptr, n, err := sa.sockaddr() + if err != nil { + return err + } + return bind(fd, ptr, n) +} + +func Connect(fd Handle, sa Sockaddr) (err error) { + ptr, n, err := sa.sockaddr() + if err != nil { + return err + } + return connect(fd, ptr, n) +} + +func Getsockname(fd Handle) (sa Sockaddr, err error) { + var rsa RawSockaddrAny + l := int32(unsafe.Sizeof(rsa)) + if err = getsockname(fd, &rsa, &l); err != nil { + return + } + return rsa.Sockaddr() +} + +func Getpeername(fd Handle) (sa Sockaddr, err error) { + var rsa RawSockaddrAny + l := int32(unsafe.Sizeof(rsa)) + if err = getpeername(fd, &rsa, &l); err != nil { + return + } + return rsa.Sockaddr() +} + +func Listen(s Handle, n int) (err error) { + return listen(s, int32(n)) +} + +func Shutdown(fd Handle, how int) (err error) { + return shutdown(fd, int32(how)) +} + +func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) { + rsa, l, err := to.sockaddr() + if err != nil { + return err + } + return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine) +} + +func LoadGetAddrInfo() error { + return procGetAddrInfoW.Find() +} + +var connectExFunc struct { + once sync.Once + addr uintptr + err error +} + +func LoadConnectEx() error { + connectExFunc.once.Do(func() { + var s Handle + s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) + if connectExFunc.err != nil { + return + } + defer CloseHandle(s) + var n uint32 + connectExFunc.err = WSAIoctl(s, + SIO_GET_EXTENSION_FUNCTION_POINTER, + (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)), + uint32(unsafe.Sizeof(WSAID_CONNECTEX)), + (*byte)(unsafe.Pointer(&connectExFunc.addr)), + uint32(unsafe.Sizeof(connectExFunc.addr)), + &n, nil, 0) + }) + return connectExFunc.err +} + +func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error { + err := LoadConnectEx() + if err != nil { + return errorspkg.New("failed to find ConnectEx: " + err.Error()) + } + ptr, n, err := sa.sockaddr() + if err != nil { + return err + } + return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) +} + +// Invented structures to support what package os expects. +type Rusage struct { + CreationTime Filetime + ExitTime Filetime + KernelTime Filetime + UserTime Filetime +} + +type WaitStatus struct { + ExitCode uint32 +} + +func (w WaitStatus) Exited() bool { return true } + +func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) } + +func (w WaitStatus) Signal() Signal { return -1 } + +func (w WaitStatus) CoreDump() bool { return false } + +func (w WaitStatus) Stopped() bool { return false } + +func (w WaitStatus) Continued() bool { return false } + +func (w WaitStatus) StopSignal() Signal { return -1 } + +func (w WaitStatus) Signaled() bool { return false } + +func (w WaitStatus) TrapCause() int { return -1 } + +// Timespec is an invented structure on Windows, but here for +// consistency with the corresponding package for other operating systems. +type Timespec struct { + Sec int64 + Nsec int64 +} + +func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } + +func NsecToTimespec(nsec int64) (ts Timespec) { + ts.Sec = nsec / 1e9 + ts.Nsec = nsec % 1e9 + return +} + +// TODO(brainman): fix all needed for net + +func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, syscall.EWINDOWS } +func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) { + return 0, nil, syscall.EWINDOWS +} +func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return syscall.EWINDOWS } +func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return syscall.EWINDOWS } + +// The Linger struct is wrong but we only noticed after Go 1. +// sysLinger is the real system call structure. + +// BUG(brainman): The definition of Linger is not appropriate for direct use +// with Setsockopt and Getsockopt. +// Use SetsockoptLinger instead. + +type Linger struct { + Onoff int32 + Linger int32 +} + +type sysLinger struct { + Onoff uint16 + Linger uint16 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, syscall.EWINDOWS } + +func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { + sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)} + return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys))) +} + +func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { + return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) +} +func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { + return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) +} +func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { + return syscall.EWINDOWS +} + +func Getpid() (pid int) { return int(getCurrentProcessId()) } + +func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) { + // NOTE(rsc): The Win32finddata struct is wrong for the system call: + // the two paths are each one uint16 short. Use the correct struct, + // a win32finddata1, and then copy the results out. + // There is no loss of expressivity here, because the final + // uint16, if it is used, is supposed to be a NUL, and Go doesn't need that. + // For Go 1.1, we might avoid the allocation of win32finddata1 here + // by adding a final Bug [2]uint16 field to the struct and then + // adjusting the fields in the result directly. + var data1 win32finddata1 + handle, err = findFirstFile1(name, &data1) + if err == nil { + copyFindData(data, &data1) + } + return +} + +func FindNextFile(handle Handle, data *Win32finddata) (err error) { + var data1 win32finddata1 + err = findNextFile1(handle, &data1) + if err == nil { + copyFindData(data, &data1) + } + return +} + +func getProcessEntry(pid int) (*ProcessEntry32, error) { + snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err + } + defer CloseHandle(snapshot) + var procEntry ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = Process32First(snapshot, &procEntry); err != nil { + return nil, err + } + for { + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil + } + err = Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err + } + } +} + +func Getppid() (ppid int) { + pe, err := getProcessEntry(Getpid()) + if err != nil { + return -1 + } + return int(pe.ParentProcessID) +} + +// TODO(brainman): fix all needed for os +func Fchdir(fd Handle) (err error) { return syscall.EWINDOWS } +func Link(oldpath, newpath string) (err error) { return syscall.EWINDOWS } +func Symlink(path, link string) (err error) { return syscall.EWINDOWS } + +func Fchmod(fd Handle, mode uint32) (err error) { return syscall.EWINDOWS } +func Chown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS } +func Lchown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS } +func Fchown(fd Handle, uid int, gid int) (err error) { return syscall.EWINDOWS } + +func Getuid() (uid int) { return -1 } +func Geteuid() (euid int) { return -1 } +func Getgid() (gid int) { return -1 } +func Getegid() (egid int) { return -1 } +func Getgroups() (gids []int, err error) { return nil, syscall.EWINDOWS } + +type Signal int + +func (s Signal) Signal() {} + +func (s Signal) String() string { + if 0 <= s && int(s) < len(signals) { + str := signals[s] + if str != "" { + return str + } + } + return "signal " + itoa(int(s)) +} + +func LoadCreateSymbolicLink() error { + return procCreateSymbolicLinkW.Find() +} + +// Readlink returns the destination of the named symbolic link. +func Readlink(path string, buf []byte) (n int, err error) { + fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0) + if err != nil { + return -1, err + } + defer CloseHandle(fd) + + rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE) + var bytesReturned uint32 + err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil) + if err != nil { + return -1, err + } + + rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0])) + var s string + switch rdb.ReparseTag { + case IO_REPARSE_TAG_SYMLINK: + data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) + p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) + s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2]) + case IO_REPARSE_TAG_MOUNT_POINT: + data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) + p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) + s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2]) + default: + // the path is not a symlink or junction but another type of reparse + // point + return -1, syscall.ENOENT + } + n = copy(buf, []byte(s)) + + return n, nil +} diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go new file mode 100644 index 0000000..10dd30a --- /dev/null +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -0,0 +1,2220 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package windows + +import "unsafe" +import "syscall" + +var _ unsafe.Pointer + +var ( + modadvapi32 = syscall.NewLazyDLL("advapi32.dll") + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + modshell32 = syscall.NewLazyDLL("shell32.dll") + modmswsock = syscall.NewLazyDLL("mswsock.dll") + modcrypt32 = syscall.NewLazyDLL("crypt32.dll") + modws2_32 = syscall.NewLazyDLL("ws2_32.dll") + moddnsapi = syscall.NewLazyDLL("dnsapi.dll") + modiphlpapi = syscall.NewLazyDLL("iphlpapi.dll") + modsecur32 = syscall.NewLazyDLL("secur32.dll") + modnetapi32 = syscall.NewLazyDLL("netapi32.dll") + moduserenv = syscall.NewLazyDLL("userenv.dll") + + procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") + procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") + procReportEventW = modadvapi32.NewProc("ReportEventW") + procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") + procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") + procCreateServiceW = modadvapi32.NewProc("CreateServiceW") + procOpenServiceW = modadvapi32.NewProc("OpenServiceW") + procDeleteService = modadvapi32.NewProc("DeleteService") + procStartServiceW = modadvapi32.NewProc("StartServiceW") + procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") + procControlService = modadvapi32.NewProc("ControlService") + procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") + procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") + procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") + procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") + procChangeServiceConfig2W = modadvapi32.NewProc("ChangeServiceConfig2W") + procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") + procGetLastError = modkernel32.NewProc("GetLastError") + procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") + procFreeLibrary = modkernel32.NewProc("FreeLibrary") + procGetProcAddress = modkernel32.NewProc("GetProcAddress") + procGetVersion = modkernel32.NewProc("GetVersion") + procFormatMessageW = modkernel32.NewProc("FormatMessageW") + procExitProcess = modkernel32.NewProc("ExitProcess") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procReadFile = modkernel32.NewProc("ReadFile") + procWriteFile = modkernel32.NewProc("WriteFile") + procSetFilePointer = modkernel32.NewProc("SetFilePointer") + procCloseHandle = modkernel32.NewProc("CloseHandle") + procGetStdHandle = modkernel32.NewProc("GetStdHandle") + procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") + procFindNextFileW = modkernel32.NewProc("FindNextFileW") + procFindClose = modkernel32.NewProc("FindClose") + procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") + procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") + procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") + procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") + procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procDeleteFileW = modkernel32.NewProc("DeleteFileW") + procMoveFileW = modkernel32.NewProc("MoveFileW") + procMoveFileExW = modkernel32.NewProc("MoveFileExW") + procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") + procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") + procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") + procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") + procCancelIo = modkernel32.NewProc("CancelIo") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCreateProcessW = modkernel32.NewProc("CreateProcessW") + procOpenProcess = modkernel32.NewProc("OpenProcess") + procTerminateProcess = modkernel32.NewProc("TerminateProcess") + procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") + procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") + procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess") + procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") + procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") + procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") + procGetTempPathW = modkernel32.NewProc("GetTempPathW") + procCreatePipe = modkernel32.NewProc("CreatePipe") + procGetFileType = modkernel32.NewProc("GetFileType") + procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") + procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") + procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") + procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") + procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") + procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") + procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") + procSetFileTime = modkernel32.NewProc("SetFileTime") + procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") + procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") + procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") + procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") + procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") + procLocalFree = modkernel32.NewProc("LocalFree") + procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") + procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") + procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") + procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") + procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") + procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") + procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") + procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") + procVirtualLock = modkernel32.NewProc("VirtualLock") + procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") + procTransmitFile = modmswsock.NewProc("TransmitFile") + procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") + procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") + procCertOpenStore = modcrypt32.NewProc("CertOpenStore") + procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") + procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") + procCertCloseStore = modcrypt32.NewProc("CertCloseStore") + procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") + procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") + procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") + procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") + procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") + procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") + procRegCloseKey = modadvapi32.NewProc("RegCloseKey") + procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") + procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") + procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") + procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") + procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") + procReadConsoleW = modkernel32.NewProc("ReadConsoleW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") + procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") + procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") + procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procSetEvent = modkernel32.NewProc("SetEvent") + procWSAStartup = modws2_32.NewProc("WSAStartup") + procWSACleanup = modws2_32.NewProc("WSACleanup") + procWSAIoctl = modws2_32.NewProc("WSAIoctl") + procsocket = modws2_32.NewProc("socket") + procsetsockopt = modws2_32.NewProc("setsockopt") + procgetsockopt = modws2_32.NewProc("getsockopt") + procbind = modws2_32.NewProc("bind") + procconnect = modws2_32.NewProc("connect") + procgetsockname = modws2_32.NewProc("getsockname") + procgetpeername = modws2_32.NewProc("getpeername") + proclisten = modws2_32.NewProc("listen") + procshutdown = modws2_32.NewProc("shutdown") + procclosesocket = modws2_32.NewProc("closesocket") + procAcceptEx = modmswsock.NewProc("AcceptEx") + procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") + procWSARecv = modws2_32.NewProc("WSARecv") + procWSASend = modws2_32.NewProc("WSASend") + procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") + procWSASendTo = modws2_32.NewProc("WSASendTo") + procgethostbyname = modws2_32.NewProc("gethostbyname") + procgetservbyname = modws2_32.NewProc("getservbyname") + procntohs = modws2_32.NewProc("ntohs") + procgetprotobyname = modws2_32.NewProc("getprotobyname") + procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") + procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") + procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") + procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") + procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") + procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") + procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") + procGetACP = modkernel32.NewProc("GetACP") + procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") + procTranslateNameW = modsecur32.NewProc("TranslateNameW") + procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") + procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") + procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") + procGetLengthSid = modadvapi32.NewProc("GetLengthSid") + procCopySid = modadvapi32.NewProc("CopySid") + procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") + procFreeSid = modadvapi32.NewProc("FreeSid") + procEqualSid = modadvapi32.NewProc("EqualSid") + procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") + procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") + procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") +) + +func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procRegisterEventSourceW.Addr(), 2, uintptr(unsafe.Pointer(uncServerName)), uintptr(unsafe.Pointer(sourceName)), 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func DeregisterEventSource(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDeregisterEventSource.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procReportEventW.Addr(), 9, uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access)) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CloseServiceHandle(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procCloseServiceHandle.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall15(procCreateServiceW.Addr(), 13, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(unsafe.Pointer(displayName)), uintptr(access), uintptr(srvType), uintptr(startType), uintptr(errCtl), uintptr(unsafe.Pointer(pathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), 0, 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procOpenServiceW.Addr(), 3, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access)) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func DeleteService(service Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDeleteService.Addr(), 1, uintptr(service), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procStartServiceW.Addr(), 3, uintptr(service), uintptr(numArgs), uintptr(unsafe.Pointer(argVectors))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procQueryServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(status)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procControlService.Addr(), 3, uintptr(service), uintptr(control), uintptr(unsafe.Pointer(status))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) { + r1, _, e1 := syscall.Syscall(procStartServiceCtrlDispatcherW.Addr(), 1, uintptr(unsafe.Pointer(serviceTable)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procSetServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(serviceStatus)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) { + r1, _, e1 := syscall.Syscall12(procChangeServiceConfigW.Addr(), 11, uintptr(service), uintptr(serviceType), uintptr(startType), uintptr(errorControl), uintptr(unsafe.Pointer(binaryPathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), uintptr(unsafe.Pointer(displayName)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryServiceConfigW.Addr(), 4, uintptr(service), uintptr(unsafe.Pointer(serviceConfig)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) { + r1, _, e1 := syscall.Syscall(procChangeServiceConfig2W.Addr(), 3, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(info))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryServiceConfig2W.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetLastError() (lasterr error) { + r0, _, _ := syscall.Syscall(procGetLastError.Addr(), 0, 0, 0, 0) + if r0 != 0 { + lasterr = syscall.Errno(r0) + } + return +} + +func LoadLibrary(libname string) (handle Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(libname) + if err != nil { + return + } + return _LoadLibrary(_p0) +} + +func _LoadLibrary(libname *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FreeLibrary(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(procname) + if err != nil { + return + } + return _GetProcAddress(module, _p0) +} + +func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { + r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) + proc = uintptr(r0) + if proc == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetVersion() (ver uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetVersion.Addr(), 0, 0, 0, 0) + ver = uint32(r0) + if ver == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { + var _p0 *uint16 + if len(buf) > 0 { + _p0 = &buf[0] + } + r0, _, e1 := syscall.Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ExitProcess(exitcode uint32) { + syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) + return +} + +func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = Handle(r0) + if handle == InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { + r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) + newlowoffset = uint32(r0) + if newlowoffset == 0xffffffff { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CloseHandle(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetStdHandle(stdhandle int) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) + handle = Handle(r0) + if handle == InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) + handle = Handle(r0) + if handle == InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func findNextFile1(handle Handle, data *win32finddata1) (err error) { + r1, _, e1 := syscall.Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FindClose(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { + r1, _, e1 := syscall.Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetCurrentDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { + r1, _, e1 := syscall.Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func RemoveDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func DeleteFile(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func MoveFile(from *uint16, to *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetComputerName(buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetEndOfFile(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetSystemTimeAsFileTime(time *Filetime) { + syscall.Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) + return +} + +func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) + rc = uint32(r0) + if rc == 0xffffffff { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CancelIo(s Handle) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CancelIoEx(s Handle, o *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { + var _p0 uint32 + if inheritHandles { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall(procOpenProcess.Addr(), 3, uintptr(da), uintptr(_p0), uintptr(pid)) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func TerminateProcess(handle Handle, exitcode uint32) (err error) { + r1, _, e1 := syscall.Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetStartupInfo(startupInfo *StartupInfo) (err error) { + r1, _, e1 := syscall.Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetCurrentProcess() (pseudoHandle Handle, err error) { + r0, _, e1 := syscall.Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0) + pseudoHandle = Handle(r0) + if pseudoHandle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { + r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { + var _p0 uint32 + if bInheritHandle { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { + r0, _, e1 := syscall.Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) + event = uint32(r0) + if event == 0xffffffff { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetFileType(filehandle Handle) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { + r1, _, e1 := syscall.Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetEnvironmentStrings() (envs *uint16, err error) { + r0, _, e1 := syscall.Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) + envs = (*uint16)(unsafe.Pointer(r0)) + if envs == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FreeEnvironmentStrings(envs *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetFileAttributes(name *uint16) (attrs uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + attrs = uint32(r0) + if attrs == INVALID_FILE_ATTRIBUTES { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetFileAttributes(name *uint16, attrs uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { + r1, _, e1 := syscall.Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetCommandLine() (cmd *uint16) { + r0, _, _ := syscall.Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) + cmd = (*uint16)(unsafe.Pointer(r0)) + return +} + +func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { + r0, _, e1 := syscall.Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) + argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) + if argv == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func LocalFree(hmem Handle) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) + handle = Handle(r0) + if handle != 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FlushFileBuffers(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { + r0, _, e1 := syscall.Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) + addr = uintptr(r0) + if addr == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func UnmapViewOfFile(addr uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FlushViewOfFile(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func VirtualLock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func VirtualUnlock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + var _p0 uint32 + if watchSubTree { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { + r0, _, e1 := syscall.Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) + store = Handle(r0) + if store == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) + handle = Handle(r0) + if handle == InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { + r0, _, e1 := syscall.Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) + context = (*CertContext)(unsafe.Pointer(r0)) + if context == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { + r1, _, e1 := syscall.Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertCloseStore(store Handle, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { + r1, _, e1 := syscall.Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertFreeCertificateChain(ctx *CertChainContext) { + syscall.Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + return +} + +func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { + r0, _, e1 := syscall.Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) + context = (*CertContext)(unsafe.Pointer(r0)) + if context == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertFreeCertificateContext(ctx *CertContext) (err error) { + r1, _, e1 := syscall.Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { + r1, _, e1 := syscall.Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { + r0, _, _ := syscall.Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + +func RegCloseKey(key Handle) (regerrno error) { + r0, _, _ := syscall.Syscall(procRegCloseKey.Addr(), 1, uintptr(key), 0, 0) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + +func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { + r0, _, _ := syscall.Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + +func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { + r0, _, _ := syscall.Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + +func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { + r0, _, _ := syscall.Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + +func getCurrentProcessId() (pid uint32) { + r0, _, _ := syscall.Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) + pid = uint32(r0) + return +} + +func GetConsoleMode(console Handle, mode *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { + r1, _, e1 := syscall.Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { + r1, _, e1 := syscall.Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) + handle = Handle(r0) + if handle == InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) + if r1&0xff == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) + if r1&0xff == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetCurrentThreadId() (id uint32) { + r0, _, _ := syscall.Syscall(procGetCurrentThreadId.Addr(), 0, 0, 0, 0) + id = uint32(r0) + return +} + +func CreateEvent(eventAttrs *syscall.SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name)), 0, 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetEvent(event Handle) (err error) { + r1, _, e1 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(event), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { + r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) + if r0 != 0 { + sockerr = syscall.Errno(r0) + } + return +} + +func WSACleanup() (err error) { + r1, _, e1 := syscall.Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + r1, _, e1 := syscall.Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) + handle = Handle(r0) + if handle == InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { + r1, _, e1 := syscall.Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { + r1, _, e1 := syscall.Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func listen(s Handle, backlog int32) (err error) { + r1, _, e1 := syscall.Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func shutdown(s Handle, how int32) (err error) { + r1, _, e1 := syscall.Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func Closesocket(s Handle) (err error) { + r1, _, e1 := syscall.Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { + syscall.Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) + return +} + +func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetHostByName(name string) (h *Hostent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return + } + return _GetHostByName(_p0) +} + +func _GetHostByName(name *byte) (h *Hostent, err error) { + r0, _, e1 := syscall.Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + h = (*Hostent)(unsafe.Pointer(r0)) + if h == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetServByName(name string, proto string) (s *Servent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(proto) + if err != nil { + return + } + return _GetServByName(_p0, _p1) +} + +func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { + r0, _, e1 := syscall.Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) + s = (*Servent)(unsafe.Pointer(r0)) + if s == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func Ntohs(netshort uint16) (u uint16) { + r0, _, _ := syscall.Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) + u = uint16(r0) + return +} + +func GetProtoByName(name string) (p *Protoent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return + } + return _GetProtoByName(_p0) +} + +func _GetProtoByName(name *byte) (p *Protoent, err error) { + r0, _, e1 := syscall.Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + p = (*Protoent)(unsafe.Pointer(r0)) + if p == nil { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) { + var _p0 *uint16 + _p0, status = syscall.UTF16PtrFromString(name) + if status != nil { + return + } + return _DnsQuery(_p0, qtype, options, extra, qrs, pr) +} + +func _DnsQuery(name *uint16, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) { + r0, _, _ := syscall.Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(name)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr))) + if r0 != 0 { + status = syscall.Errno(r0) + } + return +} + +func DnsRecordListFree(rl *DNSRecord, freetype uint32) { + syscall.Syscall(procDnsRecordListFree.Addr(), 2, uintptr(unsafe.Pointer(rl)), uintptr(freetype), 0) + return +} + +func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { + r0, _, _ := syscall.Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) + same = r0 != 0 + return +} + +func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { + r0, _, _ := syscall.Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) + if r0 != 0 { + sockerr = syscall.Errno(r0) + } + return +} + +func FreeAddrInfoW(addrinfo *AddrinfoW) { + syscall.Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) + return +} + +func GetIfEntry(pIfRow *MibIfRow) (errcode error) { + r0, _, _ := syscall.Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { + r0, _, _ := syscall.Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { + r0, _, e1 := syscall.Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) + n = int32(r0) + if n == -1 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { + r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetACP() (acp uint32) { + r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0) + acp = uint32(r0) + return +} + +func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { + r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) + nwrite = int32(r0) + if nwrite == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) + if r1&0xff == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) + if r1&0xff == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { + r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) + if r0 != 0 { + neterr = syscall.Errno(r0) + } + return +} + +func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) { + r0, _, _ := syscall.Syscall(procNetGetJoinInformation.Addr(), 3, uintptr(unsafe.Pointer(server)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bufType))) + if r0 != 0 { + neterr = syscall.Errno(r0) + } + return +} + +func NetApiBufferFree(buf *byte) (neterr error) { + r0, _, _ := syscall.Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) + if r0 != 0 { + neterr = syscall.Errno(r0) + } + return +} + +func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { + r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetLengthSid(sid *SID) (len uint32) { + r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + len = uint32(r0) + return +} + +func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { + r1, _, e1 := syscall.Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) { + r1, _, e1 := syscall.Syscall12(procAllocateAndInitializeSid.Addr(), 11, uintptr(unsafe.Pointer(identAuth)), uintptr(subAuth), uintptr(subAuth0), uintptr(subAuth1), uintptr(subAuth2), uintptr(subAuth3), uintptr(subAuth4), uintptr(subAuth5), uintptr(subAuth6), uintptr(subAuth7), uintptr(unsafe.Pointer(sid)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func FreeSid(sid *SID) (err error) { + r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + if r1 != 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) { + r0, _, _ := syscall.Syscall(procEqualSid.Addr(), 2, uintptr(unsafe.Pointer(sid1)), uintptr(unsafe.Pointer(sid2)), 0) + isEqual = r0 != 0 + return +} + +func OpenProcessToken(h Handle, access uint32, token *Token) (err error) { + r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(h), uintptr(access), uintptr(unsafe.Pointer(token))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(t), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetUserProfileDirectoryW.Addr(), 3, uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} diff --git a/vendor/golang.org/x/sys/windows/ztypes_windows.go b/vendor/golang.org/x/sys/windows/ztypes_windows.go new file mode 100644 index 0000000..1fe19d1 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/ztypes_windows.go @@ -0,0 +1,1242 @@ +// 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 windows + +import "syscall" + +const ( + // Windows errors. + ERROR_FILE_NOT_FOUND syscall.Errno = 2 + ERROR_PATH_NOT_FOUND syscall.Errno = 3 + ERROR_ACCESS_DENIED syscall.Errno = 5 + ERROR_NO_MORE_FILES syscall.Errno = 18 + ERROR_HANDLE_EOF syscall.Errno = 38 + ERROR_NETNAME_DELETED syscall.Errno = 64 + ERROR_FILE_EXISTS syscall.Errno = 80 + ERROR_BROKEN_PIPE syscall.Errno = 109 + ERROR_BUFFER_OVERFLOW syscall.Errno = 111 + ERROR_INSUFFICIENT_BUFFER syscall.Errno = 122 + ERROR_MOD_NOT_FOUND syscall.Errno = 126 + ERROR_PROC_NOT_FOUND syscall.Errno = 127 + ERROR_ALREADY_EXISTS syscall.Errno = 183 + ERROR_ENVVAR_NOT_FOUND syscall.Errno = 203 + ERROR_MORE_DATA syscall.Errno = 234 + ERROR_OPERATION_ABORTED syscall.Errno = 995 + ERROR_IO_PENDING syscall.Errno = 997 + ERROR_SERVICE_SPECIFIC_ERROR syscall.Errno = 1066 + ERROR_NOT_FOUND syscall.Errno = 1168 + ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314 + WSAEACCES syscall.Errno = 10013 + WSAECONNRESET syscall.Errno = 10054 +) + +const ( + // Invented values to support what package os expects. + O_RDONLY = 0x00000 + O_WRONLY = 0x00001 + O_RDWR = 0x00002 + O_CREAT = 0x00040 + O_EXCL = 0x00080 + O_NOCTTY = 0x00100 + O_TRUNC = 0x00200 + O_NONBLOCK = 0x00800 + O_APPEND = 0x00400 + O_SYNC = 0x01000 + O_ASYNC = 0x02000 + O_CLOEXEC = 0x80000 +) + +const ( + // More invented values for signals + SIGHUP = Signal(0x1) + SIGINT = Signal(0x2) + SIGQUIT = Signal(0x3) + SIGILL = Signal(0x4) + SIGTRAP = Signal(0x5) + SIGABRT = Signal(0x6) + SIGBUS = Signal(0x7) + SIGFPE = Signal(0x8) + SIGKILL = Signal(0x9) + SIGSEGV = Signal(0xb) + SIGPIPE = Signal(0xd) + SIGALRM = Signal(0xe) + SIGTERM = Signal(0xf) +) + +var signals = [...]string{ + 1: "hangup", + 2: "interrupt", + 3: "quit", + 4: "illegal instruction", + 5: "trace/breakpoint trap", + 6: "aborted", + 7: "bus error", + 8: "floating point exception", + 9: "killed", + 10: "user defined signal 1", + 11: "segmentation fault", + 12: "user defined signal 2", + 13: "broken pipe", + 14: "alarm clock", + 15: "terminated", +} + +const ( + GENERIC_READ = 0x80000000 + GENERIC_WRITE = 0x40000000 + GENERIC_EXECUTE = 0x20000000 + GENERIC_ALL = 0x10000000 + + FILE_LIST_DIRECTORY = 0x00000001 + FILE_APPEND_DATA = 0x00000004 + FILE_WRITE_ATTRIBUTES = 0x00000100 + + FILE_SHARE_READ = 0x00000001 + FILE_SHARE_WRITE = 0x00000002 + FILE_SHARE_DELETE = 0x00000004 + FILE_ATTRIBUTE_READONLY = 0x00000001 + FILE_ATTRIBUTE_HIDDEN = 0x00000002 + FILE_ATTRIBUTE_SYSTEM = 0x00000004 + FILE_ATTRIBUTE_DIRECTORY = 0x00000010 + FILE_ATTRIBUTE_ARCHIVE = 0x00000020 + FILE_ATTRIBUTE_NORMAL = 0x00000080 + FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400 + + INVALID_FILE_ATTRIBUTES = 0xffffffff + + CREATE_NEW = 1 + CREATE_ALWAYS = 2 + OPEN_EXISTING = 3 + OPEN_ALWAYS = 4 + TRUNCATE_EXISTING = 5 + + FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 + FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 + FILE_FLAG_OVERLAPPED = 0x40000000 + + HANDLE_FLAG_INHERIT = 0x00000001 + STARTF_USESTDHANDLES = 0x00000100 + STARTF_USESHOWWINDOW = 0x00000001 + DUPLICATE_CLOSE_SOURCE = 0x00000001 + DUPLICATE_SAME_ACCESS = 0x00000002 + + STD_INPUT_HANDLE = -10 + STD_OUTPUT_HANDLE = -11 + STD_ERROR_HANDLE = -12 + + FILE_BEGIN = 0 + FILE_CURRENT = 1 + FILE_END = 2 + + LANG_ENGLISH = 0x09 + SUBLANG_ENGLISH_US = 0x01 + + FORMAT_MESSAGE_ALLOCATE_BUFFER = 256 + FORMAT_MESSAGE_IGNORE_INSERTS = 512 + FORMAT_MESSAGE_FROM_STRING = 1024 + FORMAT_MESSAGE_FROM_HMODULE = 2048 + FORMAT_MESSAGE_FROM_SYSTEM = 4096 + FORMAT_MESSAGE_ARGUMENT_ARRAY = 8192 + FORMAT_MESSAGE_MAX_WIDTH_MASK = 255 + + MAX_PATH = 260 + MAX_LONG_PATH = 32768 + + MAX_COMPUTERNAME_LENGTH = 15 + + TIME_ZONE_ID_UNKNOWN = 0 + TIME_ZONE_ID_STANDARD = 1 + + TIME_ZONE_ID_DAYLIGHT = 2 + IGNORE = 0 + INFINITE = 0xffffffff + + WAIT_TIMEOUT = 258 + WAIT_ABANDONED = 0x00000080 + WAIT_OBJECT_0 = 0x00000000 + WAIT_FAILED = 0xFFFFFFFF + + CREATE_NEW_PROCESS_GROUP = 0x00000200 + CREATE_UNICODE_ENVIRONMENT = 0x00000400 + + PROCESS_TERMINATE = 1 + PROCESS_QUERY_INFORMATION = 0x00000400 + SYNCHRONIZE = 0x00100000 + + PAGE_READONLY = 0x02 + PAGE_READWRITE = 0x04 + PAGE_WRITECOPY = 0x08 + PAGE_EXECUTE_READ = 0x20 + PAGE_EXECUTE_READWRITE = 0x40 + PAGE_EXECUTE_WRITECOPY = 0x80 + + FILE_MAP_COPY = 0x01 + FILE_MAP_WRITE = 0x02 + FILE_MAP_READ = 0x04 + FILE_MAP_EXECUTE = 0x20 + + CTRL_C_EVENT = 0 + CTRL_BREAK_EVENT = 1 + + // Windows reserves errors >= 1<<29 for application use. + APPLICATION_ERROR = 1 << 29 +) + +const ( + // flags for CreateToolhelp32Snapshot + TH32CS_SNAPHEAPLIST = 0x01 + TH32CS_SNAPPROCESS = 0x02 + TH32CS_SNAPTHREAD = 0x04 + TH32CS_SNAPMODULE = 0x08 + TH32CS_SNAPMODULE32 = 0x10 + TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPMODULE | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD + TH32CS_INHERIT = 0x80000000 +) + +const ( + // filters for ReadDirectoryChangesW + FILE_NOTIFY_CHANGE_FILE_NAME = 0x001 + FILE_NOTIFY_CHANGE_DIR_NAME = 0x002 + FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x004 + FILE_NOTIFY_CHANGE_SIZE = 0x008 + FILE_NOTIFY_CHANGE_LAST_WRITE = 0x010 + FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x020 + FILE_NOTIFY_CHANGE_CREATION = 0x040 + FILE_NOTIFY_CHANGE_SECURITY = 0x100 +) + +const ( + // do not reorder + FILE_ACTION_ADDED = iota + 1 + FILE_ACTION_REMOVED + FILE_ACTION_MODIFIED + FILE_ACTION_RENAMED_OLD_NAME + FILE_ACTION_RENAMED_NEW_NAME +) + +const ( + // wincrypt.h + PROV_RSA_FULL = 1 + PROV_RSA_SIG = 2 + PROV_DSS = 3 + PROV_FORTEZZA = 4 + PROV_MS_EXCHANGE = 5 + PROV_SSL = 6 + PROV_RSA_SCHANNEL = 12 + PROV_DSS_DH = 13 + PROV_EC_ECDSA_SIG = 14 + PROV_EC_ECNRA_SIG = 15 + PROV_EC_ECDSA_FULL = 16 + PROV_EC_ECNRA_FULL = 17 + PROV_DH_SCHANNEL = 18 + PROV_SPYRUS_LYNKS = 20 + PROV_RNG = 21 + PROV_INTEL_SEC = 22 + PROV_REPLACE_OWF = 23 + PROV_RSA_AES = 24 + CRYPT_VERIFYCONTEXT = 0xF0000000 + CRYPT_NEWKEYSET = 0x00000008 + CRYPT_DELETEKEYSET = 0x00000010 + CRYPT_MACHINE_KEYSET = 0x00000020 + CRYPT_SILENT = 0x00000040 + CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x00000080 + + USAGE_MATCH_TYPE_AND = 0 + USAGE_MATCH_TYPE_OR = 1 + + X509_ASN_ENCODING = 0x00000001 + PKCS_7_ASN_ENCODING = 0x00010000 + + CERT_STORE_PROV_MEMORY = 2 + + CERT_STORE_ADD_ALWAYS = 4 + + CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004 + + CERT_TRUST_NO_ERROR = 0x00000000 + CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001 + CERT_TRUST_IS_REVOKED = 0x00000004 + CERT_TRUST_IS_NOT_SIGNATURE_VALID = 0x00000008 + CERT_TRUST_IS_NOT_VALID_FOR_USAGE = 0x00000010 + CERT_TRUST_IS_UNTRUSTED_ROOT = 0x00000020 + CERT_TRUST_REVOCATION_STATUS_UNKNOWN = 0x00000040 + CERT_TRUST_IS_CYCLIC = 0x00000080 + CERT_TRUST_INVALID_EXTENSION = 0x00000100 + CERT_TRUST_INVALID_POLICY_CONSTRAINTS = 0x00000200 + CERT_TRUST_INVALID_BASIC_CONSTRAINTS = 0x00000400 + CERT_TRUST_INVALID_NAME_CONSTRAINTS = 0x00000800 + CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT = 0x00001000 + CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000 + CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000 + CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000 + CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000 + CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000 + CERT_TRUST_IS_EXPLICIT_DISTRUST = 0x04000000 + CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT = 0x08000000 + + CERT_CHAIN_POLICY_BASE = 1 + CERT_CHAIN_POLICY_AUTHENTICODE = 2 + CERT_CHAIN_POLICY_AUTHENTICODE_TS = 3 + CERT_CHAIN_POLICY_SSL = 4 + CERT_CHAIN_POLICY_BASIC_CONSTRAINTS = 5 + CERT_CHAIN_POLICY_NT_AUTH = 6 + CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7 + CERT_CHAIN_POLICY_EV = 8 + + CERT_E_EXPIRED = 0x800B0101 + CERT_E_ROLE = 0x800B0103 + CERT_E_PURPOSE = 0x800B0106 + CERT_E_UNTRUSTEDROOT = 0x800B0109 + CERT_E_CN_NO_MATCH = 0x800B010F + + AUTHTYPE_CLIENT = 1 + AUTHTYPE_SERVER = 2 +) + +var ( + OID_PKIX_KP_SERVER_AUTH = []byte("1.3.6.1.5.5.7.3.1\x00") + OID_SERVER_GATED_CRYPTO = []byte("1.3.6.1.4.1.311.10.3.3\x00") + OID_SGC_NETSCAPE = []byte("2.16.840.1.113730.4.1\x00") +) + +// Invented values to support what package os expects. +type Timeval struct { + Sec int32 + Usec int32 +} + +func (tv *Timeval) Nanoseconds() int64 { + return (int64(tv.Sec)*1e6 + int64(tv.Usec)) * 1e3 +} + +func NsecToTimeval(nsec int64) (tv Timeval) { + tv.Sec = int32(nsec / 1e9) + tv.Usec = int32(nsec % 1e9 / 1e3) + return +} + +type SecurityAttributes struct { + Length uint32 + SecurityDescriptor uintptr + InheritHandle uint32 +} + +type Overlapped struct { + Internal uintptr + InternalHigh uintptr + Offset uint32 + OffsetHigh uint32 + HEvent Handle +} + +type FileNotifyInformation struct { + NextEntryOffset uint32 + Action uint32 + FileNameLength uint32 + FileName uint16 +} + +type Filetime struct { + LowDateTime uint32 + HighDateTime uint32 +} + +// Nanoseconds returns Filetime ft in nanoseconds +// since Epoch (00:00:00 UTC, January 1, 1970). +func (ft *Filetime) Nanoseconds() int64 { + // 100-nanosecond intervals since January 1, 1601 + nsec := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) + // change starting time to the Epoch (00:00:00 UTC, January 1, 1970) + nsec -= 116444736000000000 + // convert into nanoseconds + nsec *= 100 + return nsec +} + +func NsecToFiletime(nsec int64) (ft Filetime) { + // convert into 100-nanosecond + nsec /= 100 + // change starting time to January 1, 1601 + nsec += 116444736000000000 + // split into high / low + ft.LowDateTime = uint32(nsec & 0xffffffff) + ft.HighDateTime = uint32(nsec >> 32 & 0xffffffff) + return ft +} + +type Win32finddata struct { + FileAttributes uint32 + CreationTime Filetime + LastAccessTime Filetime + LastWriteTime Filetime + FileSizeHigh uint32 + FileSizeLow uint32 + Reserved0 uint32 + Reserved1 uint32 + FileName [MAX_PATH - 1]uint16 + AlternateFileName [13]uint16 +} + +// This is the actual system call structure. +// Win32finddata is what we committed to in Go 1. +type win32finddata1 struct { + FileAttributes uint32 + CreationTime Filetime + LastAccessTime Filetime + LastWriteTime Filetime + FileSizeHigh uint32 + FileSizeLow uint32 + Reserved0 uint32 + Reserved1 uint32 + FileName [MAX_PATH]uint16 + AlternateFileName [14]uint16 +} + +func copyFindData(dst *Win32finddata, src *win32finddata1) { + dst.FileAttributes = src.FileAttributes + dst.CreationTime = src.CreationTime + dst.LastAccessTime = src.LastAccessTime + dst.LastWriteTime = src.LastWriteTime + dst.FileSizeHigh = src.FileSizeHigh + dst.FileSizeLow = src.FileSizeLow + dst.Reserved0 = src.Reserved0 + dst.Reserved1 = src.Reserved1 + + // The src is 1 element bigger than dst, but it must be NUL. + copy(dst.FileName[:], src.FileName[:]) + copy(dst.AlternateFileName[:], src.AlternateFileName[:]) +} + +type ByHandleFileInformation struct { + FileAttributes uint32 + CreationTime Filetime + LastAccessTime Filetime + LastWriteTime Filetime + VolumeSerialNumber uint32 + FileSizeHigh uint32 + FileSizeLow uint32 + NumberOfLinks uint32 + FileIndexHigh uint32 + FileIndexLow uint32 +} + +const ( + GetFileExInfoStandard = 0 + GetFileExMaxInfoLevel = 1 +) + +type Win32FileAttributeData struct { + FileAttributes uint32 + CreationTime Filetime + LastAccessTime Filetime + LastWriteTime Filetime + FileSizeHigh uint32 + FileSizeLow uint32 +} + +// ShowWindow constants +const ( + // winuser.h + SW_HIDE = 0 + SW_NORMAL = 1 + SW_SHOWNORMAL = 1 + SW_SHOWMINIMIZED = 2 + SW_SHOWMAXIMIZED = 3 + SW_MAXIMIZE = 3 + SW_SHOWNOACTIVATE = 4 + SW_SHOW = 5 + SW_MINIMIZE = 6 + SW_SHOWMINNOACTIVE = 7 + SW_SHOWNA = 8 + SW_RESTORE = 9 + SW_SHOWDEFAULT = 10 + SW_FORCEMINIMIZE = 11 +) + +type StartupInfo struct { + Cb uint32 + _ *uint16 + Desktop *uint16 + Title *uint16 + X uint32 + Y uint32 + XSize uint32 + YSize uint32 + XCountChars uint32 + YCountChars uint32 + FillAttribute uint32 + Flags uint32 + ShowWindow uint16 + _ uint16 + _ *byte + StdInput Handle + StdOutput Handle + StdErr Handle +} + +type ProcessInformation struct { + Process Handle + Thread Handle + ProcessId uint32 + ThreadId uint32 +} + +type ProcessEntry32 struct { + Size uint32 + Usage uint32 + ProcessID uint32 + DefaultHeapID uintptr + ModuleID uint32 + Threads uint32 + ParentProcessID uint32 + PriClassBase int32 + Flags uint32 + ExeFile [MAX_PATH]uint16 +} + +type Systemtime struct { + Year uint16 + Month uint16 + DayOfWeek uint16 + Day uint16 + Hour uint16 + Minute uint16 + Second uint16 + Milliseconds uint16 +} + +type Timezoneinformation struct { + Bias int32 + StandardName [32]uint16 + StandardDate Systemtime + StandardBias int32 + DaylightName [32]uint16 + DaylightDate Systemtime + DaylightBias int32 +} + +// Socket related. + +const ( + AF_UNSPEC = 0 + AF_UNIX = 1 + AF_INET = 2 + AF_INET6 = 23 + AF_NETBIOS = 17 + + SOCK_STREAM = 1 + SOCK_DGRAM = 2 + SOCK_RAW = 3 + SOCK_SEQPACKET = 5 + + IPPROTO_IP = 0 + IPPROTO_IPV6 = 0x29 + IPPROTO_TCP = 6 + IPPROTO_UDP = 17 + + SOL_SOCKET = 0xffff + SO_REUSEADDR = 4 + SO_KEEPALIVE = 8 + SO_DONTROUTE = 16 + SO_BROADCAST = 32 + SO_LINGER = 128 + SO_RCVBUF = 0x1002 + SO_SNDBUF = 0x1001 + SO_UPDATE_ACCEPT_CONTEXT = 0x700b + SO_UPDATE_CONNECT_CONTEXT = 0x7010 + + IOC_OUT = 0x40000000 + IOC_IN = 0x80000000 + IOC_VENDOR = 0x18000000 + IOC_INOUT = IOC_IN | IOC_OUT + IOC_WS2 = 0x08000000 + SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6 + SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4 + SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 + + // cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460 + + IP_TOS = 0x3 + IP_TTL = 0x4 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_LOOP = 0xb + IP_ADD_MEMBERSHIP = 0xc + IP_DROP_MEMBERSHIP = 0xd + + IPV6_V6ONLY = 0x1b + IPV6_UNICAST_HOPS = 0x4 + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_LOOP = 0xb + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + + SOMAXCONN = 0x7fffffff + + TCP_NODELAY = 1 + + SHUT_RD = 0 + SHUT_WR = 1 + SHUT_RDWR = 2 + + WSADESCRIPTION_LEN = 256 + WSASYS_STATUS_LEN = 128 +) + +type WSABuf struct { + Len uint32 + Buf *byte +} + +// Invented values to support what package os expects. +const ( + S_IFMT = 0x1f000 + S_IFIFO = 0x1000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFBLK = 0x6000 + S_IFREG = 0x8000 + S_IFLNK = 0xa000 + S_IFSOCK = 0xc000 + S_ISUID = 0x800 + S_ISGID = 0x400 + S_ISVTX = 0x200 + S_IRUSR = 0x100 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXUSR = 0x40 +) + +const ( + FILE_TYPE_CHAR = 0x0002 + FILE_TYPE_DISK = 0x0001 + FILE_TYPE_PIPE = 0x0003 + FILE_TYPE_REMOTE = 0x8000 + FILE_TYPE_UNKNOWN = 0x0000 +) + +type Hostent struct { + Name *byte + Aliases **byte + AddrType uint16 + Length uint16 + AddrList **byte +} + +type Protoent struct { + Name *byte + Aliases **byte + Proto uint16 +} + +const ( + DNS_TYPE_A = 0x0001 + DNS_TYPE_NS = 0x0002 + DNS_TYPE_MD = 0x0003 + DNS_TYPE_MF = 0x0004 + DNS_TYPE_CNAME = 0x0005 + DNS_TYPE_SOA = 0x0006 + DNS_TYPE_MB = 0x0007 + DNS_TYPE_MG = 0x0008 + DNS_TYPE_MR = 0x0009 + DNS_TYPE_NULL = 0x000a + DNS_TYPE_WKS = 0x000b + DNS_TYPE_PTR = 0x000c + DNS_TYPE_HINFO = 0x000d + DNS_TYPE_MINFO = 0x000e + DNS_TYPE_MX = 0x000f + DNS_TYPE_TEXT = 0x0010 + DNS_TYPE_RP = 0x0011 + DNS_TYPE_AFSDB = 0x0012 + DNS_TYPE_X25 = 0x0013 + DNS_TYPE_ISDN = 0x0014 + DNS_TYPE_RT = 0x0015 + DNS_TYPE_NSAP = 0x0016 + DNS_TYPE_NSAPPTR = 0x0017 + DNS_TYPE_SIG = 0x0018 + DNS_TYPE_KEY = 0x0019 + DNS_TYPE_PX = 0x001a + DNS_TYPE_GPOS = 0x001b + DNS_TYPE_AAAA = 0x001c + DNS_TYPE_LOC = 0x001d + DNS_TYPE_NXT = 0x001e + DNS_TYPE_EID = 0x001f + DNS_TYPE_NIMLOC = 0x0020 + DNS_TYPE_SRV = 0x0021 + DNS_TYPE_ATMA = 0x0022 + DNS_TYPE_NAPTR = 0x0023 + DNS_TYPE_KX = 0x0024 + DNS_TYPE_CERT = 0x0025 + DNS_TYPE_A6 = 0x0026 + DNS_TYPE_DNAME = 0x0027 + DNS_TYPE_SINK = 0x0028 + DNS_TYPE_OPT = 0x0029 + DNS_TYPE_DS = 0x002B + DNS_TYPE_RRSIG = 0x002E + DNS_TYPE_NSEC = 0x002F + DNS_TYPE_DNSKEY = 0x0030 + DNS_TYPE_DHCID = 0x0031 + DNS_TYPE_UINFO = 0x0064 + DNS_TYPE_UID = 0x0065 + DNS_TYPE_GID = 0x0066 + DNS_TYPE_UNSPEC = 0x0067 + DNS_TYPE_ADDRS = 0x00f8 + DNS_TYPE_TKEY = 0x00f9 + DNS_TYPE_TSIG = 0x00fa + DNS_TYPE_IXFR = 0x00fb + DNS_TYPE_AXFR = 0x00fc + DNS_TYPE_MAILB = 0x00fd + DNS_TYPE_MAILA = 0x00fe + DNS_TYPE_ALL = 0x00ff + DNS_TYPE_ANY = 0x00ff + DNS_TYPE_WINS = 0xff01 + DNS_TYPE_WINSR = 0xff02 + DNS_TYPE_NBSTAT = 0xff01 +) + +const ( + DNS_INFO_NO_RECORDS = 0x251D +) + +const ( + // flags inside DNSRecord.Dw + DnsSectionQuestion = 0x0000 + DnsSectionAnswer = 0x0001 + DnsSectionAuthority = 0x0002 + DnsSectionAdditional = 0x0003 +) + +type DNSSRVData struct { + Target *uint16 + Priority uint16 + Weight uint16 + Port uint16 + Pad uint16 +} + +type DNSPTRData struct { + Host *uint16 +} + +type DNSMXData struct { + NameExchange *uint16 + Preference uint16 + Pad uint16 +} + +type DNSTXTData struct { + StringCount uint16 + StringArray [1]*uint16 +} + +type DNSRecord struct { + Next *DNSRecord + Name *uint16 + Type uint16 + Length uint16 + Dw uint32 + Ttl uint32 + Reserved uint32 + Data [40]byte +} + +const ( + TF_DISCONNECT = 1 + TF_REUSE_SOCKET = 2 + TF_WRITE_BEHIND = 4 + TF_USE_DEFAULT_WORKER = 0 + TF_USE_SYSTEM_THREAD = 16 + TF_USE_KERNEL_APC = 32 +) + +type TransmitFileBuffers struct { + Head uintptr + HeadLength uint32 + Tail uintptr + TailLength uint32 +} + +const ( + IFF_UP = 1 + IFF_BROADCAST = 2 + IFF_LOOPBACK = 4 + IFF_POINTTOPOINT = 8 + IFF_MULTICAST = 16 +) + +const SIO_GET_INTERFACE_LIST = 0x4004747F + +// TODO(mattn): SockaddrGen is union of sockaddr/sockaddr_in/sockaddr_in6_old. +// will be fixed to change variable type as suitable. + +type SockaddrGen [24]byte + +type InterfaceInfo struct { + Flags uint32 + Address SockaddrGen + BroadcastAddress SockaddrGen + Netmask SockaddrGen +} + +type IpAddressString struct { + String [16]byte +} + +type IpMaskString IpAddressString + +type IpAddrString struct { + Next *IpAddrString + IpAddress IpAddressString + IpMask IpMaskString + Context uint32 +} + +const MAX_ADAPTER_NAME_LENGTH = 256 +const MAX_ADAPTER_DESCRIPTION_LENGTH = 128 +const MAX_ADAPTER_ADDRESS_LENGTH = 8 + +type IpAdapterInfo struct { + Next *IpAdapterInfo + ComboIndex uint32 + AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]byte + Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]byte + AddressLength uint32 + Address [MAX_ADAPTER_ADDRESS_LENGTH]byte + Index uint32 + Type uint32 + DhcpEnabled uint32 + CurrentIpAddress *IpAddrString + IpAddressList IpAddrString + GatewayList IpAddrString + DhcpServer IpAddrString + HaveWins bool + PrimaryWinsServer IpAddrString + SecondaryWinsServer IpAddrString + LeaseObtained int64 + LeaseExpires int64 +} + +const MAXLEN_PHYSADDR = 8 +const MAX_INTERFACE_NAME_LEN = 256 +const MAXLEN_IFDESCR = 256 + +type MibIfRow struct { + Name [MAX_INTERFACE_NAME_LEN]uint16 + Index uint32 + Type uint32 + Mtu uint32 + Speed uint32 + PhysAddrLen uint32 + PhysAddr [MAXLEN_PHYSADDR]byte + AdminStatus uint32 + OperStatus uint32 + LastChange uint32 + InOctets uint32 + InUcastPkts uint32 + InNUcastPkts uint32 + InDiscards uint32 + InErrors uint32 + InUnknownProtos uint32 + OutOctets uint32 + OutUcastPkts uint32 + OutNUcastPkts uint32 + OutDiscards uint32 + OutErrors uint32 + OutQLen uint32 + DescrLen uint32 + Descr [MAXLEN_IFDESCR]byte +} + +type CertContext struct { + EncodingType uint32 + EncodedCert *byte + Length uint32 + CertInfo uintptr + Store Handle +} + +type CertChainContext struct { + Size uint32 + TrustStatus CertTrustStatus + ChainCount uint32 + Chains **CertSimpleChain + LowerQualityChainCount uint32 + LowerQualityChains **CertChainContext + HasRevocationFreshnessTime uint32 + RevocationFreshnessTime uint32 +} + +type CertSimpleChain struct { + Size uint32 + TrustStatus CertTrustStatus + NumElements uint32 + Elements **CertChainElement + TrustListInfo uintptr + HasRevocationFreshnessTime uint32 + RevocationFreshnessTime uint32 +} + +type CertChainElement struct { + Size uint32 + CertContext *CertContext + TrustStatus CertTrustStatus + RevocationInfo *CertRevocationInfo + IssuanceUsage *CertEnhKeyUsage + ApplicationUsage *CertEnhKeyUsage + ExtendedErrorInfo *uint16 +} + +type CertRevocationInfo struct { + Size uint32 + RevocationResult uint32 + RevocationOid *byte + OidSpecificInfo uintptr + HasFreshnessTime uint32 + FreshnessTime uint32 + CrlInfo uintptr // *CertRevocationCrlInfo +} + +type CertTrustStatus struct { + ErrorStatus uint32 + InfoStatus uint32 +} + +type CertUsageMatch struct { + Type uint32 + Usage CertEnhKeyUsage +} + +type CertEnhKeyUsage struct { + Length uint32 + UsageIdentifiers **byte +} + +type CertChainPara struct { + Size uint32 + RequestedUsage CertUsageMatch + RequstedIssuancePolicy CertUsageMatch + URLRetrievalTimeout uint32 + CheckRevocationFreshnessTime uint32 + RevocationFreshnessTime uint32 + CacheResync *Filetime +} + +type CertChainPolicyPara struct { + Size uint32 + Flags uint32 + ExtraPolicyPara uintptr +} + +type SSLExtraCertChainPolicyPara struct { + Size uint32 + AuthType uint32 + Checks uint32 + ServerName *uint16 +} + +type CertChainPolicyStatus struct { + Size uint32 + Error uint32 + ChainIndex uint32 + ElementIndex uint32 + ExtraPolicyStatus uintptr +} + +const ( + // do not reorder + HKEY_CLASSES_ROOT = 0x80000000 + iota + HKEY_CURRENT_USER + HKEY_LOCAL_MACHINE + HKEY_USERS + HKEY_PERFORMANCE_DATA + HKEY_CURRENT_CONFIG + HKEY_DYN_DATA + + KEY_QUERY_VALUE = 1 + KEY_SET_VALUE = 2 + KEY_CREATE_SUB_KEY = 4 + KEY_ENUMERATE_SUB_KEYS = 8 + KEY_NOTIFY = 16 + KEY_CREATE_LINK = 32 + KEY_WRITE = 0x20006 + KEY_EXECUTE = 0x20019 + KEY_READ = 0x20019 + KEY_WOW64_64KEY = 0x0100 + KEY_WOW64_32KEY = 0x0200 + KEY_ALL_ACCESS = 0xf003f +) + +const ( + // do not reorder + REG_NONE = iota + REG_SZ + REG_EXPAND_SZ + REG_BINARY + REG_DWORD_LITTLE_ENDIAN + REG_DWORD_BIG_ENDIAN + REG_LINK + REG_MULTI_SZ + REG_RESOURCE_LIST + REG_FULL_RESOURCE_DESCRIPTOR + REG_RESOURCE_REQUIREMENTS_LIST + REG_QWORD_LITTLE_ENDIAN + REG_DWORD = REG_DWORD_LITTLE_ENDIAN + REG_QWORD = REG_QWORD_LITTLE_ENDIAN +) + +type AddrinfoW struct { + Flags int32 + Family int32 + Socktype int32 + Protocol int32 + Addrlen uintptr + Canonname *uint16 + Addr uintptr + Next *AddrinfoW +} + +const ( + AI_PASSIVE = 1 + AI_CANONNAME = 2 + AI_NUMERICHOST = 4 +) + +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +var WSAID_CONNECTEX = GUID{ + 0x25a207b9, + 0xddf3, + 0x4660, + [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, +} + +const ( + FILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 + FILE_SKIP_SET_EVENT_ON_HANDLE = 2 +) + +const ( + WSAPROTOCOL_LEN = 255 + MAX_PROTOCOL_CHAIN = 7 + BASE_PROTOCOL = 1 + LAYERED_PROTOCOL = 0 + + XP1_CONNECTIONLESS = 0x00000001 + XP1_GUARANTEED_DELIVERY = 0x00000002 + XP1_GUARANTEED_ORDER = 0x00000004 + XP1_MESSAGE_ORIENTED = 0x00000008 + XP1_PSEUDO_STREAM = 0x00000010 + XP1_GRACEFUL_CLOSE = 0x00000020 + XP1_EXPEDITED_DATA = 0x00000040 + XP1_CONNECT_DATA = 0x00000080 + XP1_DISCONNECT_DATA = 0x00000100 + XP1_SUPPORT_BROADCAST = 0x00000200 + XP1_SUPPORT_MULTIPOINT = 0x00000400 + XP1_MULTIPOINT_CONTROL_PLANE = 0x00000800 + XP1_MULTIPOINT_DATA_PLANE = 0x00001000 + XP1_QOS_SUPPORTED = 0x00002000 + XP1_UNI_SEND = 0x00008000 + XP1_UNI_RECV = 0x00010000 + XP1_IFS_HANDLES = 0x00020000 + XP1_PARTIAL_MESSAGE = 0x00040000 + XP1_SAN_SUPPORT_SDP = 0x00080000 + + PFL_MULTIPLE_PROTO_ENTRIES = 0x00000001 + PFL_RECOMMENDED_PROTO_ENTRY = 0x00000002 + PFL_HIDDEN = 0x00000004 + PFL_MATCHES_PROTOCOL_ZERO = 0x00000008 + PFL_NETWORKDIRECT_PROVIDER = 0x00000010 +) + +type WSAProtocolInfo struct { + ServiceFlags1 uint32 + ServiceFlags2 uint32 + ServiceFlags3 uint32 + ServiceFlags4 uint32 + ProviderFlags uint32 + ProviderId GUID + CatalogEntryId uint32 + ProtocolChain WSAProtocolChain + Version int32 + AddressFamily int32 + MaxSockAddr int32 + MinSockAddr int32 + SocketType int32 + Protocol int32 + ProtocolMaxOffset int32 + NetworkByteOrder int32 + SecurityScheme int32 + MessageSize uint32 + ProviderReserved uint32 + ProtocolName [WSAPROTOCOL_LEN + 1]uint16 +} + +type WSAProtocolChain struct { + ChainLen int32 + ChainEntries [MAX_PROTOCOL_CHAIN]uint32 +} + +type TCPKeepalive struct { + OnOff uint32 + Time uint32 + Interval uint32 +} + +type symbolicLinkReparseBuffer struct { + SubstituteNameOffset uint16 + SubstituteNameLength uint16 + PrintNameOffset uint16 + PrintNameLength uint16 + Flags uint32 + PathBuffer [1]uint16 +} + +type mountPointReparseBuffer struct { + SubstituteNameOffset uint16 + SubstituteNameLength uint16 + PrintNameOffset uint16 + PrintNameLength uint16 + PathBuffer [1]uint16 +} + +type reparseDataBuffer struct { + ReparseTag uint32 + ReparseDataLength uint16 + Reserved uint16 + + // GenericReparseBuffer + reparseBuffer byte +} + +const ( + FSCTL_GET_REPARSE_POINT = 0x900A8 + MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024 + IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 + IO_REPARSE_TAG_SYMLINK = 0xA000000C + SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 +) + +const ( + ComputerNameNetBIOS = 0 + ComputerNameDnsHostname = 1 + ComputerNameDnsDomain = 2 + ComputerNameDnsFullyQualified = 3 + ComputerNamePhysicalNetBIOS = 4 + ComputerNamePhysicalDnsHostname = 5 + ComputerNamePhysicalDnsDomain = 6 + ComputerNamePhysicalDnsFullyQualified = 7 + ComputerNameMax = 8 +) + +const ( + MOVEFILE_REPLACE_EXISTING = 0x1 + MOVEFILE_COPY_ALLOWED = 0x2 + MOVEFILE_DELAY_UNTIL_REBOOT = 0x4 + MOVEFILE_WRITE_THROUGH = 0x8 + MOVEFILE_CREATE_HARDLINK = 0x10 + MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20 +) + +const GAA_FLAG_INCLUDE_PREFIX = 0x00000010 + +const ( + IF_TYPE_OTHER = 1 + IF_TYPE_ETHERNET_CSMACD = 6 + IF_TYPE_ISO88025_TOKENRING = 9 + IF_TYPE_PPP = 23 + IF_TYPE_SOFTWARE_LOOPBACK = 24 + IF_TYPE_ATM = 37 + IF_TYPE_IEEE80211 = 71 + IF_TYPE_TUNNEL = 131 + IF_TYPE_IEEE1394 = 144 +) + +type SocketAddress struct { + Sockaddr *syscall.RawSockaddrAny + SockaddrLength int32 +} + +type IpAdapterUnicastAddress struct { + Length uint32 + Flags uint32 + Next *IpAdapterUnicastAddress + Address SocketAddress + PrefixOrigin int32 + SuffixOrigin int32 + DadState int32 + ValidLifetime uint32 + PreferredLifetime uint32 + LeaseLifetime uint32 + OnLinkPrefixLength uint8 +} + +type IpAdapterAnycastAddress struct { + Length uint32 + Flags uint32 + Next *IpAdapterAnycastAddress + Address SocketAddress +} + +type IpAdapterMulticastAddress struct { + Length uint32 + Flags uint32 + Next *IpAdapterMulticastAddress + Address SocketAddress +} + +type IpAdapterDnsServerAdapter struct { + Length uint32 + Reserved uint32 + Next *IpAdapterDnsServerAdapter + Address SocketAddress +} + +type IpAdapterPrefix struct { + Length uint32 + Flags uint32 + Next *IpAdapterPrefix + Address SocketAddress + PrefixLength uint32 +} + +type IpAdapterAddresses struct { + Length uint32 + IfIndex uint32 + Next *IpAdapterAddresses + AdapterName *byte + FirstUnicastAddress *IpAdapterUnicastAddress + FirstAnycastAddress *IpAdapterAnycastAddress + FirstMulticastAddress *IpAdapterMulticastAddress + FirstDnsServerAddress *IpAdapterDnsServerAdapter + DnsSuffix *uint16 + Description *uint16 + FriendlyName *uint16 + PhysicalAddress [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte + PhysicalAddressLength uint32 + Flags uint32 + Mtu uint32 + IfType uint32 + OperStatus uint32 + Ipv6IfIndex uint32 + ZoneIndices [16]uint32 + FirstPrefix *IpAdapterPrefix + /* more fields might be present here. */ +} + +const ( + IfOperStatusUp = 1 + IfOperStatusDown = 2 + IfOperStatusTesting = 3 + IfOperStatusUnknown = 4 + IfOperStatusDormant = 5 + IfOperStatusNotPresent = 6 + IfOperStatusLowerLayerDown = 7 +) diff --git a/vendor/golang.org/x/sys/windows/ztypes_windows_386.go b/vendor/golang.org/x/sys/windows/ztypes_windows_386.go new file mode 100644 index 0000000..10f33be --- /dev/null +++ b/vendor/golang.org/x/sys/windows/ztypes_windows_386.go @@ -0,0 +1,22 @@ +// 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 windows + +type WSAData struct { + Version uint16 + HighVersion uint16 + Description [WSADESCRIPTION_LEN + 1]byte + SystemStatus [WSASYS_STATUS_LEN + 1]byte + MaxSockets uint16 + MaxUdpDg uint16 + VendorInfo *byte +} + +type Servent struct { + Name *byte + Aliases **byte + Port uint16 + Proto *byte +} diff --git a/vendor/golang.org/x/sys/windows/ztypes_windows_amd64.go b/vendor/golang.org/x/sys/windows/ztypes_windows_amd64.go new file mode 100644 index 0000000..3f272c2 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/ztypes_windows_amd64.go @@ -0,0 +1,22 @@ +// 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 windows + +type WSAData struct { + Version uint16 + HighVersion uint16 + MaxSockets uint16 + MaxUdpDg uint16 + VendorInfo *byte + Description [WSADESCRIPTION_LEN + 1]byte + SystemStatus [WSASYS_STATUS_LEN + 1]byte +} + +type Servent struct { + Name *byte + Aliases **byte + Proto *byte + Port uint16 +} diff --git a/vendor/rsc.io/x86/LICENSE b/vendor/rsc.io/x86/LICENSE new file mode 100644 index 0000000..6a66aea --- /dev/null +++ b/vendor/rsc.io/x86/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/rsc.io/x86/x86asm/Makefile b/vendor/rsc.io/x86/x86asm/Makefile new file mode 100644 index 0000000..9eb4557 --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/Makefile @@ -0,0 +1,3 @@ +tables.go: ../x86map/map.go ../x86.csv + go run ../x86map/map.go -fmt=decoder ../x86.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go + diff --git a/vendor/rsc.io/x86/x86asm/decode.go b/vendor/rsc.io/x86/x86asm/decode.go new file mode 100644 index 0000000..d11514d --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/decode.go @@ -0,0 +1,1646 @@ +// Copyright 2014 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. + +// Table-driven decoding of x86 instructions. + +package x86asm + +import ( + "encoding/binary" + "errors" + "fmt" + "runtime" +) + +// Set trace to true to cause the decoder to print the PC sequence +// of the executed instruction codes. This is typically only useful +// when you are running a test of a single input case. +const trace = false + +// A decodeOp is a single instruction in the decoder bytecode program. +// +// The decodeOps correspond to consuming and conditionally branching +// on input bytes, consuming additional fields, and then interpreting +// consumed data as instruction arguments. The names of the xRead and xArg +// operations are taken from the Intel manual conventions, for example +// Volume 2, Section 3.1.1, page 487 of +// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf +// +// The actual decoding program is generated by ../x86map. +// +// TODO(rsc): We may be able to merge various of the memory operands +// since we don't care about, say, the distinction between m80dec and m80bcd. +// Similarly, mm and mm1 have identical meaning, as do xmm and xmm1. + +type decodeOp uint16 + +const ( + xFail decodeOp = iota // invalid instruction (return) + xMatch // completed match + xJump // jump to pc + + xCondByte // switch on instruction byte value + xCondSlashR // read and switch on instruction /r value + xCondPrefix // switch on presence of instruction prefix + xCondIs64 // switch on 64-bit processor mode + xCondDataSize // switch on operand size + xCondAddrSize // switch on address size + xCondIsMem // switch on memory vs register argument + + xSetOp // set instruction opcode + + xReadSlashR // read /r + xReadIb // read ib + xReadIw // read iw + xReadId // read id + xReadIo // read io + xReadCb // read cb + xReadCw // read cw + xReadCd // read cd + xReadCp // read cp + xReadCm // read cm + + xArg1 // arg 1 + xArg3 // arg 3 + xArgAL // arg AL + xArgAX // arg AX + xArgCL // arg CL + xArgCR0dashCR7 // arg CR0-CR7 + xArgCS // arg CS + xArgDR0dashDR7 // arg DR0-DR7 + xArgDS // arg DS + xArgDX // arg DX + xArgEAX // arg EAX + xArgEDX // arg EDX + xArgES // arg ES + xArgFS // arg FS + xArgGS // arg GS + xArgImm16 // arg imm16 + xArgImm32 // arg imm32 + xArgImm64 // arg imm64 + xArgImm8 // arg imm8 + xArgImm8u // arg imm8 but record as unsigned + xArgImm16u // arg imm8 but record as unsigned + xArgM // arg m + xArgM128 // arg m128 + xArgM1428byte // arg m14/28byte + xArgM16 // arg m16 + xArgM16and16 // arg m16&16 + xArgM16and32 // arg m16&32 + xArgM16and64 // arg m16&64 + xArgM16colon16 // arg m16:16 + xArgM16colon32 // arg m16:32 + xArgM16colon64 // arg m16:64 + xArgM16int // arg m16int + xArgM2byte // arg m2byte + xArgM32 // arg m32 + xArgM32and32 // arg m32&32 + xArgM32fp // arg m32fp + xArgM32int // arg m32int + xArgM512byte // arg m512byte + xArgM64 // arg m64 + xArgM64fp // arg m64fp + xArgM64int // arg m64int + xArgM8 // arg m8 + xArgM80bcd // arg m80bcd + xArgM80dec // arg m80dec + xArgM80fp // arg m80fp + xArgM94108byte // arg m94/108byte + xArgMm // arg mm + xArgMm1 // arg mm1 + xArgMm2 // arg mm2 + xArgMm2M64 // arg mm2/m64 + xArgMmM32 // arg mm/m32 + xArgMmM64 // arg mm/m64 + xArgMem // arg mem + xArgMoffs16 // arg moffs16 + xArgMoffs32 // arg moffs32 + xArgMoffs64 // arg moffs64 + xArgMoffs8 // arg moffs8 + xArgPtr16colon16 // arg ptr16:16 + xArgPtr16colon32 // arg ptr16:32 + xArgR16 // arg r16 + xArgR16op // arg r16 with +rw in opcode + xArgR32 // arg r32 + xArgR32M16 // arg r32/m16 + xArgR32M8 // arg r32/m8 + xArgR32op // arg r32 with +rd in opcode + xArgR64 // arg r64 + xArgR64M16 // arg r64/m16 + xArgR64op // arg r64 with +rd in opcode + xArgR8 // arg r8 + xArgR8op // arg r8 with +rb in opcode + xArgRAX // arg RAX + xArgRDX // arg RDX + xArgRM // arg r/m + xArgRM16 // arg r/m16 + xArgRM32 // arg r/m32 + xArgRM64 // arg r/m64 + xArgRM8 // arg r/m8 + xArgReg // arg reg + xArgRegM16 // arg reg/m16 + xArgRegM32 // arg reg/m32 + xArgRegM8 // arg reg/m8 + xArgRel16 // arg rel16 + xArgRel32 // arg rel32 + xArgRel8 // arg rel8 + xArgSS // arg SS + xArgST // arg ST, aka ST(0) + xArgSTi // arg ST(i) with +i in opcode + xArgSreg // arg Sreg + xArgTR0dashTR7 // arg TR0-TR7 + xArgXmm // arg xmm + xArgXMM0 // arg + xArgXmm1 // arg xmm1 + xArgXmm2 // arg xmm2 + xArgXmm2M128 // arg xmm2/m128 + xArgXmm2M16 // arg xmm2/m16 + xArgXmm2M32 // arg xmm2/m32 + xArgXmm2M64 // arg xmm2/m64 + xArgXmmM128 // arg xmm/m128 + xArgXmmM32 // arg xmm/m32 + xArgXmmM64 // arg xmm/m64 + xArgRmf16 // arg r/m16 but force mod=3 + xArgRmf32 // arg r/m32 but force mod=3 + xArgRmf64 // arg r/m64 but force mod=3 +) + +// instPrefix returns an Inst describing just one prefix byte. +// It is only used if there is a prefix followed by an unintelligible +// or invalid instruction byte sequence. +func instPrefix(b byte, mode int) (Inst, error) { + // When tracing it is useful to see what called instPrefix to report an error. + if trace { + _, file, line, _ := runtime.Caller(1) + fmt.Printf("%s:%d\n", file, line) + } + p := Prefix(b) + switch p { + case PrefixDataSize: + if mode == 16 { + p = PrefixData32 + } else { + p = PrefixData16 + } + case PrefixAddrSize: + if mode == 32 { + p = PrefixAddr16 + } else { + p = PrefixAddr32 + } + } + // Note: using composite literal with Prefix key confuses 'bundle' tool. + inst := Inst{Len: 1} + inst.Prefix = Prefixes{p} + return inst, nil +} + +// truncated reports a truncated instruction. +// For now we use instPrefix but perhaps later we will return +// a specific error here. +func truncated(src []byte, mode int) (Inst, error) { + // return Inst{}, len(src), ErrTruncated + return instPrefix(src[0], mode) // too long +} + +// These are the errors returned by Decode. +var ( + ErrInvalidMode = errors.New("invalid x86 mode in Decode") + ErrTruncated = errors.New("truncated instruction") + ErrUnrecognized = errors.New("unrecognized instruction") +) + +// decoderCover records coverage information for which parts +// of the byte code have been executed. +// TODO(rsc): This is for testing. Only use this if a flag is given. +var decoderCover []bool + +// Decode decodes the leading bytes in src as a single instruction. +// The mode arguments specifies the assumed processor mode: +// 16, 32, or 64 for 16-, 32-, and 64-bit execution modes. +func Decode(src []byte, mode int) (inst Inst, err error) { + return decode1(src, mode, false) +} + +// decode1 is the implementation of Decode but takes an extra +// gnuCompat flag to cause it to change its behavior to mimic +// bugs (or at least unique features) of GNU libopcodes as used +// by objdump. We don't believe that logic is the right thing to do +// in general, but when testing against libopcodes it simplifies the +// comparison if we adjust a few small pieces of logic. +// The affected logic is in the conditional branch for "mandatory" prefixes, +// case xCondPrefix. +func decode1(src []byte, mode int, gnuCompat bool) (Inst, error) { + switch mode { + case 16, 32, 64: + // ok + // TODO(rsc): 64-bit mode not tested, probably not working. + default: + return Inst{}, ErrInvalidMode + } + + // Maximum instruction size is 15 bytes. + // If we need to read more, return 'truncated instruction. + if len(src) > 15 { + src = src[:15] + } + + var ( + // prefix decoding information + pos = 0 // position reading src + nprefix = 0 // number of prefixes + lockIndex = -1 // index of LOCK prefix in src and inst.Prefix + repIndex = -1 // index of REP/REPN prefix in src and inst.Prefix + segIndex = -1 // index of Group 2 prefix in src and inst.Prefix + dataSizeIndex = -1 // index of Group 3 prefix in src and inst.Prefix + addrSizeIndex = -1 // index of Group 4 prefix in src and inst.Prefix + rex Prefix // rex byte if present (or 0) + rexUsed Prefix // bits used in rex byte + rexIndex = -1 // index of rex byte + + addrMode = mode // address mode (width in bits) + dataMode = mode // operand mode (width in bits) + + // decoded ModR/M fields + haveModrm bool + modrm int + mod int + regop int + rm int + + // if ModR/M is memory reference, Mem form + mem Mem + haveMem bool + + // decoded SIB fields + haveSIB bool + sib int + scale int + index int + base int + displen int + dispoff int + + // decoded immediate values + imm int64 + imm8 int8 + immc int64 + immcpos int + + // output + opshift int + inst Inst + narg int // number of arguments written to inst + ) + + if mode == 64 { + dataMode = 32 + } + + // Prefixes are certainly the most complex and underspecified part of + // decoding x86 instructions. Although the manuals say things like + // up to four prefixes, one from each group, nearly everyone seems to + // agree that in practice as many prefixes as possible, including multiple + // from a particular group or repetitions of a given prefix, can be used on + // an instruction, provided the total instruction length including prefixes + // does not exceed the agreed-upon maximum of 15 bytes. + // Everyone also agrees that if one of these prefixes is the LOCK prefix + // and the instruction is not one of the instructions that can be used with + // the LOCK prefix or if the destination is not a memory operand, + // then the instruction is invalid and produces the #UD exception. + // However, that is the end of any semblance of agreement. + // + // What happens if prefixes are given that conflict with other prefixes? + // For example, the memory segment overrides CS, DS, ES, FS, GS, SS + // conflict with each other: only one segment can be in effect. + // Disassemblers seem to agree that later prefixes take priority over + // earlier ones. I have not taken the time to write assembly programs + // to check to see if the hardware agrees. + // + // What happens if prefixes are given that have no meaning for the + // specific instruction to which they are attached? It depends. + // If they really have no meaning, they are ignored. However, a future + // processor may assign a different meaning. As a disassembler, we + // don't really know whether we're seeing a meaningless prefix or one + // whose meaning we simply haven't been told yet. + // + // Combining the two questions, what happens when conflicting + // extension prefixes are given? No one seems to know for sure. + // For example, MOVQ is 66 0F D6 /r, MOVDQ2Q is F2 0F D6 /r, + // and MOVQ2DQ is F3 0F D6 /r. What is '66 F2 F3 0F D6 /r'? + // Which prefix wins? See the xCondPrefix prefix for more. + // + // Writing assembly test cases to divine which interpretation the + // CPU uses might clarify the situation, but more likely it would + // make the situation even less clear. + + // Read non-REX prefixes. +ReadPrefixes: + for ; pos < len(src); pos++ { + p := Prefix(src[pos]) + switch p { + default: + nprefix = pos + break ReadPrefixes + + // Group 1 - lock and repeat prefixes + // According to Intel, there should only be one from this set, + // but according to AMD both can be present. + case 0xF0: + if lockIndex >= 0 { + inst.Prefix[lockIndex] |= PrefixIgnored + } + lockIndex = pos + case 0xF2, 0xF3: + if repIndex >= 0 { + inst.Prefix[repIndex] |= PrefixIgnored + } + repIndex = pos + + // Group 2 - segment override / branch hints + case 0x26, 0x2E, 0x36, 0x3E: + if mode == 64 { + p |= PrefixIgnored + break + } + fallthrough + case 0x64, 0x65: + if segIndex >= 0 { + inst.Prefix[segIndex] |= PrefixIgnored + } + segIndex = pos + + // Group 3 - operand size override + case 0x66: + if mode == 16 { + dataMode = 32 + p = PrefixData32 + } else { + dataMode = 16 + p = PrefixData16 + } + if dataSizeIndex >= 0 { + inst.Prefix[dataSizeIndex] |= PrefixIgnored + } + dataSizeIndex = pos + + // Group 4 - address size override + case 0x67: + if mode == 32 { + addrMode = 16 + p = PrefixAddr16 + } else { + addrMode = 32 + p = PrefixAddr32 + } + if addrSizeIndex >= 0 { + inst.Prefix[addrSizeIndex] |= PrefixIgnored + } + addrSizeIndex = pos + } + + if pos >= len(inst.Prefix) { + return instPrefix(src[0], mode) // too long + } + + inst.Prefix[pos] = p + } + + // Read REX prefix. + if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() { + rex = Prefix(src[pos]) + rexIndex = pos + if pos >= len(inst.Prefix) { + return instPrefix(src[0], mode) // too long + } + inst.Prefix[pos] = rex + pos++ + if rex&PrefixREXW != 0 { + dataMode = 64 + if dataSizeIndex >= 0 { + inst.Prefix[dataSizeIndex] |= PrefixIgnored + } + } + } + + // Decode instruction stream, interpreting decoding instructions. + // opshift gives the shift to use when saving the next + // opcode byte into inst.Opcode. + opshift = 24 + if decoderCover == nil { + decoderCover = make([]bool, len(decoder)) + } + + // Decode loop, executing decoder program. + var oldPC, prevPC int +Decode: + for pc := 1; ; { // TODO uint + oldPC = prevPC + prevPC = pc + if trace { + println("run", pc) + } + x := decoder[pc] + decoderCover[pc] = true + pc++ + + // Read and decode ModR/M if needed by opcode. + switch decodeOp(x) { + case xCondSlashR, xReadSlashR: + if haveModrm { + return Inst{Len: pos}, errInternal + } + haveModrm = true + if pos >= len(src) { + return truncated(src, mode) + } + modrm = int(src[pos]) + pos++ + if opshift >= 0 { + inst.Opcode |= uint32(modrm) << uint(opshift) + opshift -= 8 + } + mod = modrm >> 6 + regop = (modrm >> 3) & 07 + rm = modrm & 07 + if rex&PrefixREXR != 0 { + rexUsed |= PrefixREXR + regop |= 8 + } + if addrMode == 16 { + // 16-bit modrm form + if mod != 3 { + haveMem = true + mem = addr16[rm] + if rm == 6 && mod == 0 { + mem.Base = 0 + } + + // Consume disp16 if present. + if mod == 0 && rm == 6 || mod == 2 { + if pos+2 > len(src) { + return truncated(src, mode) + } + mem.Disp = int64(binary.LittleEndian.Uint16(src[pos:])) + pos += 2 + } + + // Consume disp8 if present. + if mod == 1 { + if pos >= len(src) { + return truncated(src, mode) + } + mem.Disp = int64(int8(src[pos])) + pos++ + } + } + } else { + haveMem = mod != 3 + + // 32-bit or 64-bit form + // Consume SIB encoding if present. + if rm == 4 && mod != 3 { + haveSIB = true + if pos >= len(src) { + return truncated(src, mode) + } + sib = int(src[pos]) + pos++ + if opshift >= 0 { + inst.Opcode |= uint32(sib) << uint(opshift) + opshift -= 8 + } + scale = sib >> 6 + index = (sib >> 3) & 07 + base = sib & 07 + if rex&PrefixREXB != 0 { + rexUsed |= PrefixREXB + base |= 8 + } + if rex&PrefixREXX != 0 { + rexUsed |= PrefixREXX + index |= 8 + } + + mem.Scale = 1 << uint(scale) + if index == 4 { + // no mem.Index + } else { + mem.Index = baseRegForBits(addrMode) + Reg(index) + } + if base&7 == 5 && mod == 0 { + // no mem.Base + } else { + mem.Base = baseRegForBits(addrMode) + Reg(base) + } + } else { + if rex&PrefixREXB != 0 { + rexUsed |= PrefixREXB + rm |= 8 + } + if mod == 0 && rm&7 == 5 || rm&7 == 4 { + // base omitted + } else if mod != 3 { + mem.Base = baseRegForBits(addrMode) + Reg(rm) + } + } + + // Consume disp32 if present. + if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 { + if pos+4 > len(src) { + return truncated(src, mode) + } + dispoff = pos + displen = 4 + mem.Disp = int64(binary.LittleEndian.Uint32(src[pos:])) + pos += 4 + } + + // Consume disp8 if present. + if mod == 1 { + if pos >= len(src) { + return truncated(src, mode) + } + dispoff = pos + displen = 1 + mem.Disp = int64(int8(src[pos])) + pos++ + } + + // In 64-bit, mod=0 rm=5 is PC-relative instead of just disp. + // See Vol 2A. Table 2-7. + if mode == 64 && mod == 0 && rm&7 == 5 { + if addrMode == 32 { + mem.Base = EIP + } else { + mem.Base = RIP + } + } + } + + if segIndex >= 0 { + mem.Segment = prefixToSegment(inst.Prefix[segIndex]) + } + } + + // Execute single opcode. + switch decodeOp(x) { + default: + println("bad op", x, "at", pc-1, "from", oldPC) + return Inst{Len: pos}, errInternal + + case xFail: + inst.Op = 0 + break Decode + + case xMatch: + break Decode + + case xJump: + pc = int(decoder[pc]) + + // Conditional branches. + + case xCondByte: + if pos >= len(src) { + return truncated(src, mode) + } + b := src[pos] + n := int(decoder[pc]) + pc++ + for i := 0; i < n; i++ { + xb, xpc := decoder[pc], int(decoder[pc+1]) + pc += 2 + if b == byte(xb) { + pc = xpc + pos++ + if opshift >= 0 { + inst.Opcode |= uint32(b) << uint(opshift) + opshift -= 8 + } + continue Decode + } + } + // xCondByte is the only conditional with a fall through, + // so that it can be used to pick off special cases before + // an xCondSlash. If the fallthrough instruction is xFail, + // advance the position so that the decoded instruction + // size includes the byte we just compared against. + if decodeOp(decoder[pc]) == xJump { + pc = int(decoder[pc+1]) + } + if decodeOp(decoder[pc]) == xFail { + pos++ + } + + case xCondIs64: + if mode == 64 { + pc = int(decoder[pc+1]) + } else { + pc = int(decoder[pc]) + } + + case xCondIsMem: + mem := haveMem + if !haveModrm { + if pos >= len(src) { + return instPrefix(src[0], mode) // too long + } + mem = src[pos]>>6 != 3 + } + if mem { + pc = int(decoder[pc+1]) + } else { + pc = int(decoder[pc]) + } + + case xCondDataSize: + switch dataMode { + case 16: + if dataSizeIndex >= 0 { + inst.Prefix[dataSizeIndex] |= PrefixImplicit + } + pc = int(decoder[pc]) + case 32: + if dataSizeIndex >= 0 { + inst.Prefix[dataSizeIndex] |= PrefixImplicit + } + pc = int(decoder[pc+1]) + case 64: + rexUsed |= PrefixREXW + pc = int(decoder[pc+2]) + } + + case xCondAddrSize: + switch addrMode { + case 16: + if addrSizeIndex >= 0 { + inst.Prefix[addrSizeIndex] |= PrefixImplicit + } + pc = int(decoder[pc]) + case 32: + if addrSizeIndex >= 0 { + inst.Prefix[addrSizeIndex] |= PrefixImplicit + } + pc = int(decoder[pc+1]) + case 64: + pc = int(decoder[pc+2]) + } + + case xCondPrefix: + // Conditional branch based on presence or absence of prefixes. + // The conflict cases here are completely undocumented and + // differ significantly between GNU libopcodes and Intel xed. + // I have not written assembly code to divine what various CPUs + // do, but it wouldn't surprise me if they are not consistent either. + // + // The basic idea is to switch on the presence of a prefix, so that + // for example: + // + // xCondPrefix, 4 + // 0xF3, 123, + // 0xF2, 234, + // 0x66, 345, + // 0, 456 + // + // branch to 123 if the F3 prefix is present, 234 if the F2 prefix + // is present, 66 if the 345 prefix is present, and 456 otherwise. + // The prefixes are given in descending order so that the 0 will be last. + // + // It is unclear what should happen if multiple conditions are + // satisfied: what if F2 and F3 are both present, or if 66 and F2 + // are present, or if all three are present? The one chosen becomes + // part of the opcode and the others do not. Perhaps the answer + // depends on the specific opcodes in question. + // + // The only clear example is that CRC32 is F2 0F 38 F1 /r, and + // it comes in 16-bit and 32-bit forms based on the 66 prefix, + // so 66 F2 0F 38 F1 /r should be treated as F2 taking priority, + // with the 66 being only an operand size override, and probably + // F2 66 0F 38 F1 /r should be treated the same. + // Perhaps that rule is specific to the case of CRC32, since no + // 66 0F 38 F1 instruction is defined (today) (that we know of). + // However, both libopcodes and xed seem to generalize this + // example and choose F2/F3 in preference to 66, and we + // do the same. + // + // Next, what if both F2 and F3 are present? Which wins? + // The Intel xed rule, and ours, is that the one that occurs last wins. + // The GNU libopcodes rule, which we implement only in gnuCompat mode, + // is that F3 beats F2 unless F3 has no special meaning, in which + // case F3 can be a modified on an F2 special meaning. + // + // Concretely, + // 66 0F D6 /r is MOVQ + // F2 0F D6 /r is MOVDQ2Q + // F3 0F D6 /r is MOVQ2DQ. + // + // F2 66 0F D6 /r is 66 + MOVDQ2Q always. + // 66 F2 0F D6 /r is 66 + MOVDQ2Q always. + // F3 66 0F D6 /r is 66 + MOVQ2DQ always. + // 66 F3 0F D6 /r is 66 + MOVQ2DQ always. + // F2 F3 0F D6 /r is F2 + MOVQ2DQ always. + // F3 F2 0F D6 /r is F3 + MOVQ2DQ in Intel xed, but F2 + MOVQ2DQ in GNU libopcodes. + // Adding 66 anywhere in the prefix section of the + // last two cases does not change the outcome. + // + // Finally, what if there is a variant in which 66 is a mandatory + // prefix rather than an operand size override, but we know of + // no corresponding F2/F3 form, and we see both F2/F3 and 66. + // Does F2/F3 still take priority, so that the result is an unknown + // instruction, or does the 66 take priority, so that the extended + // 66 instruction should be interpreted as having a REP/REPN prefix? + // Intel xed does the former and GNU libopcodes does the latter. + // We side with Intel xed, unless we are trying to match libopcodes + // more closely during the comparison-based test suite. + // + // In 64-bit mode REX.W is another valid prefix to test for, but + // there is less ambiguity about that. When present, REX.W is + // always the first entry in the table. + n := int(decoder[pc]) + pc++ + sawF3 := false + for j := 0; j < n; j++ { + prefix := Prefix(decoder[pc+2*j]) + if prefix.IsREX() { + rexUsed |= prefix + if rex&prefix == prefix { + pc = int(decoder[pc+2*j+1]) + continue Decode + } + continue + } + ok := false + if prefix == 0 { + ok = true + } else if prefix.IsREX() { + rexUsed |= prefix + if rex&prefix == prefix { + ok = true + } + } else { + if prefix == 0xF3 { + sawF3 = true + } + switch prefix { + case PrefixLOCK: + if lockIndex >= 0 { + inst.Prefix[lockIndex] |= PrefixImplicit + ok = true + } + case PrefixREP, PrefixREPN: + if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix { + inst.Prefix[repIndex] |= PrefixImplicit + ok = true + } + if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || decoder[pc+2*(j+1)] != 0xF2) { + // Check to see if earlier prefix F3 is present. + for i := repIndex - 1; i >= 0; i-- { + if inst.Prefix[i]&0xFF == prefix { + inst.Prefix[i] |= PrefixImplicit + ok = true + } + } + } + if gnuCompat && !ok && prefix == 0xF2 && repIndex >= 0 && !sawF3 && inst.Prefix[repIndex]&0xFF == 0xF3 { + // Check to see if earlier prefix F2 is present. + for i := repIndex - 1; i >= 0; i-- { + if inst.Prefix[i]&0xFF == prefix { + inst.Prefix[i] |= PrefixImplicit + ok = true + } + } + } + case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS: + if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix { + inst.Prefix[segIndex] |= PrefixImplicit + ok = true + } + case PrefixDataSize: + // Looking for 66 mandatory prefix. + // The F2/F3 mandatory prefixes take priority when both are present. + // If we got this far in the xCondPrefix table and an F2/F3 is present, + // it means the table didn't have any entry for that prefix. But if 66 has + // special meaning, perhaps F2/F3 have special meaning that we don't know. + // Intel xed works this way, treating the F2/F3 as inhibiting the 66. + // GNU libopcodes allows the 66 to match. We do what Intel xed does + // except in gnuCompat mode. + if repIndex >= 0 && !gnuCompat { + inst.Op = 0 + break Decode + } + if dataSizeIndex >= 0 { + inst.Prefix[dataSizeIndex] |= PrefixImplicit + ok = true + } + case PrefixAddrSize: + if addrSizeIndex >= 0 { + inst.Prefix[addrSizeIndex] |= PrefixImplicit + ok = true + } + } + } + if ok { + pc = int(decoder[pc+2*j+1]) + continue Decode + } + } + inst.Op = 0 + break Decode + + case xCondSlashR: + pc = int(decoder[pc+regop&7]) + + // Input. + + case xReadSlashR: + // done above + + case xReadIb: + if pos >= len(src) { + return truncated(src, mode) + } + imm8 = int8(src[pos]) + pos++ + + case xReadIw: + if pos+2 > len(src) { + return truncated(src, mode) + } + imm = int64(binary.LittleEndian.Uint16(src[pos:])) + pos += 2 + + case xReadId: + if pos+4 > len(src) { + return truncated(src, mode) + } + imm = int64(binary.LittleEndian.Uint32(src[pos:])) + pos += 4 + + case xReadIo: + if pos+8 > len(src) { + return truncated(src, mode) + } + imm = int64(binary.LittleEndian.Uint64(src[pos:])) + pos += 8 + + case xReadCb: + if pos >= len(src) { + return truncated(src, mode) + } + immcpos = pos + immc = int64(src[pos]) + pos++ + + case xReadCw: + if pos+2 > len(src) { + return truncated(src, mode) + } + immcpos = pos + immc = int64(binary.LittleEndian.Uint16(src[pos:])) + pos += 2 + + case xReadCm: + immcpos = pos + if addrMode == 16 { + if pos+2 > len(src) { + return truncated(src, mode) + } + immc = int64(binary.LittleEndian.Uint16(src[pos:])) + pos += 2 + } else if addrMode == 32 { + if pos+4 > len(src) { + return truncated(src, mode) + } + immc = int64(binary.LittleEndian.Uint32(src[pos:])) + pos += 4 + } else { + if pos+8 > len(src) { + return truncated(src, mode) + } + immc = int64(binary.LittleEndian.Uint64(src[pos:])) + pos += 8 + } + case xReadCd: + immcpos = pos + if pos+4 > len(src) { + return truncated(src, mode) + } + immc = int64(binary.LittleEndian.Uint32(src[pos:])) + pos += 4 + + case xReadCp: + immcpos = pos + if pos+6 > len(src) { + return truncated(src, mode) + } + w := binary.LittleEndian.Uint32(src[pos:]) + w2 := binary.LittleEndian.Uint16(src[pos+4:]) + immc = int64(w2)<<32 | int64(w) + pos += 6 + + // Output. + + case xSetOp: + inst.Op = Op(decoder[pc]) + pc++ + + case xArg1, + xArg3, + xArgAL, + xArgAX, + xArgCL, + xArgCS, + xArgDS, + xArgDX, + xArgEAX, + xArgEDX, + xArgES, + xArgFS, + xArgGS, + xArgRAX, + xArgRDX, + xArgSS, + xArgST, + xArgXMM0: + inst.Args[narg] = fixedArg[x] + narg++ + + case xArgImm8: + inst.Args[narg] = Imm(imm8) + narg++ + + case xArgImm8u: + inst.Args[narg] = Imm(uint8(imm8)) + narg++ + + case xArgImm16: + inst.Args[narg] = Imm(int16(imm)) + narg++ + + case xArgImm16u: + inst.Args[narg] = Imm(uint16(imm)) + narg++ + + case xArgImm32: + inst.Args[narg] = Imm(int32(imm)) + narg++ + + case xArgImm64: + inst.Args[narg] = Imm(imm) + narg++ + + case xArgM, + xArgM128, + xArgM1428byte, + xArgM16, + xArgM16and16, + xArgM16and32, + xArgM16and64, + xArgM16colon16, + xArgM16colon32, + xArgM16colon64, + xArgM16int, + xArgM2byte, + xArgM32, + xArgM32and32, + xArgM32fp, + xArgM32int, + xArgM512byte, + xArgM64, + xArgM64fp, + xArgM64int, + xArgM8, + xArgM80bcd, + xArgM80dec, + xArgM80fp, + xArgM94108byte, + xArgMem: + if !haveMem { + inst.Op = 0 + break Decode + } + inst.Args[narg] = mem + inst.MemBytes = int(memBytes[decodeOp(x)]) + if mem.Base == RIP { + inst.PCRel = displen + inst.PCRelOff = dispoff + } + narg++ + + case xArgPtr16colon16: + inst.Args[narg] = Imm(immc >> 16) + inst.Args[narg+1] = Imm(immc & (1<<16 - 1)) + narg += 2 + + case xArgPtr16colon32: + inst.Args[narg] = Imm(immc >> 32) + inst.Args[narg+1] = Imm(immc & (1<<32 - 1)) + narg += 2 + + case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64: + // TODO(rsc): Can address be 64 bits? + mem = Mem{Disp: int64(immc)} + if segIndex >= 0 { + mem.Segment = prefixToSegment(inst.Prefix[segIndex]) + inst.Prefix[segIndex] |= PrefixImplicit + } + inst.Args[narg] = mem + inst.MemBytes = int(memBytes[decodeOp(x)]) + if mem.Base == RIP { + inst.PCRel = displen + inst.PCRelOff = dispoff + } + narg++ + + case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgDR0dashDR7: + base := baseReg[x] + index := Reg(regop) + if rex != 0 && base == AL && index >= 4 { + rexUsed |= PrefixREX + index -= 4 + base = SPB + } + inst.Args[narg] = base + index + narg++ + + case xArgMm, xArgMm1, xArgTR0dashTR7: + inst.Args[narg] = baseReg[x] + Reg(regop&7) + narg++ + + case xArgCR0dashCR7: + // AMD documents an extension that the LOCK prefix + // can be used in place of a REX prefix in order to access + // CR8 from 32-bit mode. The LOCK prefix is allowed in + // all modes, provided the corresponding CPUID bit is set. + if lockIndex >= 0 { + inst.Prefix[lockIndex] |= PrefixImplicit + regop += 8 + } + inst.Args[narg] = CR0 + Reg(regop) + narg++ + + case xArgSreg: + regop &= 7 + if regop >= 6 { + inst.Op = 0 + break Decode + } + inst.Args[narg] = ES + Reg(regop) + narg++ + + case xArgRmf16, xArgRmf32, xArgRmf64: + base := baseReg[x] + index := Reg(modrm & 07) + if rex&PrefixREXB != 0 { + rexUsed |= PrefixREXB + index += 8 + } + inst.Args[narg] = base + index + narg++ + + case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi: + n := inst.Opcode >> uint(opshift+8) & 07 + base := baseReg[x] + index := Reg(n) + if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi { + rexUsed |= PrefixREXB + index += 8 + } + if rex != 0 && base == AL && index >= 4 { + rexUsed |= PrefixREX + index -= 4 + base = SPB + } + inst.Args[narg] = base + index + narg++ + + case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M8, xArgR64M16, + xArgMmM32, xArgMmM64, xArgMm2M64, + xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgXmmM128, xArgXmmM32, xArgXmm2M128: + if haveMem { + inst.Args[narg] = mem + inst.MemBytes = int(memBytes[decodeOp(x)]) + if mem.Base == RIP { + inst.PCRel = displen + inst.PCRelOff = dispoff + } + } else { + base := baseReg[x] + index := Reg(rm) + switch decodeOp(x) { + case xArgMmM32, xArgMmM64, xArgMm2M64: + // There are only 8 MMX registers, so these ignore the REX.X bit. + index &= 7 + case xArgRM8: + if rex != 0 && index >= 4 { + rexUsed |= PrefixREX + index -= 4 + base = SPB + } + } + inst.Args[narg] = base + index + } + narg++ + + case xArgMm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag + if haveMem { + inst.Op = 0 + break Decode + } + inst.Args[narg] = baseReg[x] + Reg(rm&7) + narg++ + + case xArgXmm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag + if haveMem { + inst.Op = 0 + break Decode + } + inst.Args[narg] = baseReg[x] + Reg(rm) + narg++ + + case xArgRel8: + inst.PCRelOff = immcpos + inst.PCRel = 1 + inst.Args[narg] = Rel(int8(immc)) + narg++ + + case xArgRel16: + inst.PCRelOff = immcpos + inst.PCRel = 2 + inst.Args[narg] = Rel(int16(immc)) + narg++ + + case xArgRel32: + inst.PCRelOff = immcpos + inst.PCRel = 4 + inst.Args[narg] = Rel(int32(immc)) + narg++ + } + } + + if inst.Op == 0 { + // Invalid instruction. + if nprefix > 0 { + return instPrefix(src[0], mode) // invalid instruction + } + return Inst{Len: pos}, ErrUnrecognized + } + + // Matched! Hooray! + + // 90 decodes as XCHG EAX, EAX but is NOP. + // 66 90 decodes as XCHG AX, AX and is NOP too. + // 48 90 decodes as XCHG RAX, RAX and is NOP too. + // 43 90 decodes as XCHG R8D, EAX and is *not* NOP. + // F3 90 decodes as REP XCHG EAX, EAX but is PAUSE. + // It's all too special to handle in the decoding tables, at least for now. + if inst.Op == XCHG && inst.Opcode>>24 == 0x90 { + if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX { + inst.Op = NOP + if dataSizeIndex >= 0 { + inst.Prefix[dataSizeIndex] &^= PrefixImplicit + } + inst.Args[0] = nil + inst.Args[1] = nil + } + if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 { + inst.Prefix[repIndex] |= PrefixImplicit + inst.Op = PAUSE + inst.Args[0] = nil + inst.Args[1] = nil + } else if gnuCompat { + for i := nprefix - 1; i >= 0; i-- { + if inst.Prefix[i]&0xFF == 0xF3 { + inst.Prefix[i] |= PrefixImplicit + inst.Op = PAUSE + inst.Args[0] = nil + inst.Args[1] = nil + break + } + } + } + } + + // defaultSeg returns the default segment for an implicit + // memory reference: the final override if present, or else DS. + defaultSeg := func() Reg { + if segIndex >= 0 { + inst.Prefix[segIndex] |= PrefixImplicit + return prefixToSegment(inst.Prefix[segIndex]) + } + return DS + } + + // Add implicit arguments not present in the tables. + // Normally we shy away from making implicit arguments explicit, + // following the Intel manuals, but adding the arguments seems + // the best way to express the effect of the segment override prefixes. + // TODO(rsc): Perhaps add these to the tables and + // create bytecode instructions for them. + usedAddrSize := false + switch inst.Op { + case INSB, INSW, INSD: + inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX} + inst.Args[1] = DX + usedAddrSize = true + + case OUTSB, OUTSW, OUTSD: + inst.Args[0] = DX + inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX} + usedAddrSize = true + + case MOVSB, MOVSW, MOVSD, MOVSQ: + inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX} + inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX} + usedAddrSize = true + + case CMPSB, CMPSW, CMPSD, CMPSQ: + inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX} + inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX} + usedAddrSize = true + + case LODSB, LODSW, LODSD, LODSQ: + switch inst.Op { + case LODSB: + inst.Args[0] = AL + case LODSW: + inst.Args[0] = AX + case LODSD: + inst.Args[0] = EAX + case LODSQ: + inst.Args[0] = RAX + } + inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX} + usedAddrSize = true + + case STOSB, STOSW, STOSD, STOSQ: + inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX} + switch inst.Op { + case STOSB: + inst.Args[1] = AL + case STOSW: + inst.Args[1] = AX + case STOSD: + inst.Args[1] = EAX + case STOSQ: + inst.Args[1] = RAX + } + usedAddrSize = true + + case SCASB, SCASW, SCASD, SCASQ: + inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX} + switch inst.Op { + case SCASB: + inst.Args[0] = AL + case SCASW: + inst.Args[0] = AX + case SCASD: + inst.Args[0] = EAX + case SCASQ: + inst.Args[0] = RAX + } + usedAddrSize = true + + case XLATB: + inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + BX - AX} + usedAddrSize = true + } + + // If we used the address size annotation to construct the + // argument list, mark that prefix as implicit: it doesn't need + // to be shown when printing the instruction. + if haveMem || usedAddrSize { + if addrSizeIndex >= 0 { + inst.Prefix[addrSizeIndex] |= PrefixImplicit + } + } + + // Similarly, if there's some memory operand, the segment + // will be shown there and doesn't need to be shown as an + // explicit prefix. + if haveMem { + if segIndex >= 0 { + inst.Prefix[segIndex] |= PrefixImplicit + } + } + + // Branch predict prefixes are overloaded segment prefixes, + // since segment prefixes don't make sense on conditional jumps. + // Rewrite final instance to prediction prefix. + // The set of instructions to which the prefixes apply (other then the + // Jcc conditional jumps) is not 100% clear from the manuals, but + // the disassemblers seem to agree about the LOOP and JCXZ instructions, + // so we'll follow along. + // TODO(rsc): Perhaps this instruction class should be derived from the CSV. + if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ { + PredictLoop: + for i := nprefix - 1; i >= 0; i-- { + p := inst.Prefix[i] + switch p & 0xFF { + case PrefixCS: + inst.Prefix[i] = PrefixPN + break PredictLoop + case PrefixDS: + inst.Prefix[i] = PrefixPT + break PredictLoop + } + } + } + + // The BND prefix is part of the Intel Memory Protection Extensions (MPX). + // A REPN applied to certain control transfers is a BND prefix to bound + // the range of possible destinations. There's surprisingly little documentation + // about this, so we just do what libopcodes and xed agree on. + // In particular, it's unclear why a REPN applied to LOOP or JCXZ instructions + // does not turn into a BND. + // TODO(rsc): Perhaps this instruction class should be derived from the CSV. + if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET { + for i := nprefix - 1; i >= 0; i-- { + p := inst.Prefix[i] + if p&^PrefixIgnored == PrefixREPN { + inst.Prefix[i] = PrefixBND + break + } + } + } + + // The LOCK prefix only applies to certain instructions, and then only + // to instances of the instruction with a memory destination. + // Other uses of LOCK are invalid and cause a processor exception, + // in contrast to the "just ignore it" spirit applied to all other prefixes. + // Mark invalid lock prefixes. + hasLock := false + if lockIndex >= 0 && inst.Prefix[lockIndex]&PrefixImplicit == 0 { + switch inst.Op { + // TODO(rsc): Perhaps this instruction class should be derived from the CSV. + case ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG: + if isMem(inst.Args[0]) { + hasLock = true + break + } + fallthrough + default: + inst.Prefix[lockIndex] |= PrefixInvalid + } + } + + // In certain cases, all of which require a memory destination, + // the REPN and REP prefixes are interpreted as XACQUIRE and XRELEASE + // from the Intel Transactional Synchroniation Extensions (TSX). + // + // The specific rules are: + // (1) Any instruction with a valid LOCK prefix can have XACQUIRE or XRELEASE. + // (2) Any XCHG, which always has an implicit LOCK, can have XACQUIRE or XRELEASE. + // (3) Any 0x88-, 0x89-, 0xC6-, or 0xC7-opcode MOV can have XRELEASE. + if isMem(inst.Args[0]) { + if inst.Op == XCHG { + hasLock = true + } + + for i := len(inst.Prefix) - 1; i >= 0; i-- { + p := inst.Prefix[i] &^ PrefixIgnored + switch p { + case PrefixREPN: + if hasLock { + inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXACQUIRE + } + + case PrefixREP: + if hasLock { + inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE + } + + if inst.Op == MOV { + op := (inst.Opcode >> 24) &^ 1 + if op == 0x88 || op == 0xC6 { + inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE + } + } + } + } + } + + // If REP is used on a non-REP-able instruction, mark the prefix as ignored. + if repIndex >= 0 { + switch inst.Prefix[repIndex] { + case PrefixREP, PrefixREPN: + switch inst.Op { + // According to the manuals, the REP/REPE prefix applies to all of these, + // while the REPN applies only to some of them. However, both libopcodes + // and xed show both prefixes explicitly for all instructions, so we do the same. + // TODO(rsc): Perhaps this instruction class should be derived from the CSV. + case INSB, INSW, INSD, + MOVSB, MOVSW, MOVSD, MOVSQ, + OUTSB, OUTSW, OUTSD, + LODSB, LODSW, LODSD, LODSQ, + CMPSB, CMPSW, CMPSD, CMPSQ, + SCASB, SCASW, SCASD, SCASQ, + STOSB, STOSW, STOSD, STOSQ: + // ok + default: + inst.Prefix[repIndex] |= PrefixIgnored + } + } + } + + // If REX was present, mark implicit if all the 1 bits were consumed. + if rexIndex >= 0 { + if rexUsed != 0 { + rexUsed |= PrefixREX + } + if rex&^rexUsed == 0 { + inst.Prefix[rexIndex] |= PrefixImplicit + } + } + + inst.DataSize = dataMode + inst.AddrSize = addrMode + inst.Mode = mode + inst.Len = pos + return inst, nil +} + +var errInternal = errors.New("internal error") + +// addr16 records the eight 16-bit addressing modes. +var addr16 = [8]Mem{ + {Base: BX, Scale: 1, Index: SI}, + {Base: BX, Scale: 1, Index: DI}, + {Base: BP, Scale: 1, Index: SI}, + {Base: BP, Scale: 1, Index: DI}, + {Base: SI}, + {Base: DI}, + {Base: BP}, + {Base: BX}, +} + +// baseReg returns the base register for a given register size in bits. +func baseRegForBits(bits int) Reg { + switch bits { + case 8: + return AL + case 16: + return AX + case 32: + return EAX + case 64: + return RAX + } + return 0 +} + +// baseReg records the base register for argument types that specify +// a range of registers indexed by op, regop, or rm. +var baseReg = [...]Reg{ + xArgDR0dashDR7: DR0, + xArgMm1: M0, + xArgMm2: M0, + xArgMm2M64: M0, + xArgMm: M0, + xArgMmM32: M0, + xArgMmM64: M0, + xArgR16: AX, + xArgR16op: AX, + xArgR32: EAX, + xArgR32M16: EAX, + xArgR32M8: EAX, + xArgR32op: EAX, + xArgR64: RAX, + xArgR64M16: RAX, + xArgR64op: RAX, + xArgR8: AL, + xArgR8op: AL, + xArgRM16: AX, + xArgRM32: EAX, + xArgRM64: RAX, + xArgRM8: AL, + xArgRmf16: AX, + xArgRmf32: EAX, + xArgRmf64: RAX, + xArgSTi: F0, + xArgTR0dashTR7: TR0, + xArgXmm1: X0, + xArgXmm2: X0, + xArgXmm2M128: X0, + xArgXmm2M16: X0, + xArgXmm2M32: X0, + xArgXmm2M64: X0, + xArgXmm: X0, + xArgXmmM128: X0, + xArgXmmM32: X0, + xArgXmmM64: X0, +} + +// prefixToSegment returns the segment register +// corresponding to a particular segment prefix. +func prefixToSegment(p Prefix) Reg { + switch p &^ PrefixImplicit { + case PrefixCS: + return CS + case PrefixDS: + return DS + case PrefixES: + return ES + case PrefixFS: + return FS + case PrefixGS: + return GS + case PrefixSS: + return SS + } + return 0 +} + +// fixedArg records the fixed arguments corresponding to the given bytecodes. +var fixedArg = [...]Arg{ + xArg1: Imm(1), + xArg3: Imm(3), + xArgAL: AL, + xArgAX: AX, + xArgDX: DX, + xArgEAX: EAX, + xArgEDX: EDX, + xArgRAX: RAX, + xArgRDX: RDX, + xArgCL: CL, + xArgCS: CS, + xArgDS: DS, + xArgES: ES, + xArgFS: FS, + xArgGS: GS, + xArgSS: SS, + xArgST: F0, + xArgXMM0: X0, +} + +// memBytes records the size of the memory pointed at +// by a memory argument of the given form. +var memBytes = [...]int8{ + xArgM128: 128 / 8, + xArgM16: 16 / 8, + xArgM16and16: (16 + 16) / 8, + xArgM16colon16: (16 + 16) / 8, + xArgM16colon32: (16 + 32) / 8, + xArgM16int: 16 / 8, + xArgM2byte: 2, + xArgM32: 32 / 8, + xArgM32and32: (32 + 32) / 8, + xArgM32fp: 32 / 8, + xArgM32int: 32 / 8, + xArgM64: 64 / 8, + xArgM64fp: 64 / 8, + xArgM64int: 64 / 8, + xArgMm2M64: 64 / 8, + xArgMmM32: 32 / 8, + xArgMmM64: 64 / 8, + xArgMoffs16: 16 / 8, + xArgMoffs32: 32 / 8, + xArgMoffs64: 64 / 8, + xArgMoffs8: 8 / 8, + xArgR32M16: 16 / 8, + xArgR32M8: 8 / 8, + xArgR64M16: 16 / 8, + xArgRM16: 16 / 8, + xArgRM32: 32 / 8, + xArgRM64: 64 / 8, + xArgRM8: 8 / 8, + xArgXmm2M128: 128 / 8, + xArgXmm2M16: 16 / 8, + xArgXmm2M32: 32 / 8, + xArgXmm2M64: 64 / 8, + xArgXmm: 128 / 8, + xArgXmmM128: 128 / 8, + xArgXmmM32: 32 / 8, + xArgXmmM64: 64 / 8, +} + +// isCondJmp records the conditional jumps. +var isCondJmp = [maxOp + 1]bool{ + JA: true, + JAE: true, + JB: true, + JBE: true, + JE: true, + JG: true, + JGE: true, + JL: true, + JLE: true, + JNE: true, + JNO: true, + JNP: true, + JNS: true, + JO: true, + JP: true, + JS: true, +} + +// isLoop records the loop operators. +var isLoop = [maxOp + 1]bool{ + LOOP: true, + LOOPE: true, + LOOPNE: true, + JECXZ: true, + JRCXZ: true, +} diff --git a/vendor/rsc.io/x86/x86asm/gnu.go b/vendor/rsc.io/x86/x86asm/gnu.go new file mode 100644 index 0000000..e2ff801 --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/gnu.go @@ -0,0 +1,926 @@ +// Copyright 2014 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 x86asm + +import ( + "fmt" + "strings" +) + +// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils. +// This general form is often called ``AT&T syntax'' as a reference to AT&T System V Unix. +func GNUSyntax(inst Inst) string { + // Rewrite instruction to mimic GNU peculiarities. + // Note that inst has been passed by value and contains + // no pointers, so any changes we make here are local + // and will not propagate back out to the caller. + + // Adjust opcode [sic]. + switch inst.Op { + case FDIV, FDIVR, FSUB, FSUBR, FDIVP, FDIVRP, FSUBP, FSUBRP: + // DC E0, DC F0: libopcodes swaps FSUBR/FSUB and FDIVR/FDIV, at least + // if you believe the Intel manual is correct (the encoding is irregular as given; + // libopcodes uses the more regular expected encoding). + // TODO(rsc): Test to ensure Intel manuals are correct and report to libopcodes maintainers? + // NOTE: iant thinks this is deliberate, but we can't find the history. + _, reg1 := inst.Args[0].(Reg) + _, reg2 := inst.Args[1].(Reg) + if reg1 && reg2 && (inst.Opcode>>24 == 0xDC || inst.Opcode>>24 == 0xDE) { + switch inst.Op { + case FDIV: + inst.Op = FDIVR + case FDIVR: + inst.Op = FDIV + case FSUB: + inst.Op = FSUBR + case FSUBR: + inst.Op = FSUB + case FDIVP: + inst.Op = FDIVRP + case FDIVRP: + inst.Op = FDIVP + case FSUBP: + inst.Op = FSUBRP + case FSUBRP: + inst.Op = FSUBP + } + } + + case MOVNTSD: + // MOVNTSD is F2 0F 2B /r. + // MOVNTSS is F3 0F 2B /r (supposedly; not in manuals). + // Usually inner prefixes win for display, + // so that F3 F2 0F 2B 11 is REP MOVNTSD + // and F2 F3 0F 2B 11 is REPN MOVNTSS. + // Libopcodes always prefers MOVNTSS regardless of prefix order. + if countPrefix(&inst, 0xF3) > 0 { + found := false + for i := len(inst.Prefix) - 1; i >= 0; i-- { + switch inst.Prefix[i] & 0xFF { + case 0xF3: + if !found { + found = true + inst.Prefix[i] |= PrefixImplicit + } + case 0xF2: + inst.Prefix[i] &^= PrefixImplicit + } + } + inst.Op = MOVNTSS + } + } + + // Add implicit arguments. + switch inst.Op { + case MONITOR: + inst.Args[0] = EDX + inst.Args[1] = ECX + inst.Args[2] = EAX + if inst.AddrSize == 16 { + inst.Args[2] = AX + } + + case MWAIT: + if inst.Mode == 64 { + inst.Args[0] = RCX + inst.Args[1] = RAX + } else { + inst.Args[0] = ECX + inst.Args[1] = EAX + } + } + + // Adjust which prefixes will be displayed. + // The rule is to display all the prefixes not implied by + // the usual instruction display, that is, all the prefixes + // except the ones with PrefixImplicit set. + // However, of course, there are exceptions to the rule. + switch inst.Op { + case CRC32: + // CRC32 has a mandatory F2 prefix. + // If there are multiple F2s and no F3s, the extra F2s do not print. + // (And Decode has already marked them implicit.) + // However, if there is an F3 anywhere, then the extra F2s do print. + // If there are multiple F2 prefixes *and* an (ignored) F3, + // then libopcodes prints the extra F2s as REPNs. + if countPrefix(&inst, 0xF2) > 1 { + unmarkImplicit(&inst, 0xF2) + markLastImplicit(&inst, 0xF2) + } + + // An unused data size override should probably be shown, + // to distinguish DATA16 CRC32B from plain CRC32B, + // but libopcodes always treats the final override as implicit + // and the others as explicit. + unmarkImplicit(&inst, PrefixDataSize) + markLastImplicit(&inst, PrefixDataSize) + + case CVTSI2SD, CVTSI2SS: + if !isMem(inst.Args[1]) { + markLastImplicit(&inst, PrefixDataSize) + } + + case CVTSD2SI, CVTSS2SI, CVTTSD2SI, CVTTSS2SI, + ENTER, FLDENV, FNSAVE, FNSTENV, FRSTOR, LGDT, LIDT, LRET, + POP, PUSH, RET, SGDT, SIDT, SYSRET, XBEGIN: + markLastImplicit(&inst, PrefixDataSize) + + case LOOP, LOOPE, LOOPNE, MONITOR: + markLastImplicit(&inst, PrefixAddrSize) + + case MOV: + // The 16-bit and 32-bit forms of MOV Sreg, dst and MOV src, Sreg + // cannot be distinguished when src or dst refers to memory, because + // Sreg is always a 16-bit value, even when we're doing a 32-bit + // instruction. Because the instruction tables distinguished these two, + // any operand size prefix has been marked as used (to decide which + // branch to take). Unmark it, so that it will show up in disassembly, + // so that the reader can tell the size of memory operand. + // up with the same arguments + dst, _ := inst.Args[0].(Reg) + src, _ := inst.Args[1].(Reg) + if ES <= src && src <= GS && isMem(inst.Args[0]) || ES <= dst && dst <= GS && isMem(inst.Args[1]) { + unmarkImplicit(&inst, PrefixDataSize) + } + + case MOVDQU: + if countPrefix(&inst, 0xF3) > 1 { + unmarkImplicit(&inst, 0xF3) + markLastImplicit(&inst, 0xF3) + } + + case MOVQ2DQ: + markLastImplicit(&inst, PrefixDataSize) + + case SLDT, SMSW, STR, FXRSTOR, XRSTOR, XSAVE, XSAVEOPT, CMPXCHG8B: + if isMem(inst.Args[0]) { + unmarkImplicit(&inst, PrefixDataSize) + } + + case SYSEXIT: + unmarkImplicit(&inst, PrefixDataSize) + } + + if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ { + if countPrefix(&inst, PrefixCS) > 0 && countPrefix(&inst, PrefixDS) > 0 { + for i, p := range inst.Prefix { + switch p & 0xFFF { + case PrefixPN, PrefixPT: + inst.Prefix[i] &= 0xF0FF // cut interpretation bits, producing original segment prefix + } + } + } + } + + // XACQUIRE/XRELEASE adjustment. + if inst.Op == MOV { + // MOV into memory is a candidate for turning REP into XRELEASE. + // However, if the REP is followed by a REPN, that REPN blocks the + // conversion. + haveREPN := false + for i := len(inst.Prefix) - 1; i >= 0; i-- { + switch inst.Prefix[i] &^ PrefixIgnored { + case PrefixREPN: + haveREPN = true + case PrefixXRELEASE: + if haveREPN { + inst.Prefix[i] = PrefixREP + } + } + } + } + + // We only format the final F2/F3 as XRELEASE/XACQUIRE. + haveXA := false + haveXR := false + for i := len(inst.Prefix) - 1; i >= 0; i-- { + switch inst.Prefix[i] &^ PrefixIgnored { + case PrefixXRELEASE: + if !haveXR { + haveXR = true + } else { + inst.Prefix[i] = PrefixREP + } + + case PrefixXACQUIRE: + if !haveXA { + haveXA = true + } else { + inst.Prefix[i] = PrefixREPN + } + } + } + + // Determine opcode. + op := strings.ToLower(inst.Op.String()) + if alt := gnuOp[inst.Op]; alt != "" { + op = alt + } + + // Determine opcode suffix. + // Libopcodes omits the suffix if the width of the operation + // can be inferred from a register arguments. For example, + // add $1, %ebx has no suffix because you can tell from the + // 32-bit register destination that it is a 32-bit add, + // but in addl $1, (%ebx), the destination is memory, so the + // size is not evident without the l suffix. + needSuffix := true +SuffixLoop: + for i, a := range inst.Args { + if a == nil { + break + } + switch a := a.(type) { + case Reg: + switch inst.Op { + case MOVSX, MOVZX: + continue + + case SHL, SHR, RCL, RCR, ROL, ROR, SAR: + if i == 1 { + // shift count does not tell us operand size + continue + } + + case CRC32: + // The source argument does tell us operand size, + // but libopcodes still always puts a suffix on crc32. + continue + + case PUSH, POP: + // Even though segment registers are 16-bit, push and pop + // can save/restore them from 32-bit slots, so they + // do not imply operand size. + if ES <= a && a <= GS { + continue + } + + case CVTSI2SD, CVTSI2SS: + // The integer register argument takes priority. + if X0 <= a && a <= X15 { + continue + } + } + + if AL <= a && a <= R15 || ES <= a && a <= GS || X0 <= a && a <= X15 || M0 <= a && a <= M7 { + needSuffix = false + break SuffixLoop + } + } + } + + if needSuffix { + switch inst.Op { + case CMPXCHG8B, FLDCW, FNSTCW, FNSTSW, LDMXCSR, LLDT, LMSW, LTR, PCLMULQDQ, + SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL, SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS, + SLDT, SMSW, STMXCSR, STR, VERR, VERW: + // For various reasons, libopcodes emits no suffix for these instructions. + + case CRC32: + op += byteSizeSuffix(argBytes(&inst, inst.Args[1])) + + case LGDT, LIDT, SGDT, SIDT: + op += byteSizeSuffix(inst.DataSize / 8) + + case MOVZX, MOVSX: + // Integer size conversions get two suffixes. + op = op[:4] + byteSizeSuffix(argBytes(&inst, inst.Args[1])) + byteSizeSuffix(argBytes(&inst, inst.Args[0])) + + case LOOP, LOOPE, LOOPNE: + // Add w suffix to indicate use of CX register instead of ECX. + if inst.AddrSize == 16 { + op += "w" + } + + case CALL, ENTER, JMP, LCALL, LEAVE, LJMP, LRET, RET, SYSRET, XBEGIN: + // Add w suffix to indicate use of 16-bit target. + // Exclude JMP rel8. + if inst.Opcode>>24 == 0xEB { + break + } + if inst.DataSize == 16 && inst.Mode != 16 { + markLastImplicit(&inst, PrefixDataSize) + op += "w" + } else if inst.Mode == 64 { + op += "q" + } + + case FRSTOR, FNSAVE, FNSTENV, FLDENV: + // Add s suffix to indicate shortened FPU state (I guess). + if inst.DataSize == 16 { + op += "s" + } + + case PUSH, POP: + if markLastImplicit(&inst, PrefixDataSize) { + op += byteSizeSuffix(inst.DataSize / 8) + } else if inst.Mode == 64 { + op += "q" + } else { + op += byteSizeSuffix(inst.MemBytes) + } + + default: + if isFloat(inst.Op) { + // I can't explain any of this, but it's what libopcodes does. + switch inst.MemBytes { + default: + if (inst.Op == FLD || inst.Op == FSTP) && isMem(inst.Args[0]) { + op += "t" + } + case 4: + if isFloatInt(inst.Op) { + op += "l" + } else { + op += "s" + } + case 8: + if isFloatInt(inst.Op) { + op += "ll" + } else { + op += "l" + } + } + break + } + + op += byteSizeSuffix(inst.MemBytes) + } + } + + // Adjust special case opcodes. + switch inst.Op { + case 0: + if inst.Prefix[0] != 0 { + return strings.ToLower(inst.Prefix[0].String()) + } + + case INT: + if inst.Opcode>>24 == 0xCC { + inst.Args[0] = nil + op = "int3" + } + + case CMPPS, CMPPD, CMPSD_XMM, CMPSS: + imm, ok := inst.Args[2].(Imm) + if ok && 0 <= imm && imm < 8 { + inst.Args[2] = nil + op = cmppsOps[imm] + op[3:] + } + + case PCLMULQDQ: + imm, ok := inst.Args[2].(Imm) + if ok && imm&^0x11 == 0 { + inst.Args[2] = nil + op = pclmulqOps[(imm&0x10)>>3|(imm&1)] + } + + case XLATB: + if markLastImplicit(&inst, PrefixAddrSize) { + op = "xlat" // not xlatb + } + } + + // Build list of argument strings. + var ( + usedPrefixes bool // segment prefixes consumed by Mem formatting + args []string // formatted arguments + ) + for i, a := range inst.Args { + if a == nil { + break + } + switch inst.Op { + case MOVSB, MOVSW, MOVSD, MOVSQ, OUTSB, OUTSW, OUTSD: + if i == 0 { + usedPrefixes = true // disable use of prefixes for first argument + } else { + usedPrefixes = false + } + } + if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 { + continue + } + args = append(args, gnuArg(&inst, a, &usedPrefixes)) + } + + // The default is to print the arguments in reverse Intel order. + // A few instructions inhibit this behavior. + switch inst.Op { + case BOUND, LCALL, ENTER, LJMP: + // no reverse + default: + // reverse args + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + } + + // Build prefix string. + // Must be after argument formatting, which can turn off segment prefixes. + var ( + prefix = "" // output string + numAddr = 0 + numData = 0 + implicitData = false + ) + for _, p := range inst.Prefix { + if p&0xFF == PrefixDataSize && p&PrefixImplicit != 0 { + implicitData = true + } + } + for _, p := range inst.Prefix { + if p == 0 { + break + } + if p&PrefixImplicit != 0 { + continue + } + switch p &^ (PrefixIgnored | PrefixInvalid) { + default: + if p.IsREX() { + if p&0xFF == PrefixREX { + prefix += "rex " + } else { + prefix += "rex." + p.String()[4:] + " " + } + break + } + prefix += strings.ToLower(p.String()) + " " + + case PrefixPN: + op += ",pn" + continue + + case PrefixPT: + op += ",pt" + continue + + case PrefixAddrSize, PrefixAddr16, PrefixAddr32: + // For unknown reasons, if the addr16 prefix is repeated, + // libopcodes displays all but the last as addr32, even though + // the addressing form used in a memory reference is clearly + // still 16-bit. + n := 32 + if inst.Mode == 32 { + n = 16 + } + numAddr++ + if countPrefix(&inst, PrefixAddrSize) > numAddr { + n = inst.Mode + } + prefix += fmt.Sprintf("addr%d ", n) + continue + + case PrefixData16, PrefixData32: + if implicitData && countPrefix(&inst, PrefixDataSize) > 1 { + // Similar to the addr32 logic above, but it only kicks in + // when something used the data size prefix (one is implicit). + n := 16 + if inst.Mode == 16 { + n = 32 + } + numData++ + if countPrefix(&inst, PrefixDataSize) > numData { + if inst.Mode == 16 { + n = 16 + } else { + n = 32 + } + } + prefix += fmt.Sprintf("data%d ", n) + continue + } + prefix += strings.ToLower(p.String()) + " " + } + } + + // Finally! Put it all together. + text := prefix + op + if args != nil { + text += " " + // Indirect call/jmp gets a star to distinguish from direct jump address. + if (inst.Op == CALL || inst.Op == JMP || inst.Op == LJMP || inst.Op == LCALL) && (isMem(inst.Args[0]) || isReg(inst.Args[0])) { + text += "*" + } + text += strings.Join(args, ",") + } + return text +} + +// gnuArg returns the GNU syntax for the argument x from the instruction inst. +// If *usedPrefixes is false and x is a Mem, then the formatting +// includes any segment prefixes and sets *usedPrefixes to true. +func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string { + if x == nil { + return "" + } + switch x := x.(type) { + case Reg: + switch inst.Op { + case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI: + if inst.DataSize == 16 && EAX <= x && x <= R15L { + x -= EAX - AX + } + + case IN, INSB, INSW, INSD, OUT, OUTSB, OUTSW, OUTSD: + // DX is the port, but libopcodes prints it as if it were a memory reference. + if x == DX { + return "(%dx)" + } + } + return gccRegName[x] + case Mem: + seg := "" + var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool + switch x.Segment { + case CS: + haveCS = true + case DS: + haveDS = true + case ES: + haveES = true + case FS: + haveFS = true + case GS: + haveGS = true + case SS: + haveSS = true + } + switch inst.Op { + case INSB, INSW, INSD, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ: + // These do not accept segment prefixes, at least in the GNU rendering. + default: + if *usedPrefixes { + break + } + for i := len(inst.Prefix) - 1; i >= 0; i-- { + p := inst.Prefix[i] &^ PrefixIgnored + if p == 0 { + continue + } + switch p { + case PrefixCS: + if !haveCS { + haveCS = true + inst.Prefix[i] |= PrefixImplicit + } + case PrefixDS: + if !haveDS { + haveDS = true + inst.Prefix[i] |= PrefixImplicit + } + case PrefixES: + if !haveES { + haveES = true + inst.Prefix[i] |= PrefixImplicit + } + case PrefixFS: + if !haveFS { + haveFS = true + inst.Prefix[i] |= PrefixImplicit + } + case PrefixGS: + if !haveGS { + haveGS = true + inst.Prefix[i] |= PrefixImplicit + } + case PrefixSS: + if !haveSS { + haveSS = true + inst.Prefix[i] |= PrefixImplicit + } + } + } + *usedPrefixes = true + } + if haveCS { + seg += "%cs:" + } + if haveDS { + seg += "%ds:" + } + if haveSS { + seg += "%ss:" + } + if haveES { + seg += "%es:" + } + if haveFS { + seg += "%fs:" + } + if haveGS { + seg += "%gs:" + } + disp := "" + if x.Disp != 0 { + disp = fmt.Sprintf("%#x", x.Disp) + } + if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == ESP || x.Base == RSP || x.Base == 0 && inst.Mode == 64) { + if x.Base == 0 { + return seg + disp + } + return fmt.Sprintf("%s%s(%s)", seg, disp, gccRegName[x.Base]) + } + base := gccRegName[x.Base] + if x.Base == 0 { + base = "" + } + index := gccRegName[x.Index] + if x.Index == 0 { + if inst.AddrSize == 64 { + index = "%riz" + } else { + index = "%eiz" + } + } + if AX <= x.Base && x.Base <= DI { + // 16-bit addressing - no scale + return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index) + } + return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale) + case Rel: + return fmt.Sprintf(".%+#x", int32(x)) + case Imm: + if inst.Mode == 32 { + return fmt.Sprintf("$%#x", uint32(x)) + } + return fmt.Sprintf("$%#x", int64(x)) + } + return x.String() +} + +var gccRegName = [...]string{ + 0: "REG0", + AL: "%al", + CL: "%cl", + BL: "%bl", + DL: "%dl", + AH: "%ah", + CH: "%ch", + BH: "%bh", + DH: "%dh", + SPB: "%spl", + BPB: "%bpl", + SIB: "%sil", + DIB: "%dil", + R8B: "%r8b", + R9B: "%r9b", + R10B: "%r10b", + R11B: "%r11b", + R12B: "%r12b", + R13B: "%r13b", + R14B: "%r14b", + R15B: "%r15b", + AX: "%ax", + CX: "%cx", + BX: "%bx", + DX: "%dx", + SP: "%sp", + BP: "%bp", + SI: "%si", + DI: "%di", + R8W: "%r8w", + R9W: "%r9w", + R10W: "%r10w", + R11W: "%r11w", + R12W: "%r12w", + R13W: "%r13w", + R14W: "%r14w", + R15W: "%r15w", + EAX: "%eax", + ECX: "%ecx", + EDX: "%edx", + EBX: "%ebx", + ESP: "%esp", + EBP: "%ebp", + ESI: "%esi", + EDI: "%edi", + R8L: "%r8d", + R9L: "%r9d", + R10L: "%r10d", + R11L: "%r11d", + R12L: "%r12d", + R13L: "%r13d", + R14L: "%r14d", + R15L: "%r15d", + RAX: "%rax", + RCX: "%rcx", + RDX: "%rdx", + RBX: "%rbx", + RSP: "%rsp", + RBP: "%rbp", + RSI: "%rsi", + RDI: "%rdi", + R8: "%r8", + R9: "%r9", + R10: "%r10", + R11: "%r11", + R12: "%r12", + R13: "%r13", + R14: "%r14", + R15: "%r15", + IP: "%ip", + EIP: "%eip", + RIP: "%rip", + F0: "%st", + F1: "%st(1)", + F2: "%st(2)", + F3: "%st(3)", + F4: "%st(4)", + F5: "%st(5)", + F6: "%st(6)", + F7: "%st(7)", + M0: "%mm0", + M1: "%mm1", + M2: "%mm2", + M3: "%mm3", + M4: "%mm4", + M5: "%mm5", + M6: "%mm6", + M7: "%mm7", + X0: "%xmm0", + X1: "%xmm1", + X2: "%xmm2", + X3: "%xmm3", + X4: "%xmm4", + X5: "%xmm5", + X6: "%xmm6", + X7: "%xmm7", + X8: "%xmm8", + X9: "%xmm9", + X10: "%xmm10", + X11: "%xmm11", + X12: "%xmm12", + X13: "%xmm13", + X14: "%xmm14", + X15: "%xmm15", + CS: "%cs", + SS: "%ss", + DS: "%ds", + ES: "%es", + FS: "%fs", + GS: "%gs", + GDTR: "%gdtr", + IDTR: "%idtr", + LDTR: "%ldtr", + MSW: "%msw", + TASK: "%task", + CR0: "%cr0", + CR1: "%cr1", + CR2: "%cr2", + CR3: "%cr3", + CR4: "%cr4", + CR5: "%cr5", + CR6: "%cr6", + CR7: "%cr7", + CR8: "%cr8", + CR9: "%cr9", + CR10: "%cr10", + CR11: "%cr11", + CR12: "%cr12", + CR13: "%cr13", + CR14: "%cr14", + CR15: "%cr15", + DR0: "%db0", + DR1: "%db1", + DR2: "%db2", + DR3: "%db3", + DR4: "%db4", + DR5: "%db5", + DR6: "%db6", + DR7: "%db7", + TR0: "%tr0", + TR1: "%tr1", + TR2: "%tr2", + TR3: "%tr3", + TR4: "%tr4", + TR5: "%tr5", + TR6: "%tr6", + TR7: "%tr7", +} + +var gnuOp = map[Op]string{ + CBW: "cbtw", + CDQ: "cltd", + CMPSD: "cmpsl", + CMPSD_XMM: "cmpsd", + CWD: "cwtd", + CWDE: "cwtl", + CQO: "cqto", + INSD: "insl", + IRET: "iretw", + IRETD: "iret", + IRETQ: "iretq", + LODSB: "lods", + LODSD: "lods", + LODSQ: "lods", + LODSW: "lods", + MOVSD: "movsl", + MOVSD_XMM: "movsd", + OUTSD: "outsl", + POPA: "popaw", + POPAD: "popa", + POPF: "popfw", + POPFD: "popf", + PUSHA: "pushaw", + PUSHAD: "pusha", + PUSHF: "pushfw", + PUSHFD: "pushf", + SCASB: "scas", + SCASD: "scas", + SCASQ: "scas", + SCASW: "scas", + STOSB: "stos", + STOSD: "stos", + STOSQ: "stos", + STOSW: "stos", + XLATB: "xlat", +} + +var cmppsOps = []string{ + "cmpeq", + "cmplt", + "cmple", + "cmpunord", + "cmpneq", + "cmpnlt", + "cmpnle", + "cmpord", +} + +var pclmulqOps = []string{ + "pclmullqlqdq", + "pclmulhqlqdq", + "pclmullqhqdq", + "pclmulhqhqdq", +} + +func countPrefix(inst *Inst, target Prefix) int { + n := 0 + for _, p := range inst.Prefix { + if p&0xFF == target&0xFF { + n++ + } + } + return n +} + +func markLastImplicit(inst *Inst, prefix Prefix) bool { + for i := len(inst.Prefix) - 1; i >= 0; i-- { + p := inst.Prefix[i] + if p&0xFF == prefix { + inst.Prefix[i] |= PrefixImplicit + return true + } + } + return false +} + +func unmarkImplicit(inst *Inst, prefix Prefix) { + for i := len(inst.Prefix) - 1; i >= 0; i-- { + p := inst.Prefix[i] + if p&0xFF == prefix { + inst.Prefix[i] &^= PrefixImplicit + } + } +} + +func byteSizeSuffix(b int) string { + switch b { + case 1: + return "b" + case 2: + return "w" + case 4: + return "l" + case 8: + return "q" + } + return "" +} + +func argBytes(inst *Inst, arg Arg) int { + if isMem(arg) { + return inst.MemBytes + } + return regBytes(arg) +} + +func isFloat(op Op) bool { + switch op { + case FADD, FCOM, FCOMP, FDIV, FDIVR, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR, FLD, FMUL, FST, FSTP, FSUB, FSUBR: + return true + } + return false +} + +func isFloatInt(op Op) bool { + switch op { + case FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR: + return true + } + return false +} diff --git a/vendor/rsc.io/x86/x86asm/inst.go b/vendor/rsc.io/x86/x86asm/inst.go new file mode 100644 index 0000000..eccd954 --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/inst.go @@ -0,0 +1,643 @@ +// Copyright 2014 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 x86asm implements decoding of x86 machine code. +package x86asm + +import ( + "bytes" + "fmt" +) + +// An Inst is a single instruction. +type Inst struct { + Prefix Prefixes // Prefixes applied to the instruction. + Op Op // Opcode mnemonic + Opcode uint32 // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc) + Args Args // Instruction arguments, in Intel order + Mode int // processor mode in bits: 16, 32, or 64 + AddrSize int // address size in bits: 16, 32, or 64 + DataSize int // operand size in bits: 16, 32, or 64 + MemBytes int // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on. + Len int // length of encoded instruction in bytes + PCRel int // length of PC-relative address in instruction encoding + PCRelOff int // index of start of PC-relative address in instruction encoding +} + +// Prefixes is an array of prefixes associated with a single instruction. +// The prefixes are listed in the same order as found in the instruction: +// each prefix byte corresponds to one slot in the array. The first zero +// in the array marks the end of the prefixes. +type Prefixes [14]Prefix + +// A Prefix represents an Intel instruction prefix. +// The low 8 bits are the actual prefix byte encoding, +// and the top 8 bits contain distinguishing bits and metadata. +type Prefix uint16 + +const ( + // Metadata about the role of a prefix in an instruction. + PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text + PrefixIgnored Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix + PrefixInvalid Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK) + + // Memory segment overrides. + PrefixES Prefix = 0x26 // ES segment override + PrefixCS Prefix = 0x2E // CS segment override + PrefixSS Prefix = 0x36 // SS segment override + PrefixDS Prefix = 0x3E // DS segment override + PrefixFS Prefix = 0x64 // FS segment override + PrefixGS Prefix = 0x65 // GS segment override + + // Branch prediction. + PrefixPN Prefix = 0x12E // predict not taken (conditional branch only) + PrefixPT Prefix = 0x13E // predict taken (conditional branch only) + + // Size attributes. + PrefixDataSize Prefix = 0x66 // operand size override + PrefixData16 Prefix = 0x166 + PrefixData32 Prefix = 0x266 + PrefixAddrSize Prefix = 0x67 // address size override + PrefixAddr16 Prefix = 0x167 + PrefixAddr32 Prefix = 0x267 + + // One of a kind. + PrefixLOCK Prefix = 0xF0 // lock + PrefixREPN Prefix = 0xF2 // repeat not zero + PrefixXACQUIRE Prefix = 0x1F2 + PrefixBND Prefix = 0x2F2 + PrefixREP Prefix = 0xF3 // repeat + PrefixXRELEASE Prefix = 0x1F3 + + // The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10). + // the other bits are set or not according to the intended use. + PrefixREX Prefix = 0x40 // REX 64-bit extension prefix + PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width) + PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm) + PrefixREXX Prefix = 0x02 // extension bit X (index field in sib) + PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib) +) + +// IsREX reports whether p is a REX prefix byte. +func (p Prefix) IsREX() bool { + return p&0xF0 == PrefixREX +} + +func (p Prefix) String() string { + p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid + if s := prefixNames[p]; s != "" { + return s + } + + if p.IsREX() { + s := "REX." + if p&PrefixREXW != 0 { + s += "W" + } + if p&PrefixREXR != 0 { + s += "R" + } + if p&PrefixREXX != 0 { + s += "X" + } + if p&PrefixREXB != 0 { + s += "B" + } + return s + } + + return fmt.Sprintf("Prefix(%#x)", int(p)) +} + +// An Op is an x86 opcode. +type Op uint32 + +func (op Op) String() string { + i := int(op) + if i < 0 || i >= len(opNames) || opNames[i] == "" { + return fmt.Sprintf("Op(%d)", i) + } + return opNames[i] +} + +// An Args holds the instruction arguments. +// If an instruction has fewer than 4 arguments, +// the final elements in the array are nil. +type Args [4]Arg + +// An Arg is a single instruction argument, +// one of these types: Reg, Mem, Imm, Rel. +type Arg interface { + String() string + isArg() +} + +// Note that the implements of Arg that follow are all sized +// so that on a 64-bit machine the data can be inlined in +// the interface value instead of requiring an allocation. + +// A Reg is a single register. +// The zero Reg value has no name but indicates ``no register.'' +type Reg uint8 + +const ( + _ Reg = iota + + // 8-bit + AL + CL + DL + BL + AH + CH + DH + BH + SPB + BPB + SIB + DIB + R8B + R9B + R10B + R11B + R12B + R13B + R14B + R15B + + // 16-bit + AX + CX + DX + BX + SP + BP + SI + DI + R8W + R9W + R10W + R11W + R12W + R13W + R14W + R15W + + // 32-bit + EAX + ECX + EDX + EBX + ESP + EBP + ESI + EDI + R8L + R9L + R10L + R11L + R12L + R13L + R14L + R15L + + // 64-bit + RAX + RCX + RDX + RBX + RSP + RBP + RSI + RDI + R8 + R9 + R10 + R11 + R12 + R13 + R14 + R15 + + // Instruction pointer. + IP // 16-bit + EIP // 32-bit + RIP // 64-bit + + // 387 floating point registers. + F0 + F1 + F2 + F3 + F4 + F5 + F6 + F7 + + // MMX registers. + M0 + M1 + M2 + M3 + M4 + M5 + M6 + M7 + + // XMM registers. + X0 + X1 + X2 + X3 + X4 + X5 + X6 + X7 + X8 + X9 + X10 + X11 + X12 + X13 + X14 + X15 + + // Segment registers. + ES + CS + SS + DS + FS + GS + + // System registers. + GDTR + IDTR + LDTR + MSW + TASK + + // Control registers. + CR0 + CR1 + CR2 + CR3 + CR4 + CR5 + CR6 + CR7 + CR8 + CR9 + CR10 + CR11 + CR12 + CR13 + CR14 + CR15 + + // Debug registers. + DR0 + DR1 + DR2 + DR3 + DR4 + DR5 + DR6 + DR7 + DR8 + DR9 + DR10 + DR11 + DR12 + DR13 + DR14 + DR15 + + // Task registers. + TR0 + TR1 + TR2 + TR3 + TR4 + TR5 + TR6 + TR7 +) + +const regMax = TR7 + +func (Reg) isArg() {} + +func (r Reg) String() string { + i := int(r) + if i < 0 || i >= len(regNames) || regNames[i] == "" { + return fmt.Sprintf("Reg(%d)", i) + } + return regNames[i] +} + +// A Mem is a memory reference. +// The general form is Segment:[Base+Scale*Index+Disp]. +type Mem struct { + Segment Reg + Base Reg + Scale uint8 + Index Reg + Disp int64 +} + +func (Mem) isArg() {} + +func (m Mem) String() string { + var base, plus, scale, index, disp string + + if m.Base != 0 { + base = m.Base.String() + } + if m.Scale != 0 { + if m.Base != 0 { + plus = "+" + } + if m.Scale > 1 { + scale = fmt.Sprintf("%d*", m.Scale) + } + index = m.Index.String() + } + if m.Disp != 0 || m.Base == 0 && m.Scale == 0 { + disp = fmt.Sprintf("%+#x", m.Disp) + } + return "[" + base + plus + scale + index + disp + "]" +} + +// A Rel is an offset relative to the current instruction pointer. +type Rel int32 + +func (Rel) isArg() {} + +func (r Rel) String() string { + return fmt.Sprintf(".%+d", r) +} + +// An Imm is an integer constant. +type Imm int64 + +func (Imm) isArg() {} + +func (i Imm) String() string { + return fmt.Sprintf("%#x", int64(i)) +} + +func (i Inst) String() string { + var buf bytes.Buffer + for _, p := range i.Prefix { + if p == 0 { + break + } + if p&PrefixImplicit != 0 { + continue + } + fmt.Fprintf(&buf, "%v ", p) + } + fmt.Fprintf(&buf, "%v", i.Op) + sep := " " + for _, v := range i.Args { + if v == nil { + break + } + fmt.Fprintf(&buf, "%s%v", sep, v) + sep = ", " + } + return buf.String() +} + +func isReg(a Arg) bool { + _, ok := a.(Reg) + return ok +} + +func isSegReg(a Arg) bool { + r, ok := a.(Reg) + return ok && ES <= r && r <= GS +} + +func isMem(a Arg) bool { + _, ok := a.(Mem) + return ok +} + +func isImm(a Arg) bool { + _, ok := a.(Imm) + return ok +} + +func regBytes(a Arg) int { + r, ok := a.(Reg) + if !ok { + return 0 + } + if AL <= r && r <= R15B { + return 1 + } + if AX <= r && r <= R15W { + return 2 + } + if EAX <= r && r <= R15L { + return 4 + } + if RAX <= r && r <= R15 { + return 8 + } + return 0 +} + +func isSegment(p Prefix) bool { + switch p { + case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS: + return true + } + return false +} + +// The Op definitions and string list are in tables.go. + +var prefixNames = map[Prefix]string{ + PrefixCS: "CS", + PrefixDS: "DS", + PrefixES: "ES", + PrefixFS: "FS", + PrefixGS: "GS", + PrefixSS: "SS", + PrefixLOCK: "LOCK", + PrefixREP: "REP", + PrefixREPN: "REPN", + PrefixAddrSize: "ADDRSIZE", + PrefixDataSize: "DATASIZE", + PrefixAddr16: "ADDR16", + PrefixData16: "DATA16", + PrefixAddr32: "ADDR32", + PrefixData32: "DATA32", + PrefixBND: "BND", + PrefixXACQUIRE: "XACQUIRE", + PrefixXRELEASE: "XRELEASE", + PrefixREX: "REX", + PrefixPT: "PT", + PrefixPN: "PN", +} + +var regNames = [...]string{ + AL: "AL", + CL: "CL", + BL: "BL", + DL: "DL", + AH: "AH", + CH: "CH", + BH: "BH", + DH: "DH", + SPB: "SPB", + BPB: "BPB", + SIB: "SIB", + DIB: "DIB", + R8B: "R8B", + R9B: "R9B", + R10B: "R10B", + R11B: "R11B", + R12B: "R12B", + R13B: "R13B", + R14B: "R14B", + R15B: "R15B", + AX: "AX", + CX: "CX", + BX: "BX", + DX: "DX", + SP: "SP", + BP: "BP", + SI: "SI", + DI: "DI", + R8W: "R8W", + R9W: "R9W", + R10W: "R10W", + R11W: "R11W", + R12W: "R12W", + R13W: "R13W", + R14W: "R14W", + R15W: "R15W", + EAX: "EAX", + ECX: "ECX", + EDX: "EDX", + EBX: "EBX", + ESP: "ESP", + EBP: "EBP", + ESI: "ESI", + EDI: "EDI", + R8L: "R8L", + R9L: "R9L", + R10L: "R10L", + R11L: "R11L", + R12L: "R12L", + R13L: "R13L", + R14L: "R14L", + R15L: "R15L", + RAX: "RAX", + RCX: "RCX", + RDX: "RDX", + RBX: "RBX", + RSP: "RSP", + RBP: "RBP", + RSI: "RSI", + RDI: "RDI", + R8: "R8", + R9: "R9", + R10: "R10", + R11: "R11", + R12: "R12", + R13: "R13", + R14: "R14", + R15: "R15", + IP: "IP", + EIP: "EIP", + RIP: "RIP", + F0: "F0", + F1: "F1", + F2: "F2", + F3: "F3", + F4: "F4", + F5: "F5", + F6: "F6", + F7: "F7", + M0: "M0", + M1: "M1", + M2: "M2", + M3: "M3", + M4: "M4", + M5: "M5", + M6: "M6", + M7: "M7", + X0: "X0", + X1: "X1", + X2: "X2", + X3: "X3", + X4: "X4", + X5: "X5", + X6: "X6", + X7: "X7", + X8: "X8", + X9: "X9", + X10: "X10", + X11: "X11", + X12: "X12", + X13: "X13", + X14: "X14", + X15: "X15", + CS: "CS", + SS: "SS", + DS: "DS", + ES: "ES", + FS: "FS", + GS: "GS", + GDTR: "GDTR", + IDTR: "IDTR", + LDTR: "LDTR", + MSW: "MSW", + TASK: "TASK", + CR0: "CR0", + CR1: "CR1", + CR2: "CR2", + CR3: "CR3", + CR4: "CR4", + CR5: "CR5", + CR6: "CR6", + CR7: "CR7", + CR8: "CR8", + CR9: "CR9", + CR10: "CR10", + CR11: "CR11", + CR12: "CR12", + CR13: "CR13", + CR14: "CR14", + CR15: "CR15", + DR0: "DR0", + DR1: "DR1", + DR2: "DR2", + DR3: "DR3", + DR4: "DR4", + DR5: "DR5", + DR6: "DR6", + DR7: "DR7", + DR8: "DR8", + DR9: "DR9", + DR10: "DR10", + DR11: "DR11", + DR12: "DR12", + DR13: "DR13", + DR14: "DR14", + DR15: "DR15", + TR0: "TR0", + TR1: "TR1", + TR2: "TR2", + TR3: "TR3", + TR4: "TR4", + TR5: "TR5", + TR6: "TR6", + TR7: "TR7", +} diff --git a/vendor/rsc.io/x86/x86asm/intel.go b/vendor/rsc.io/x86/x86asm/intel.go new file mode 100644 index 0000000..90af9dd --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/intel.go @@ -0,0 +1,518 @@ +// Copyright 2014 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 x86asm + +import ( + "fmt" + "strings" +) + +// IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool. +func IntelSyntax(inst Inst) string { + var iargs []Arg + for _, a := range inst.Args { + if a == nil { + break + } + iargs = append(iargs, a) + } + + switch inst.Op { + case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, LOOPNE, JCXZ, JECXZ, JRCXZ, LOOP, LOOPE, MOV, XLATB: + if inst.Op == MOV && (inst.Opcode>>16)&0xFFFC != 0x0F20 { + break + } + for i, p := range inst.Prefix { + if p&0xFF == PrefixAddrSize { + inst.Prefix[i] &^= PrefixImplicit + } + } + } + + switch inst.Op { + case MOV: + dst, _ := inst.Args[0].(Reg) + src, _ := inst.Args[1].(Reg) + if ES <= dst && dst <= GS && EAX <= src && src <= R15L { + src -= EAX - AX + iargs[1] = src + } + if ES <= dst && dst <= GS && RAX <= src && src <= R15 { + src -= RAX - AX + iargs[1] = src + } + + if inst.Opcode>>24&^3 == 0xA0 { + for i, p := range inst.Prefix { + if p&0xFF == PrefixAddrSize { + inst.Prefix[i] |= PrefixImplicit + } + } + } + } + + switch inst.Op { + case AAM, AAD: + if imm, ok := iargs[0].(Imm); ok { + if inst.DataSize == 32 { + iargs[0] = Imm(uint32(int8(imm))) + } else if inst.DataSize == 16 { + iargs[0] = Imm(uint16(int8(imm))) + } + } + + case PUSH: + if imm, ok := iargs[0].(Imm); ok { + iargs[0] = Imm(uint32(imm)) + } + } + + for _, p := range inst.Prefix { + if p&PrefixImplicit != 0 { + for j, pj := range inst.Prefix { + if pj&0xFF == p&0xFF { + inst.Prefix[j] |= PrefixImplicit + } + } + } + } + + if inst.Op != 0 { + for i, p := range inst.Prefix { + switch p &^ PrefixIgnored { + case PrefixData16, PrefixData32, PrefixCS, PrefixDS, PrefixES, PrefixSS: + inst.Prefix[i] |= PrefixImplicit + } + if p.IsREX() { + inst.Prefix[i] |= PrefixImplicit + } + } + } + + if isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ { + for i, p := range inst.Prefix { + if p == PrefixPT || p == PrefixPN { + inst.Prefix[i] |= PrefixImplicit + } + } + } + + switch inst.Op { + case AAA, AAS, CBW, CDQE, CLC, CLD, CLI, CLTS, CMC, CPUID, CQO, CWD, DAA, DAS, + FDECSTP, FINCSTP, FNCLEX, FNINIT, FNOP, FWAIT, HLT, + ICEBP, INSB, INSD, INSW, INT, INTO, INVD, IRET, IRETQ, + LAHF, LEAVE, LRET, MONITOR, MWAIT, NOP, OUTSB, OUTSD, OUTSW, + PAUSE, POPA, POPF, POPFQ, PUSHA, PUSHF, PUSHFQ, + RDMSR, RDPMC, RDTSC, RDTSCP, RET, RSM, + SAHF, STC, STD, STI, SYSENTER, SYSEXIT, SYSRET, + UD2, WBINVD, WRMSR, XEND, XLATB, XTEST: + + if inst.Op == NOP && inst.Opcode>>24 != 0x90 { + break + } + if inst.Op == RET && inst.Opcode>>24 != 0xC3 { + break + } + if inst.Op == INT && inst.Opcode>>24 != 0xCC { + break + } + if inst.Op == LRET && inst.Opcode>>24 != 0xcb { + break + } + for i, p := range inst.Prefix { + if p&0xFF == PrefixDataSize { + inst.Prefix[i] &^= PrefixImplicit | PrefixIgnored + } + } + + case 0: + // ok + } + + switch inst.Op { + case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, MONITOR, MWAIT, XLATB: + iargs = nil + + case STOSB, STOSW, STOSD, STOSQ: + iargs = iargs[:1] + + case LODSB, LODSW, LODSD, LODSQ, SCASB, SCASW, SCASD, SCASQ: + iargs = iargs[1:] + } + + const ( + haveData16 = 1 << iota + haveData32 + haveAddr16 + haveAddr32 + haveXacquire + haveXrelease + haveLock + haveHintTaken + haveHintNotTaken + haveBnd + ) + var prefixBits uint32 + prefix := "" + for _, p := range inst.Prefix { + if p == 0 { + break + } + if p&0xFF == 0xF3 { + prefixBits &^= haveBnd + } + if p&(PrefixImplicit|PrefixIgnored) != 0 { + continue + } + switch p { + default: + prefix += strings.ToLower(p.String()) + " " + case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS: + if inst.Op == 0 { + prefix += strings.ToLower(p.String()) + " " + } + case PrefixREPN: + prefix += "repne " + case PrefixLOCK: + prefixBits |= haveLock + case PrefixData16, PrefixDataSize: + prefixBits |= haveData16 + case PrefixData32: + prefixBits |= haveData32 + case PrefixAddrSize, PrefixAddr16: + prefixBits |= haveAddr16 + case PrefixAddr32: + prefixBits |= haveAddr32 + case PrefixXACQUIRE: + prefixBits |= haveXacquire + case PrefixXRELEASE: + prefixBits |= haveXrelease + case PrefixPT: + prefixBits |= haveHintTaken + case PrefixPN: + prefixBits |= haveHintNotTaken + case PrefixBND: + prefixBits |= haveBnd + } + } + switch inst.Op { + case JMP: + if inst.Opcode>>24 == 0xEB { + prefixBits &^= haveBnd + } + case RET, LRET: + prefixBits &^= haveData16 | haveData32 + } + + if prefixBits&haveXacquire != 0 { + prefix += "xacquire " + } + if prefixBits&haveXrelease != 0 { + prefix += "xrelease " + } + if prefixBits&haveLock != 0 { + prefix += "lock " + } + if prefixBits&haveBnd != 0 { + prefix += "bnd " + } + if prefixBits&haveHintTaken != 0 { + prefix += "hint-taken " + } + if prefixBits&haveHintNotTaken != 0 { + prefix += "hint-not-taken " + } + if prefixBits&haveAddr16 != 0 { + prefix += "addr16 " + } + if prefixBits&haveAddr32 != 0 { + prefix += "addr32 " + } + if prefixBits&haveData16 != 0 { + prefix += "data16 " + } + if prefixBits&haveData32 != 0 { + prefix += "data32 " + } + + if inst.Op == 0 { + if prefix == "" { + return "" + } + return prefix[:len(prefix)-1] + } + + var args []string + for _, a := range iargs { + if a == nil { + break + } + args = append(args, intelArg(&inst, a)) + } + + var op string + switch inst.Op { + case NOP: + if inst.Opcode>>24 == 0x0F { + if inst.DataSize == 16 { + args = append(args, "ax") + } else { + args = append(args, "eax") + } + } + + case BLENDVPD, BLENDVPS, PBLENDVB: + args = args[:2] + + case INT: + if inst.Opcode>>24 == 0xCC { + args = nil + op = "int3" + } + + case LCALL, LJMP: + if len(args) == 2 { + args[0], args[1] = args[1], args[0] + } + + case FCHS, FABS, FTST, FLDPI, FLDL2E, FLDLG2, F2XM1, FXAM, FLD1, FLDL2T, FSQRT, FRNDINT, FCOS, FSIN: + if len(args) == 0 { + args = append(args, "st0") + } + + case FPTAN, FSINCOS, FUCOMPP, FCOMPP, FYL2X, FPATAN, FXTRACT, FPREM1, FPREM, FYL2XP1, FSCALE: + if len(args) == 0 { + args = []string{"st0", "st1"} + } + + case FST, FSTP, FISTTP, FIST, FISTP, FBSTP: + if len(args) == 1 { + args = append(args, "st0") + } + + case FLD, FXCH, FCOM, FCOMP, FIADD, FIMUL, FICOM, FICOMP, FISUBR, FIDIV, FUCOM, FUCOMP, FILD, FBLD, FADD, FMUL, FSUB, FSUBR, FISUB, FDIV, FDIVR, FIDIVR: + if len(args) == 1 { + args = []string{"st0", args[0]} + } + + case MASKMOVDQU, MASKMOVQ, XLATB, OUTSB, OUTSW, OUTSD: + FixSegment: + for i := len(inst.Prefix) - 1; i >= 0; i-- { + p := inst.Prefix[i] & 0xFF + switch p { + case PrefixCS, PrefixES, PrefixFS, PrefixGS, PrefixSS: + if inst.Mode != 64 || p == PrefixFS || p == PrefixGS { + args = append(args, strings.ToLower((inst.Prefix[i] & 0xFF).String())) + break FixSegment + } + case PrefixDS: + if inst.Mode != 64 { + break FixSegment + } + } + } + } + + if op == "" { + op = intelOp[inst.Op] + } + if op == "" { + op = strings.ToLower(inst.Op.String()) + } + if args != nil { + op += " " + strings.Join(args, ", ") + } + return prefix + op +} + +func intelArg(inst *Inst, arg Arg) string { + switch a := arg.(type) { + case Imm: + if inst.Mode == 32 { + return fmt.Sprintf("%#x", uint32(a)) + } + if Imm(int32(a)) == a { + return fmt.Sprintf("%#x", int64(a)) + } + return fmt.Sprintf("%#x", uint64(a)) + case Mem: + if a.Base == EIP { + a.Base = RIP + } + prefix := "" + switch inst.MemBytes { + case 1: + prefix = "byte " + case 2: + prefix = "word " + case 4: + prefix = "dword " + case 8: + prefix = "qword " + case 16: + prefix = "xmmword " + } + switch inst.Op { + case INVLPG: + prefix = "byte " + case STOSB, MOVSB, CMPSB, LODSB, SCASB: + prefix = "byte " + case STOSW, MOVSW, CMPSW, LODSW, SCASW: + prefix = "word " + case STOSD, MOVSD, CMPSD, LODSD, SCASD: + prefix = "dword " + case STOSQ, MOVSQ, CMPSQ, LODSQ, SCASQ: + prefix = "qword " + case LAR: + prefix = "word " + case BOUND: + if inst.Mode == 32 { + prefix = "qword " + } else { + prefix = "dword " + } + case PREFETCHW, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, CLFLUSH: + prefix = "zmmword " + } + switch inst.Op { + case MOVSB, MOVSW, MOVSD, MOVSQ, CMPSB, CMPSW, CMPSD, CMPSQ, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ, LODSB, LODSW, LODSD, LODSQ: + switch a.Base { + case DI, EDI, RDI: + if a.Segment == ES { + a.Segment = 0 + } + case SI, ESI, RSI: + if a.Segment == DS { + a.Segment = 0 + } + } + case LEA: + a.Segment = 0 + default: + switch a.Base { + case SP, ESP, RSP, BP, EBP, RBP: + if a.Segment == SS { + a.Segment = 0 + } + default: + if a.Segment == DS { + a.Segment = 0 + } + } + } + + if inst.Mode == 64 && a.Segment != FS && a.Segment != GS { + a.Segment = 0 + } + + prefix += "ptr " + if a.Segment != 0 { + prefix += strings.ToLower(a.Segment.String()) + ":" + } + prefix += "[" + if a.Base != 0 { + prefix += intelArg(inst, a.Base) + } + if a.Scale != 0 && a.Index != 0 { + if a.Base != 0 { + prefix += "+" + } + prefix += fmt.Sprintf("%s*%d", intelArg(inst, a.Index), a.Scale) + } + if a.Disp != 0 { + if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) { + prefix += fmt.Sprintf("%#x", uint64(a.Disp)) + } else { + prefix += fmt.Sprintf("%+#x", a.Disp) + } + } + prefix += "]" + return prefix + case Rel: + return fmt.Sprintf(".%+#x", int64(a)) + case Reg: + if int(a) < len(intelReg) && intelReg[a] != "" { + return intelReg[a] + } + } + return strings.ToLower(arg.String()) +} + +var intelOp = map[Op]string{ + JAE: "jnb", + JA: "jnbe", + JGE: "jnl", + JNE: "jnz", + JG: "jnle", + JE: "jz", + SETAE: "setnb", + SETA: "setnbe", + SETGE: "setnl", + SETNE: "setnz", + SETG: "setnle", + SETE: "setz", + CMOVAE: "cmovnb", + CMOVA: "cmovnbe", + CMOVGE: "cmovnl", + CMOVNE: "cmovnz", + CMOVG: "cmovnle", + CMOVE: "cmovz", + LCALL: "call far", + LJMP: "jmp far", + LRET: "ret far", + ICEBP: "int1", + MOVSD_XMM: "movsd", + XLATB: "xlat", +} + +var intelReg = [...]string{ + F0: "st0", + F1: "st1", + F2: "st2", + F3: "st3", + F4: "st4", + F5: "st5", + F6: "st6", + F7: "st7", + M0: "mmx0", + M1: "mmx1", + M2: "mmx2", + M3: "mmx3", + M4: "mmx4", + M5: "mmx5", + M6: "mmx6", + M7: "mmx7", + X0: "xmm0", + X1: "xmm1", + X2: "xmm2", + X3: "xmm3", + X4: "xmm4", + X5: "xmm5", + X6: "xmm6", + X7: "xmm7", + X8: "xmm8", + X9: "xmm9", + X10: "xmm10", + X11: "xmm11", + X12: "xmm12", + X13: "xmm13", + X14: "xmm14", + X15: "xmm15", + + // TODO: Maybe the constants are named wrong. + SPB: "spl", + BPB: "bpl", + SIB: "sil", + DIB: "dil", + + R8L: "r8d", + R9L: "r9d", + R10L: "r10d", + R11L: "r11d", + R12L: "r12d", + R13L: "r13d", + R14L: "r14d", + R15L: "r15d", +} diff --git a/vendor/rsc.io/x86/x86asm/plan9x.go b/vendor/rsc.io/x86/x86asm/plan9x.go new file mode 100644 index 0000000..ccbdea4 --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/plan9x.go @@ -0,0 +1,346 @@ +// Copyright 2014 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 x86asm + +import ( + "fmt" + "strings" +) + +// plan9Syntax returns the Go assembler syntax for the instruction. +// The syntax was originally defined by Plan 9. +// The pc is the program counter of the instruction, used for expanding +// PC-relative addresses into absolute ones. +// The symname function queries the symbol table for the program +// being disassembled. Given a target address it returns the name and base +// address of the symbol containing the target, if any; otherwise it returns "", 0. +func plan9Syntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string { + if symname == nil { + symname = func(uint64) (string, uint64) { return "", 0 } + } + var args []string + for i := len(inst.Args) - 1; i >= 0; i-- { + a := inst.Args[i] + if a == nil { + continue + } + args = append(args, plan9Arg(&inst, pc, symname, a)) + } + + var last Prefix + for _, p := range inst.Prefix { + if p == 0 || p.IsREX() { + break + } + last = p + } + + prefix := "" + switch last & 0xFF { + case 0, 0x66, 0x67: + // ignore + case PrefixREPN: + prefix += "REPNE " + default: + prefix += last.String() + " " + } + + op := inst.Op.String() + if plan9Suffix[inst.Op] { + switch inst.DataSize { + case 8: + op += "B" + case 16: + op += "W" + case 32: + op += "L" + case 64: + op += "Q" + } + } + + if args != nil { + op += " " + strings.Join(args, ", ") + } + + return prefix + op +} + +func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string { + switch a := arg.(type) { + case Reg: + return plan9Reg[a] + case Rel: + if pc == 0 { + break + } + // If the absolute address is the start of a symbol, use the name. + // Otherwise use the raw address, so that things like relative + // jumps show up as JMP 0x123 instead of JMP f+10(SB). + // It is usually easier to search for 0x123 than to do the mental + // arithmetic to find f+10. + addr := pc + uint64(inst.Len) + uint64(a) + if s, base := symname(addr); s != "" && addr == base { + return fmt.Sprintf("%s(SB)", s) + } + return fmt.Sprintf("%#x", addr) + + case Imm: + if s, base := symname(uint64(a)); s != "" { + suffix := "" + if uint64(a) != base { + suffix = fmt.Sprintf("%+d", uint64(a)-base) + } + return fmt.Sprintf("$%s%s(SB)", s, suffix) + } + if inst.Mode == 32 { + return fmt.Sprintf("$%#x", uint32(a)) + } + if Imm(int32(a)) == a { + return fmt.Sprintf("$%#x", int64(a)) + } + return fmt.Sprintf("$%#x", uint64(a)) + case Mem: + if a.Segment == 0 && a.Disp != 0 && a.Base == 0 && (a.Index == 0 || a.Scale == 0) { + if s, base := symname(uint64(a.Disp)); s != "" { + suffix := "" + if uint64(a.Disp) != base { + suffix = fmt.Sprintf("%+d", uint64(a.Disp)-base) + } + return fmt.Sprintf("%s%s(SB)", s, suffix) + } + } + s := "" + if a.Segment != 0 { + s += fmt.Sprintf("%s:", plan9Reg[a.Segment]) + } + if a.Disp != 0 { + s += fmt.Sprintf("%#x", a.Disp) + } else { + s += "0" + } + if a.Base != 0 { + s += fmt.Sprintf("(%s)", plan9Reg[a.Base]) + } + if a.Index != 0 && a.Scale != 0 { + s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale) + } + return s + } + return arg.String() +} + +var plan9Suffix = [maxOp + 1]bool{ + ADC: true, + ADD: true, + AND: true, + BSF: true, + BSR: true, + BT: true, + BTC: true, + BTR: true, + BTS: true, + CMP: true, + CMPXCHG: true, + CVTSI2SD: true, + CVTSI2SS: true, + CVTSD2SI: true, + CVTSS2SI: true, + CVTTSD2SI: true, + CVTTSS2SI: true, + DEC: true, + DIV: true, + FLDENV: true, + FRSTOR: true, + IDIV: true, + IMUL: true, + IN: true, + INC: true, + LEA: true, + MOV: true, + MOVNTI: true, + MUL: true, + NEG: true, + NOP: true, + NOT: true, + OR: true, + OUT: true, + POP: true, + POPA: true, + PUSH: true, + PUSHA: true, + RCL: true, + RCR: true, + ROL: true, + ROR: true, + SAR: true, + SBB: true, + SHL: true, + SHLD: true, + SHR: true, + SHRD: true, + SUB: true, + TEST: true, + XADD: true, + XCHG: true, + XOR: true, +} + +var plan9Reg = [...]string{ + AL: "AL", + CL: "CL", + BL: "BL", + DL: "DL", + AH: "AH", + CH: "CH", + BH: "BH", + DH: "DH", + SPB: "SP", + BPB: "BP", + SIB: "SI", + DIB: "DI", + R8B: "R8", + R9B: "R9", + R10B: "R10", + R11B: "R11", + R12B: "R12", + R13B: "R13", + R14B: "R14", + R15B: "R15", + AX: "AX", + CX: "CX", + BX: "BX", + DX: "DX", + SP: "SP", + BP: "BP", + SI: "SI", + DI: "DI", + R8W: "R8", + R9W: "R9", + R10W: "R10", + R11W: "R11", + R12W: "R12", + R13W: "R13", + R14W: "R14", + R15W: "R15", + EAX: "AX", + ECX: "CX", + EDX: "DX", + EBX: "BX", + ESP: "SP", + EBP: "BP", + ESI: "SI", + EDI: "DI", + R8L: "R8", + R9L: "R9", + R10L: "R10", + R11L: "R11", + R12L: "R12", + R13L: "R13", + R14L: "R14", + R15L: "R15", + RAX: "AX", + RCX: "CX", + RDX: "DX", + RBX: "BX", + RSP: "SP", + RBP: "BP", + RSI: "SI", + RDI: "DI", + R8: "R8", + R9: "R9", + R10: "R10", + R11: "R11", + R12: "R12", + R13: "R13", + R14: "R14", + R15: "R15", + IP: "IP", + EIP: "IP", + RIP: "IP", + F0: "F0", + F1: "F1", + F2: "F2", + F3: "F3", + F4: "F4", + F5: "F5", + F6: "F6", + F7: "F7", + M0: "M0", + M1: "M1", + M2: "M2", + M3: "M3", + M4: "M4", + M5: "M5", + M6: "M6", + M7: "M7", + X0: "X0", + X1: "X1", + X2: "X2", + X3: "X3", + X4: "X4", + X5: "X5", + X6: "X6", + X7: "X7", + X8: "X8", + X9: "X9", + X10: "X10", + X11: "X11", + X12: "X12", + X13: "X13", + X14: "X14", + X15: "X15", + CS: "CS", + SS: "SS", + DS: "DS", + ES: "ES", + FS: "FS", + GS: "GS", + GDTR: "GDTR", + IDTR: "IDTR", + LDTR: "LDTR", + MSW: "MSW", + TASK: "TASK", + CR0: "CR0", + CR1: "CR1", + CR2: "CR2", + CR3: "CR3", + CR4: "CR4", + CR5: "CR5", + CR6: "CR6", + CR7: "CR7", + CR8: "CR8", + CR9: "CR9", + CR10: "CR10", + CR11: "CR11", + CR12: "CR12", + CR13: "CR13", + CR14: "CR14", + CR15: "CR15", + DR0: "DR0", + DR1: "DR1", + DR2: "DR2", + DR3: "DR3", + DR4: "DR4", + DR5: "DR5", + DR6: "DR6", + DR7: "DR7", + DR8: "DR8", + DR9: "DR9", + DR10: "DR10", + DR11: "DR11", + DR12: "DR12", + DR13: "DR13", + DR14: "DR14", + DR15: "DR15", + TR0: "TR0", + TR1: "TR1", + TR2: "TR2", + TR3: "TR3", + TR4: "TR4", + TR5: "TR5", + TR6: "TR6", + TR7: "TR7", +} diff --git a/vendor/rsc.io/x86/x86asm/tables.go b/vendor/rsc.io/x86/x86asm/tables.go new file mode 100644 index 0000000..3d08d5e --- /dev/null +++ b/vendor/rsc.io/x86/x86asm/tables.go @@ -0,0 +1,9760 @@ +// DO NOT EDIT +// generated by: x86map -fmt=decoder ../x86.csv + +package x86asm + +var decoder = [...]uint16{ + uint16(xFail), + /*1*/ uint16(xCondByte), 243, + 0x00, 490, + 0x01, 496, + 0x02, 525, + 0x03, 531, + 0x04, 560, + 0x05, 566, + 0x06, 595, + 0x07, 602, + 0x08, 609, + 0x09, 615, + 0x0A, 644, + 0x0B, 650, + 0x0C, 679, + 0x0D, 685, + 0x0E, 714, + 0x0F, 721, + 0x10, 8026, + 0x11, 8032, + 0x12, 8061, + 0x13, 8067, + 0x14, 8096, + 0x15, 8102, + 0x16, 8131, + 0x17, 8138, + 0x18, 8145, + 0x19, 8151, + 0x1A, 8180, + 0x1B, 8186, + 0x1C, 8215, + 0x1D, 8221, + 0x1E, 8250, + 0x1F, 8257, + 0x20, 8264, + 0x21, 8270, + 0x22, 8299, + 0x23, 8305, + 0x24, 8334, + 0x25, 8340, + 0x27, 8369, + 0x28, 8375, + 0x29, 8381, + 0x2A, 8410, + 0x2B, 8416, + 0x2C, 8445, + 0x2D, 8451, + 0x2F, 8480, + 0x30, 8486, + 0x31, 8492, + 0x32, 8521, + 0x33, 8527, + 0x34, 8556, + 0x35, 8562, + 0x37, 8591, + 0x38, 8597, + 0x39, 8603, + 0x3A, 8632, + 0x3B, 8638, + 0x3C, 8667, + 0x3D, 8673, + 0x3F, 8702, + 0x40, 8708, + 0x41, 8708, + 0x42, 8708, + 0x43, 8708, + 0x44, 8708, + 0x45, 8708, + 0x46, 8708, + 0x47, 8708, + 0x48, 8723, + 0x49, 8723, + 0x4a, 8723, + 0x4b, 8723, + 0x4c, 8723, + 0x4d, 8723, + 0x4e, 8723, + 0x4f, 8723, + 0x50, 8738, + 0x51, 8738, + 0x52, 8738, + 0x53, 8738, + 0x54, 8738, + 0x55, 8738, + 0x56, 8738, + 0x57, 8738, + 0x58, 8765, + 0x59, 8765, + 0x5a, 8765, + 0x5b, 8765, + 0x5c, 8765, + 0x5d, 8765, + 0x5e, 8765, + 0x5f, 8765, + 0x60, 8792, + 0x61, 8805, + 0x62, 8818, + 0x63, 8837, + 0x68, 8868, + 0x69, 8887, + 0x6A, 8922, + 0x6B, 8927, + 0x6C, 8962, + 0x6D, 8965, + 0x6E, 8978, + 0x6F, 8981, + 0x70, 8994, + 0x71, 8999, + 0x72, 9004, + 0x73, 9009, + 0x74, 9014, + 0x75, 9019, + 0x76, 9024, + 0x77, 9029, + 0x78, 9034, + 0x79, 9039, + 0x7A, 9044, + 0x7B, 9049, + 0x7C, 9054, + 0x7D, 9059, + 0x7E, 9064, + 0x7F, 9069, + 0x80, 9074, + 0x81, 9131, + 0x83, 9372, + 0x84, 9613, + 0x85, 9619, + 0x86, 9648, + 0x87, 9654, + 0x88, 9683, + 0x89, 9689, + 0x8A, 9711, + 0x8B, 9717, + 0x8C, 9739, + 0x8D, 9768, + 0x8E, 9797, + 0x8F, 9826, + 0x90, 9862, + 0x91, 9862, + 0x92, 9862, + 0x93, 9862, + 0x94, 9862, + 0x95, 9862, + 0x96, 9862, + 0x97, 9862, + 0x98, 9888, + 0x99, 9908, + 0x9A, 9928, + 0x9B, 9945, + 0x9C, 9948, + 0x9D, 9971, + 0x9E, 9994, + 0x9F, 9997, + 0xA0, 10000, + 0xA1, 10019, + 0xA2, 10041, + 0xA3, 10060, + 0xA4, 10082, + 0xA5, 10085, + 0xA6, 10105, + 0xA7, 10108, + 0xA8, 10128, + 0xA9, 10134, + 0xAA, 10163, + 0xAB, 10166, + 0xAC, 10186, + 0xAD, 10189, + 0xAE, 10209, + 0xAF, 10212, + 0xb0, 10232, + 0xb1, 10232, + 0xb2, 10232, + 0xb3, 10232, + 0xb4, 10232, + 0xb5, 10232, + 0xb6, 10232, + 0xb7, 10232, + 0xb8, 10238, + 0xb9, 10238, + 0xba, 10238, + 0xbb, 10238, + 0xbc, 10238, + 0xbd, 10238, + 0xbe, 10238, + 0xbf, 10238, + 0xC0, 10267, + 0xC1, 10318, + 0xC2, 10516, + 0xC3, 10521, + 0xC4, 10524, + 0xC5, 10543, + 0xC6, 10562, + 0xC7, 10586, + 0xC8, 10647, + 0xC9, 10654, + 0xCA, 10677, + 0xCB, 10682, + 0xCC, 10685, + 0xCD, 10689, + 0xCE, 10694, + 0xCF, 10700, + 0xD0, 10720, + 0xD1, 10764, + 0xD2, 10955, + 0xD3, 10999, + 0xD4, 11190, + 0xD5, 11198, + 0xD7, 11206, + 0xD8, 11219, + 0xD9, 11428, + 0xDA, 11637, + 0xDB, 11769, + 0xDC, 11940, + 0xDD, 12109, + 0xDE, 12248, + 0xDF, 12422, + 0xE0, 12533, + 0xE1, 12538, + 0xE2, 12543, + 0xE3, 12548, + 0xE4, 12574, + 0xE5, 12580, + 0xE6, 12602, + 0xE7, 12608, + 0xE8, 12630, + 0xE9, 12661, + 0xEA, 12692, + 0xEB, 12709, + 0xEC, 12714, + 0xED, 12719, + 0xEE, 12738, + 0xEF, 12743, + 0xF1, 12762, + 0xF4, 12765, + 0xF5, 12768, + 0xF6, 12771, + 0xF7, 12810, + 0xF8, 12986, + 0xF9, 12989, + 0xFA, 12992, + 0xFB, 12995, + 0xFC, 12998, + 0xFD, 13001, + 0xFE, 13004, + 0xFF, 13021, + uint16(xFail), + /*490*/ uint16(xSetOp), uint16(ADD), + /*492*/ uint16(xReadSlashR), + /*493*/ uint16(xArgRM8), + /*494*/ uint16(xArgR8), + /*495*/ uint16(xMatch), + /*496*/ uint16(xCondIs64), 499, 515, + /*499*/ uint16(xCondDataSize), 503, 509, 0, + /*503*/ uint16(xSetOp), uint16(ADD), + /*505*/ uint16(xReadSlashR), + /*506*/ uint16(xArgRM16), + /*507*/ uint16(xArgR16), + /*508*/ uint16(xMatch), + /*509*/ uint16(xSetOp), uint16(ADD), + /*511*/ uint16(xReadSlashR), + /*512*/ uint16(xArgRM32), + /*513*/ uint16(xArgR32), + /*514*/ uint16(xMatch), + /*515*/ uint16(xCondDataSize), 503, 509, 519, + /*519*/ uint16(xSetOp), uint16(ADD), + /*521*/ uint16(xReadSlashR), + /*522*/ uint16(xArgRM64), + /*523*/ uint16(xArgR64), + /*524*/ uint16(xMatch), + /*525*/ uint16(xSetOp), uint16(ADD), + /*527*/ uint16(xReadSlashR), + /*528*/ uint16(xArgR8), + /*529*/ uint16(xArgRM8), + /*530*/ uint16(xMatch), + /*531*/ uint16(xCondIs64), 534, 550, + /*534*/ uint16(xCondDataSize), 538, 544, 0, + /*538*/ uint16(xSetOp), uint16(ADD), + /*540*/ uint16(xReadSlashR), + /*541*/ uint16(xArgR16), + /*542*/ uint16(xArgRM16), + /*543*/ uint16(xMatch), + /*544*/ uint16(xSetOp), uint16(ADD), + /*546*/ uint16(xReadSlashR), + /*547*/ uint16(xArgR32), + /*548*/ uint16(xArgRM32), + /*549*/ uint16(xMatch), + /*550*/ uint16(xCondDataSize), 538, 544, 554, + /*554*/ uint16(xSetOp), uint16(ADD), + /*556*/ uint16(xReadSlashR), + /*557*/ uint16(xArgR64), + /*558*/ uint16(xArgRM64), + /*559*/ uint16(xMatch), + /*560*/ uint16(xSetOp), uint16(ADD), + /*562*/ uint16(xReadIb), + /*563*/ uint16(xArgAL), + /*564*/ uint16(xArgImm8u), + /*565*/ uint16(xMatch), + /*566*/ uint16(xCondIs64), 569, 585, + /*569*/ uint16(xCondDataSize), 573, 579, 0, + /*573*/ uint16(xSetOp), uint16(ADD), + /*575*/ uint16(xReadIw), + /*576*/ uint16(xArgAX), + /*577*/ uint16(xArgImm16), + /*578*/ uint16(xMatch), + /*579*/ uint16(xSetOp), uint16(ADD), + /*581*/ uint16(xReadId), + /*582*/ uint16(xArgEAX), + /*583*/ uint16(xArgImm32), + /*584*/ uint16(xMatch), + /*585*/ uint16(xCondDataSize), 573, 579, 589, + /*589*/ uint16(xSetOp), uint16(ADD), + /*591*/ uint16(xReadId), + /*592*/ uint16(xArgRAX), + /*593*/ uint16(xArgImm32), + /*594*/ uint16(xMatch), + /*595*/ uint16(xCondIs64), 598, 0, + /*598*/ uint16(xSetOp), uint16(PUSH), + /*600*/ uint16(xArgES), + /*601*/ uint16(xMatch), + /*602*/ uint16(xCondIs64), 605, 0, + /*605*/ uint16(xSetOp), uint16(POP), + /*607*/ uint16(xArgES), + /*608*/ uint16(xMatch), + /*609*/ uint16(xSetOp), uint16(OR), + /*611*/ uint16(xReadSlashR), + /*612*/ uint16(xArgRM8), + /*613*/ uint16(xArgR8), + /*614*/ uint16(xMatch), + /*615*/ uint16(xCondIs64), 618, 634, + /*618*/ uint16(xCondDataSize), 622, 628, 0, + /*622*/ uint16(xSetOp), uint16(OR), + /*624*/ uint16(xReadSlashR), + /*625*/ uint16(xArgRM16), + /*626*/ uint16(xArgR16), + /*627*/ uint16(xMatch), + /*628*/ uint16(xSetOp), uint16(OR), + /*630*/ uint16(xReadSlashR), + /*631*/ uint16(xArgRM32), + /*632*/ uint16(xArgR32), + /*633*/ uint16(xMatch), + /*634*/ uint16(xCondDataSize), 622, 628, 638, + /*638*/ uint16(xSetOp), uint16(OR), + /*640*/ uint16(xReadSlashR), + /*641*/ uint16(xArgRM64), + /*642*/ uint16(xArgR64), + /*643*/ uint16(xMatch), + /*644*/ uint16(xSetOp), uint16(OR), + /*646*/ uint16(xReadSlashR), + /*647*/ uint16(xArgR8), + /*648*/ uint16(xArgRM8), + /*649*/ uint16(xMatch), + /*650*/ uint16(xCondIs64), 653, 669, + /*653*/ uint16(xCondDataSize), 657, 663, 0, + /*657*/ uint16(xSetOp), uint16(OR), + /*659*/ uint16(xReadSlashR), + /*660*/ uint16(xArgR16), + /*661*/ uint16(xArgRM16), + /*662*/ uint16(xMatch), + /*663*/ uint16(xSetOp), uint16(OR), + /*665*/ uint16(xReadSlashR), + /*666*/ uint16(xArgR32), + /*667*/ uint16(xArgRM32), + /*668*/ uint16(xMatch), + /*669*/ uint16(xCondDataSize), 657, 663, 673, + /*673*/ uint16(xSetOp), uint16(OR), + /*675*/ uint16(xReadSlashR), + /*676*/ uint16(xArgR64), + /*677*/ uint16(xArgRM64), + /*678*/ uint16(xMatch), + /*679*/ uint16(xSetOp), uint16(OR), + /*681*/ uint16(xReadIb), + /*682*/ uint16(xArgAL), + /*683*/ uint16(xArgImm8u), + /*684*/ uint16(xMatch), + /*685*/ uint16(xCondIs64), 688, 704, + /*688*/ uint16(xCondDataSize), 692, 698, 0, + /*692*/ uint16(xSetOp), uint16(OR), + /*694*/ uint16(xReadIw), + /*695*/ uint16(xArgAX), + /*696*/ uint16(xArgImm16), + /*697*/ uint16(xMatch), + /*698*/ uint16(xSetOp), uint16(OR), + /*700*/ uint16(xReadId), + /*701*/ uint16(xArgEAX), + /*702*/ uint16(xArgImm32), + /*703*/ uint16(xMatch), + /*704*/ uint16(xCondDataSize), 692, 698, 708, + /*708*/ uint16(xSetOp), uint16(OR), + /*710*/ uint16(xReadId), + /*711*/ uint16(xArgRAX), + /*712*/ uint16(xArgImm32), + /*713*/ uint16(xMatch), + /*714*/ uint16(xCondIs64), 717, 0, + /*717*/ uint16(xSetOp), uint16(PUSH), + /*719*/ uint16(xArgCS), + /*720*/ uint16(xMatch), + /*721*/ uint16(xCondByte), 228, + 0x00, 1180, + 0x01, 1237, + 0x02, 1345, + 0x03, 1367, + 0x05, 1389, + 0x06, 1395, + 0x07, 1398, + 0x08, 1404, + 0x09, 1407, + 0x0B, 1410, + 0x0D, 1413, + 0x10, 1426, + 0x11, 1460, + 0x12, 1494, + 0x13, 1537, + 0x14, 1555, + 0x15, 1573, + 0x16, 1591, + 0x17, 1626, + 0x18, 1644, + 0x1F, 1669, + 0x20, 1690, + 0x21, 1705, + 0x22, 1720, + 0x23, 1735, + 0x24, 1750, + 0x26, 1765, + 0x28, 1780, + 0x29, 1798, + 0x2A, 1816, + 0x2B, 1903, + 0x2C, 1937, + 0x2D, 2024, + 0x2E, 2111, + 0x2F, 2129, + 0x30, 2147, + 0x31, 2150, + 0x32, 2153, + 0x33, 2156, + 0x34, 2159, + 0x35, 2162, + 0x38, 2172, + 0x3A, 3073, + 0x40, 3484, + 0x41, 3513, + 0x42, 3542, + 0x43, 3571, + 0x44, 3600, + 0x45, 3629, + 0x46, 3658, + 0x47, 3687, + 0x48, 3716, + 0x49, 3745, + 0x4A, 3774, + 0x4B, 3803, + 0x4C, 3832, + 0x4D, 3861, + 0x4E, 3890, + 0x4F, 3919, + 0x50, 3948, + 0x51, 3966, + 0x52, 4000, + 0x53, 4018, + 0x54, 4036, + 0x55, 4054, + 0x56, 4072, + 0x57, 4090, + 0x58, 4108, + 0x59, 4142, + 0x5A, 4176, + 0x5B, 4210, + 0x5C, 4236, + 0x5D, 4270, + 0x5E, 4304, + 0x5F, 4338, + 0x60, 4372, + 0x61, 4390, + 0x62, 4408, + 0x63, 4426, + 0x64, 4444, + 0x65, 4462, + 0x66, 4480, + 0x67, 4498, + 0x68, 4516, + 0x69, 4534, + 0x6A, 4552, + 0x6B, 4570, + 0x6C, 4588, + 0x6D, 4598, + 0x6E, 4608, + 0x6F, 4675, + 0x70, 4701, + 0x71, 4743, + 0x72, 4806, + 0x73, 4869, + 0x74, 4934, + 0x75, 4952, + 0x76, 4970, + 0x77, 4988, + 0x7C, 4991, + 0x7D, 5009, + 0x7E, 5027, + 0x7F, 5104, + 0x80, 5130, + 0x81, 5161, + 0x82, 5192, + 0x83, 5223, + 0x84, 5254, + 0x85, 5285, + 0x86, 5316, + 0x87, 5347, + 0x88, 5378, + 0x89, 5409, + 0x8A, 5440, + 0x8B, 5471, + 0x8C, 5502, + 0x8D, 5533, + 0x8E, 5564, + 0x8F, 5595, + 0x90, 5626, + 0x91, 5631, + 0x92, 5636, + 0x93, 5641, + 0x94, 5646, + 0x95, 5651, + 0x96, 5656, + 0x97, 5661, + 0x98, 5666, + 0x99, 5671, + 0x9A, 5676, + 0x9B, 5681, + 0x9C, 5686, + 0x9D, 5691, + 0x9E, 5696, + 0x9F, 5701, + 0xA0, 5706, + 0xA1, 5710, + 0xA2, 5737, + 0xA3, 5740, + 0xA4, 5769, + 0xA5, 5804, + 0xA8, 5836, + 0xA9, 5840, + 0xAA, 5867, + 0xAB, 5870, + 0xAC, 5899, + 0xAD, 5934, + 0xAE, 5966, + 0xAF, 6224, + 0xB0, 6253, + 0xB1, 6259, + 0xB2, 6288, + 0xB3, 6317, + 0xB4, 6346, + 0xB5, 6375, + 0xB6, 6404, + 0xB7, 6433, + 0xB8, 6462, + 0xB9, 6499, + 0xBA, 6502, + 0xBB, 6627, + 0xBC, 6656, + 0xBD, 6723, + 0xBE, 6790, + 0xBF, 6819, + 0xC0, 6848, + 0xC1, 6854, + 0xC2, 6883, + 0xC3, 6925, + 0xC4, 6954, + 0xC5, 6976, + 0xC6, 6998, + 0xC7, 7020, + 0xc8, 7149, + 0xc9, 7149, + 0xca, 7149, + 0xcb, 7149, + 0xcc, 7149, + 0xcd, 7149, + 0xce, 7149, + 0xcf, 7149, + 0xD0, 7172, + 0xD1, 7190, + 0xD2, 7208, + 0xD3, 7226, + 0xD4, 7244, + 0xD5, 7262, + 0xD6, 7280, + 0xD7, 7306, + 0xD8, 7324, + 0xD9, 7342, + 0xDA, 7360, + 0xDB, 7378, + 0xDC, 7396, + 0xDD, 7414, + 0xDE, 7432, + 0xDF, 7450, + 0xE0, 7468, + 0xE1, 7486, + 0xE2, 7504, + 0xE3, 7522, + 0xE4, 7540, + 0xE5, 7558, + 0xE6, 7576, + 0xE7, 7602, + 0xE8, 7620, + 0xE9, 7638, + 0xEA, 7656, + 0xEB, 7674, + 0xEC, 7692, + 0xED, 7710, + 0xEE, 7728, + 0xEF, 7746, + 0xF0, 7764, + 0xF1, 7774, + 0xF2, 7792, + 0xF3, 7810, + 0xF4, 7828, + 0xF5, 7846, + 0xF6, 7864, + 0xF7, 7882, + 0xF8, 7900, + 0xF9, 7918, + 0xFA, 7936, + 0xFB, 7954, + 0xFC, 7972, + 0xFD, 7990, + 0xFE, 8008, + uint16(xFail), + /*1180*/ uint16(xCondSlashR), + 1189, // 0 + 1205, // 1 + 1221, // 2 + 1225, // 3 + 1229, // 4 + 1233, // 5 + 0, // 6 + 0, // 7 + /*1189*/ uint16(xCondDataSize), 1193, 1197, 1201, + /*1193*/ uint16(xSetOp), uint16(SLDT), + /*1195*/ uint16(xArgRM16), + /*1196*/ uint16(xMatch), + /*1197*/ uint16(xSetOp), uint16(SLDT), + /*1199*/ uint16(xArgR32M16), + /*1200*/ uint16(xMatch), + /*1201*/ uint16(xSetOp), uint16(SLDT), + /*1203*/ uint16(xArgR64M16), + /*1204*/ uint16(xMatch), + /*1205*/ uint16(xCondDataSize), 1209, 1213, 1217, + /*1209*/ uint16(xSetOp), uint16(STR), + /*1211*/ uint16(xArgRM16), + /*1212*/ uint16(xMatch), + /*1213*/ uint16(xSetOp), uint16(STR), + /*1215*/ uint16(xArgR32M16), + /*1216*/ uint16(xMatch), + /*1217*/ uint16(xSetOp), uint16(STR), + /*1219*/ uint16(xArgR64M16), + /*1220*/ uint16(xMatch), + /*1221*/ uint16(xSetOp), uint16(LLDT), + /*1223*/ uint16(xArgRM16), + /*1224*/ uint16(xMatch), + /*1225*/ uint16(xSetOp), uint16(LTR), + /*1227*/ uint16(xArgRM16), + /*1228*/ uint16(xMatch), + /*1229*/ uint16(xSetOp), uint16(VERR), + /*1231*/ uint16(xArgRM16), + /*1232*/ uint16(xMatch), + /*1233*/ uint16(xSetOp), uint16(VERW), + /*1235*/ uint16(xArgRM16), + /*1236*/ uint16(xMatch), + /*1237*/ uint16(xCondByte), 8, + 0xC8, 1318, + 0xC9, 1321, + 0xD0, 1324, + 0xD1, 1327, + 0xD5, 1330, + 0xD6, 1333, + 0xF8, 1336, + 0xF9, 1342, + /*1255*/ uint16(xCondSlashR), + 1264, // 0 + 1268, // 1 + 1272, // 2 + 1283, // 3 + 1294, // 4 + 0, // 5 + 1310, // 6 + 1314, // 7 + /*1264*/ uint16(xSetOp), uint16(SGDT), + /*1266*/ uint16(xArgM), + /*1267*/ uint16(xMatch), + /*1268*/ uint16(xSetOp), uint16(SIDT), + /*1270*/ uint16(xArgM), + /*1271*/ uint16(xMatch), + /*1272*/ uint16(xCondIs64), 1275, 1279, + /*1275*/ uint16(xSetOp), uint16(LGDT), + /*1277*/ uint16(xArgM16and32), + /*1278*/ uint16(xMatch), + /*1279*/ uint16(xSetOp), uint16(LGDT), + /*1281*/ uint16(xArgM16and64), + /*1282*/ uint16(xMatch), + /*1283*/ uint16(xCondIs64), 1286, 1290, + /*1286*/ uint16(xSetOp), uint16(LIDT), + /*1288*/ uint16(xArgM16and32), + /*1289*/ uint16(xMatch), + /*1290*/ uint16(xSetOp), uint16(LIDT), + /*1292*/ uint16(xArgM16and64), + /*1293*/ uint16(xMatch), + /*1294*/ uint16(xCondDataSize), 1298, 1302, 1306, + /*1298*/ uint16(xSetOp), uint16(SMSW), + /*1300*/ uint16(xArgRM16), + /*1301*/ uint16(xMatch), + /*1302*/ uint16(xSetOp), uint16(SMSW), + /*1304*/ uint16(xArgR32M16), + /*1305*/ uint16(xMatch), + /*1306*/ uint16(xSetOp), uint16(SMSW), + /*1308*/ uint16(xArgR64M16), + /*1309*/ uint16(xMatch), + /*1310*/ uint16(xSetOp), uint16(LMSW), + /*1312*/ uint16(xArgRM16), + /*1313*/ uint16(xMatch), + /*1314*/ uint16(xSetOp), uint16(INVLPG), + /*1316*/ uint16(xArgM), + /*1317*/ uint16(xMatch), + /*1318*/ uint16(xSetOp), uint16(MONITOR), + /*1320*/ uint16(xMatch), + /*1321*/ uint16(xSetOp), uint16(MWAIT), + /*1323*/ uint16(xMatch), + /*1324*/ uint16(xSetOp), uint16(XGETBV), + /*1326*/ uint16(xMatch), + /*1327*/ uint16(xSetOp), uint16(XSETBV), + /*1329*/ uint16(xMatch), + /*1330*/ uint16(xSetOp), uint16(XEND), + /*1332*/ uint16(xMatch), + /*1333*/ uint16(xSetOp), uint16(XTEST), + /*1335*/ uint16(xMatch), + /*1336*/ uint16(xCondIs64), 0, 1339, + /*1339*/ uint16(xSetOp), uint16(SWAPGS), + /*1341*/ uint16(xMatch), + /*1342*/ uint16(xSetOp), uint16(RDTSCP), + /*1344*/ uint16(xMatch), + /*1345*/ uint16(xCondDataSize), 1349, 1355, 1361, + /*1349*/ uint16(xSetOp), uint16(LAR), + /*1351*/ uint16(xReadSlashR), + /*1352*/ uint16(xArgR16), + /*1353*/ uint16(xArgRM16), + /*1354*/ uint16(xMatch), + /*1355*/ uint16(xSetOp), uint16(LAR), + /*1357*/ uint16(xReadSlashR), + /*1358*/ uint16(xArgR32), + /*1359*/ uint16(xArgR32M16), + /*1360*/ uint16(xMatch), + /*1361*/ uint16(xSetOp), uint16(LAR), + /*1363*/ uint16(xReadSlashR), + /*1364*/ uint16(xArgR64), + /*1365*/ uint16(xArgR64M16), + /*1366*/ uint16(xMatch), + /*1367*/ uint16(xCondDataSize), 1371, 1377, 1383, + /*1371*/ uint16(xSetOp), uint16(LSL), + /*1373*/ uint16(xReadSlashR), + /*1374*/ uint16(xArgR16), + /*1375*/ uint16(xArgRM16), + /*1376*/ uint16(xMatch), + /*1377*/ uint16(xSetOp), uint16(LSL), + /*1379*/ uint16(xReadSlashR), + /*1380*/ uint16(xArgR32), + /*1381*/ uint16(xArgR32M16), + /*1382*/ uint16(xMatch), + /*1383*/ uint16(xSetOp), uint16(LSL), + /*1385*/ uint16(xReadSlashR), + /*1386*/ uint16(xArgR64), + /*1387*/ uint16(xArgR32M16), + /*1388*/ uint16(xMatch), + /*1389*/ uint16(xCondIs64), 0, 1392, + /*1392*/ uint16(xSetOp), uint16(SYSCALL), + /*1394*/ uint16(xMatch), + /*1395*/ uint16(xSetOp), uint16(CLTS), + /*1397*/ uint16(xMatch), + /*1398*/ uint16(xCondIs64), 0, 1401, + /*1401*/ uint16(xSetOp), uint16(SYSRET), + /*1403*/ uint16(xMatch), + /*1404*/ uint16(xSetOp), uint16(INVD), + /*1406*/ uint16(xMatch), + /*1407*/ uint16(xSetOp), uint16(WBINVD), + /*1409*/ uint16(xMatch), + /*1410*/ uint16(xSetOp), uint16(UD2), + /*1412*/ uint16(xMatch), + /*1413*/ uint16(xCondSlashR), + 0, // 0 + 1422, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*1422*/ uint16(xSetOp), uint16(PREFETCHW), + /*1424*/ uint16(xArgM8), + /*1425*/ uint16(xMatch), + /*1426*/ uint16(xCondPrefix), 4, + 0xF3, 1454, + 0xF2, 1448, + 0x66, 1442, + 0x0, 1436, + /*1436*/ uint16(xSetOp), uint16(MOVUPS), + /*1438*/ uint16(xReadSlashR), + /*1439*/ uint16(xArgXmm1), + /*1440*/ uint16(xArgXmm2M128), + /*1441*/ uint16(xMatch), + /*1442*/ uint16(xSetOp), uint16(MOVUPD), + /*1444*/ uint16(xReadSlashR), + /*1445*/ uint16(xArgXmm1), + /*1446*/ uint16(xArgXmm2M128), + /*1447*/ uint16(xMatch), + /*1448*/ uint16(xSetOp), uint16(MOVSD_XMM), + /*1450*/ uint16(xReadSlashR), + /*1451*/ uint16(xArgXmm1), + /*1452*/ uint16(xArgXmm2M64), + /*1453*/ uint16(xMatch), + /*1454*/ uint16(xSetOp), uint16(MOVSS), + /*1456*/ uint16(xReadSlashR), + /*1457*/ uint16(xArgXmm1), + /*1458*/ uint16(xArgXmm2M32), + /*1459*/ uint16(xMatch), + /*1460*/ uint16(xCondPrefix), 4, + 0xF3, 1488, + 0xF2, 1482, + 0x66, 1476, + 0x0, 1470, + /*1470*/ uint16(xSetOp), uint16(MOVUPS), + /*1472*/ uint16(xReadSlashR), + /*1473*/ uint16(xArgXmm2M128), + /*1474*/ uint16(xArgXmm1), + /*1475*/ uint16(xMatch), + /*1476*/ uint16(xSetOp), uint16(MOVUPD), + /*1478*/ uint16(xReadSlashR), + /*1479*/ uint16(xArgXmm2M128), + /*1480*/ uint16(xArgXmm), + /*1481*/ uint16(xMatch), + /*1482*/ uint16(xSetOp), uint16(MOVSD_XMM), + /*1484*/ uint16(xReadSlashR), + /*1485*/ uint16(xArgXmm2M64), + /*1486*/ uint16(xArgXmm1), + /*1487*/ uint16(xMatch), + /*1488*/ uint16(xSetOp), uint16(MOVSS), + /*1490*/ uint16(xReadSlashR), + /*1491*/ uint16(xArgXmm2M32), + /*1492*/ uint16(xArgXmm), + /*1493*/ uint16(xMatch), + /*1494*/ uint16(xCondPrefix), 4, + 0xF3, 1531, + 0xF2, 1525, + 0x66, 1519, + 0x0, 1504, + /*1504*/ uint16(xCondIsMem), 1507, 1513, + /*1507*/ uint16(xSetOp), uint16(MOVHLPS), + /*1509*/ uint16(xReadSlashR), + /*1510*/ uint16(xArgXmm1), + /*1511*/ uint16(xArgXmm2), + /*1512*/ uint16(xMatch), + /*1513*/ uint16(xSetOp), uint16(MOVLPS), + /*1515*/ uint16(xReadSlashR), + /*1516*/ uint16(xArgXmm), + /*1517*/ uint16(xArgM64), + /*1518*/ uint16(xMatch), + /*1519*/ uint16(xSetOp), uint16(MOVLPD), + /*1521*/ uint16(xReadSlashR), + /*1522*/ uint16(xArgXmm), + /*1523*/ uint16(xArgXmm2M64), + /*1524*/ uint16(xMatch), + /*1525*/ uint16(xSetOp), uint16(MOVDDUP), + /*1527*/ uint16(xReadSlashR), + /*1528*/ uint16(xArgXmm1), + /*1529*/ uint16(xArgXmm2M64), + /*1530*/ uint16(xMatch), + /*1531*/ uint16(xSetOp), uint16(MOVSLDUP), + /*1533*/ uint16(xReadSlashR), + /*1534*/ uint16(xArgXmm1), + /*1535*/ uint16(xArgXmm2M128), + /*1536*/ uint16(xMatch), + /*1537*/ uint16(xCondPrefix), 2, + 0x66, 1549, + 0x0, 1543, + /*1543*/ uint16(xSetOp), uint16(MOVLPS), + /*1545*/ uint16(xReadSlashR), + /*1546*/ uint16(xArgM64), + /*1547*/ uint16(xArgXmm), + /*1548*/ uint16(xMatch), + /*1549*/ uint16(xSetOp), uint16(MOVLPD), + /*1551*/ uint16(xReadSlashR), + /*1552*/ uint16(xArgXmm2M64), + /*1553*/ uint16(xArgXmm), + /*1554*/ uint16(xMatch), + /*1555*/ uint16(xCondPrefix), 2, + 0x66, 1567, + 0x0, 1561, + /*1561*/ uint16(xSetOp), uint16(UNPCKLPS), + /*1563*/ uint16(xReadSlashR), + /*1564*/ uint16(xArgXmm1), + /*1565*/ uint16(xArgXmm2M128), + /*1566*/ uint16(xMatch), + /*1567*/ uint16(xSetOp), uint16(UNPCKLPD), + /*1569*/ uint16(xReadSlashR), + /*1570*/ uint16(xArgXmm1), + /*1571*/ uint16(xArgXmm2M128), + /*1572*/ uint16(xMatch), + /*1573*/ uint16(xCondPrefix), 2, + 0x66, 1585, + 0x0, 1579, + /*1579*/ uint16(xSetOp), uint16(UNPCKHPS), + /*1581*/ uint16(xReadSlashR), + /*1582*/ uint16(xArgXmm1), + /*1583*/ uint16(xArgXmm2M128), + /*1584*/ uint16(xMatch), + /*1585*/ uint16(xSetOp), uint16(UNPCKHPD), + /*1587*/ uint16(xReadSlashR), + /*1588*/ uint16(xArgXmm1), + /*1589*/ uint16(xArgXmm2M128), + /*1590*/ uint16(xMatch), + /*1591*/ uint16(xCondPrefix), 3, + 0xF3, 1620, + 0x66, 1614, + 0x0, 1599, + /*1599*/ uint16(xCondIsMem), 1602, 1608, + /*1602*/ uint16(xSetOp), uint16(MOVLHPS), + /*1604*/ uint16(xReadSlashR), + /*1605*/ uint16(xArgXmm1), + /*1606*/ uint16(xArgXmm2), + /*1607*/ uint16(xMatch), + /*1608*/ uint16(xSetOp), uint16(MOVHPS), + /*1610*/ uint16(xReadSlashR), + /*1611*/ uint16(xArgXmm), + /*1612*/ uint16(xArgM64), + /*1613*/ uint16(xMatch), + /*1614*/ uint16(xSetOp), uint16(MOVHPD), + /*1616*/ uint16(xReadSlashR), + /*1617*/ uint16(xArgXmm), + /*1618*/ uint16(xArgXmm2M64), + /*1619*/ uint16(xMatch), + /*1620*/ uint16(xSetOp), uint16(MOVSHDUP), + /*1622*/ uint16(xReadSlashR), + /*1623*/ uint16(xArgXmm1), + /*1624*/ uint16(xArgXmm2M128), + /*1625*/ uint16(xMatch), + /*1626*/ uint16(xCondPrefix), 2, + 0x66, 1638, + 0x0, 1632, + /*1632*/ uint16(xSetOp), uint16(MOVHPS), + /*1634*/ uint16(xReadSlashR), + /*1635*/ uint16(xArgM64), + /*1636*/ uint16(xArgXmm), + /*1637*/ uint16(xMatch), + /*1638*/ uint16(xSetOp), uint16(MOVHPD), + /*1640*/ uint16(xReadSlashR), + /*1641*/ uint16(xArgXmm2M64), + /*1642*/ uint16(xArgXmm), + /*1643*/ uint16(xMatch), + /*1644*/ uint16(xCondSlashR), + 1653, // 0 + 1657, // 1 + 1661, // 2 + 1665, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*1653*/ uint16(xSetOp), uint16(PREFETCHNTA), + /*1655*/ uint16(xArgM8), + /*1656*/ uint16(xMatch), + /*1657*/ uint16(xSetOp), uint16(PREFETCHT0), + /*1659*/ uint16(xArgM8), + /*1660*/ uint16(xMatch), + /*1661*/ uint16(xSetOp), uint16(PREFETCHT1), + /*1663*/ uint16(xArgM8), + /*1664*/ uint16(xMatch), + /*1665*/ uint16(xSetOp), uint16(PREFETCHT2), + /*1667*/ uint16(xArgM8), + /*1668*/ uint16(xMatch), + /*1669*/ uint16(xCondSlashR), + 1678, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*1678*/ uint16(xCondDataSize), 1682, 1686, 0, + /*1682*/ uint16(xSetOp), uint16(NOP), + /*1684*/ uint16(xArgRM16), + /*1685*/ uint16(xMatch), + /*1686*/ uint16(xSetOp), uint16(NOP), + /*1688*/ uint16(xArgRM32), + /*1689*/ uint16(xMatch), + /*1690*/ uint16(xCondIs64), 1693, 1699, + /*1693*/ uint16(xSetOp), uint16(MOV), + /*1695*/ uint16(xReadSlashR), + /*1696*/ uint16(xArgRmf32), + /*1697*/ uint16(xArgCR0dashCR7), + /*1698*/ uint16(xMatch), + /*1699*/ uint16(xSetOp), uint16(MOV), + /*1701*/ uint16(xReadSlashR), + /*1702*/ uint16(xArgRmf64), + /*1703*/ uint16(xArgCR0dashCR7), + /*1704*/ uint16(xMatch), + /*1705*/ uint16(xCondIs64), 1708, 1714, + /*1708*/ uint16(xSetOp), uint16(MOV), + /*1710*/ uint16(xReadSlashR), + /*1711*/ uint16(xArgRmf32), + /*1712*/ uint16(xArgDR0dashDR7), + /*1713*/ uint16(xMatch), + /*1714*/ uint16(xSetOp), uint16(MOV), + /*1716*/ uint16(xReadSlashR), + /*1717*/ uint16(xArgRmf64), + /*1718*/ uint16(xArgDR0dashDR7), + /*1719*/ uint16(xMatch), + /*1720*/ uint16(xCondIs64), 1723, 1729, + /*1723*/ uint16(xSetOp), uint16(MOV), + /*1725*/ uint16(xReadSlashR), + /*1726*/ uint16(xArgCR0dashCR7), + /*1727*/ uint16(xArgRmf32), + /*1728*/ uint16(xMatch), + /*1729*/ uint16(xSetOp), uint16(MOV), + /*1731*/ uint16(xReadSlashR), + /*1732*/ uint16(xArgCR0dashCR7), + /*1733*/ uint16(xArgRmf64), + /*1734*/ uint16(xMatch), + /*1735*/ uint16(xCondIs64), 1738, 1744, + /*1738*/ uint16(xSetOp), uint16(MOV), + /*1740*/ uint16(xReadSlashR), + /*1741*/ uint16(xArgDR0dashDR7), + /*1742*/ uint16(xArgRmf32), + /*1743*/ uint16(xMatch), + /*1744*/ uint16(xSetOp), uint16(MOV), + /*1746*/ uint16(xReadSlashR), + /*1747*/ uint16(xArgDR0dashDR7), + /*1748*/ uint16(xArgRmf64), + /*1749*/ uint16(xMatch), + /*1750*/ uint16(xCondIs64), 1753, 1759, + /*1753*/ uint16(xSetOp), uint16(MOV), + /*1755*/ uint16(xReadSlashR), + /*1756*/ uint16(xArgRmf32), + /*1757*/ uint16(xArgTR0dashTR7), + /*1758*/ uint16(xMatch), + /*1759*/ uint16(xSetOp), uint16(MOV), + /*1761*/ uint16(xReadSlashR), + /*1762*/ uint16(xArgRmf64), + /*1763*/ uint16(xArgTR0dashTR7), + /*1764*/ uint16(xMatch), + /*1765*/ uint16(xCondIs64), 1768, 1774, + /*1768*/ uint16(xSetOp), uint16(MOV), + /*1770*/ uint16(xReadSlashR), + /*1771*/ uint16(xArgTR0dashTR7), + /*1772*/ uint16(xArgRmf32), + /*1773*/ uint16(xMatch), + /*1774*/ uint16(xSetOp), uint16(MOV), + /*1776*/ uint16(xReadSlashR), + /*1777*/ uint16(xArgTR0dashTR7), + /*1778*/ uint16(xArgRmf64), + /*1779*/ uint16(xMatch), + /*1780*/ uint16(xCondPrefix), 2, + 0x66, 1792, + 0x0, 1786, + /*1786*/ uint16(xSetOp), uint16(MOVAPS), + /*1788*/ uint16(xReadSlashR), + /*1789*/ uint16(xArgXmm1), + /*1790*/ uint16(xArgXmm2M128), + /*1791*/ uint16(xMatch), + /*1792*/ uint16(xSetOp), uint16(MOVAPD), + /*1794*/ uint16(xReadSlashR), + /*1795*/ uint16(xArgXmm1), + /*1796*/ uint16(xArgXmm2M128), + /*1797*/ uint16(xMatch), + /*1798*/ uint16(xCondPrefix), 2, + 0x66, 1810, + 0x0, 1804, + /*1804*/ uint16(xSetOp), uint16(MOVAPS), + /*1806*/ uint16(xReadSlashR), + /*1807*/ uint16(xArgXmm2M128), + /*1808*/ uint16(xArgXmm1), + /*1809*/ uint16(xMatch), + /*1810*/ uint16(xSetOp), uint16(MOVAPD), + /*1812*/ uint16(xReadSlashR), + /*1813*/ uint16(xArgXmm2M128), + /*1814*/ uint16(xArgXmm1), + /*1815*/ uint16(xMatch), + /*1816*/ uint16(xCondIs64), 1819, 1873, + /*1819*/ uint16(xCondPrefix), 4, + 0xF3, 1857, + 0xF2, 1841, + 0x66, 1835, + 0x0, 1829, + /*1829*/ uint16(xSetOp), uint16(CVTPI2PS), + /*1831*/ uint16(xReadSlashR), + /*1832*/ uint16(xArgXmm), + /*1833*/ uint16(xArgMmM64), + /*1834*/ uint16(xMatch), + /*1835*/ uint16(xSetOp), uint16(CVTPI2PD), + /*1837*/ uint16(xReadSlashR), + /*1838*/ uint16(xArgXmm), + /*1839*/ uint16(xArgMmM64), + /*1840*/ uint16(xMatch), + /*1841*/ uint16(xCondDataSize), 1845, 1851, 0, + /*1845*/ uint16(xSetOp), uint16(CVTSI2SD), + /*1847*/ uint16(xReadSlashR), + /*1848*/ uint16(xArgXmm), + /*1849*/ uint16(xArgRM32), + /*1850*/ uint16(xMatch), + /*1851*/ uint16(xSetOp), uint16(CVTSI2SD), + /*1853*/ uint16(xReadSlashR), + /*1854*/ uint16(xArgXmm), + /*1855*/ uint16(xArgRM32), + /*1856*/ uint16(xMatch), + /*1857*/ uint16(xCondDataSize), 1861, 1867, 0, + /*1861*/ uint16(xSetOp), uint16(CVTSI2SS), + /*1863*/ uint16(xReadSlashR), + /*1864*/ uint16(xArgXmm), + /*1865*/ uint16(xArgRM32), + /*1866*/ uint16(xMatch), + /*1867*/ uint16(xSetOp), uint16(CVTSI2SS), + /*1869*/ uint16(xReadSlashR), + /*1870*/ uint16(xArgXmm), + /*1871*/ uint16(xArgRM32), + /*1872*/ uint16(xMatch), + /*1873*/ uint16(xCondPrefix), 4, + 0xF3, 1893, + 0xF2, 1883, + 0x66, 1835, + 0x0, 1829, + /*1883*/ uint16(xCondDataSize), 1845, 1851, 1887, + /*1887*/ uint16(xSetOp), uint16(CVTSI2SD), + /*1889*/ uint16(xReadSlashR), + /*1890*/ uint16(xArgXmm), + /*1891*/ uint16(xArgRM64), + /*1892*/ uint16(xMatch), + /*1893*/ uint16(xCondDataSize), 1861, 1867, 1897, + /*1897*/ uint16(xSetOp), uint16(CVTSI2SS), + /*1899*/ uint16(xReadSlashR), + /*1900*/ uint16(xArgXmm), + /*1901*/ uint16(xArgRM64), + /*1902*/ uint16(xMatch), + /*1903*/ uint16(xCondPrefix), 4, + 0xF3, 1931, + 0xF2, 1925, + 0x66, 1919, + 0x0, 1913, + /*1913*/ uint16(xSetOp), uint16(MOVNTPS), + /*1915*/ uint16(xReadSlashR), + /*1916*/ uint16(xArgM128), + /*1917*/ uint16(xArgXmm), + /*1918*/ uint16(xMatch), + /*1919*/ uint16(xSetOp), uint16(MOVNTPD), + /*1921*/ uint16(xReadSlashR), + /*1922*/ uint16(xArgM128), + /*1923*/ uint16(xArgXmm), + /*1924*/ uint16(xMatch), + /*1925*/ uint16(xSetOp), uint16(MOVNTSD), + /*1927*/ uint16(xReadSlashR), + /*1928*/ uint16(xArgM64), + /*1929*/ uint16(xArgXmm), + /*1930*/ uint16(xMatch), + /*1931*/ uint16(xSetOp), uint16(MOVNTSS), + /*1933*/ uint16(xReadSlashR), + /*1934*/ uint16(xArgM32), + /*1935*/ uint16(xArgXmm), + /*1936*/ uint16(xMatch), + /*1937*/ uint16(xCondIs64), 1940, 1994, + /*1940*/ uint16(xCondPrefix), 4, + 0xF3, 1978, + 0xF2, 1962, + 0x66, 1956, + 0x0, 1950, + /*1950*/ uint16(xSetOp), uint16(CVTTPS2PI), + /*1952*/ uint16(xReadSlashR), + /*1953*/ uint16(xArgMm), + /*1954*/ uint16(xArgXmmM64), + /*1955*/ uint16(xMatch), + /*1956*/ uint16(xSetOp), uint16(CVTTPD2PI), + /*1958*/ uint16(xReadSlashR), + /*1959*/ uint16(xArgMm), + /*1960*/ uint16(xArgXmmM128), + /*1961*/ uint16(xMatch), + /*1962*/ uint16(xCondDataSize), 1966, 1972, 0, + /*1966*/ uint16(xSetOp), uint16(CVTTSD2SI), + /*1968*/ uint16(xReadSlashR), + /*1969*/ uint16(xArgR32), + /*1970*/ uint16(xArgXmmM64), + /*1971*/ uint16(xMatch), + /*1972*/ uint16(xSetOp), uint16(CVTTSD2SI), + /*1974*/ uint16(xReadSlashR), + /*1975*/ uint16(xArgR32), + /*1976*/ uint16(xArgXmmM64), + /*1977*/ uint16(xMatch), + /*1978*/ uint16(xCondDataSize), 1982, 1988, 0, + /*1982*/ uint16(xSetOp), uint16(CVTTSS2SI), + /*1984*/ uint16(xReadSlashR), + /*1985*/ uint16(xArgR32), + /*1986*/ uint16(xArgXmmM32), + /*1987*/ uint16(xMatch), + /*1988*/ uint16(xSetOp), uint16(CVTTSS2SI), + /*1990*/ uint16(xReadSlashR), + /*1991*/ uint16(xArgR32), + /*1992*/ uint16(xArgXmmM32), + /*1993*/ uint16(xMatch), + /*1994*/ uint16(xCondPrefix), 4, + 0xF3, 2014, + 0xF2, 2004, + 0x66, 1956, + 0x0, 1950, + /*2004*/ uint16(xCondDataSize), 1966, 1972, 2008, + /*2008*/ uint16(xSetOp), uint16(CVTTSD2SI), + /*2010*/ uint16(xReadSlashR), + /*2011*/ uint16(xArgR64), + /*2012*/ uint16(xArgXmmM64), + /*2013*/ uint16(xMatch), + /*2014*/ uint16(xCondDataSize), 1982, 1988, 2018, + /*2018*/ uint16(xSetOp), uint16(CVTTSS2SI), + /*2020*/ uint16(xReadSlashR), + /*2021*/ uint16(xArgR64), + /*2022*/ uint16(xArgXmmM32), + /*2023*/ uint16(xMatch), + /*2024*/ uint16(xCondIs64), 2027, 2081, + /*2027*/ uint16(xCondPrefix), 4, + 0xF3, 2065, + 0xF2, 2049, + 0x66, 2043, + 0x0, 2037, + /*2037*/ uint16(xSetOp), uint16(CVTPS2PI), + /*2039*/ uint16(xReadSlashR), + /*2040*/ uint16(xArgMm), + /*2041*/ uint16(xArgXmmM64), + /*2042*/ uint16(xMatch), + /*2043*/ uint16(xSetOp), uint16(CVTPD2PI), + /*2045*/ uint16(xReadSlashR), + /*2046*/ uint16(xArgMm), + /*2047*/ uint16(xArgXmmM128), + /*2048*/ uint16(xMatch), + /*2049*/ uint16(xCondDataSize), 2053, 2059, 0, + /*2053*/ uint16(xSetOp), uint16(CVTSD2SI), + /*2055*/ uint16(xReadSlashR), + /*2056*/ uint16(xArgR32), + /*2057*/ uint16(xArgXmmM64), + /*2058*/ uint16(xMatch), + /*2059*/ uint16(xSetOp), uint16(CVTSD2SI), + /*2061*/ uint16(xReadSlashR), + /*2062*/ uint16(xArgR32), + /*2063*/ uint16(xArgXmmM64), + /*2064*/ uint16(xMatch), + /*2065*/ uint16(xCondDataSize), 2069, 2075, 0, + /*2069*/ uint16(xSetOp), uint16(CVTSS2SI), + /*2071*/ uint16(xReadSlashR), + /*2072*/ uint16(xArgR32), + /*2073*/ uint16(xArgXmmM32), + /*2074*/ uint16(xMatch), + /*2075*/ uint16(xSetOp), uint16(CVTSS2SI), + /*2077*/ uint16(xReadSlashR), + /*2078*/ uint16(xArgR32), + /*2079*/ uint16(xArgXmmM32), + /*2080*/ uint16(xMatch), + /*2081*/ uint16(xCondPrefix), 4, + 0xF3, 2101, + 0xF2, 2091, + 0x66, 2043, + 0x0, 2037, + /*2091*/ uint16(xCondDataSize), 2053, 2059, 2095, + /*2095*/ uint16(xSetOp), uint16(CVTSD2SI), + /*2097*/ uint16(xReadSlashR), + /*2098*/ uint16(xArgR64), + /*2099*/ uint16(xArgXmmM64), + /*2100*/ uint16(xMatch), + /*2101*/ uint16(xCondDataSize), 2069, 2075, 2105, + /*2105*/ uint16(xSetOp), uint16(CVTSS2SI), + /*2107*/ uint16(xReadSlashR), + /*2108*/ uint16(xArgR64), + /*2109*/ uint16(xArgXmmM32), + /*2110*/ uint16(xMatch), + /*2111*/ uint16(xCondPrefix), 2, + 0x66, 2123, + 0x0, 2117, + /*2117*/ uint16(xSetOp), uint16(UCOMISS), + /*2119*/ uint16(xReadSlashR), + /*2120*/ uint16(xArgXmm1), + /*2121*/ uint16(xArgXmm2M32), + /*2122*/ uint16(xMatch), + /*2123*/ uint16(xSetOp), uint16(UCOMISD), + /*2125*/ uint16(xReadSlashR), + /*2126*/ uint16(xArgXmm1), + /*2127*/ uint16(xArgXmm2M64), + /*2128*/ uint16(xMatch), + /*2129*/ uint16(xCondPrefix), 2, + 0x66, 2141, + 0x0, 2135, + /*2135*/ uint16(xSetOp), uint16(COMISS), + /*2137*/ uint16(xReadSlashR), + /*2138*/ uint16(xArgXmm1), + /*2139*/ uint16(xArgXmm2M32), + /*2140*/ uint16(xMatch), + /*2141*/ uint16(xSetOp), uint16(COMISD), + /*2143*/ uint16(xReadSlashR), + /*2144*/ uint16(xArgXmm1), + /*2145*/ uint16(xArgXmm2M64), + /*2146*/ uint16(xMatch), + /*2147*/ uint16(xSetOp), uint16(WRMSR), + /*2149*/ uint16(xMatch), + /*2150*/ uint16(xSetOp), uint16(RDTSC), + /*2152*/ uint16(xMatch), + /*2153*/ uint16(xSetOp), uint16(RDMSR), + /*2155*/ uint16(xMatch), + /*2156*/ uint16(xSetOp), uint16(RDPMC), + /*2158*/ uint16(xMatch), + /*2159*/ uint16(xSetOp), uint16(SYSENTER), + /*2161*/ uint16(xMatch), + /*2162*/ uint16(xCondDataSize), 2166, 2166, 2169, + /*2166*/ uint16(xSetOp), uint16(SYSEXIT), + /*2168*/ uint16(xMatch), + /*2169*/ uint16(xSetOp), uint16(SYSEXIT), + /*2171*/ uint16(xMatch), + /*2172*/ uint16(xCondByte), 54, + 0x00, 2283, + 0x01, 2301, + 0x02, 2319, + 0x03, 2337, + 0x04, 2355, + 0x05, 2373, + 0x06, 2391, + 0x07, 2409, + 0x08, 2427, + 0x09, 2445, + 0x0A, 2463, + 0x0B, 2481, + 0x10, 2499, + 0x14, 2510, + 0x15, 2521, + 0x17, 2532, + 0x1C, 2542, + 0x1D, 2560, + 0x1E, 2578, + 0x20, 2596, + 0x21, 2606, + 0x22, 2616, + 0x23, 2626, + 0x24, 2636, + 0x25, 2646, + 0x28, 2656, + 0x29, 2666, + 0x2A, 2676, + 0x2B, 2686, + 0x30, 2696, + 0x31, 2706, + 0x32, 2716, + 0x33, 2726, + 0x34, 2736, + 0x35, 2746, + 0x37, 2756, + 0x38, 2766, + 0x39, 2776, + 0x3A, 2786, + 0x3B, 2796, + 0x3C, 2806, + 0x3D, 2816, + 0x3E, 2826, + 0x3F, 2836, + 0x40, 2846, + 0x41, 2856, + 0x82, 2866, + 0xDB, 2889, + 0xDC, 2899, + 0xDD, 2909, + 0xDE, 2919, + 0xDF, 2929, + 0xF0, 2939, + 0xF1, 3006, + uint16(xFail), + /*2283*/ uint16(xCondPrefix), 2, + 0x66, 2295, + 0x0, 2289, + /*2289*/ uint16(xSetOp), uint16(PSHUFB), + /*2291*/ uint16(xReadSlashR), + /*2292*/ uint16(xArgMm1), + /*2293*/ uint16(xArgMm2M64), + /*2294*/ uint16(xMatch), + /*2295*/ uint16(xSetOp), uint16(PSHUFB), + /*2297*/ uint16(xReadSlashR), + /*2298*/ uint16(xArgXmm1), + /*2299*/ uint16(xArgXmm2M128), + /*2300*/ uint16(xMatch), + /*2301*/ uint16(xCondPrefix), 2, + 0x66, 2313, + 0x0, 2307, + /*2307*/ uint16(xSetOp), uint16(PHADDW), + /*2309*/ uint16(xReadSlashR), + /*2310*/ uint16(xArgMm1), + /*2311*/ uint16(xArgMm2M64), + /*2312*/ uint16(xMatch), + /*2313*/ uint16(xSetOp), uint16(PHADDW), + /*2315*/ uint16(xReadSlashR), + /*2316*/ uint16(xArgXmm1), + /*2317*/ uint16(xArgXmm2M128), + /*2318*/ uint16(xMatch), + /*2319*/ uint16(xCondPrefix), 2, + 0x66, 2331, + 0x0, 2325, + /*2325*/ uint16(xSetOp), uint16(PHADDD), + /*2327*/ uint16(xReadSlashR), + /*2328*/ uint16(xArgMm1), + /*2329*/ uint16(xArgMm2M64), + /*2330*/ uint16(xMatch), + /*2331*/ uint16(xSetOp), uint16(PHADDD), + /*2333*/ uint16(xReadSlashR), + /*2334*/ uint16(xArgXmm1), + /*2335*/ uint16(xArgXmm2M128), + /*2336*/ uint16(xMatch), + /*2337*/ uint16(xCondPrefix), 2, + 0x66, 2349, + 0x0, 2343, + /*2343*/ uint16(xSetOp), uint16(PHADDSW), + /*2345*/ uint16(xReadSlashR), + /*2346*/ uint16(xArgMm1), + /*2347*/ uint16(xArgMm2M64), + /*2348*/ uint16(xMatch), + /*2349*/ uint16(xSetOp), uint16(PHADDSW), + /*2351*/ uint16(xReadSlashR), + /*2352*/ uint16(xArgXmm1), + /*2353*/ uint16(xArgXmm2M128), + /*2354*/ uint16(xMatch), + /*2355*/ uint16(xCondPrefix), 2, + 0x66, 2367, + 0x0, 2361, + /*2361*/ uint16(xSetOp), uint16(PMADDUBSW), + /*2363*/ uint16(xReadSlashR), + /*2364*/ uint16(xArgMm1), + /*2365*/ uint16(xArgMm2M64), + /*2366*/ uint16(xMatch), + /*2367*/ uint16(xSetOp), uint16(PMADDUBSW), + /*2369*/ uint16(xReadSlashR), + /*2370*/ uint16(xArgXmm1), + /*2371*/ uint16(xArgXmm2M128), + /*2372*/ uint16(xMatch), + /*2373*/ uint16(xCondPrefix), 2, + 0x66, 2385, + 0x0, 2379, + /*2379*/ uint16(xSetOp), uint16(PHSUBW), + /*2381*/ uint16(xReadSlashR), + /*2382*/ uint16(xArgMm1), + /*2383*/ uint16(xArgMm2M64), + /*2384*/ uint16(xMatch), + /*2385*/ uint16(xSetOp), uint16(PHSUBW), + /*2387*/ uint16(xReadSlashR), + /*2388*/ uint16(xArgXmm1), + /*2389*/ uint16(xArgXmm2M128), + /*2390*/ uint16(xMatch), + /*2391*/ uint16(xCondPrefix), 2, + 0x66, 2403, + 0x0, 2397, + /*2397*/ uint16(xSetOp), uint16(PHSUBD), + /*2399*/ uint16(xReadSlashR), + /*2400*/ uint16(xArgMm1), + /*2401*/ uint16(xArgMm2M64), + /*2402*/ uint16(xMatch), + /*2403*/ uint16(xSetOp), uint16(PHSUBD), + /*2405*/ uint16(xReadSlashR), + /*2406*/ uint16(xArgXmm1), + /*2407*/ uint16(xArgXmm2M128), + /*2408*/ uint16(xMatch), + /*2409*/ uint16(xCondPrefix), 2, + 0x66, 2421, + 0x0, 2415, + /*2415*/ uint16(xSetOp), uint16(PHSUBSW), + /*2417*/ uint16(xReadSlashR), + /*2418*/ uint16(xArgMm1), + /*2419*/ uint16(xArgMm2M64), + /*2420*/ uint16(xMatch), + /*2421*/ uint16(xSetOp), uint16(PHSUBSW), + /*2423*/ uint16(xReadSlashR), + /*2424*/ uint16(xArgXmm1), + /*2425*/ uint16(xArgXmm2M128), + /*2426*/ uint16(xMatch), + /*2427*/ uint16(xCondPrefix), 2, + 0x66, 2439, + 0x0, 2433, + /*2433*/ uint16(xSetOp), uint16(PSIGNB), + /*2435*/ uint16(xReadSlashR), + /*2436*/ uint16(xArgMm1), + /*2437*/ uint16(xArgMm2M64), + /*2438*/ uint16(xMatch), + /*2439*/ uint16(xSetOp), uint16(PSIGNB), + /*2441*/ uint16(xReadSlashR), + /*2442*/ uint16(xArgXmm1), + /*2443*/ uint16(xArgXmm2M128), + /*2444*/ uint16(xMatch), + /*2445*/ uint16(xCondPrefix), 2, + 0x66, 2457, + 0x0, 2451, + /*2451*/ uint16(xSetOp), uint16(PSIGNW), + /*2453*/ uint16(xReadSlashR), + /*2454*/ uint16(xArgMm1), + /*2455*/ uint16(xArgMm2M64), + /*2456*/ uint16(xMatch), + /*2457*/ uint16(xSetOp), uint16(PSIGNW), + /*2459*/ uint16(xReadSlashR), + /*2460*/ uint16(xArgXmm1), + /*2461*/ uint16(xArgXmm2M128), + /*2462*/ uint16(xMatch), + /*2463*/ uint16(xCondPrefix), 2, + 0x66, 2475, + 0x0, 2469, + /*2469*/ uint16(xSetOp), uint16(PSIGND), + /*2471*/ uint16(xReadSlashR), + /*2472*/ uint16(xArgMm1), + /*2473*/ uint16(xArgMm2M64), + /*2474*/ uint16(xMatch), + /*2475*/ uint16(xSetOp), uint16(PSIGND), + /*2477*/ uint16(xReadSlashR), + /*2478*/ uint16(xArgXmm1), + /*2479*/ uint16(xArgXmm2M128), + /*2480*/ uint16(xMatch), + /*2481*/ uint16(xCondPrefix), 2, + 0x66, 2493, + 0x0, 2487, + /*2487*/ uint16(xSetOp), uint16(PMULHRSW), + /*2489*/ uint16(xReadSlashR), + /*2490*/ uint16(xArgMm1), + /*2491*/ uint16(xArgMm2M64), + /*2492*/ uint16(xMatch), + /*2493*/ uint16(xSetOp), uint16(PMULHRSW), + /*2495*/ uint16(xReadSlashR), + /*2496*/ uint16(xArgXmm1), + /*2497*/ uint16(xArgXmm2M128), + /*2498*/ uint16(xMatch), + /*2499*/ uint16(xCondPrefix), 1, + 0x66, 2503, + /*2503*/ uint16(xSetOp), uint16(PBLENDVB), + /*2505*/ uint16(xReadSlashR), + /*2506*/ uint16(xArgXmm1), + /*2507*/ uint16(xArgXmm2M128), + /*2508*/ uint16(xArgXMM0), + /*2509*/ uint16(xMatch), + /*2510*/ uint16(xCondPrefix), 1, + 0x66, 2514, + /*2514*/ uint16(xSetOp), uint16(BLENDVPS), + /*2516*/ uint16(xReadSlashR), + /*2517*/ uint16(xArgXmm1), + /*2518*/ uint16(xArgXmm2M128), + /*2519*/ uint16(xArgXMM0), + /*2520*/ uint16(xMatch), + /*2521*/ uint16(xCondPrefix), 1, + 0x66, 2525, + /*2525*/ uint16(xSetOp), uint16(BLENDVPD), + /*2527*/ uint16(xReadSlashR), + /*2528*/ uint16(xArgXmm1), + /*2529*/ uint16(xArgXmm2M128), + /*2530*/ uint16(xArgXMM0), + /*2531*/ uint16(xMatch), + /*2532*/ uint16(xCondPrefix), 1, + 0x66, 2536, + /*2536*/ uint16(xSetOp), uint16(PTEST), + /*2538*/ uint16(xReadSlashR), + /*2539*/ uint16(xArgXmm1), + /*2540*/ uint16(xArgXmm2M128), + /*2541*/ uint16(xMatch), + /*2542*/ uint16(xCondPrefix), 2, + 0x66, 2554, + 0x0, 2548, + /*2548*/ uint16(xSetOp), uint16(PABSB), + /*2550*/ uint16(xReadSlashR), + /*2551*/ uint16(xArgMm1), + /*2552*/ uint16(xArgMm2M64), + /*2553*/ uint16(xMatch), + /*2554*/ uint16(xSetOp), uint16(PABSB), + /*2556*/ uint16(xReadSlashR), + /*2557*/ uint16(xArgXmm1), + /*2558*/ uint16(xArgXmm2M128), + /*2559*/ uint16(xMatch), + /*2560*/ uint16(xCondPrefix), 2, + 0x66, 2572, + 0x0, 2566, + /*2566*/ uint16(xSetOp), uint16(PABSW), + /*2568*/ uint16(xReadSlashR), + /*2569*/ uint16(xArgMm1), + /*2570*/ uint16(xArgMm2M64), + /*2571*/ uint16(xMatch), + /*2572*/ uint16(xSetOp), uint16(PABSW), + /*2574*/ uint16(xReadSlashR), + /*2575*/ uint16(xArgXmm1), + /*2576*/ uint16(xArgXmm2M128), + /*2577*/ uint16(xMatch), + /*2578*/ uint16(xCondPrefix), 2, + 0x66, 2590, + 0x0, 2584, + /*2584*/ uint16(xSetOp), uint16(PABSD), + /*2586*/ uint16(xReadSlashR), + /*2587*/ uint16(xArgMm1), + /*2588*/ uint16(xArgMm2M64), + /*2589*/ uint16(xMatch), + /*2590*/ uint16(xSetOp), uint16(PABSD), + /*2592*/ uint16(xReadSlashR), + /*2593*/ uint16(xArgXmm1), + /*2594*/ uint16(xArgXmm2M128), + /*2595*/ uint16(xMatch), + /*2596*/ uint16(xCondPrefix), 1, + 0x66, 2600, + /*2600*/ uint16(xSetOp), uint16(PMOVSXBW), + /*2602*/ uint16(xReadSlashR), + /*2603*/ uint16(xArgXmm1), + /*2604*/ uint16(xArgXmm2M64), + /*2605*/ uint16(xMatch), + /*2606*/ uint16(xCondPrefix), 1, + 0x66, 2610, + /*2610*/ uint16(xSetOp), uint16(PMOVSXBD), + /*2612*/ uint16(xReadSlashR), + /*2613*/ uint16(xArgXmm1), + /*2614*/ uint16(xArgXmm2M32), + /*2615*/ uint16(xMatch), + /*2616*/ uint16(xCondPrefix), 1, + 0x66, 2620, + /*2620*/ uint16(xSetOp), uint16(PMOVSXBQ), + /*2622*/ uint16(xReadSlashR), + /*2623*/ uint16(xArgXmm1), + /*2624*/ uint16(xArgXmm2M16), + /*2625*/ uint16(xMatch), + /*2626*/ uint16(xCondPrefix), 1, + 0x66, 2630, + /*2630*/ uint16(xSetOp), uint16(PMOVSXWD), + /*2632*/ uint16(xReadSlashR), + /*2633*/ uint16(xArgXmm1), + /*2634*/ uint16(xArgXmm2M64), + /*2635*/ uint16(xMatch), + /*2636*/ uint16(xCondPrefix), 1, + 0x66, 2640, + /*2640*/ uint16(xSetOp), uint16(PMOVSXWQ), + /*2642*/ uint16(xReadSlashR), + /*2643*/ uint16(xArgXmm1), + /*2644*/ uint16(xArgXmm2M32), + /*2645*/ uint16(xMatch), + /*2646*/ uint16(xCondPrefix), 1, + 0x66, 2650, + /*2650*/ uint16(xSetOp), uint16(PMOVSXDQ), + /*2652*/ uint16(xReadSlashR), + /*2653*/ uint16(xArgXmm1), + /*2654*/ uint16(xArgXmm2M64), + /*2655*/ uint16(xMatch), + /*2656*/ uint16(xCondPrefix), 1, + 0x66, 2660, + /*2660*/ uint16(xSetOp), uint16(PMULDQ), + /*2662*/ uint16(xReadSlashR), + /*2663*/ uint16(xArgXmm1), + /*2664*/ uint16(xArgXmm2M128), + /*2665*/ uint16(xMatch), + /*2666*/ uint16(xCondPrefix), 1, + 0x66, 2670, + /*2670*/ uint16(xSetOp), uint16(PCMPEQQ), + /*2672*/ uint16(xReadSlashR), + /*2673*/ uint16(xArgXmm1), + /*2674*/ uint16(xArgXmm2M128), + /*2675*/ uint16(xMatch), + /*2676*/ uint16(xCondPrefix), 1, + 0x66, 2680, + /*2680*/ uint16(xSetOp), uint16(MOVNTDQA), + /*2682*/ uint16(xReadSlashR), + /*2683*/ uint16(xArgXmm1), + /*2684*/ uint16(xArgM128), + /*2685*/ uint16(xMatch), + /*2686*/ uint16(xCondPrefix), 1, + 0x66, 2690, + /*2690*/ uint16(xSetOp), uint16(PACKUSDW), + /*2692*/ uint16(xReadSlashR), + /*2693*/ uint16(xArgXmm1), + /*2694*/ uint16(xArgXmm2M128), + /*2695*/ uint16(xMatch), + /*2696*/ uint16(xCondPrefix), 1, + 0x66, 2700, + /*2700*/ uint16(xSetOp), uint16(PMOVZXBW), + /*2702*/ uint16(xReadSlashR), + /*2703*/ uint16(xArgXmm1), + /*2704*/ uint16(xArgXmm2M64), + /*2705*/ uint16(xMatch), + /*2706*/ uint16(xCondPrefix), 1, + 0x66, 2710, + /*2710*/ uint16(xSetOp), uint16(PMOVZXBD), + /*2712*/ uint16(xReadSlashR), + /*2713*/ uint16(xArgXmm1), + /*2714*/ uint16(xArgXmm2M32), + /*2715*/ uint16(xMatch), + /*2716*/ uint16(xCondPrefix), 1, + 0x66, 2720, + /*2720*/ uint16(xSetOp), uint16(PMOVZXBQ), + /*2722*/ uint16(xReadSlashR), + /*2723*/ uint16(xArgXmm1), + /*2724*/ uint16(xArgXmm2M16), + /*2725*/ uint16(xMatch), + /*2726*/ uint16(xCondPrefix), 1, + 0x66, 2730, + /*2730*/ uint16(xSetOp), uint16(PMOVZXWD), + /*2732*/ uint16(xReadSlashR), + /*2733*/ uint16(xArgXmm1), + /*2734*/ uint16(xArgXmm2M64), + /*2735*/ uint16(xMatch), + /*2736*/ uint16(xCondPrefix), 1, + 0x66, 2740, + /*2740*/ uint16(xSetOp), uint16(PMOVZXWQ), + /*2742*/ uint16(xReadSlashR), + /*2743*/ uint16(xArgXmm1), + /*2744*/ uint16(xArgXmm2M32), + /*2745*/ uint16(xMatch), + /*2746*/ uint16(xCondPrefix), 1, + 0x66, 2750, + /*2750*/ uint16(xSetOp), uint16(PMOVZXDQ), + /*2752*/ uint16(xReadSlashR), + /*2753*/ uint16(xArgXmm1), + /*2754*/ uint16(xArgXmm2M64), + /*2755*/ uint16(xMatch), + /*2756*/ uint16(xCondPrefix), 1, + 0x66, 2760, + /*2760*/ uint16(xSetOp), uint16(PCMPGTQ), + /*2762*/ uint16(xReadSlashR), + /*2763*/ uint16(xArgXmm1), + /*2764*/ uint16(xArgXmm2M128), + /*2765*/ uint16(xMatch), + /*2766*/ uint16(xCondPrefix), 1, + 0x66, 2770, + /*2770*/ uint16(xSetOp), uint16(PMINSB), + /*2772*/ uint16(xReadSlashR), + /*2773*/ uint16(xArgXmm1), + /*2774*/ uint16(xArgXmm2M128), + /*2775*/ uint16(xMatch), + /*2776*/ uint16(xCondPrefix), 1, + 0x66, 2780, + /*2780*/ uint16(xSetOp), uint16(PMINSD), + /*2782*/ uint16(xReadSlashR), + /*2783*/ uint16(xArgXmm1), + /*2784*/ uint16(xArgXmm2M128), + /*2785*/ uint16(xMatch), + /*2786*/ uint16(xCondPrefix), 1, + 0x66, 2790, + /*2790*/ uint16(xSetOp), uint16(PMINUW), + /*2792*/ uint16(xReadSlashR), + /*2793*/ uint16(xArgXmm1), + /*2794*/ uint16(xArgXmm2M128), + /*2795*/ uint16(xMatch), + /*2796*/ uint16(xCondPrefix), 1, + 0x66, 2800, + /*2800*/ uint16(xSetOp), uint16(PMINUD), + /*2802*/ uint16(xReadSlashR), + /*2803*/ uint16(xArgXmm1), + /*2804*/ uint16(xArgXmm2M128), + /*2805*/ uint16(xMatch), + /*2806*/ uint16(xCondPrefix), 1, + 0x66, 2810, + /*2810*/ uint16(xSetOp), uint16(PMAXSB), + /*2812*/ uint16(xReadSlashR), + /*2813*/ uint16(xArgXmm1), + /*2814*/ uint16(xArgXmm2M128), + /*2815*/ uint16(xMatch), + /*2816*/ uint16(xCondPrefix), 1, + 0x66, 2820, + /*2820*/ uint16(xSetOp), uint16(PMAXSD), + /*2822*/ uint16(xReadSlashR), + /*2823*/ uint16(xArgXmm1), + /*2824*/ uint16(xArgXmm2M128), + /*2825*/ uint16(xMatch), + /*2826*/ uint16(xCondPrefix), 1, + 0x66, 2830, + /*2830*/ uint16(xSetOp), uint16(PMAXUW), + /*2832*/ uint16(xReadSlashR), + /*2833*/ uint16(xArgXmm1), + /*2834*/ uint16(xArgXmm2M128), + /*2835*/ uint16(xMatch), + /*2836*/ uint16(xCondPrefix), 1, + 0x66, 2840, + /*2840*/ uint16(xSetOp), uint16(PMAXUD), + /*2842*/ uint16(xReadSlashR), + /*2843*/ uint16(xArgXmm1), + /*2844*/ uint16(xArgXmm2M128), + /*2845*/ uint16(xMatch), + /*2846*/ uint16(xCondPrefix), 1, + 0x66, 2850, + /*2850*/ uint16(xSetOp), uint16(PMULLD), + /*2852*/ uint16(xReadSlashR), + /*2853*/ uint16(xArgXmm1), + /*2854*/ uint16(xArgXmm2M128), + /*2855*/ uint16(xMatch), + /*2856*/ uint16(xCondPrefix), 1, + 0x66, 2860, + /*2860*/ uint16(xSetOp), uint16(PHMINPOSUW), + /*2862*/ uint16(xReadSlashR), + /*2863*/ uint16(xArgXmm1), + /*2864*/ uint16(xArgXmm2M128), + /*2865*/ uint16(xMatch), + /*2866*/ uint16(xCondIs64), 2869, 2879, + /*2869*/ uint16(xCondPrefix), 1, + 0x66, 2873, + /*2873*/ uint16(xSetOp), uint16(INVPCID), + /*2875*/ uint16(xReadSlashR), + /*2876*/ uint16(xArgR32), + /*2877*/ uint16(xArgM128), + /*2878*/ uint16(xMatch), + /*2879*/ uint16(xCondPrefix), 1, + 0x66, 2883, + /*2883*/ uint16(xSetOp), uint16(INVPCID), + /*2885*/ uint16(xReadSlashR), + /*2886*/ uint16(xArgR64), + /*2887*/ uint16(xArgM128), + /*2888*/ uint16(xMatch), + /*2889*/ uint16(xCondPrefix), 1, + 0x66, 2893, + /*2893*/ uint16(xSetOp), uint16(AESIMC), + /*2895*/ uint16(xReadSlashR), + /*2896*/ uint16(xArgXmm1), + /*2897*/ uint16(xArgXmm2M128), + /*2898*/ uint16(xMatch), + /*2899*/ uint16(xCondPrefix), 1, + 0x66, 2903, + /*2903*/ uint16(xSetOp), uint16(AESENC), + /*2905*/ uint16(xReadSlashR), + /*2906*/ uint16(xArgXmm1), + /*2907*/ uint16(xArgXmm2M128), + /*2908*/ uint16(xMatch), + /*2909*/ uint16(xCondPrefix), 1, + 0x66, 2913, + /*2913*/ uint16(xSetOp), uint16(AESENCLAST), + /*2915*/ uint16(xReadSlashR), + /*2916*/ uint16(xArgXmm1), + /*2917*/ uint16(xArgXmm2M128), + /*2918*/ uint16(xMatch), + /*2919*/ uint16(xCondPrefix), 1, + 0x66, 2923, + /*2923*/ uint16(xSetOp), uint16(AESDEC), + /*2925*/ uint16(xReadSlashR), + /*2926*/ uint16(xArgXmm1), + /*2927*/ uint16(xArgXmm2M128), + /*2928*/ uint16(xMatch), + /*2929*/ uint16(xCondPrefix), 1, + 0x66, 2933, + /*2933*/ uint16(xSetOp), uint16(AESDECLAST), + /*2935*/ uint16(xReadSlashR), + /*2936*/ uint16(xArgXmm1), + /*2937*/ uint16(xArgXmm2M128), + /*2938*/ uint16(xMatch), + /*2939*/ uint16(xCondIs64), 2942, 2980, + /*2942*/ uint16(xCondPrefix), 2, + 0xF2, 2964, + 0x0, 2948, + /*2948*/ uint16(xCondDataSize), 2952, 2958, 0, + /*2952*/ uint16(xSetOp), uint16(MOVBE), + /*2954*/ uint16(xReadSlashR), + /*2955*/ uint16(xArgR16), + /*2956*/ uint16(xArgM16), + /*2957*/ uint16(xMatch), + /*2958*/ uint16(xSetOp), uint16(MOVBE), + /*2960*/ uint16(xReadSlashR), + /*2961*/ uint16(xArgR32), + /*2962*/ uint16(xArgM32), + /*2963*/ uint16(xMatch), + /*2964*/ uint16(xCondDataSize), 2968, 2974, 0, + /*2968*/ uint16(xSetOp), uint16(CRC32), + /*2970*/ uint16(xReadSlashR), + /*2971*/ uint16(xArgR32), + /*2972*/ uint16(xArgRM8), + /*2973*/ uint16(xMatch), + /*2974*/ uint16(xSetOp), uint16(CRC32), + /*2976*/ uint16(xReadSlashR), + /*2977*/ uint16(xArgR32), + /*2978*/ uint16(xArgRM8), + /*2979*/ uint16(xMatch), + /*2980*/ uint16(xCondPrefix), 2, + 0xF2, 2996, + 0x0, 2986, + /*2986*/ uint16(xCondDataSize), 2952, 2958, 2990, + /*2990*/ uint16(xSetOp), uint16(MOVBE), + /*2992*/ uint16(xReadSlashR), + /*2993*/ uint16(xArgR64), + /*2994*/ uint16(xArgM64), + /*2995*/ uint16(xMatch), + /*2996*/ uint16(xCondDataSize), 2968, 2974, 3000, + /*3000*/ uint16(xSetOp), uint16(CRC32), + /*3002*/ uint16(xReadSlashR), + /*3003*/ uint16(xArgR64), + /*3004*/ uint16(xArgRM8), + /*3005*/ uint16(xMatch), + /*3006*/ uint16(xCondIs64), 3009, 3047, + /*3009*/ uint16(xCondPrefix), 2, + 0xF2, 3031, + 0x0, 3015, + /*3015*/ uint16(xCondDataSize), 3019, 3025, 0, + /*3019*/ uint16(xSetOp), uint16(MOVBE), + /*3021*/ uint16(xReadSlashR), + /*3022*/ uint16(xArgM16), + /*3023*/ uint16(xArgR16), + /*3024*/ uint16(xMatch), + /*3025*/ uint16(xSetOp), uint16(MOVBE), + /*3027*/ uint16(xReadSlashR), + /*3028*/ uint16(xArgM32), + /*3029*/ uint16(xArgR32), + /*3030*/ uint16(xMatch), + /*3031*/ uint16(xCondDataSize), 3035, 3041, 0, + /*3035*/ uint16(xSetOp), uint16(CRC32), + /*3037*/ uint16(xReadSlashR), + /*3038*/ uint16(xArgR32), + /*3039*/ uint16(xArgRM16), + /*3040*/ uint16(xMatch), + /*3041*/ uint16(xSetOp), uint16(CRC32), + /*3043*/ uint16(xReadSlashR), + /*3044*/ uint16(xArgR32), + /*3045*/ uint16(xArgRM32), + /*3046*/ uint16(xMatch), + /*3047*/ uint16(xCondPrefix), 2, + 0xF2, 3063, + 0x0, 3053, + /*3053*/ uint16(xCondDataSize), 3019, 3025, 3057, + /*3057*/ uint16(xSetOp), uint16(MOVBE), + /*3059*/ uint16(xReadSlashR), + /*3060*/ uint16(xArgM64), + /*3061*/ uint16(xArgR64), + /*3062*/ uint16(xMatch), + /*3063*/ uint16(xCondDataSize), 3035, 3041, 3067, + /*3067*/ uint16(xSetOp), uint16(CRC32), + /*3069*/ uint16(xReadSlashR), + /*3070*/ uint16(xArgR64), + /*3071*/ uint16(xArgRM64), + /*3072*/ uint16(xMatch), + /*3073*/ uint16(xCondByte), 24, + 0x08, 3124, + 0x09, 3136, + 0x0A, 3148, + 0x0B, 3160, + 0x0C, 3172, + 0x0D, 3184, + 0x0E, 3196, + 0x0F, 3208, + 0x14, 3230, + 0x15, 3242, + 0x16, 3254, + 0x17, 3297, + 0x20, 3309, + 0x21, 3321, + 0x22, 3333, + 0x40, 3376, + 0x41, 3388, + 0x42, 3400, + 0x44, 3412, + 0x60, 3424, + 0x61, 3436, + 0x62, 3448, + 0x63, 3460, + 0xDF, 3472, + uint16(xFail), + /*3124*/ uint16(xCondPrefix), 1, + 0x66, 3128, + /*3128*/ uint16(xSetOp), uint16(ROUNDPS), + /*3130*/ uint16(xReadSlashR), + /*3131*/ uint16(xReadIb), + /*3132*/ uint16(xArgXmm1), + /*3133*/ uint16(xArgXmm2M128), + /*3134*/ uint16(xArgImm8u), + /*3135*/ uint16(xMatch), + /*3136*/ uint16(xCondPrefix), 1, + 0x66, 3140, + /*3140*/ uint16(xSetOp), uint16(ROUNDPD), + /*3142*/ uint16(xReadSlashR), + /*3143*/ uint16(xReadIb), + /*3144*/ uint16(xArgXmm1), + /*3145*/ uint16(xArgXmm2M128), + /*3146*/ uint16(xArgImm8u), + /*3147*/ uint16(xMatch), + /*3148*/ uint16(xCondPrefix), 1, + 0x66, 3152, + /*3152*/ uint16(xSetOp), uint16(ROUNDSS), + /*3154*/ uint16(xReadSlashR), + /*3155*/ uint16(xReadIb), + /*3156*/ uint16(xArgXmm1), + /*3157*/ uint16(xArgXmm2M32), + /*3158*/ uint16(xArgImm8u), + /*3159*/ uint16(xMatch), + /*3160*/ uint16(xCondPrefix), 1, + 0x66, 3164, + /*3164*/ uint16(xSetOp), uint16(ROUNDSD), + /*3166*/ uint16(xReadSlashR), + /*3167*/ uint16(xReadIb), + /*3168*/ uint16(xArgXmm1), + /*3169*/ uint16(xArgXmm2M64), + /*3170*/ uint16(xArgImm8u), + /*3171*/ uint16(xMatch), + /*3172*/ uint16(xCondPrefix), 1, + 0x66, 3176, + /*3176*/ uint16(xSetOp), uint16(BLENDPS), + /*3178*/ uint16(xReadSlashR), + /*3179*/ uint16(xReadIb), + /*3180*/ uint16(xArgXmm1), + /*3181*/ uint16(xArgXmm2M128), + /*3182*/ uint16(xArgImm8u), + /*3183*/ uint16(xMatch), + /*3184*/ uint16(xCondPrefix), 1, + 0x66, 3188, + /*3188*/ uint16(xSetOp), uint16(BLENDPD), + /*3190*/ uint16(xReadSlashR), + /*3191*/ uint16(xReadIb), + /*3192*/ uint16(xArgXmm1), + /*3193*/ uint16(xArgXmm2M128), + /*3194*/ uint16(xArgImm8u), + /*3195*/ uint16(xMatch), + /*3196*/ uint16(xCondPrefix), 1, + 0x66, 3200, + /*3200*/ uint16(xSetOp), uint16(PBLENDW), + /*3202*/ uint16(xReadSlashR), + /*3203*/ uint16(xReadIb), + /*3204*/ uint16(xArgXmm1), + /*3205*/ uint16(xArgXmm2M128), + /*3206*/ uint16(xArgImm8u), + /*3207*/ uint16(xMatch), + /*3208*/ uint16(xCondPrefix), 2, + 0x66, 3222, + 0x0, 3214, + /*3214*/ uint16(xSetOp), uint16(PALIGNR), + /*3216*/ uint16(xReadSlashR), + /*3217*/ uint16(xReadIb), + /*3218*/ uint16(xArgMm1), + /*3219*/ uint16(xArgMm2M64), + /*3220*/ uint16(xArgImm8u), + /*3221*/ uint16(xMatch), + /*3222*/ uint16(xSetOp), uint16(PALIGNR), + /*3224*/ uint16(xReadSlashR), + /*3225*/ uint16(xReadIb), + /*3226*/ uint16(xArgXmm1), + /*3227*/ uint16(xArgXmm2M128), + /*3228*/ uint16(xArgImm8u), + /*3229*/ uint16(xMatch), + /*3230*/ uint16(xCondPrefix), 1, + 0x66, 3234, + /*3234*/ uint16(xSetOp), uint16(PEXTRB), + /*3236*/ uint16(xReadSlashR), + /*3237*/ uint16(xReadIb), + /*3238*/ uint16(xArgR32M8), + /*3239*/ uint16(xArgXmm1), + /*3240*/ uint16(xArgImm8u), + /*3241*/ uint16(xMatch), + /*3242*/ uint16(xCondPrefix), 1, + 0x66, 3246, + /*3246*/ uint16(xSetOp), uint16(PEXTRW), + /*3248*/ uint16(xReadSlashR), + /*3249*/ uint16(xReadIb), + /*3250*/ uint16(xArgR32M16), + /*3251*/ uint16(xArgXmm1), + /*3252*/ uint16(xArgImm8u), + /*3253*/ uint16(xMatch), + /*3254*/ uint16(xCondIs64), 3257, 3281, + /*3257*/ uint16(xCondPrefix), 1, + 0x66, 3261, + /*3261*/ uint16(xCondDataSize), 3265, 3273, 0, + /*3265*/ uint16(xSetOp), uint16(PEXTRD), + /*3267*/ uint16(xReadSlashR), + /*3268*/ uint16(xReadIb), + /*3269*/ uint16(xArgRM32), + /*3270*/ uint16(xArgXmm1), + /*3271*/ uint16(xArgImm8u), + /*3272*/ uint16(xMatch), + /*3273*/ uint16(xSetOp), uint16(PEXTRD), + /*3275*/ uint16(xReadSlashR), + /*3276*/ uint16(xReadIb), + /*3277*/ uint16(xArgRM32), + /*3278*/ uint16(xArgXmm1), + /*3279*/ uint16(xArgImm8u), + /*3280*/ uint16(xMatch), + /*3281*/ uint16(xCondPrefix), 1, + 0x66, 3285, + /*3285*/ uint16(xCondDataSize), 3265, 3273, 3289, + /*3289*/ uint16(xSetOp), uint16(PEXTRQ), + /*3291*/ uint16(xReadSlashR), + /*3292*/ uint16(xReadIb), + /*3293*/ uint16(xArgRM64), + /*3294*/ uint16(xArgXmm1), + /*3295*/ uint16(xArgImm8u), + /*3296*/ uint16(xMatch), + /*3297*/ uint16(xCondPrefix), 1, + 0x66, 3301, + /*3301*/ uint16(xSetOp), uint16(EXTRACTPS), + /*3303*/ uint16(xReadSlashR), + /*3304*/ uint16(xReadIb), + /*3305*/ uint16(xArgRM32), + /*3306*/ uint16(xArgXmm1), + /*3307*/ uint16(xArgImm8u), + /*3308*/ uint16(xMatch), + /*3309*/ uint16(xCondPrefix), 1, + 0x66, 3313, + /*3313*/ uint16(xSetOp), uint16(PINSRB), + /*3315*/ uint16(xReadSlashR), + /*3316*/ uint16(xReadIb), + /*3317*/ uint16(xArgXmm1), + /*3318*/ uint16(xArgR32M8), + /*3319*/ uint16(xArgImm8u), + /*3320*/ uint16(xMatch), + /*3321*/ uint16(xCondPrefix), 1, + 0x66, 3325, + /*3325*/ uint16(xSetOp), uint16(INSERTPS), + /*3327*/ uint16(xReadSlashR), + /*3328*/ uint16(xReadIb), + /*3329*/ uint16(xArgXmm1), + /*3330*/ uint16(xArgXmm2M32), + /*3331*/ uint16(xArgImm8u), + /*3332*/ uint16(xMatch), + /*3333*/ uint16(xCondIs64), 3336, 3360, + /*3336*/ uint16(xCondPrefix), 1, + 0x66, 3340, + /*3340*/ uint16(xCondDataSize), 3344, 3352, 0, + /*3344*/ uint16(xSetOp), uint16(PINSRD), + /*3346*/ uint16(xReadSlashR), + /*3347*/ uint16(xReadIb), + /*3348*/ uint16(xArgXmm1), + /*3349*/ uint16(xArgRM32), + /*3350*/ uint16(xArgImm8u), + /*3351*/ uint16(xMatch), + /*3352*/ uint16(xSetOp), uint16(PINSRD), + /*3354*/ uint16(xReadSlashR), + /*3355*/ uint16(xReadIb), + /*3356*/ uint16(xArgXmm1), + /*3357*/ uint16(xArgRM32), + /*3358*/ uint16(xArgImm8u), + /*3359*/ uint16(xMatch), + /*3360*/ uint16(xCondPrefix), 1, + 0x66, 3364, + /*3364*/ uint16(xCondDataSize), 3344, 3352, 3368, + /*3368*/ uint16(xSetOp), uint16(PINSRQ), + /*3370*/ uint16(xReadSlashR), + /*3371*/ uint16(xReadIb), + /*3372*/ uint16(xArgXmm1), + /*3373*/ uint16(xArgRM64), + /*3374*/ uint16(xArgImm8u), + /*3375*/ uint16(xMatch), + /*3376*/ uint16(xCondPrefix), 1, + 0x66, 3380, + /*3380*/ uint16(xSetOp), uint16(DPPS), + /*3382*/ uint16(xReadSlashR), + /*3383*/ uint16(xReadIb), + /*3384*/ uint16(xArgXmm1), + /*3385*/ uint16(xArgXmm2M128), + /*3386*/ uint16(xArgImm8u), + /*3387*/ uint16(xMatch), + /*3388*/ uint16(xCondPrefix), 1, + 0x66, 3392, + /*3392*/ uint16(xSetOp), uint16(DPPD), + /*3394*/ uint16(xReadSlashR), + /*3395*/ uint16(xReadIb), + /*3396*/ uint16(xArgXmm1), + /*3397*/ uint16(xArgXmm2M128), + /*3398*/ uint16(xArgImm8u), + /*3399*/ uint16(xMatch), + /*3400*/ uint16(xCondPrefix), 1, + 0x66, 3404, + /*3404*/ uint16(xSetOp), uint16(MPSADBW), + /*3406*/ uint16(xReadSlashR), + /*3407*/ uint16(xReadIb), + /*3408*/ uint16(xArgXmm1), + /*3409*/ uint16(xArgXmm2M128), + /*3410*/ uint16(xArgImm8u), + /*3411*/ uint16(xMatch), + /*3412*/ uint16(xCondPrefix), 1, + 0x66, 3416, + /*3416*/ uint16(xSetOp), uint16(PCLMULQDQ), + /*3418*/ uint16(xReadSlashR), + /*3419*/ uint16(xReadIb), + /*3420*/ uint16(xArgXmm1), + /*3421*/ uint16(xArgXmm2M128), + /*3422*/ uint16(xArgImm8u), + /*3423*/ uint16(xMatch), + /*3424*/ uint16(xCondPrefix), 1, + 0x66, 3428, + /*3428*/ uint16(xSetOp), uint16(PCMPESTRM), + /*3430*/ uint16(xReadSlashR), + /*3431*/ uint16(xReadIb), + /*3432*/ uint16(xArgXmm1), + /*3433*/ uint16(xArgXmm2M128), + /*3434*/ uint16(xArgImm8u), + /*3435*/ uint16(xMatch), + /*3436*/ uint16(xCondPrefix), 1, + 0x66, 3440, + /*3440*/ uint16(xSetOp), uint16(PCMPESTRI), + /*3442*/ uint16(xReadSlashR), + /*3443*/ uint16(xReadIb), + /*3444*/ uint16(xArgXmm1), + /*3445*/ uint16(xArgXmm2M128), + /*3446*/ uint16(xArgImm8u), + /*3447*/ uint16(xMatch), + /*3448*/ uint16(xCondPrefix), 1, + 0x66, 3452, + /*3452*/ uint16(xSetOp), uint16(PCMPISTRM), + /*3454*/ uint16(xReadSlashR), + /*3455*/ uint16(xReadIb), + /*3456*/ uint16(xArgXmm1), + /*3457*/ uint16(xArgXmm2M128), + /*3458*/ uint16(xArgImm8u), + /*3459*/ uint16(xMatch), + /*3460*/ uint16(xCondPrefix), 1, + 0x66, 3464, + /*3464*/ uint16(xSetOp), uint16(PCMPISTRI), + /*3466*/ uint16(xReadSlashR), + /*3467*/ uint16(xReadIb), + /*3468*/ uint16(xArgXmm1), + /*3469*/ uint16(xArgXmm2M128), + /*3470*/ uint16(xArgImm8u), + /*3471*/ uint16(xMatch), + /*3472*/ uint16(xCondPrefix), 1, + 0x66, 3476, + /*3476*/ uint16(xSetOp), uint16(AESKEYGENASSIST), + /*3478*/ uint16(xReadSlashR), + /*3479*/ uint16(xReadIb), + /*3480*/ uint16(xArgXmm1), + /*3481*/ uint16(xArgXmm2M128), + /*3482*/ uint16(xArgImm8u), + /*3483*/ uint16(xMatch), + /*3484*/ uint16(xCondIs64), 3487, 3503, + /*3487*/ uint16(xCondDataSize), 3491, 3497, 0, + /*3491*/ uint16(xSetOp), uint16(CMOVO), + /*3493*/ uint16(xReadSlashR), + /*3494*/ uint16(xArgR16), + /*3495*/ uint16(xArgRM16), + /*3496*/ uint16(xMatch), + /*3497*/ uint16(xSetOp), uint16(CMOVO), + /*3499*/ uint16(xReadSlashR), + /*3500*/ uint16(xArgR32), + /*3501*/ uint16(xArgRM32), + /*3502*/ uint16(xMatch), + /*3503*/ uint16(xCondDataSize), 3491, 3497, 3507, + /*3507*/ uint16(xSetOp), uint16(CMOVO), + /*3509*/ uint16(xReadSlashR), + /*3510*/ uint16(xArgR64), + /*3511*/ uint16(xArgRM64), + /*3512*/ uint16(xMatch), + /*3513*/ uint16(xCondIs64), 3516, 3532, + /*3516*/ uint16(xCondDataSize), 3520, 3526, 0, + /*3520*/ uint16(xSetOp), uint16(CMOVNO), + /*3522*/ uint16(xReadSlashR), + /*3523*/ uint16(xArgR16), + /*3524*/ uint16(xArgRM16), + /*3525*/ uint16(xMatch), + /*3526*/ uint16(xSetOp), uint16(CMOVNO), + /*3528*/ uint16(xReadSlashR), + /*3529*/ uint16(xArgR32), + /*3530*/ uint16(xArgRM32), + /*3531*/ uint16(xMatch), + /*3532*/ uint16(xCondDataSize), 3520, 3526, 3536, + /*3536*/ uint16(xSetOp), uint16(CMOVNO), + /*3538*/ uint16(xReadSlashR), + /*3539*/ uint16(xArgR64), + /*3540*/ uint16(xArgRM64), + /*3541*/ uint16(xMatch), + /*3542*/ uint16(xCondIs64), 3545, 3561, + /*3545*/ uint16(xCondDataSize), 3549, 3555, 0, + /*3549*/ uint16(xSetOp), uint16(CMOVB), + /*3551*/ uint16(xReadSlashR), + /*3552*/ uint16(xArgR16), + /*3553*/ uint16(xArgRM16), + /*3554*/ uint16(xMatch), + /*3555*/ uint16(xSetOp), uint16(CMOVB), + /*3557*/ uint16(xReadSlashR), + /*3558*/ uint16(xArgR32), + /*3559*/ uint16(xArgRM32), + /*3560*/ uint16(xMatch), + /*3561*/ uint16(xCondDataSize), 3549, 3555, 3565, + /*3565*/ uint16(xSetOp), uint16(CMOVB), + /*3567*/ uint16(xReadSlashR), + /*3568*/ uint16(xArgR64), + /*3569*/ uint16(xArgRM64), + /*3570*/ uint16(xMatch), + /*3571*/ uint16(xCondIs64), 3574, 3590, + /*3574*/ uint16(xCondDataSize), 3578, 3584, 0, + /*3578*/ uint16(xSetOp), uint16(CMOVAE), + /*3580*/ uint16(xReadSlashR), + /*3581*/ uint16(xArgR16), + /*3582*/ uint16(xArgRM16), + /*3583*/ uint16(xMatch), + /*3584*/ uint16(xSetOp), uint16(CMOVAE), + /*3586*/ uint16(xReadSlashR), + /*3587*/ uint16(xArgR32), + /*3588*/ uint16(xArgRM32), + /*3589*/ uint16(xMatch), + /*3590*/ uint16(xCondDataSize), 3578, 3584, 3594, + /*3594*/ uint16(xSetOp), uint16(CMOVAE), + /*3596*/ uint16(xReadSlashR), + /*3597*/ uint16(xArgR64), + /*3598*/ uint16(xArgRM64), + /*3599*/ uint16(xMatch), + /*3600*/ uint16(xCondIs64), 3603, 3619, + /*3603*/ uint16(xCondDataSize), 3607, 3613, 0, + /*3607*/ uint16(xSetOp), uint16(CMOVE), + /*3609*/ uint16(xReadSlashR), + /*3610*/ uint16(xArgR16), + /*3611*/ uint16(xArgRM16), + /*3612*/ uint16(xMatch), + /*3613*/ uint16(xSetOp), uint16(CMOVE), + /*3615*/ uint16(xReadSlashR), + /*3616*/ uint16(xArgR32), + /*3617*/ uint16(xArgRM32), + /*3618*/ uint16(xMatch), + /*3619*/ uint16(xCondDataSize), 3607, 3613, 3623, + /*3623*/ uint16(xSetOp), uint16(CMOVE), + /*3625*/ uint16(xReadSlashR), + /*3626*/ uint16(xArgR64), + /*3627*/ uint16(xArgRM64), + /*3628*/ uint16(xMatch), + /*3629*/ uint16(xCondIs64), 3632, 3648, + /*3632*/ uint16(xCondDataSize), 3636, 3642, 0, + /*3636*/ uint16(xSetOp), uint16(CMOVNE), + /*3638*/ uint16(xReadSlashR), + /*3639*/ uint16(xArgR16), + /*3640*/ uint16(xArgRM16), + /*3641*/ uint16(xMatch), + /*3642*/ uint16(xSetOp), uint16(CMOVNE), + /*3644*/ uint16(xReadSlashR), + /*3645*/ uint16(xArgR32), + /*3646*/ uint16(xArgRM32), + /*3647*/ uint16(xMatch), + /*3648*/ uint16(xCondDataSize), 3636, 3642, 3652, + /*3652*/ uint16(xSetOp), uint16(CMOVNE), + /*3654*/ uint16(xReadSlashR), + /*3655*/ uint16(xArgR64), + /*3656*/ uint16(xArgRM64), + /*3657*/ uint16(xMatch), + /*3658*/ uint16(xCondIs64), 3661, 3677, + /*3661*/ uint16(xCondDataSize), 3665, 3671, 0, + /*3665*/ uint16(xSetOp), uint16(CMOVBE), + /*3667*/ uint16(xReadSlashR), + /*3668*/ uint16(xArgR16), + /*3669*/ uint16(xArgRM16), + /*3670*/ uint16(xMatch), + /*3671*/ uint16(xSetOp), uint16(CMOVBE), + /*3673*/ uint16(xReadSlashR), + /*3674*/ uint16(xArgR32), + /*3675*/ uint16(xArgRM32), + /*3676*/ uint16(xMatch), + /*3677*/ uint16(xCondDataSize), 3665, 3671, 3681, + /*3681*/ uint16(xSetOp), uint16(CMOVBE), + /*3683*/ uint16(xReadSlashR), + /*3684*/ uint16(xArgR64), + /*3685*/ uint16(xArgRM64), + /*3686*/ uint16(xMatch), + /*3687*/ uint16(xCondIs64), 3690, 3706, + /*3690*/ uint16(xCondDataSize), 3694, 3700, 0, + /*3694*/ uint16(xSetOp), uint16(CMOVA), + /*3696*/ uint16(xReadSlashR), + /*3697*/ uint16(xArgR16), + /*3698*/ uint16(xArgRM16), + /*3699*/ uint16(xMatch), + /*3700*/ uint16(xSetOp), uint16(CMOVA), + /*3702*/ uint16(xReadSlashR), + /*3703*/ uint16(xArgR32), + /*3704*/ uint16(xArgRM32), + /*3705*/ uint16(xMatch), + /*3706*/ uint16(xCondDataSize), 3694, 3700, 3710, + /*3710*/ uint16(xSetOp), uint16(CMOVA), + /*3712*/ uint16(xReadSlashR), + /*3713*/ uint16(xArgR64), + /*3714*/ uint16(xArgRM64), + /*3715*/ uint16(xMatch), + /*3716*/ uint16(xCondIs64), 3719, 3735, + /*3719*/ uint16(xCondDataSize), 3723, 3729, 0, + /*3723*/ uint16(xSetOp), uint16(CMOVS), + /*3725*/ uint16(xReadSlashR), + /*3726*/ uint16(xArgR16), + /*3727*/ uint16(xArgRM16), + /*3728*/ uint16(xMatch), + /*3729*/ uint16(xSetOp), uint16(CMOVS), + /*3731*/ uint16(xReadSlashR), + /*3732*/ uint16(xArgR32), + /*3733*/ uint16(xArgRM32), + /*3734*/ uint16(xMatch), + /*3735*/ uint16(xCondDataSize), 3723, 3729, 3739, + /*3739*/ uint16(xSetOp), uint16(CMOVS), + /*3741*/ uint16(xReadSlashR), + /*3742*/ uint16(xArgR64), + /*3743*/ uint16(xArgRM64), + /*3744*/ uint16(xMatch), + /*3745*/ uint16(xCondIs64), 3748, 3764, + /*3748*/ uint16(xCondDataSize), 3752, 3758, 0, + /*3752*/ uint16(xSetOp), uint16(CMOVNS), + /*3754*/ uint16(xReadSlashR), + /*3755*/ uint16(xArgR16), + /*3756*/ uint16(xArgRM16), + /*3757*/ uint16(xMatch), + /*3758*/ uint16(xSetOp), uint16(CMOVNS), + /*3760*/ uint16(xReadSlashR), + /*3761*/ uint16(xArgR32), + /*3762*/ uint16(xArgRM32), + /*3763*/ uint16(xMatch), + /*3764*/ uint16(xCondDataSize), 3752, 3758, 3768, + /*3768*/ uint16(xSetOp), uint16(CMOVNS), + /*3770*/ uint16(xReadSlashR), + /*3771*/ uint16(xArgR64), + /*3772*/ uint16(xArgRM64), + /*3773*/ uint16(xMatch), + /*3774*/ uint16(xCondIs64), 3777, 3793, + /*3777*/ uint16(xCondDataSize), 3781, 3787, 0, + /*3781*/ uint16(xSetOp), uint16(CMOVP), + /*3783*/ uint16(xReadSlashR), + /*3784*/ uint16(xArgR16), + /*3785*/ uint16(xArgRM16), + /*3786*/ uint16(xMatch), + /*3787*/ uint16(xSetOp), uint16(CMOVP), + /*3789*/ uint16(xReadSlashR), + /*3790*/ uint16(xArgR32), + /*3791*/ uint16(xArgRM32), + /*3792*/ uint16(xMatch), + /*3793*/ uint16(xCondDataSize), 3781, 3787, 3797, + /*3797*/ uint16(xSetOp), uint16(CMOVP), + /*3799*/ uint16(xReadSlashR), + /*3800*/ uint16(xArgR64), + /*3801*/ uint16(xArgRM64), + /*3802*/ uint16(xMatch), + /*3803*/ uint16(xCondIs64), 3806, 3822, + /*3806*/ uint16(xCondDataSize), 3810, 3816, 0, + /*3810*/ uint16(xSetOp), uint16(CMOVNP), + /*3812*/ uint16(xReadSlashR), + /*3813*/ uint16(xArgR16), + /*3814*/ uint16(xArgRM16), + /*3815*/ uint16(xMatch), + /*3816*/ uint16(xSetOp), uint16(CMOVNP), + /*3818*/ uint16(xReadSlashR), + /*3819*/ uint16(xArgR32), + /*3820*/ uint16(xArgRM32), + /*3821*/ uint16(xMatch), + /*3822*/ uint16(xCondDataSize), 3810, 3816, 3826, + /*3826*/ uint16(xSetOp), uint16(CMOVNP), + /*3828*/ uint16(xReadSlashR), + /*3829*/ uint16(xArgR64), + /*3830*/ uint16(xArgRM64), + /*3831*/ uint16(xMatch), + /*3832*/ uint16(xCondIs64), 3835, 3851, + /*3835*/ uint16(xCondDataSize), 3839, 3845, 0, + /*3839*/ uint16(xSetOp), uint16(CMOVL), + /*3841*/ uint16(xReadSlashR), + /*3842*/ uint16(xArgR16), + /*3843*/ uint16(xArgRM16), + /*3844*/ uint16(xMatch), + /*3845*/ uint16(xSetOp), uint16(CMOVL), + /*3847*/ uint16(xReadSlashR), + /*3848*/ uint16(xArgR32), + /*3849*/ uint16(xArgRM32), + /*3850*/ uint16(xMatch), + /*3851*/ uint16(xCondDataSize), 3839, 3845, 3855, + /*3855*/ uint16(xSetOp), uint16(CMOVL), + /*3857*/ uint16(xReadSlashR), + /*3858*/ uint16(xArgR64), + /*3859*/ uint16(xArgRM64), + /*3860*/ uint16(xMatch), + /*3861*/ uint16(xCondIs64), 3864, 3880, + /*3864*/ uint16(xCondDataSize), 3868, 3874, 0, + /*3868*/ uint16(xSetOp), uint16(CMOVGE), + /*3870*/ uint16(xReadSlashR), + /*3871*/ uint16(xArgR16), + /*3872*/ uint16(xArgRM16), + /*3873*/ uint16(xMatch), + /*3874*/ uint16(xSetOp), uint16(CMOVGE), + /*3876*/ uint16(xReadSlashR), + /*3877*/ uint16(xArgR32), + /*3878*/ uint16(xArgRM32), + /*3879*/ uint16(xMatch), + /*3880*/ uint16(xCondDataSize), 3868, 3874, 3884, + /*3884*/ uint16(xSetOp), uint16(CMOVGE), + /*3886*/ uint16(xReadSlashR), + /*3887*/ uint16(xArgR64), + /*3888*/ uint16(xArgRM64), + /*3889*/ uint16(xMatch), + /*3890*/ uint16(xCondIs64), 3893, 3909, + /*3893*/ uint16(xCondDataSize), 3897, 3903, 0, + /*3897*/ uint16(xSetOp), uint16(CMOVLE), + /*3899*/ uint16(xReadSlashR), + /*3900*/ uint16(xArgR16), + /*3901*/ uint16(xArgRM16), + /*3902*/ uint16(xMatch), + /*3903*/ uint16(xSetOp), uint16(CMOVLE), + /*3905*/ uint16(xReadSlashR), + /*3906*/ uint16(xArgR32), + /*3907*/ uint16(xArgRM32), + /*3908*/ uint16(xMatch), + /*3909*/ uint16(xCondDataSize), 3897, 3903, 3913, + /*3913*/ uint16(xSetOp), uint16(CMOVLE), + /*3915*/ uint16(xReadSlashR), + /*3916*/ uint16(xArgR64), + /*3917*/ uint16(xArgRM64), + /*3918*/ uint16(xMatch), + /*3919*/ uint16(xCondIs64), 3922, 3938, + /*3922*/ uint16(xCondDataSize), 3926, 3932, 0, + /*3926*/ uint16(xSetOp), uint16(CMOVG), + /*3928*/ uint16(xReadSlashR), + /*3929*/ uint16(xArgR16), + /*3930*/ uint16(xArgRM16), + /*3931*/ uint16(xMatch), + /*3932*/ uint16(xSetOp), uint16(CMOVG), + /*3934*/ uint16(xReadSlashR), + /*3935*/ uint16(xArgR32), + /*3936*/ uint16(xArgRM32), + /*3937*/ uint16(xMatch), + /*3938*/ uint16(xCondDataSize), 3926, 3932, 3942, + /*3942*/ uint16(xSetOp), uint16(CMOVG), + /*3944*/ uint16(xReadSlashR), + /*3945*/ uint16(xArgR64), + /*3946*/ uint16(xArgRM64), + /*3947*/ uint16(xMatch), + /*3948*/ uint16(xCondPrefix), 2, + 0x66, 3960, + 0x0, 3954, + /*3954*/ uint16(xSetOp), uint16(MOVMSKPS), + /*3956*/ uint16(xReadSlashR), + /*3957*/ uint16(xArgR32), + /*3958*/ uint16(xArgXmm2), + /*3959*/ uint16(xMatch), + /*3960*/ uint16(xSetOp), uint16(MOVMSKPD), + /*3962*/ uint16(xReadSlashR), + /*3963*/ uint16(xArgR32), + /*3964*/ uint16(xArgXmm2), + /*3965*/ uint16(xMatch), + /*3966*/ uint16(xCondPrefix), 4, + 0xF3, 3994, + 0xF2, 3988, + 0x66, 3982, + 0x0, 3976, + /*3976*/ uint16(xSetOp), uint16(SQRTPS), + /*3978*/ uint16(xReadSlashR), + /*3979*/ uint16(xArgXmm1), + /*3980*/ uint16(xArgXmm2M128), + /*3981*/ uint16(xMatch), + /*3982*/ uint16(xSetOp), uint16(SQRTPD), + /*3984*/ uint16(xReadSlashR), + /*3985*/ uint16(xArgXmm1), + /*3986*/ uint16(xArgXmm2M128), + /*3987*/ uint16(xMatch), + /*3988*/ uint16(xSetOp), uint16(SQRTSD), + /*3990*/ uint16(xReadSlashR), + /*3991*/ uint16(xArgXmm1), + /*3992*/ uint16(xArgXmm2M64), + /*3993*/ uint16(xMatch), + /*3994*/ uint16(xSetOp), uint16(SQRTSS), + /*3996*/ uint16(xReadSlashR), + /*3997*/ uint16(xArgXmm1), + /*3998*/ uint16(xArgXmm2M32), + /*3999*/ uint16(xMatch), + /*4000*/ uint16(xCondPrefix), 2, + 0xF3, 4012, + 0x0, 4006, + /*4006*/ uint16(xSetOp), uint16(RSQRTPS), + /*4008*/ uint16(xReadSlashR), + /*4009*/ uint16(xArgXmm1), + /*4010*/ uint16(xArgXmm2M128), + /*4011*/ uint16(xMatch), + /*4012*/ uint16(xSetOp), uint16(RSQRTSS), + /*4014*/ uint16(xReadSlashR), + /*4015*/ uint16(xArgXmm1), + /*4016*/ uint16(xArgXmm2M32), + /*4017*/ uint16(xMatch), + /*4018*/ uint16(xCondPrefix), 2, + 0xF3, 4030, + 0x0, 4024, + /*4024*/ uint16(xSetOp), uint16(RCPPS), + /*4026*/ uint16(xReadSlashR), + /*4027*/ uint16(xArgXmm1), + /*4028*/ uint16(xArgXmm2M128), + /*4029*/ uint16(xMatch), + /*4030*/ uint16(xSetOp), uint16(RCPSS), + /*4032*/ uint16(xReadSlashR), + /*4033*/ uint16(xArgXmm1), + /*4034*/ uint16(xArgXmm2M32), + /*4035*/ uint16(xMatch), + /*4036*/ uint16(xCondPrefix), 2, + 0x66, 4048, + 0x0, 4042, + /*4042*/ uint16(xSetOp), uint16(ANDPS), + /*4044*/ uint16(xReadSlashR), + /*4045*/ uint16(xArgXmm1), + /*4046*/ uint16(xArgXmm2M128), + /*4047*/ uint16(xMatch), + /*4048*/ uint16(xSetOp), uint16(ANDPD), + /*4050*/ uint16(xReadSlashR), + /*4051*/ uint16(xArgXmm1), + /*4052*/ uint16(xArgXmm2M128), + /*4053*/ uint16(xMatch), + /*4054*/ uint16(xCondPrefix), 2, + 0x66, 4066, + 0x0, 4060, + /*4060*/ uint16(xSetOp), uint16(ANDNPS), + /*4062*/ uint16(xReadSlashR), + /*4063*/ uint16(xArgXmm1), + /*4064*/ uint16(xArgXmm2M128), + /*4065*/ uint16(xMatch), + /*4066*/ uint16(xSetOp), uint16(ANDNPD), + /*4068*/ uint16(xReadSlashR), + /*4069*/ uint16(xArgXmm1), + /*4070*/ uint16(xArgXmm2M128), + /*4071*/ uint16(xMatch), + /*4072*/ uint16(xCondPrefix), 2, + 0x66, 4084, + 0x0, 4078, + /*4078*/ uint16(xSetOp), uint16(ORPS), + /*4080*/ uint16(xReadSlashR), + /*4081*/ uint16(xArgXmm1), + /*4082*/ uint16(xArgXmm2M128), + /*4083*/ uint16(xMatch), + /*4084*/ uint16(xSetOp), uint16(ORPD), + /*4086*/ uint16(xReadSlashR), + /*4087*/ uint16(xArgXmm1), + /*4088*/ uint16(xArgXmm2M128), + /*4089*/ uint16(xMatch), + /*4090*/ uint16(xCondPrefix), 2, + 0x66, 4102, + 0x0, 4096, + /*4096*/ uint16(xSetOp), uint16(XORPS), + /*4098*/ uint16(xReadSlashR), + /*4099*/ uint16(xArgXmm1), + /*4100*/ uint16(xArgXmm2M128), + /*4101*/ uint16(xMatch), + /*4102*/ uint16(xSetOp), uint16(XORPD), + /*4104*/ uint16(xReadSlashR), + /*4105*/ uint16(xArgXmm1), + /*4106*/ uint16(xArgXmm2M128), + /*4107*/ uint16(xMatch), + /*4108*/ uint16(xCondPrefix), 4, + 0xF3, 4136, + 0xF2, 4130, + 0x66, 4124, + 0x0, 4118, + /*4118*/ uint16(xSetOp), uint16(ADDPS), + /*4120*/ uint16(xReadSlashR), + /*4121*/ uint16(xArgXmm1), + /*4122*/ uint16(xArgXmm2M128), + /*4123*/ uint16(xMatch), + /*4124*/ uint16(xSetOp), uint16(ADDPD), + /*4126*/ uint16(xReadSlashR), + /*4127*/ uint16(xArgXmm1), + /*4128*/ uint16(xArgXmm2M128), + /*4129*/ uint16(xMatch), + /*4130*/ uint16(xSetOp), uint16(ADDSD), + /*4132*/ uint16(xReadSlashR), + /*4133*/ uint16(xArgXmm1), + /*4134*/ uint16(xArgXmm2M64), + /*4135*/ uint16(xMatch), + /*4136*/ uint16(xSetOp), uint16(ADDSS), + /*4138*/ uint16(xReadSlashR), + /*4139*/ uint16(xArgXmm1), + /*4140*/ uint16(xArgXmm2M32), + /*4141*/ uint16(xMatch), + /*4142*/ uint16(xCondPrefix), 4, + 0xF3, 4170, + 0xF2, 4164, + 0x66, 4158, + 0x0, 4152, + /*4152*/ uint16(xSetOp), uint16(MULPS), + /*4154*/ uint16(xReadSlashR), + /*4155*/ uint16(xArgXmm1), + /*4156*/ uint16(xArgXmm2M128), + /*4157*/ uint16(xMatch), + /*4158*/ uint16(xSetOp), uint16(MULPD), + /*4160*/ uint16(xReadSlashR), + /*4161*/ uint16(xArgXmm1), + /*4162*/ uint16(xArgXmm2M128), + /*4163*/ uint16(xMatch), + /*4164*/ uint16(xSetOp), uint16(MULSD), + /*4166*/ uint16(xReadSlashR), + /*4167*/ uint16(xArgXmm1), + /*4168*/ uint16(xArgXmm2M64), + /*4169*/ uint16(xMatch), + /*4170*/ uint16(xSetOp), uint16(MULSS), + /*4172*/ uint16(xReadSlashR), + /*4173*/ uint16(xArgXmm1), + /*4174*/ uint16(xArgXmm2M32), + /*4175*/ uint16(xMatch), + /*4176*/ uint16(xCondPrefix), 4, + 0xF3, 4204, + 0xF2, 4198, + 0x66, 4192, + 0x0, 4186, + /*4186*/ uint16(xSetOp), uint16(CVTPS2PD), + /*4188*/ uint16(xReadSlashR), + /*4189*/ uint16(xArgXmm1), + /*4190*/ uint16(xArgXmm2M64), + /*4191*/ uint16(xMatch), + /*4192*/ uint16(xSetOp), uint16(CVTPD2PS), + /*4194*/ uint16(xReadSlashR), + /*4195*/ uint16(xArgXmm1), + /*4196*/ uint16(xArgXmm2M128), + /*4197*/ uint16(xMatch), + /*4198*/ uint16(xSetOp), uint16(CVTSD2SS), + /*4200*/ uint16(xReadSlashR), + /*4201*/ uint16(xArgXmm1), + /*4202*/ uint16(xArgXmm2M64), + /*4203*/ uint16(xMatch), + /*4204*/ uint16(xSetOp), uint16(CVTSS2SD), + /*4206*/ uint16(xReadSlashR), + /*4207*/ uint16(xArgXmm1), + /*4208*/ uint16(xArgXmm2M32), + /*4209*/ uint16(xMatch), + /*4210*/ uint16(xCondPrefix), 3, + 0xF3, 4230, + 0x66, 4224, + 0x0, 4218, + /*4218*/ uint16(xSetOp), uint16(CVTDQ2PS), + /*4220*/ uint16(xReadSlashR), + /*4221*/ uint16(xArgXmm1), + /*4222*/ uint16(xArgXmm2M128), + /*4223*/ uint16(xMatch), + /*4224*/ uint16(xSetOp), uint16(CVTPS2DQ), + /*4226*/ uint16(xReadSlashR), + /*4227*/ uint16(xArgXmm1), + /*4228*/ uint16(xArgXmm2M128), + /*4229*/ uint16(xMatch), + /*4230*/ uint16(xSetOp), uint16(CVTTPS2DQ), + /*4232*/ uint16(xReadSlashR), + /*4233*/ uint16(xArgXmm1), + /*4234*/ uint16(xArgXmm2M128), + /*4235*/ uint16(xMatch), + /*4236*/ uint16(xCondPrefix), 4, + 0xF3, 4264, + 0xF2, 4258, + 0x66, 4252, + 0x0, 4246, + /*4246*/ uint16(xSetOp), uint16(SUBPS), + /*4248*/ uint16(xReadSlashR), + /*4249*/ uint16(xArgXmm1), + /*4250*/ uint16(xArgXmm2M128), + /*4251*/ uint16(xMatch), + /*4252*/ uint16(xSetOp), uint16(SUBPD), + /*4254*/ uint16(xReadSlashR), + /*4255*/ uint16(xArgXmm1), + /*4256*/ uint16(xArgXmm2M128), + /*4257*/ uint16(xMatch), + /*4258*/ uint16(xSetOp), uint16(SUBSD), + /*4260*/ uint16(xReadSlashR), + /*4261*/ uint16(xArgXmm1), + /*4262*/ uint16(xArgXmm2M64), + /*4263*/ uint16(xMatch), + /*4264*/ uint16(xSetOp), uint16(SUBSS), + /*4266*/ uint16(xReadSlashR), + /*4267*/ uint16(xArgXmm1), + /*4268*/ uint16(xArgXmm2M32), + /*4269*/ uint16(xMatch), + /*4270*/ uint16(xCondPrefix), 4, + 0xF3, 4298, + 0xF2, 4292, + 0x66, 4286, + 0x0, 4280, + /*4280*/ uint16(xSetOp), uint16(MINPS), + /*4282*/ uint16(xReadSlashR), + /*4283*/ uint16(xArgXmm1), + /*4284*/ uint16(xArgXmm2M128), + /*4285*/ uint16(xMatch), + /*4286*/ uint16(xSetOp), uint16(MINPD), + /*4288*/ uint16(xReadSlashR), + /*4289*/ uint16(xArgXmm1), + /*4290*/ uint16(xArgXmm2M128), + /*4291*/ uint16(xMatch), + /*4292*/ uint16(xSetOp), uint16(MINSD), + /*4294*/ uint16(xReadSlashR), + /*4295*/ uint16(xArgXmm1), + /*4296*/ uint16(xArgXmm2M64), + /*4297*/ uint16(xMatch), + /*4298*/ uint16(xSetOp), uint16(MINSS), + /*4300*/ uint16(xReadSlashR), + /*4301*/ uint16(xArgXmm1), + /*4302*/ uint16(xArgXmm2M32), + /*4303*/ uint16(xMatch), + /*4304*/ uint16(xCondPrefix), 4, + 0xF3, 4332, + 0xF2, 4326, + 0x66, 4320, + 0x0, 4314, + /*4314*/ uint16(xSetOp), uint16(DIVPS), + /*4316*/ uint16(xReadSlashR), + /*4317*/ uint16(xArgXmm1), + /*4318*/ uint16(xArgXmm2M128), + /*4319*/ uint16(xMatch), + /*4320*/ uint16(xSetOp), uint16(DIVPD), + /*4322*/ uint16(xReadSlashR), + /*4323*/ uint16(xArgXmm1), + /*4324*/ uint16(xArgXmm2M128), + /*4325*/ uint16(xMatch), + /*4326*/ uint16(xSetOp), uint16(DIVSD), + /*4328*/ uint16(xReadSlashR), + /*4329*/ uint16(xArgXmm1), + /*4330*/ uint16(xArgXmm2M64), + /*4331*/ uint16(xMatch), + /*4332*/ uint16(xSetOp), uint16(DIVSS), + /*4334*/ uint16(xReadSlashR), + /*4335*/ uint16(xArgXmm1), + /*4336*/ uint16(xArgXmm2M32), + /*4337*/ uint16(xMatch), + /*4338*/ uint16(xCondPrefix), 4, + 0xF3, 4366, + 0xF2, 4360, + 0x66, 4354, + 0x0, 4348, + /*4348*/ uint16(xSetOp), uint16(MAXPS), + /*4350*/ uint16(xReadSlashR), + /*4351*/ uint16(xArgXmm1), + /*4352*/ uint16(xArgXmm2M128), + /*4353*/ uint16(xMatch), + /*4354*/ uint16(xSetOp), uint16(MAXPD), + /*4356*/ uint16(xReadSlashR), + /*4357*/ uint16(xArgXmm1), + /*4358*/ uint16(xArgXmm2M128), + /*4359*/ uint16(xMatch), + /*4360*/ uint16(xSetOp), uint16(MAXSD), + /*4362*/ uint16(xReadSlashR), + /*4363*/ uint16(xArgXmm1), + /*4364*/ uint16(xArgXmm2M64), + /*4365*/ uint16(xMatch), + /*4366*/ uint16(xSetOp), uint16(MAXSS), + /*4368*/ uint16(xReadSlashR), + /*4369*/ uint16(xArgXmm1), + /*4370*/ uint16(xArgXmm2M32), + /*4371*/ uint16(xMatch), + /*4372*/ uint16(xCondPrefix), 2, + 0x66, 4384, + 0x0, 4378, + /*4378*/ uint16(xSetOp), uint16(PUNPCKLBW), + /*4380*/ uint16(xReadSlashR), + /*4381*/ uint16(xArgMm), + /*4382*/ uint16(xArgMmM32), + /*4383*/ uint16(xMatch), + /*4384*/ uint16(xSetOp), uint16(PUNPCKLBW), + /*4386*/ uint16(xReadSlashR), + /*4387*/ uint16(xArgXmm1), + /*4388*/ uint16(xArgXmm2M128), + /*4389*/ uint16(xMatch), + /*4390*/ uint16(xCondPrefix), 2, + 0x66, 4402, + 0x0, 4396, + /*4396*/ uint16(xSetOp), uint16(PUNPCKLWD), + /*4398*/ uint16(xReadSlashR), + /*4399*/ uint16(xArgMm), + /*4400*/ uint16(xArgMmM32), + /*4401*/ uint16(xMatch), + /*4402*/ uint16(xSetOp), uint16(PUNPCKLWD), + /*4404*/ uint16(xReadSlashR), + /*4405*/ uint16(xArgXmm1), + /*4406*/ uint16(xArgXmm2M128), + /*4407*/ uint16(xMatch), + /*4408*/ uint16(xCondPrefix), 2, + 0x66, 4420, + 0x0, 4414, + /*4414*/ uint16(xSetOp), uint16(PUNPCKLDQ), + /*4416*/ uint16(xReadSlashR), + /*4417*/ uint16(xArgMm), + /*4418*/ uint16(xArgMmM32), + /*4419*/ uint16(xMatch), + /*4420*/ uint16(xSetOp), uint16(PUNPCKLDQ), + /*4422*/ uint16(xReadSlashR), + /*4423*/ uint16(xArgXmm1), + /*4424*/ uint16(xArgXmm2M128), + /*4425*/ uint16(xMatch), + /*4426*/ uint16(xCondPrefix), 2, + 0x66, 4438, + 0x0, 4432, + /*4432*/ uint16(xSetOp), uint16(PACKSSWB), + /*4434*/ uint16(xReadSlashR), + /*4435*/ uint16(xArgMm1), + /*4436*/ uint16(xArgMm2M64), + /*4437*/ uint16(xMatch), + /*4438*/ uint16(xSetOp), uint16(PACKSSWB), + /*4440*/ uint16(xReadSlashR), + /*4441*/ uint16(xArgXmm1), + /*4442*/ uint16(xArgXmm2M128), + /*4443*/ uint16(xMatch), + /*4444*/ uint16(xCondPrefix), 2, + 0x66, 4456, + 0x0, 4450, + /*4450*/ uint16(xSetOp), uint16(PCMPGTB), + /*4452*/ uint16(xReadSlashR), + /*4453*/ uint16(xArgMm), + /*4454*/ uint16(xArgMmM64), + /*4455*/ uint16(xMatch), + /*4456*/ uint16(xSetOp), uint16(PCMPGTB), + /*4458*/ uint16(xReadSlashR), + /*4459*/ uint16(xArgXmm1), + /*4460*/ uint16(xArgXmm2M128), + /*4461*/ uint16(xMatch), + /*4462*/ uint16(xCondPrefix), 2, + 0x66, 4474, + 0x0, 4468, + /*4468*/ uint16(xSetOp), uint16(PCMPGTW), + /*4470*/ uint16(xReadSlashR), + /*4471*/ uint16(xArgMm), + /*4472*/ uint16(xArgMmM64), + /*4473*/ uint16(xMatch), + /*4474*/ uint16(xSetOp), uint16(PCMPGTW), + /*4476*/ uint16(xReadSlashR), + /*4477*/ uint16(xArgXmm1), + /*4478*/ uint16(xArgXmm2M128), + /*4479*/ uint16(xMatch), + /*4480*/ uint16(xCondPrefix), 2, + 0x66, 4492, + 0x0, 4486, + /*4486*/ uint16(xSetOp), uint16(PCMPGTD), + /*4488*/ uint16(xReadSlashR), + /*4489*/ uint16(xArgMm), + /*4490*/ uint16(xArgMmM64), + /*4491*/ uint16(xMatch), + /*4492*/ uint16(xSetOp), uint16(PCMPGTD), + /*4494*/ uint16(xReadSlashR), + /*4495*/ uint16(xArgXmm1), + /*4496*/ uint16(xArgXmm2M128), + /*4497*/ uint16(xMatch), + /*4498*/ uint16(xCondPrefix), 2, + 0x66, 4510, + 0x0, 4504, + /*4504*/ uint16(xSetOp), uint16(PACKUSWB), + /*4506*/ uint16(xReadSlashR), + /*4507*/ uint16(xArgMm), + /*4508*/ uint16(xArgMmM64), + /*4509*/ uint16(xMatch), + /*4510*/ uint16(xSetOp), uint16(PACKUSWB), + /*4512*/ uint16(xReadSlashR), + /*4513*/ uint16(xArgXmm1), + /*4514*/ uint16(xArgXmm2M128), + /*4515*/ uint16(xMatch), + /*4516*/ uint16(xCondPrefix), 2, + 0x66, 4528, + 0x0, 4522, + /*4522*/ uint16(xSetOp), uint16(PUNPCKHBW), + /*4524*/ uint16(xReadSlashR), + /*4525*/ uint16(xArgMm), + /*4526*/ uint16(xArgMmM64), + /*4527*/ uint16(xMatch), + /*4528*/ uint16(xSetOp), uint16(PUNPCKHBW), + /*4530*/ uint16(xReadSlashR), + /*4531*/ uint16(xArgXmm1), + /*4532*/ uint16(xArgXmm2M128), + /*4533*/ uint16(xMatch), + /*4534*/ uint16(xCondPrefix), 2, + 0x66, 4546, + 0x0, 4540, + /*4540*/ uint16(xSetOp), uint16(PUNPCKHWD), + /*4542*/ uint16(xReadSlashR), + /*4543*/ uint16(xArgMm), + /*4544*/ uint16(xArgMmM64), + /*4545*/ uint16(xMatch), + /*4546*/ uint16(xSetOp), uint16(PUNPCKHWD), + /*4548*/ uint16(xReadSlashR), + /*4549*/ uint16(xArgXmm1), + /*4550*/ uint16(xArgXmm2M128), + /*4551*/ uint16(xMatch), + /*4552*/ uint16(xCondPrefix), 2, + 0x66, 4564, + 0x0, 4558, + /*4558*/ uint16(xSetOp), uint16(PUNPCKHDQ), + /*4560*/ uint16(xReadSlashR), + /*4561*/ uint16(xArgMm), + /*4562*/ uint16(xArgMmM64), + /*4563*/ uint16(xMatch), + /*4564*/ uint16(xSetOp), uint16(PUNPCKHDQ), + /*4566*/ uint16(xReadSlashR), + /*4567*/ uint16(xArgXmm1), + /*4568*/ uint16(xArgXmm2M128), + /*4569*/ uint16(xMatch), + /*4570*/ uint16(xCondPrefix), 2, + 0x66, 4582, + 0x0, 4576, + /*4576*/ uint16(xSetOp), uint16(PACKSSDW), + /*4578*/ uint16(xReadSlashR), + /*4579*/ uint16(xArgMm1), + /*4580*/ uint16(xArgMm2M64), + /*4581*/ uint16(xMatch), + /*4582*/ uint16(xSetOp), uint16(PACKSSDW), + /*4584*/ uint16(xReadSlashR), + /*4585*/ uint16(xArgXmm1), + /*4586*/ uint16(xArgXmm2M128), + /*4587*/ uint16(xMatch), + /*4588*/ uint16(xCondPrefix), 1, + 0x66, 4592, + /*4592*/ uint16(xSetOp), uint16(PUNPCKLQDQ), + /*4594*/ uint16(xReadSlashR), + /*4595*/ uint16(xArgXmm1), + /*4596*/ uint16(xArgXmm2M128), + /*4597*/ uint16(xMatch), + /*4598*/ uint16(xCondPrefix), 1, + 0x66, 4602, + /*4602*/ uint16(xSetOp), uint16(PUNPCKHQDQ), + /*4604*/ uint16(xReadSlashR), + /*4605*/ uint16(xArgXmm1), + /*4606*/ uint16(xArgXmm2M128), + /*4607*/ uint16(xMatch), + /*4608*/ uint16(xCondIs64), 4611, 4649, + /*4611*/ uint16(xCondPrefix), 2, + 0x66, 4633, + 0x0, 4617, + /*4617*/ uint16(xCondDataSize), 4621, 4627, 0, + /*4621*/ uint16(xSetOp), uint16(MOVD), + /*4623*/ uint16(xReadSlashR), + /*4624*/ uint16(xArgMm), + /*4625*/ uint16(xArgRM32), + /*4626*/ uint16(xMatch), + /*4627*/ uint16(xSetOp), uint16(MOVD), + /*4629*/ uint16(xReadSlashR), + /*4630*/ uint16(xArgMm), + /*4631*/ uint16(xArgRM32), + /*4632*/ uint16(xMatch), + /*4633*/ uint16(xCondDataSize), 4637, 4643, 0, + /*4637*/ uint16(xSetOp), uint16(MOVD), + /*4639*/ uint16(xReadSlashR), + /*4640*/ uint16(xArgXmm), + /*4641*/ uint16(xArgRM32), + /*4642*/ uint16(xMatch), + /*4643*/ uint16(xSetOp), uint16(MOVD), + /*4645*/ uint16(xReadSlashR), + /*4646*/ uint16(xArgXmm), + /*4647*/ uint16(xArgRM32), + /*4648*/ uint16(xMatch), + /*4649*/ uint16(xCondPrefix), 2, + 0x66, 4665, + 0x0, 4655, + /*4655*/ uint16(xCondDataSize), 4621, 4627, 4659, + /*4659*/ uint16(xSetOp), uint16(MOVQ), + /*4661*/ uint16(xReadSlashR), + /*4662*/ uint16(xArgMm), + /*4663*/ uint16(xArgRM64), + /*4664*/ uint16(xMatch), + /*4665*/ uint16(xCondDataSize), 4637, 4643, 4669, + /*4669*/ uint16(xSetOp), uint16(MOVQ), + /*4671*/ uint16(xReadSlashR), + /*4672*/ uint16(xArgXmm), + /*4673*/ uint16(xArgRM64), + /*4674*/ uint16(xMatch), + /*4675*/ uint16(xCondPrefix), 3, + 0xF3, 4695, + 0x66, 4689, + 0x0, 4683, + /*4683*/ uint16(xSetOp), uint16(MOVQ), + /*4685*/ uint16(xReadSlashR), + /*4686*/ uint16(xArgMm), + /*4687*/ uint16(xArgMmM64), + /*4688*/ uint16(xMatch), + /*4689*/ uint16(xSetOp), uint16(MOVDQA), + /*4691*/ uint16(xReadSlashR), + /*4692*/ uint16(xArgXmm1), + /*4693*/ uint16(xArgXmm2M128), + /*4694*/ uint16(xMatch), + /*4695*/ uint16(xSetOp), uint16(MOVDQU), + /*4697*/ uint16(xReadSlashR), + /*4698*/ uint16(xArgXmm1), + /*4699*/ uint16(xArgXmm2M128), + /*4700*/ uint16(xMatch), + /*4701*/ uint16(xCondPrefix), 4, + 0xF3, 4735, + 0xF2, 4727, + 0x66, 4719, + 0x0, 4711, + /*4711*/ uint16(xSetOp), uint16(PSHUFW), + /*4713*/ uint16(xReadSlashR), + /*4714*/ uint16(xReadIb), + /*4715*/ uint16(xArgMm1), + /*4716*/ uint16(xArgMm2M64), + /*4717*/ uint16(xArgImm8u), + /*4718*/ uint16(xMatch), + /*4719*/ uint16(xSetOp), uint16(PSHUFD), + /*4721*/ uint16(xReadSlashR), + /*4722*/ uint16(xReadIb), + /*4723*/ uint16(xArgXmm1), + /*4724*/ uint16(xArgXmm2M128), + /*4725*/ uint16(xArgImm8u), + /*4726*/ uint16(xMatch), + /*4727*/ uint16(xSetOp), uint16(PSHUFLW), + /*4729*/ uint16(xReadSlashR), + /*4730*/ uint16(xReadIb), + /*4731*/ uint16(xArgXmm1), + /*4732*/ uint16(xArgXmm2M128), + /*4733*/ uint16(xArgImm8u), + /*4734*/ uint16(xMatch), + /*4735*/ uint16(xSetOp), uint16(PSHUFHW), + /*4737*/ uint16(xReadSlashR), + /*4738*/ uint16(xReadIb), + /*4739*/ uint16(xArgXmm1), + /*4740*/ uint16(xArgXmm2M128), + /*4741*/ uint16(xArgImm8u), + /*4742*/ uint16(xMatch), + /*4743*/ uint16(xCondSlashR), + 0, // 0 + 0, // 1 + 4752, // 2 + 0, // 3 + 4770, // 4 + 0, // 5 + 4788, // 6 + 0, // 7 + /*4752*/ uint16(xCondPrefix), 2, + 0x66, 4764, + 0x0, 4758, + /*4758*/ uint16(xSetOp), uint16(PSRLW), + /*4760*/ uint16(xReadIb), + /*4761*/ uint16(xArgMm2), + /*4762*/ uint16(xArgImm8u), + /*4763*/ uint16(xMatch), + /*4764*/ uint16(xSetOp), uint16(PSRLW), + /*4766*/ uint16(xReadIb), + /*4767*/ uint16(xArgXmm2), + /*4768*/ uint16(xArgImm8u), + /*4769*/ uint16(xMatch), + /*4770*/ uint16(xCondPrefix), 2, + 0x66, 4782, + 0x0, 4776, + /*4776*/ uint16(xSetOp), uint16(PSRAW), + /*4778*/ uint16(xReadIb), + /*4779*/ uint16(xArgMm2), + /*4780*/ uint16(xArgImm8u), + /*4781*/ uint16(xMatch), + /*4782*/ uint16(xSetOp), uint16(PSRAW), + /*4784*/ uint16(xReadIb), + /*4785*/ uint16(xArgXmm2), + /*4786*/ uint16(xArgImm8u), + /*4787*/ uint16(xMatch), + /*4788*/ uint16(xCondPrefix), 2, + 0x66, 4800, + 0x0, 4794, + /*4794*/ uint16(xSetOp), uint16(PSLLW), + /*4796*/ uint16(xReadIb), + /*4797*/ uint16(xArgMm2), + /*4798*/ uint16(xArgImm8u), + /*4799*/ uint16(xMatch), + /*4800*/ uint16(xSetOp), uint16(PSLLW), + /*4802*/ uint16(xReadIb), + /*4803*/ uint16(xArgXmm2), + /*4804*/ uint16(xArgImm8u), + /*4805*/ uint16(xMatch), + /*4806*/ uint16(xCondSlashR), + 0, // 0 + 0, // 1 + 4815, // 2 + 0, // 3 + 4833, // 4 + 0, // 5 + 4851, // 6 + 0, // 7 + /*4815*/ uint16(xCondPrefix), 2, + 0x66, 4827, + 0x0, 4821, + /*4821*/ uint16(xSetOp), uint16(PSRLD), + /*4823*/ uint16(xReadIb), + /*4824*/ uint16(xArgMm2), + /*4825*/ uint16(xArgImm8u), + /*4826*/ uint16(xMatch), + /*4827*/ uint16(xSetOp), uint16(PSRLD), + /*4829*/ uint16(xReadIb), + /*4830*/ uint16(xArgXmm2), + /*4831*/ uint16(xArgImm8u), + /*4832*/ uint16(xMatch), + /*4833*/ uint16(xCondPrefix), 2, + 0x66, 4845, + 0x0, 4839, + /*4839*/ uint16(xSetOp), uint16(PSRAD), + /*4841*/ uint16(xReadIb), + /*4842*/ uint16(xArgMm2), + /*4843*/ uint16(xArgImm8u), + /*4844*/ uint16(xMatch), + /*4845*/ uint16(xSetOp), uint16(PSRAD), + /*4847*/ uint16(xReadIb), + /*4848*/ uint16(xArgXmm2), + /*4849*/ uint16(xArgImm8u), + /*4850*/ uint16(xMatch), + /*4851*/ uint16(xCondPrefix), 2, + 0x66, 4863, + 0x0, 4857, + /*4857*/ uint16(xSetOp), uint16(PSLLD), + /*4859*/ uint16(xReadIb), + /*4860*/ uint16(xArgMm2), + /*4861*/ uint16(xArgImm8u), + /*4862*/ uint16(xMatch), + /*4863*/ uint16(xSetOp), uint16(PSLLD), + /*4865*/ uint16(xReadIb), + /*4866*/ uint16(xArgXmm2), + /*4867*/ uint16(xArgImm8u), + /*4868*/ uint16(xMatch), + /*4869*/ uint16(xCondSlashR), + 0, // 0 + 0, // 1 + 4878, // 2 + 4896, // 3 + 0, // 4 + 0, // 5 + 4906, // 6 + 4924, // 7 + /*4878*/ uint16(xCondPrefix), 2, + 0x66, 4890, + 0x0, 4884, + /*4884*/ uint16(xSetOp), uint16(PSRLQ), + /*4886*/ uint16(xReadIb), + /*4887*/ uint16(xArgMm2), + /*4888*/ uint16(xArgImm8u), + /*4889*/ uint16(xMatch), + /*4890*/ uint16(xSetOp), uint16(PSRLQ), + /*4892*/ uint16(xReadIb), + /*4893*/ uint16(xArgXmm2), + /*4894*/ uint16(xArgImm8u), + /*4895*/ uint16(xMatch), + /*4896*/ uint16(xCondPrefix), 1, + 0x66, 4900, + /*4900*/ uint16(xSetOp), uint16(PSRLDQ), + /*4902*/ uint16(xReadIb), + /*4903*/ uint16(xArgXmm2), + /*4904*/ uint16(xArgImm8u), + /*4905*/ uint16(xMatch), + /*4906*/ uint16(xCondPrefix), 2, + 0x66, 4918, + 0x0, 4912, + /*4912*/ uint16(xSetOp), uint16(PSLLQ), + /*4914*/ uint16(xReadIb), + /*4915*/ uint16(xArgMm2), + /*4916*/ uint16(xArgImm8u), + /*4917*/ uint16(xMatch), + /*4918*/ uint16(xSetOp), uint16(PSLLQ), + /*4920*/ uint16(xReadIb), + /*4921*/ uint16(xArgXmm2), + /*4922*/ uint16(xArgImm8u), + /*4923*/ uint16(xMatch), + /*4924*/ uint16(xCondPrefix), 1, + 0x66, 4928, + /*4928*/ uint16(xSetOp), uint16(PSLLDQ), + /*4930*/ uint16(xReadIb), + /*4931*/ uint16(xArgXmm2), + /*4932*/ uint16(xArgImm8u), + /*4933*/ uint16(xMatch), + /*4934*/ uint16(xCondPrefix), 2, + 0x66, 4946, + 0x0, 4940, + /*4940*/ uint16(xSetOp), uint16(PCMPEQB), + /*4942*/ uint16(xReadSlashR), + /*4943*/ uint16(xArgMm), + /*4944*/ uint16(xArgMmM64), + /*4945*/ uint16(xMatch), + /*4946*/ uint16(xSetOp), uint16(PCMPEQB), + /*4948*/ uint16(xReadSlashR), + /*4949*/ uint16(xArgXmm1), + /*4950*/ uint16(xArgXmm2M128), + /*4951*/ uint16(xMatch), + /*4952*/ uint16(xCondPrefix), 2, + 0x66, 4964, + 0x0, 4958, + /*4958*/ uint16(xSetOp), uint16(PCMPEQW), + /*4960*/ uint16(xReadSlashR), + /*4961*/ uint16(xArgMm), + /*4962*/ uint16(xArgMmM64), + /*4963*/ uint16(xMatch), + /*4964*/ uint16(xSetOp), uint16(PCMPEQW), + /*4966*/ uint16(xReadSlashR), + /*4967*/ uint16(xArgXmm1), + /*4968*/ uint16(xArgXmm2M128), + /*4969*/ uint16(xMatch), + /*4970*/ uint16(xCondPrefix), 2, + 0x66, 4982, + 0x0, 4976, + /*4976*/ uint16(xSetOp), uint16(PCMPEQD), + /*4978*/ uint16(xReadSlashR), + /*4979*/ uint16(xArgMm), + /*4980*/ uint16(xArgMmM64), + /*4981*/ uint16(xMatch), + /*4982*/ uint16(xSetOp), uint16(PCMPEQD), + /*4984*/ uint16(xReadSlashR), + /*4985*/ uint16(xArgXmm1), + /*4986*/ uint16(xArgXmm2M128), + /*4987*/ uint16(xMatch), + /*4988*/ uint16(xSetOp), uint16(EMMS), + /*4990*/ uint16(xMatch), + /*4991*/ uint16(xCondPrefix), 2, + 0xF2, 5003, + 0x66, 4997, + /*4997*/ uint16(xSetOp), uint16(HADDPD), + /*4999*/ uint16(xReadSlashR), + /*5000*/ uint16(xArgXmm1), + /*5001*/ uint16(xArgXmm2M128), + /*5002*/ uint16(xMatch), + /*5003*/ uint16(xSetOp), uint16(HADDPS), + /*5005*/ uint16(xReadSlashR), + /*5006*/ uint16(xArgXmm1), + /*5007*/ uint16(xArgXmm2M128), + /*5008*/ uint16(xMatch), + /*5009*/ uint16(xCondPrefix), 2, + 0xF2, 5021, + 0x66, 5015, + /*5015*/ uint16(xSetOp), uint16(HSUBPD), + /*5017*/ uint16(xReadSlashR), + /*5018*/ uint16(xArgXmm1), + /*5019*/ uint16(xArgXmm2M128), + /*5020*/ uint16(xMatch), + /*5021*/ uint16(xSetOp), uint16(HSUBPS), + /*5023*/ uint16(xReadSlashR), + /*5024*/ uint16(xArgXmm1), + /*5025*/ uint16(xArgXmm2M128), + /*5026*/ uint16(xMatch), + /*5027*/ uint16(xCondIs64), 5030, 5076, + /*5030*/ uint16(xCondPrefix), 3, + 0xF3, 5070, + 0x66, 5054, + 0x0, 5038, + /*5038*/ uint16(xCondDataSize), 5042, 5048, 0, + /*5042*/ uint16(xSetOp), uint16(MOVD), + /*5044*/ uint16(xReadSlashR), + /*5045*/ uint16(xArgRM32), + /*5046*/ uint16(xArgMm), + /*5047*/ uint16(xMatch), + /*5048*/ uint16(xSetOp), uint16(MOVD), + /*5050*/ uint16(xReadSlashR), + /*5051*/ uint16(xArgRM32), + /*5052*/ uint16(xArgMm), + /*5053*/ uint16(xMatch), + /*5054*/ uint16(xCondDataSize), 5058, 5064, 0, + /*5058*/ uint16(xSetOp), uint16(MOVD), + /*5060*/ uint16(xReadSlashR), + /*5061*/ uint16(xArgRM32), + /*5062*/ uint16(xArgXmm), + /*5063*/ uint16(xMatch), + /*5064*/ uint16(xSetOp), uint16(MOVD), + /*5066*/ uint16(xReadSlashR), + /*5067*/ uint16(xArgRM32), + /*5068*/ uint16(xArgXmm), + /*5069*/ uint16(xMatch), + /*5070*/ uint16(xSetOp), uint16(MOVQ), + /*5072*/ uint16(xReadSlashR), + /*5073*/ uint16(xArgXmm1), + /*5074*/ uint16(xArgXmm2M64), + /*5075*/ uint16(xMatch), + /*5076*/ uint16(xCondPrefix), 3, + 0xF3, 5070, + 0x66, 5094, + 0x0, 5084, + /*5084*/ uint16(xCondDataSize), 5042, 5048, 5088, + /*5088*/ uint16(xSetOp), uint16(MOVQ), + /*5090*/ uint16(xReadSlashR), + /*5091*/ uint16(xArgRM64), + /*5092*/ uint16(xArgMm), + /*5093*/ uint16(xMatch), + /*5094*/ uint16(xCondDataSize), 5058, 5064, 5098, + /*5098*/ uint16(xSetOp), uint16(MOVQ), + /*5100*/ uint16(xReadSlashR), + /*5101*/ uint16(xArgRM64), + /*5102*/ uint16(xArgXmm), + /*5103*/ uint16(xMatch), + /*5104*/ uint16(xCondPrefix), 3, + 0xF3, 5124, + 0x66, 5118, + 0x0, 5112, + /*5112*/ uint16(xSetOp), uint16(MOVQ), + /*5114*/ uint16(xReadSlashR), + /*5115*/ uint16(xArgMmM64), + /*5116*/ uint16(xArgMm), + /*5117*/ uint16(xMatch), + /*5118*/ uint16(xSetOp), uint16(MOVDQA), + /*5120*/ uint16(xReadSlashR), + /*5121*/ uint16(xArgXmm2M128), + /*5122*/ uint16(xArgXmm1), + /*5123*/ uint16(xMatch), + /*5124*/ uint16(xSetOp), uint16(MOVDQU), + /*5126*/ uint16(xReadSlashR), + /*5127*/ uint16(xArgXmm2M128), + /*5128*/ uint16(xArgXmm1), + /*5129*/ uint16(xMatch), + /*5130*/ uint16(xCondIs64), 5133, 5147, + /*5133*/ uint16(xCondDataSize), 5137, 5142, 0, + /*5137*/ uint16(xSetOp), uint16(JO), + /*5139*/ uint16(xReadCw), + /*5140*/ uint16(xArgRel16), + /*5141*/ uint16(xMatch), + /*5142*/ uint16(xSetOp), uint16(JO), + /*5144*/ uint16(xReadCd), + /*5145*/ uint16(xArgRel32), + /*5146*/ uint16(xMatch), + /*5147*/ uint16(xCondDataSize), 5151, 5142, 5156, + /*5151*/ uint16(xSetOp), uint16(JO), + /*5153*/ uint16(xReadCd), + /*5154*/ uint16(xArgRel32), + /*5155*/ uint16(xMatch), + /*5156*/ uint16(xSetOp), uint16(JO), + /*5158*/ uint16(xReadCd), + /*5159*/ uint16(xArgRel32), + /*5160*/ uint16(xMatch), + /*5161*/ uint16(xCondIs64), 5164, 5178, + /*5164*/ uint16(xCondDataSize), 5168, 5173, 0, + /*5168*/ uint16(xSetOp), uint16(JNO), + /*5170*/ uint16(xReadCw), + /*5171*/ uint16(xArgRel16), + /*5172*/ uint16(xMatch), + /*5173*/ uint16(xSetOp), uint16(JNO), + /*5175*/ uint16(xReadCd), + /*5176*/ uint16(xArgRel32), + /*5177*/ uint16(xMatch), + /*5178*/ uint16(xCondDataSize), 5182, 5173, 5187, + /*5182*/ uint16(xSetOp), uint16(JNO), + /*5184*/ uint16(xReadCd), + /*5185*/ uint16(xArgRel32), + /*5186*/ uint16(xMatch), + /*5187*/ uint16(xSetOp), uint16(JNO), + /*5189*/ uint16(xReadCd), + /*5190*/ uint16(xArgRel32), + /*5191*/ uint16(xMatch), + /*5192*/ uint16(xCondIs64), 5195, 5209, + /*5195*/ uint16(xCondDataSize), 5199, 5204, 0, + /*5199*/ uint16(xSetOp), uint16(JB), + /*5201*/ uint16(xReadCw), + /*5202*/ uint16(xArgRel16), + /*5203*/ uint16(xMatch), + /*5204*/ uint16(xSetOp), uint16(JB), + /*5206*/ uint16(xReadCd), + /*5207*/ uint16(xArgRel32), + /*5208*/ uint16(xMatch), + /*5209*/ uint16(xCondDataSize), 5213, 5204, 5218, + /*5213*/ uint16(xSetOp), uint16(JB), + /*5215*/ uint16(xReadCd), + /*5216*/ uint16(xArgRel32), + /*5217*/ uint16(xMatch), + /*5218*/ uint16(xSetOp), uint16(JB), + /*5220*/ uint16(xReadCd), + /*5221*/ uint16(xArgRel32), + /*5222*/ uint16(xMatch), + /*5223*/ uint16(xCondIs64), 5226, 5240, + /*5226*/ uint16(xCondDataSize), 5230, 5235, 0, + /*5230*/ uint16(xSetOp), uint16(JAE), + /*5232*/ uint16(xReadCw), + /*5233*/ uint16(xArgRel16), + /*5234*/ uint16(xMatch), + /*5235*/ uint16(xSetOp), uint16(JAE), + /*5237*/ uint16(xReadCd), + /*5238*/ uint16(xArgRel32), + /*5239*/ uint16(xMatch), + /*5240*/ uint16(xCondDataSize), 5244, 5235, 5249, + /*5244*/ uint16(xSetOp), uint16(JAE), + /*5246*/ uint16(xReadCd), + /*5247*/ uint16(xArgRel32), + /*5248*/ uint16(xMatch), + /*5249*/ uint16(xSetOp), uint16(JAE), + /*5251*/ uint16(xReadCd), + /*5252*/ uint16(xArgRel32), + /*5253*/ uint16(xMatch), + /*5254*/ uint16(xCondIs64), 5257, 5271, + /*5257*/ uint16(xCondDataSize), 5261, 5266, 0, + /*5261*/ uint16(xSetOp), uint16(JE), + /*5263*/ uint16(xReadCw), + /*5264*/ uint16(xArgRel16), + /*5265*/ uint16(xMatch), + /*5266*/ uint16(xSetOp), uint16(JE), + /*5268*/ uint16(xReadCd), + /*5269*/ uint16(xArgRel32), + /*5270*/ uint16(xMatch), + /*5271*/ uint16(xCondDataSize), 5275, 5266, 5280, + /*5275*/ uint16(xSetOp), uint16(JE), + /*5277*/ uint16(xReadCd), + /*5278*/ uint16(xArgRel32), + /*5279*/ uint16(xMatch), + /*5280*/ uint16(xSetOp), uint16(JE), + /*5282*/ uint16(xReadCd), + /*5283*/ uint16(xArgRel32), + /*5284*/ uint16(xMatch), + /*5285*/ uint16(xCondIs64), 5288, 5302, + /*5288*/ uint16(xCondDataSize), 5292, 5297, 0, + /*5292*/ uint16(xSetOp), uint16(JNE), + /*5294*/ uint16(xReadCw), + /*5295*/ uint16(xArgRel16), + /*5296*/ uint16(xMatch), + /*5297*/ uint16(xSetOp), uint16(JNE), + /*5299*/ uint16(xReadCd), + /*5300*/ uint16(xArgRel32), + /*5301*/ uint16(xMatch), + /*5302*/ uint16(xCondDataSize), 5306, 5297, 5311, + /*5306*/ uint16(xSetOp), uint16(JNE), + /*5308*/ uint16(xReadCd), + /*5309*/ uint16(xArgRel32), + /*5310*/ uint16(xMatch), + /*5311*/ uint16(xSetOp), uint16(JNE), + /*5313*/ uint16(xReadCd), + /*5314*/ uint16(xArgRel32), + /*5315*/ uint16(xMatch), + /*5316*/ uint16(xCondIs64), 5319, 5333, + /*5319*/ uint16(xCondDataSize), 5323, 5328, 0, + /*5323*/ uint16(xSetOp), uint16(JBE), + /*5325*/ uint16(xReadCw), + /*5326*/ uint16(xArgRel16), + /*5327*/ uint16(xMatch), + /*5328*/ uint16(xSetOp), uint16(JBE), + /*5330*/ uint16(xReadCd), + /*5331*/ uint16(xArgRel32), + /*5332*/ uint16(xMatch), + /*5333*/ uint16(xCondDataSize), 5337, 5328, 5342, + /*5337*/ uint16(xSetOp), uint16(JBE), + /*5339*/ uint16(xReadCd), + /*5340*/ uint16(xArgRel32), + /*5341*/ uint16(xMatch), + /*5342*/ uint16(xSetOp), uint16(JBE), + /*5344*/ uint16(xReadCd), + /*5345*/ uint16(xArgRel32), + /*5346*/ uint16(xMatch), + /*5347*/ uint16(xCondIs64), 5350, 5364, + /*5350*/ uint16(xCondDataSize), 5354, 5359, 0, + /*5354*/ uint16(xSetOp), uint16(JA), + /*5356*/ uint16(xReadCw), + /*5357*/ uint16(xArgRel16), + /*5358*/ uint16(xMatch), + /*5359*/ uint16(xSetOp), uint16(JA), + /*5361*/ uint16(xReadCd), + /*5362*/ uint16(xArgRel32), + /*5363*/ uint16(xMatch), + /*5364*/ uint16(xCondDataSize), 5368, 5359, 5373, + /*5368*/ uint16(xSetOp), uint16(JA), + /*5370*/ uint16(xReadCd), + /*5371*/ uint16(xArgRel32), + /*5372*/ uint16(xMatch), + /*5373*/ uint16(xSetOp), uint16(JA), + /*5375*/ uint16(xReadCd), + /*5376*/ uint16(xArgRel32), + /*5377*/ uint16(xMatch), + /*5378*/ uint16(xCondIs64), 5381, 5395, + /*5381*/ uint16(xCondDataSize), 5385, 5390, 0, + /*5385*/ uint16(xSetOp), uint16(JS), + /*5387*/ uint16(xReadCw), + /*5388*/ uint16(xArgRel16), + /*5389*/ uint16(xMatch), + /*5390*/ uint16(xSetOp), uint16(JS), + /*5392*/ uint16(xReadCd), + /*5393*/ uint16(xArgRel32), + /*5394*/ uint16(xMatch), + /*5395*/ uint16(xCondDataSize), 5399, 5390, 5404, + /*5399*/ uint16(xSetOp), uint16(JS), + /*5401*/ uint16(xReadCd), + /*5402*/ uint16(xArgRel32), + /*5403*/ uint16(xMatch), + /*5404*/ uint16(xSetOp), uint16(JS), + /*5406*/ uint16(xReadCd), + /*5407*/ uint16(xArgRel32), + /*5408*/ uint16(xMatch), + /*5409*/ uint16(xCondIs64), 5412, 5426, + /*5412*/ uint16(xCondDataSize), 5416, 5421, 0, + /*5416*/ uint16(xSetOp), uint16(JNS), + /*5418*/ uint16(xReadCw), + /*5419*/ uint16(xArgRel16), + /*5420*/ uint16(xMatch), + /*5421*/ uint16(xSetOp), uint16(JNS), + /*5423*/ uint16(xReadCd), + /*5424*/ uint16(xArgRel32), + /*5425*/ uint16(xMatch), + /*5426*/ uint16(xCondDataSize), 5430, 5421, 5435, + /*5430*/ uint16(xSetOp), uint16(JNS), + /*5432*/ uint16(xReadCd), + /*5433*/ uint16(xArgRel32), + /*5434*/ uint16(xMatch), + /*5435*/ uint16(xSetOp), uint16(JNS), + /*5437*/ uint16(xReadCd), + /*5438*/ uint16(xArgRel32), + /*5439*/ uint16(xMatch), + /*5440*/ uint16(xCondIs64), 5443, 5457, + /*5443*/ uint16(xCondDataSize), 5447, 5452, 0, + /*5447*/ uint16(xSetOp), uint16(JP), + /*5449*/ uint16(xReadCw), + /*5450*/ uint16(xArgRel16), + /*5451*/ uint16(xMatch), + /*5452*/ uint16(xSetOp), uint16(JP), + /*5454*/ uint16(xReadCd), + /*5455*/ uint16(xArgRel32), + /*5456*/ uint16(xMatch), + /*5457*/ uint16(xCondDataSize), 5461, 5452, 5466, + /*5461*/ uint16(xSetOp), uint16(JP), + /*5463*/ uint16(xReadCd), + /*5464*/ uint16(xArgRel32), + /*5465*/ uint16(xMatch), + /*5466*/ uint16(xSetOp), uint16(JP), + /*5468*/ uint16(xReadCd), + /*5469*/ uint16(xArgRel32), + /*5470*/ uint16(xMatch), + /*5471*/ uint16(xCondIs64), 5474, 5488, + /*5474*/ uint16(xCondDataSize), 5478, 5483, 0, + /*5478*/ uint16(xSetOp), uint16(JNP), + /*5480*/ uint16(xReadCw), + /*5481*/ uint16(xArgRel16), + /*5482*/ uint16(xMatch), + /*5483*/ uint16(xSetOp), uint16(JNP), + /*5485*/ uint16(xReadCd), + /*5486*/ uint16(xArgRel32), + /*5487*/ uint16(xMatch), + /*5488*/ uint16(xCondDataSize), 5492, 5483, 5497, + /*5492*/ uint16(xSetOp), uint16(JNP), + /*5494*/ uint16(xReadCd), + /*5495*/ uint16(xArgRel32), + /*5496*/ uint16(xMatch), + /*5497*/ uint16(xSetOp), uint16(JNP), + /*5499*/ uint16(xReadCd), + /*5500*/ uint16(xArgRel32), + /*5501*/ uint16(xMatch), + /*5502*/ uint16(xCondIs64), 5505, 5519, + /*5505*/ uint16(xCondDataSize), 5509, 5514, 0, + /*5509*/ uint16(xSetOp), uint16(JL), + /*5511*/ uint16(xReadCw), + /*5512*/ uint16(xArgRel16), + /*5513*/ uint16(xMatch), + /*5514*/ uint16(xSetOp), uint16(JL), + /*5516*/ uint16(xReadCd), + /*5517*/ uint16(xArgRel32), + /*5518*/ uint16(xMatch), + /*5519*/ uint16(xCondDataSize), 5523, 5514, 5528, + /*5523*/ uint16(xSetOp), uint16(JL), + /*5525*/ uint16(xReadCd), + /*5526*/ uint16(xArgRel32), + /*5527*/ uint16(xMatch), + /*5528*/ uint16(xSetOp), uint16(JL), + /*5530*/ uint16(xReadCd), + /*5531*/ uint16(xArgRel32), + /*5532*/ uint16(xMatch), + /*5533*/ uint16(xCondIs64), 5536, 5550, + /*5536*/ uint16(xCondDataSize), 5540, 5545, 0, + /*5540*/ uint16(xSetOp), uint16(JGE), + /*5542*/ uint16(xReadCw), + /*5543*/ uint16(xArgRel16), + /*5544*/ uint16(xMatch), + /*5545*/ uint16(xSetOp), uint16(JGE), + /*5547*/ uint16(xReadCd), + /*5548*/ uint16(xArgRel32), + /*5549*/ uint16(xMatch), + /*5550*/ uint16(xCondDataSize), 5554, 5545, 5559, + /*5554*/ uint16(xSetOp), uint16(JGE), + /*5556*/ uint16(xReadCd), + /*5557*/ uint16(xArgRel32), + /*5558*/ uint16(xMatch), + /*5559*/ uint16(xSetOp), uint16(JGE), + /*5561*/ uint16(xReadCd), + /*5562*/ uint16(xArgRel32), + /*5563*/ uint16(xMatch), + /*5564*/ uint16(xCondIs64), 5567, 5581, + /*5567*/ uint16(xCondDataSize), 5571, 5576, 0, + /*5571*/ uint16(xSetOp), uint16(JLE), + /*5573*/ uint16(xReadCw), + /*5574*/ uint16(xArgRel16), + /*5575*/ uint16(xMatch), + /*5576*/ uint16(xSetOp), uint16(JLE), + /*5578*/ uint16(xReadCd), + /*5579*/ uint16(xArgRel32), + /*5580*/ uint16(xMatch), + /*5581*/ uint16(xCondDataSize), 5585, 5576, 5590, + /*5585*/ uint16(xSetOp), uint16(JLE), + /*5587*/ uint16(xReadCd), + /*5588*/ uint16(xArgRel32), + /*5589*/ uint16(xMatch), + /*5590*/ uint16(xSetOp), uint16(JLE), + /*5592*/ uint16(xReadCd), + /*5593*/ uint16(xArgRel32), + /*5594*/ uint16(xMatch), + /*5595*/ uint16(xCondIs64), 5598, 5612, + /*5598*/ uint16(xCondDataSize), 5602, 5607, 0, + /*5602*/ uint16(xSetOp), uint16(JG), + /*5604*/ uint16(xReadCw), + /*5605*/ uint16(xArgRel16), + /*5606*/ uint16(xMatch), + /*5607*/ uint16(xSetOp), uint16(JG), + /*5609*/ uint16(xReadCd), + /*5610*/ uint16(xArgRel32), + /*5611*/ uint16(xMatch), + /*5612*/ uint16(xCondDataSize), 5616, 5607, 5621, + /*5616*/ uint16(xSetOp), uint16(JG), + /*5618*/ uint16(xReadCd), + /*5619*/ uint16(xArgRel32), + /*5620*/ uint16(xMatch), + /*5621*/ uint16(xSetOp), uint16(JG), + /*5623*/ uint16(xReadCd), + /*5624*/ uint16(xArgRel32), + /*5625*/ uint16(xMatch), + /*5626*/ uint16(xSetOp), uint16(SETO), + /*5628*/ uint16(xReadSlashR), + /*5629*/ uint16(xArgRM8), + /*5630*/ uint16(xMatch), + /*5631*/ uint16(xSetOp), uint16(SETNO), + /*5633*/ uint16(xReadSlashR), + /*5634*/ uint16(xArgRM8), + /*5635*/ uint16(xMatch), + /*5636*/ uint16(xSetOp), uint16(SETB), + /*5638*/ uint16(xReadSlashR), + /*5639*/ uint16(xArgRM8), + /*5640*/ uint16(xMatch), + /*5641*/ uint16(xSetOp), uint16(SETAE), + /*5643*/ uint16(xReadSlashR), + /*5644*/ uint16(xArgRM8), + /*5645*/ uint16(xMatch), + /*5646*/ uint16(xSetOp), uint16(SETE), + /*5648*/ uint16(xReadSlashR), + /*5649*/ uint16(xArgRM8), + /*5650*/ uint16(xMatch), + /*5651*/ uint16(xSetOp), uint16(SETNE), + /*5653*/ uint16(xReadSlashR), + /*5654*/ uint16(xArgRM8), + /*5655*/ uint16(xMatch), + /*5656*/ uint16(xSetOp), uint16(SETBE), + /*5658*/ uint16(xReadSlashR), + /*5659*/ uint16(xArgRM8), + /*5660*/ uint16(xMatch), + /*5661*/ uint16(xSetOp), uint16(SETA), + /*5663*/ uint16(xReadSlashR), + /*5664*/ uint16(xArgRM8), + /*5665*/ uint16(xMatch), + /*5666*/ uint16(xSetOp), uint16(SETS), + /*5668*/ uint16(xReadSlashR), + /*5669*/ uint16(xArgRM8), + /*5670*/ uint16(xMatch), + /*5671*/ uint16(xSetOp), uint16(SETNS), + /*5673*/ uint16(xReadSlashR), + /*5674*/ uint16(xArgRM8), + /*5675*/ uint16(xMatch), + /*5676*/ uint16(xSetOp), uint16(SETP), + /*5678*/ uint16(xReadSlashR), + /*5679*/ uint16(xArgRM8), + /*5680*/ uint16(xMatch), + /*5681*/ uint16(xSetOp), uint16(SETNP), + /*5683*/ uint16(xReadSlashR), + /*5684*/ uint16(xArgRM8), + /*5685*/ uint16(xMatch), + /*5686*/ uint16(xSetOp), uint16(SETL), + /*5688*/ uint16(xReadSlashR), + /*5689*/ uint16(xArgRM8), + /*5690*/ uint16(xMatch), + /*5691*/ uint16(xSetOp), uint16(SETGE), + /*5693*/ uint16(xReadSlashR), + /*5694*/ uint16(xArgRM8), + /*5695*/ uint16(xMatch), + /*5696*/ uint16(xSetOp), uint16(SETLE), + /*5698*/ uint16(xReadSlashR), + /*5699*/ uint16(xArgRM8), + /*5700*/ uint16(xMatch), + /*5701*/ uint16(xSetOp), uint16(SETG), + /*5703*/ uint16(xReadSlashR), + /*5704*/ uint16(xArgRM8), + /*5705*/ uint16(xMatch), + /*5706*/ uint16(xSetOp), uint16(PUSH), + /*5708*/ uint16(xArgFS), + /*5709*/ uint16(xMatch), + /*5710*/ uint16(xCondIs64), 5713, 5725, + /*5713*/ uint16(xCondDataSize), 5717, 5721, 0, + /*5717*/ uint16(xSetOp), uint16(POP), + /*5719*/ uint16(xArgFS), + /*5720*/ uint16(xMatch), + /*5721*/ uint16(xSetOp), uint16(POP), + /*5723*/ uint16(xArgFS), + /*5724*/ uint16(xMatch), + /*5725*/ uint16(xCondDataSize), 5717, 5729, 5733, + /*5729*/ uint16(xSetOp), uint16(POP), + /*5731*/ uint16(xArgFS), + /*5732*/ uint16(xMatch), + /*5733*/ uint16(xSetOp), uint16(POP), + /*5735*/ uint16(xArgFS), + /*5736*/ uint16(xMatch), + /*5737*/ uint16(xSetOp), uint16(CPUID), + /*5739*/ uint16(xMatch), + /*5740*/ uint16(xCondIs64), 5743, 5759, + /*5743*/ uint16(xCondDataSize), 5747, 5753, 0, + /*5747*/ uint16(xSetOp), uint16(BT), + /*5749*/ uint16(xReadSlashR), + /*5750*/ uint16(xArgRM16), + /*5751*/ uint16(xArgR16), + /*5752*/ uint16(xMatch), + /*5753*/ uint16(xSetOp), uint16(BT), + /*5755*/ uint16(xReadSlashR), + /*5756*/ uint16(xArgRM32), + /*5757*/ uint16(xArgR32), + /*5758*/ uint16(xMatch), + /*5759*/ uint16(xCondDataSize), 5747, 5753, 5763, + /*5763*/ uint16(xSetOp), uint16(BT), + /*5765*/ uint16(xReadSlashR), + /*5766*/ uint16(xArgRM64), + /*5767*/ uint16(xArgR64), + /*5768*/ uint16(xMatch), + /*5769*/ uint16(xCondIs64), 5772, 5792, + /*5772*/ uint16(xCondDataSize), 5776, 5784, 0, + /*5776*/ uint16(xSetOp), uint16(SHLD), + /*5778*/ uint16(xReadSlashR), + /*5779*/ uint16(xReadIb), + /*5780*/ uint16(xArgRM16), + /*5781*/ uint16(xArgR16), + /*5782*/ uint16(xArgImm8u), + /*5783*/ uint16(xMatch), + /*5784*/ uint16(xSetOp), uint16(SHLD), + /*5786*/ uint16(xReadSlashR), + /*5787*/ uint16(xReadIb), + /*5788*/ uint16(xArgRM32), + /*5789*/ uint16(xArgR32), + /*5790*/ uint16(xArgImm8u), + /*5791*/ uint16(xMatch), + /*5792*/ uint16(xCondDataSize), 5776, 5784, 5796, + /*5796*/ uint16(xSetOp), uint16(SHLD), + /*5798*/ uint16(xReadSlashR), + /*5799*/ uint16(xReadIb), + /*5800*/ uint16(xArgRM64), + /*5801*/ uint16(xArgR64), + /*5802*/ uint16(xArgImm8u), + /*5803*/ uint16(xMatch), + /*5804*/ uint16(xCondIs64), 5807, 5825, + /*5807*/ uint16(xCondDataSize), 5811, 5818, 0, + /*5811*/ uint16(xSetOp), uint16(SHLD), + /*5813*/ uint16(xReadSlashR), + /*5814*/ uint16(xArgRM16), + /*5815*/ uint16(xArgR16), + /*5816*/ uint16(xArgCL), + /*5817*/ uint16(xMatch), + /*5818*/ uint16(xSetOp), uint16(SHLD), + /*5820*/ uint16(xReadSlashR), + /*5821*/ uint16(xArgRM32), + /*5822*/ uint16(xArgR32), + /*5823*/ uint16(xArgCL), + /*5824*/ uint16(xMatch), + /*5825*/ uint16(xCondDataSize), 5811, 5818, 5829, + /*5829*/ uint16(xSetOp), uint16(SHLD), + /*5831*/ uint16(xReadSlashR), + /*5832*/ uint16(xArgRM64), + /*5833*/ uint16(xArgR64), + /*5834*/ uint16(xArgCL), + /*5835*/ uint16(xMatch), + /*5836*/ uint16(xSetOp), uint16(PUSH), + /*5838*/ uint16(xArgGS), + /*5839*/ uint16(xMatch), + /*5840*/ uint16(xCondIs64), 5843, 5855, + /*5843*/ uint16(xCondDataSize), 5847, 5851, 0, + /*5847*/ uint16(xSetOp), uint16(POP), + /*5849*/ uint16(xArgGS), + /*5850*/ uint16(xMatch), + /*5851*/ uint16(xSetOp), uint16(POP), + /*5853*/ uint16(xArgGS), + /*5854*/ uint16(xMatch), + /*5855*/ uint16(xCondDataSize), 5847, 5859, 5863, + /*5859*/ uint16(xSetOp), uint16(POP), + /*5861*/ uint16(xArgGS), + /*5862*/ uint16(xMatch), + /*5863*/ uint16(xSetOp), uint16(POP), + /*5865*/ uint16(xArgGS), + /*5866*/ uint16(xMatch), + /*5867*/ uint16(xSetOp), uint16(RSM), + /*5869*/ uint16(xMatch), + /*5870*/ uint16(xCondIs64), 5873, 5889, + /*5873*/ uint16(xCondDataSize), 5877, 5883, 0, + /*5877*/ uint16(xSetOp), uint16(BTS), + /*5879*/ uint16(xReadSlashR), + /*5880*/ uint16(xArgRM16), + /*5881*/ uint16(xArgR16), + /*5882*/ uint16(xMatch), + /*5883*/ uint16(xSetOp), uint16(BTS), + /*5885*/ uint16(xReadSlashR), + /*5886*/ uint16(xArgRM32), + /*5887*/ uint16(xArgR32), + /*5888*/ uint16(xMatch), + /*5889*/ uint16(xCondDataSize), 5877, 5883, 5893, + /*5893*/ uint16(xSetOp), uint16(BTS), + /*5895*/ uint16(xReadSlashR), + /*5896*/ uint16(xArgRM64), + /*5897*/ uint16(xArgR64), + /*5898*/ uint16(xMatch), + /*5899*/ uint16(xCondIs64), 5902, 5922, + /*5902*/ uint16(xCondDataSize), 5906, 5914, 0, + /*5906*/ uint16(xSetOp), uint16(SHRD), + /*5908*/ uint16(xReadSlashR), + /*5909*/ uint16(xReadIb), + /*5910*/ uint16(xArgRM16), + /*5911*/ uint16(xArgR16), + /*5912*/ uint16(xArgImm8u), + /*5913*/ uint16(xMatch), + /*5914*/ uint16(xSetOp), uint16(SHRD), + /*5916*/ uint16(xReadSlashR), + /*5917*/ uint16(xReadIb), + /*5918*/ uint16(xArgRM32), + /*5919*/ uint16(xArgR32), + /*5920*/ uint16(xArgImm8u), + /*5921*/ uint16(xMatch), + /*5922*/ uint16(xCondDataSize), 5906, 5914, 5926, + /*5926*/ uint16(xSetOp), uint16(SHRD), + /*5928*/ uint16(xReadSlashR), + /*5929*/ uint16(xReadIb), + /*5930*/ uint16(xArgRM64), + /*5931*/ uint16(xArgR64), + /*5932*/ uint16(xArgImm8u), + /*5933*/ uint16(xMatch), + /*5934*/ uint16(xCondIs64), 5937, 5955, + /*5937*/ uint16(xCondDataSize), 5941, 5948, 0, + /*5941*/ uint16(xSetOp), uint16(SHRD), + /*5943*/ uint16(xReadSlashR), + /*5944*/ uint16(xArgRM16), + /*5945*/ uint16(xArgR16), + /*5946*/ uint16(xArgCL), + /*5947*/ uint16(xMatch), + /*5948*/ uint16(xSetOp), uint16(SHRD), + /*5950*/ uint16(xReadSlashR), + /*5951*/ uint16(xArgRM32), + /*5952*/ uint16(xArgR32), + /*5953*/ uint16(xArgCL), + /*5954*/ uint16(xMatch), + /*5955*/ uint16(xCondDataSize), 5941, 5948, 5959, + /*5959*/ uint16(xSetOp), uint16(SHRD), + /*5961*/ uint16(xReadSlashR), + /*5962*/ uint16(xArgRM64), + /*5963*/ uint16(xArgR64), + /*5964*/ uint16(xArgCL), + /*5965*/ uint16(xMatch), + /*5966*/ uint16(xCondByte), 3, + 0xE8, 6215, + 0xF0, 6218, + 0xF8, 6221, + /*5974*/ uint16(xCondSlashR), + 5983, // 0 + 6037, // 1 + 6091, // 2 + 6120, // 3 + 6149, // 4 + 6172, // 5 + 6195, // 6 + 6211, // 7 + /*5983*/ uint16(xCondIs64), 5986, 5998, + /*5986*/ uint16(xCondDataSize), 5990, 5994, 0, + /*5990*/ uint16(xSetOp), uint16(FXSAVE), + /*5992*/ uint16(xArgM512byte), + /*5993*/ uint16(xMatch), + /*5994*/ uint16(xSetOp), uint16(FXSAVE), + /*5996*/ uint16(xArgM512byte), + /*5997*/ uint16(xMatch), + /*5998*/ uint16(xCondPrefix), 2, + 0xF3, 6012, + 0x0, 6004, + /*6004*/ uint16(xCondDataSize), 5990, 5994, 6008, + /*6008*/ uint16(xSetOp), uint16(FXSAVE64), + /*6010*/ uint16(xArgM512byte), + /*6011*/ uint16(xMatch), + /*6012*/ uint16(xCondDataSize), 6016, 6023, 6030, + /*6016*/ uint16(xCondIsMem), 6019, 0, + /*6019*/ uint16(xSetOp), uint16(RDFSBASE), + /*6021*/ uint16(xArgRM32), + /*6022*/ uint16(xMatch), + /*6023*/ uint16(xCondIsMem), 6026, 0, + /*6026*/ uint16(xSetOp), uint16(RDFSBASE), + /*6028*/ uint16(xArgRM32), + /*6029*/ uint16(xMatch), + /*6030*/ uint16(xCondIsMem), 6033, 0, + /*6033*/ uint16(xSetOp), uint16(RDFSBASE), + /*6035*/ uint16(xArgRM64), + /*6036*/ uint16(xMatch), + /*6037*/ uint16(xCondIs64), 6040, 6052, + /*6040*/ uint16(xCondDataSize), 6044, 6048, 0, + /*6044*/ uint16(xSetOp), uint16(FXRSTOR), + /*6046*/ uint16(xArgM512byte), + /*6047*/ uint16(xMatch), + /*6048*/ uint16(xSetOp), uint16(FXRSTOR), + /*6050*/ uint16(xArgM512byte), + /*6051*/ uint16(xMatch), + /*6052*/ uint16(xCondPrefix), 2, + 0xF3, 6066, + 0x0, 6058, + /*6058*/ uint16(xCondDataSize), 6044, 6048, 6062, + /*6062*/ uint16(xSetOp), uint16(FXRSTOR64), + /*6064*/ uint16(xArgM512byte), + /*6065*/ uint16(xMatch), + /*6066*/ uint16(xCondDataSize), 6070, 6077, 6084, + /*6070*/ uint16(xCondIsMem), 6073, 0, + /*6073*/ uint16(xSetOp), uint16(RDGSBASE), + /*6075*/ uint16(xArgRM32), + /*6076*/ uint16(xMatch), + /*6077*/ uint16(xCondIsMem), 6080, 0, + /*6080*/ uint16(xSetOp), uint16(RDGSBASE), + /*6082*/ uint16(xArgRM32), + /*6083*/ uint16(xMatch), + /*6084*/ uint16(xCondIsMem), 6087, 0, + /*6087*/ uint16(xSetOp), uint16(RDGSBASE), + /*6089*/ uint16(xArgRM64), + /*6090*/ uint16(xMatch), + /*6091*/ uint16(xCondIs64), 6094, 6098, + /*6094*/ uint16(xSetOp), uint16(LDMXCSR), + /*6096*/ uint16(xArgM32), + /*6097*/ uint16(xMatch), + /*6098*/ uint16(xCondPrefix), 2, + 0xF3, 6104, + 0x0, 6094, + /*6104*/ uint16(xCondDataSize), 6108, 6112, 6116, + /*6108*/ uint16(xSetOp), uint16(WRFSBASE), + /*6110*/ uint16(xArgRM32), + /*6111*/ uint16(xMatch), + /*6112*/ uint16(xSetOp), uint16(WRFSBASE), + /*6114*/ uint16(xArgRM32), + /*6115*/ uint16(xMatch), + /*6116*/ uint16(xSetOp), uint16(WRFSBASE), + /*6118*/ uint16(xArgRM64), + /*6119*/ uint16(xMatch), + /*6120*/ uint16(xCondIs64), 6123, 6127, + /*6123*/ uint16(xSetOp), uint16(STMXCSR), + /*6125*/ uint16(xArgM32), + /*6126*/ uint16(xMatch), + /*6127*/ uint16(xCondPrefix), 2, + 0xF3, 6133, + 0x0, 6123, + /*6133*/ uint16(xCondDataSize), 6137, 6141, 6145, + /*6137*/ uint16(xSetOp), uint16(WRGSBASE), + /*6139*/ uint16(xArgRM32), + /*6140*/ uint16(xMatch), + /*6141*/ uint16(xSetOp), uint16(WRGSBASE), + /*6143*/ uint16(xArgRM32), + /*6144*/ uint16(xMatch), + /*6145*/ uint16(xSetOp), uint16(WRGSBASE), + /*6147*/ uint16(xArgRM64), + /*6148*/ uint16(xMatch), + /*6149*/ uint16(xCondIs64), 6152, 6164, + /*6152*/ uint16(xCondDataSize), 6156, 6160, 0, + /*6156*/ uint16(xSetOp), uint16(XSAVE), + /*6158*/ uint16(xArgMem), + /*6159*/ uint16(xMatch), + /*6160*/ uint16(xSetOp), uint16(XSAVE), + /*6162*/ uint16(xArgMem), + /*6163*/ uint16(xMatch), + /*6164*/ uint16(xCondDataSize), 6156, 6160, 6168, + /*6168*/ uint16(xSetOp), uint16(XSAVE64), + /*6170*/ uint16(xArgMem), + /*6171*/ uint16(xMatch), + /*6172*/ uint16(xCondIs64), 6175, 6187, + /*6175*/ uint16(xCondDataSize), 6179, 6183, 0, + /*6179*/ uint16(xSetOp), uint16(XRSTOR), + /*6181*/ uint16(xArgMem), + /*6182*/ uint16(xMatch), + /*6183*/ uint16(xSetOp), uint16(XRSTOR), + /*6185*/ uint16(xArgMem), + /*6186*/ uint16(xMatch), + /*6187*/ uint16(xCondDataSize), 6179, 6183, 6191, + /*6191*/ uint16(xSetOp), uint16(XRSTOR64), + /*6193*/ uint16(xArgMem), + /*6194*/ uint16(xMatch), + /*6195*/ uint16(xCondDataSize), 6199, 6203, 6207, + /*6199*/ uint16(xSetOp), uint16(XSAVEOPT), + /*6201*/ uint16(xArgMem), + /*6202*/ uint16(xMatch), + /*6203*/ uint16(xSetOp), uint16(XSAVEOPT), + /*6205*/ uint16(xArgMem), + /*6206*/ uint16(xMatch), + /*6207*/ uint16(xSetOp), uint16(XSAVEOPT64), + /*6209*/ uint16(xArgMem), + /*6210*/ uint16(xMatch), + /*6211*/ uint16(xSetOp), uint16(CLFLUSH), + /*6213*/ uint16(xArgM8), + /*6214*/ uint16(xMatch), + /*6215*/ uint16(xSetOp), uint16(LFENCE), + /*6217*/ uint16(xMatch), + /*6218*/ uint16(xSetOp), uint16(MFENCE), + /*6220*/ uint16(xMatch), + /*6221*/ uint16(xSetOp), uint16(SFENCE), + /*6223*/ uint16(xMatch), + /*6224*/ uint16(xCondIs64), 6227, 6243, + /*6227*/ uint16(xCondDataSize), 6231, 6237, 0, + /*6231*/ uint16(xSetOp), uint16(IMUL), + /*6233*/ uint16(xReadSlashR), + /*6234*/ uint16(xArgR16), + /*6235*/ uint16(xArgRM16), + /*6236*/ uint16(xMatch), + /*6237*/ uint16(xSetOp), uint16(IMUL), + /*6239*/ uint16(xReadSlashR), + /*6240*/ uint16(xArgR32), + /*6241*/ uint16(xArgRM32), + /*6242*/ uint16(xMatch), + /*6243*/ uint16(xCondDataSize), 6231, 6237, 6247, + /*6247*/ uint16(xSetOp), uint16(IMUL), + /*6249*/ uint16(xReadSlashR), + /*6250*/ uint16(xArgR64), + /*6251*/ uint16(xArgRM64), + /*6252*/ uint16(xMatch), + /*6253*/ uint16(xSetOp), uint16(CMPXCHG), + /*6255*/ uint16(xReadSlashR), + /*6256*/ uint16(xArgRM8), + /*6257*/ uint16(xArgR8), + /*6258*/ uint16(xMatch), + /*6259*/ uint16(xCondIs64), 6262, 6278, + /*6262*/ uint16(xCondDataSize), 6266, 6272, 0, + /*6266*/ uint16(xSetOp), uint16(CMPXCHG), + /*6268*/ uint16(xReadSlashR), + /*6269*/ uint16(xArgRM16), + /*6270*/ uint16(xArgR16), + /*6271*/ uint16(xMatch), + /*6272*/ uint16(xSetOp), uint16(CMPXCHG), + /*6274*/ uint16(xReadSlashR), + /*6275*/ uint16(xArgRM32), + /*6276*/ uint16(xArgR32), + /*6277*/ uint16(xMatch), + /*6278*/ uint16(xCondDataSize), 6266, 6272, 6282, + /*6282*/ uint16(xSetOp), uint16(CMPXCHG), + /*6284*/ uint16(xReadSlashR), + /*6285*/ uint16(xArgRM64), + /*6286*/ uint16(xArgR64), + /*6287*/ uint16(xMatch), + /*6288*/ uint16(xCondIs64), 6291, 6307, + /*6291*/ uint16(xCondDataSize), 6295, 6301, 0, + /*6295*/ uint16(xSetOp), uint16(LSS), + /*6297*/ uint16(xReadSlashR), + /*6298*/ uint16(xArgR16), + /*6299*/ uint16(xArgM16colon16), + /*6300*/ uint16(xMatch), + /*6301*/ uint16(xSetOp), uint16(LSS), + /*6303*/ uint16(xReadSlashR), + /*6304*/ uint16(xArgR32), + /*6305*/ uint16(xArgM16colon32), + /*6306*/ uint16(xMatch), + /*6307*/ uint16(xCondDataSize), 6295, 6301, 6311, + /*6311*/ uint16(xSetOp), uint16(LSS), + /*6313*/ uint16(xReadSlashR), + /*6314*/ uint16(xArgR64), + /*6315*/ uint16(xArgM16colon64), + /*6316*/ uint16(xMatch), + /*6317*/ uint16(xCondIs64), 6320, 6336, + /*6320*/ uint16(xCondDataSize), 6324, 6330, 0, + /*6324*/ uint16(xSetOp), uint16(BTR), + /*6326*/ uint16(xReadSlashR), + /*6327*/ uint16(xArgRM16), + /*6328*/ uint16(xArgR16), + /*6329*/ uint16(xMatch), + /*6330*/ uint16(xSetOp), uint16(BTR), + /*6332*/ uint16(xReadSlashR), + /*6333*/ uint16(xArgRM32), + /*6334*/ uint16(xArgR32), + /*6335*/ uint16(xMatch), + /*6336*/ uint16(xCondDataSize), 6324, 6330, 6340, + /*6340*/ uint16(xSetOp), uint16(BTR), + /*6342*/ uint16(xReadSlashR), + /*6343*/ uint16(xArgRM64), + /*6344*/ uint16(xArgR64), + /*6345*/ uint16(xMatch), + /*6346*/ uint16(xCondIs64), 6349, 6365, + /*6349*/ uint16(xCondDataSize), 6353, 6359, 0, + /*6353*/ uint16(xSetOp), uint16(LFS), + /*6355*/ uint16(xReadSlashR), + /*6356*/ uint16(xArgR16), + /*6357*/ uint16(xArgM16colon16), + /*6358*/ uint16(xMatch), + /*6359*/ uint16(xSetOp), uint16(LFS), + /*6361*/ uint16(xReadSlashR), + /*6362*/ uint16(xArgR32), + /*6363*/ uint16(xArgM16colon32), + /*6364*/ uint16(xMatch), + /*6365*/ uint16(xCondDataSize), 6353, 6359, 6369, + /*6369*/ uint16(xSetOp), uint16(LFS), + /*6371*/ uint16(xReadSlashR), + /*6372*/ uint16(xArgR64), + /*6373*/ uint16(xArgM16colon64), + /*6374*/ uint16(xMatch), + /*6375*/ uint16(xCondIs64), 6378, 6394, + /*6378*/ uint16(xCondDataSize), 6382, 6388, 0, + /*6382*/ uint16(xSetOp), uint16(LGS), + /*6384*/ uint16(xReadSlashR), + /*6385*/ uint16(xArgR16), + /*6386*/ uint16(xArgM16colon16), + /*6387*/ uint16(xMatch), + /*6388*/ uint16(xSetOp), uint16(LGS), + /*6390*/ uint16(xReadSlashR), + /*6391*/ uint16(xArgR32), + /*6392*/ uint16(xArgM16colon32), + /*6393*/ uint16(xMatch), + /*6394*/ uint16(xCondDataSize), 6382, 6388, 6398, + /*6398*/ uint16(xSetOp), uint16(LGS), + /*6400*/ uint16(xReadSlashR), + /*6401*/ uint16(xArgR64), + /*6402*/ uint16(xArgM16colon64), + /*6403*/ uint16(xMatch), + /*6404*/ uint16(xCondIs64), 6407, 6423, + /*6407*/ uint16(xCondDataSize), 6411, 6417, 0, + /*6411*/ uint16(xSetOp), uint16(MOVZX), + /*6413*/ uint16(xReadSlashR), + /*6414*/ uint16(xArgR16), + /*6415*/ uint16(xArgRM8), + /*6416*/ uint16(xMatch), + /*6417*/ uint16(xSetOp), uint16(MOVZX), + /*6419*/ uint16(xReadSlashR), + /*6420*/ uint16(xArgR32), + /*6421*/ uint16(xArgRM8), + /*6422*/ uint16(xMatch), + /*6423*/ uint16(xCondDataSize), 6411, 6417, 6427, + /*6427*/ uint16(xSetOp), uint16(MOVZX), + /*6429*/ uint16(xReadSlashR), + /*6430*/ uint16(xArgR64), + /*6431*/ uint16(xArgRM8), + /*6432*/ uint16(xMatch), + /*6433*/ uint16(xCondIs64), 6436, 6452, + /*6436*/ uint16(xCondDataSize), 6440, 6446, 0, + /*6440*/ uint16(xSetOp), uint16(MOVZX), + /*6442*/ uint16(xReadSlashR), + /*6443*/ uint16(xArgR16), + /*6444*/ uint16(xArgRM16), + /*6445*/ uint16(xMatch), + /*6446*/ uint16(xSetOp), uint16(MOVZX), + /*6448*/ uint16(xReadSlashR), + /*6449*/ uint16(xArgR32), + /*6450*/ uint16(xArgRM16), + /*6451*/ uint16(xMatch), + /*6452*/ uint16(xCondDataSize), 6440, 6446, 6456, + /*6456*/ uint16(xSetOp), uint16(MOVZX), + /*6458*/ uint16(xReadSlashR), + /*6459*/ uint16(xArgR64), + /*6460*/ uint16(xArgRM16), + /*6461*/ uint16(xMatch), + /*6462*/ uint16(xCondIs64), 6465, 6485, + /*6465*/ uint16(xCondPrefix), 1, + 0xF3, 6469, + /*6469*/ uint16(xCondDataSize), 6473, 6479, 0, + /*6473*/ uint16(xSetOp), uint16(POPCNT), + /*6475*/ uint16(xReadSlashR), + /*6476*/ uint16(xArgR16), + /*6477*/ uint16(xArgRM16), + /*6478*/ uint16(xMatch), + /*6479*/ uint16(xSetOp), uint16(POPCNT), + /*6481*/ uint16(xReadSlashR), + /*6482*/ uint16(xArgR32), + /*6483*/ uint16(xArgRM32), + /*6484*/ uint16(xMatch), + /*6485*/ uint16(xCondPrefix), 1, + 0xF3, 6489, + /*6489*/ uint16(xCondDataSize), 6473, 6479, 6493, + /*6493*/ uint16(xSetOp), uint16(POPCNT), + /*6495*/ uint16(xReadSlashR), + /*6496*/ uint16(xArgR64), + /*6497*/ uint16(xArgRM64), + /*6498*/ uint16(xMatch), + /*6499*/ uint16(xSetOp), uint16(UD1), + /*6501*/ uint16(xMatch), + /*6502*/ uint16(xCondSlashR), + 0, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 6511, // 4 + 6540, // 5 + 6569, // 6 + 6598, // 7 + /*6511*/ uint16(xCondIs64), 6514, 6530, + /*6514*/ uint16(xCondDataSize), 6518, 6524, 0, + /*6518*/ uint16(xSetOp), uint16(BT), + /*6520*/ uint16(xReadIb), + /*6521*/ uint16(xArgRM16), + /*6522*/ uint16(xArgImm8u), + /*6523*/ uint16(xMatch), + /*6524*/ uint16(xSetOp), uint16(BT), + /*6526*/ uint16(xReadIb), + /*6527*/ uint16(xArgRM32), + /*6528*/ uint16(xArgImm8u), + /*6529*/ uint16(xMatch), + /*6530*/ uint16(xCondDataSize), 6518, 6524, 6534, + /*6534*/ uint16(xSetOp), uint16(BT), + /*6536*/ uint16(xReadIb), + /*6537*/ uint16(xArgRM64), + /*6538*/ uint16(xArgImm8u), + /*6539*/ uint16(xMatch), + /*6540*/ uint16(xCondIs64), 6543, 6559, + /*6543*/ uint16(xCondDataSize), 6547, 6553, 0, + /*6547*/ uint16(xSetOp), uint16(BTS), + /*6549*/ uint16(xReadIb), + /*6550*/ uint16(xArgRM16), + /*6551*/ uint16(xArgImm8u), + /*6552*/ uint16(xMatch), + /*6553*/ uint16(xSetOp), uint16(BTS), + /*6555*/ uint16(xReadIb), + /*6556*/ uint16(xArgRM32), + /*6557*/ uint16(xArgImm8u), + /*6558*/ uint16(xMatch), + /*6559*/ uint16(xCondDataSize), 6547, 6553, 6563, + /*6563*/ uint16(xSetOp), uint16(BTS), + /*6565*/ uint16(xReadIb), + /*6566*/ uint16(xArgRM64), + /*6567*/ uint16(xArgImm8u), + /*6568*/ uint16(xMatch), + /*6569*/ uint16(xCondIs64), 6572, 6588, + /*6572*/ uint16(xCondDataSize), 6576, 6582, 0, + /*6576*/ uint16(xSetOp), uint16(BTR), + /*6578*/ uint16(xReadIb), + /*6579*/ uint16(xArgRM16), + /*6580*/ uint16(xArgImm8u), + /*6581*/ uint16(xMatch), + /*6582*/ uint16(xSetOp), uint16(BTR), + /*6584*/ uint16(xReadIb), + /*6585*/ uint16(xArgRM32), + /*6586*/ uint16(xArgImm8u), + /*6587*/ uint16(xMatch), + /*6588*/ uint16(xCondDataSize), 6576, 6582, 6592, + /*6592*/ uint16(xSetOp), uint16(BTR), + /*6594*/ uint16(xReadIb), + /*6595*/ uint16(xArgRM64), + /*6596*/ uint16(xArgImm8u), + /*6597*/ uint16(xMatch), + /*6598*/ uint16(xCondIs64), 6601, 6617, + /*6601*/ uint16(xCondDataSize), 6605, 6611, 0, + /*6605*/ uint16(xSetOp), uint16(BTC), + /*6607*/ uint16(xReadIb), + /*6608*/ uint16(xArgRM16), + /*6609*/ uint16(xArgImm8u), + /*6610*/ uint16(xMatch), + /*6611*/ uint16(xSetOp), uint16(BTC), + /*6613*/ uint16(xReadIb), + /*6614*/ uint16(xArgRM32), + /*6615*/ uint16(xArgImm8u), + /*6616*/ uint16(xMatch), + /*6617*/ uint16(xCondDataSize), 6605, 6611, 6621, + /*6621*/ uint16(xSetOp), uint16(BTC), + /*6623*/ uint16(xReadIb), + /*6624*/ uint16(xArgRM64), + /*6625*/ uint16(xArgImm8u), + /*6626*/ uint16(xMatch), + /*6627*/ uint16(xCondIs64), 6630, 6646, + /*6630*/ uint16(xCondDataSize), 6634, 6640, 0, + /*6634*/ uint16(xSetOp), uint16(BTC), + /*6636*/ uint16(xReadSlashR), + /*6637*/ uint16(xArgRM16), + /*6638*/ uint16(xArgR16), + /*6639*/ uint16(xMatch), + /*6640*/ uint16(xSetOp), uint16(BTC), + /*6642*/ uint16(xReadSlashR), + /*6643*/ uint16(xArgRM32), + /*6644*/ uint16(xArgR32), + /*6645*/ uint16(xMatch), + /*6646*/ uint16(xCondDataSize), 6634, 6640, 6650, + /*6650*/ uint16(xSetOp), uint16(BTC), + /*6652*/ uint16(xReadSlashR), + /*6653*/ uint16(xArgRM64), + /*6654*/ uint16(xArgR64), + /*6655*/ uint16(xMatch), + /*6656*/ uint16(xCondIs64), 6659, 6697, + /*6659*/ uint16(xCondPrefix), 2, + 0xF3, 6681, + 0x0, 6665, + /*6665*/ uint16(xCondDataSize), 6669, 6675, 0, + /*6669*/ uint16(xSetOp), uint16(BSF), + /*6671*/ uint16(xReadSlashR), + /*6672*/ uint16(xArgR16), + /*6673*/ uint16(xArgRM16), + /*6674*/ uint16(xMatch), + /*6675*/ uint16(xSetOp), uint16(BSF), + /*6677*/ uint16(xReadSlashR), + /*6678*/ uint16(xArgR32), + /*6679*/ uint16(xArgRM32), + /*6680*/ uint16(xMatch), + /*6681*/ uint16(xCondDataSize), 6685, 6691, 0, + /*6685*/ uint16(xSetOp), uint16(TZCNT), + /*6687*/ uint16(xReadSlashR), + /*6688*/ uint16(xArgR16), + /*6689*/ uint16(xArgRM16), + /*6690*/ uint16(xMatch), + /*6691*/ uint16(xSetOp), uint16(TZCNT), + /*6693*/ uint16(xReadSlashR), + /*6694*/ uint16(xArgR32), + /*6695*/ uint16(xArgRM32), + /*6696*/ uint16(xMatch), + /*6697*/ uint16(xCondPrefix), 2, + 0xF3, 6713, + 0x0, 6703, + /*6703*/ uint16(xCondDataSize), 6669, 6675, 6707, + /*6707*/ uint16(xSetOp), uint16(BSF), + /*6709*/ uint16(xReadSlashR), + /*6710*/ uint16(xArgR64), + /*6711*/ uint16(xArgRM64), + /*6712*/ uint16(xMatch), + /*6713*/ uint16(xCondDataSize), 6685, 6691, 6717, + /*6717*/ uint16(xSetOp), uint16(TZCNT), + /*6719*/ uint16(xReadSlashR), + /*6720*/ uint16(xArgR64), + /*6721*/ uint16(xArgRM64), + /*6722*/ uint16(xMatch), + /*6723*/ uint16(xCondIs64), 6726, 6764, + /*6726*/ uint16(xCondPrefix), 2, + 0xF3, 6748, + 0x0, 6732, + /*6732*/ uint16(xCondDataSize), 6736, 6742, 0, + /*6736*/ uint16(xSetOp), uint16(BSR), + /*6738*/ uint16(xReadSlashR), + /*6739*/ uint16(xArgR16), + /*6740*/ uint16(xArgRM16), + /*6741*/ uint16(xMatch), + /*6742*/ uint16(xSetOp), uint16(BSR), + /*6744*/ uint16(xReadSlashR), + /*6745*/ uint16(xArgR32), + /*6746*/ uint16(xArgRM32), + /*6747*/ uint16(xMatch), + /*6748*/ uint16(xCondDataSize), 6752, 6758, 0, + /*6752*/ uint16(xSetOp), uint16(LZCNT), + /*6754*/ uint16(xReadSlashR), + /*6755*/ uint16(xArgR16), + /*6756*/ uint16(xArgRM16), + /*6757*/ uint16(xMatch), + /*6758*/ uint16(xSetOp), uint16(LZCNT), + /*6760*/ uint16(xReadSlashR), + /*6761*/ uint16(xArgR32), + /*6762*/ uint16(xArgRM32), + /*6763*/ uint16(xMatch), + /*6764*/ uint16(xCondPrefix), 2, + 0xF3, 6780, + 0x0, 6770, + /*6770*/ uint16(xCondDataSize), 6736, 6742, 6774, + /*6774*/ uint16(xSetOp), uint16(BSR), + /*6776*/ uint16(xReadSlashR), + /*6777*/ uint16(xArgR64), + /*6778*/ uint16(xArgRM64), + /*6779*/ uint16(xMatch), + /*6780*/ uint16(xCondDataSize), 6752, 6758, 6784, + /*6784*/ uint16(xSetOp), uint16(LZCNT), + /*6786*/ uint16(xReadSlashR), + /*6787*/ uint16(xArgR64), + /*6788*/ uint16(xArgRM64), + /*6789*/ uint16(xMatch), + /*6790*/ uint16(xCondIs64), 6793, 6809, + /*6793*/ uint16(xCondDataSize), 6797, 6803, 0, + /*6797*/ uint16(xSetOp), uint16(MOVSX), + /*6799*/ uint16(xReadSlashR), + /*6800*/ uint16(xArgR16), + /*6801*/ uint16(xArgRM8), + /*6802*/ uint16(xMatch), + /*6803*/ uint16(xSetOp), uint16(MOVSX), + /*6805*/ uint16(xReadSlashR), + /*6806*/ uint16(xArgR32), + /*6807*/ uint16(xArgRM8), + /*6808*/ uint16(xMatch), + /*6809*/ uint16(xCondDataSize), 6797, 6803, 6813, + /*6813*/ uint16(xSetOp), uint16(MOVSX), + /*6815*/ uint16(xReadSlashR), + /*6816*/ uint16(xArgR64), + /*6817*/ uint16(xArgRM8), + /*6818*/ uint16(xMatch), + /*6819*/ uint16(xCondIs64), 6822, 6838, + /*6822*/ uint16(xCondDataSize), 6826, 6832, 0, + /*6826*/ uint16(xSetOp), uint16(MOVSX), + /*6828*/ uint16(xReadSlashR), + /*6829*/ uint16(xArgR16), + /*6830*/ uint16(xArgRM16), + /*6831*/ uint16(xMatch), + /*6832*/ uint16(xSetOp), uint16(MOVSX), + /*6834*/ uint16(xReadSlashR), + /*6835*/ uint16(xArgR32), + /*6836*/ uint16(xArgRM16), + /*6837*/ uint16(xMatch), + /*6838*/ uint16(xCondDataSize), 6826, 6832, 6842, + /*6842*/ uint16(xSetOp), uint16(MOVSX), + /*6844*/ uint16(xReadSlashR), + /*6845*/ uint16(xArgR64), + /*6846*/ uint16(xArgRM16), + /*6847*/ uint16(xMatch), + /*6848*/ uint16(xSetOp), uint16(XADD), + /*6850*/ uint16(xReadSlashR), + /*6851*/ uint16(xArgRM8), + /*6852*/ uint16(xArgR8), + /*6853*/ uint16(xMatch), + /*6854*/ uint16(xCondIs64), 6857, 6873, + /*6857*/ uint16(xCondDataSize), 6861, 6867, 0, + /*6861*/ uint16(xSetOp), uint16(XADD), + /*6863*/ uint16(xReadSlashR), + /*6864*/ uint16(xArgRM16), + /*6865*/ uint16(xArgR16), + /*6866*/ uint16(xMatch), + /*6867*/ uint16(xSetOp), uint16(XADD), + /*6869*/ uint16(xReadSlashR), + /*6870*/ uint16(xArgRM32), + /*6871*/ uint16(xArgR32), + /*6872*/ uint16(xMatch), + /*6873*/ uint16(xCondDataSize), 6861, 6867, 6877, + /*6877*/ uint16(xSetOp), uint16(XADD), + /*6879*/ uint16(xReadSlashR), + /*6880*/ uint16(xArgRM64), + /*6881*/ uint16(xArgR64), + /*6882*/ uint16(xMatch), + /*6883*/ uint16(xCondPrefix), 4, + 0xF3, 6917, + 0xF2, 6909, + 0x66, 6901, + 0x0, 6893, + /*6893*/ uint16(xSetOp), uint16(CMPPS), + /*6895*/ uint16(xReadSlashR), + /*6896*/ uint16(xReadIb), + /*6897*/ uint16(xArgXmm1), + /*6898*/ uint16(xArgXmm2M128), + /*6899*/ uint16(xArgImm8u), + /*6900*/ uint16(xMatch), + /*6901*/ uint16(xSetOp), uint16(CMPPD), + /*6903*/ uint16(xReadSlashR), + /*6904*/ uint16(xReadIb), + /*6905*/ uint16(xArgXmm1), + /*6906*/ uint16(xArgXmm2M128), + /*6907*/ uint16(xArgImm8u), + /*6908*/ uint16(xMatch), + /*6909*/ uint16(xSetOp), uint16(CMPSD_XMM), + /*6911*/ uint16(xReadSlashR), + /*6912*/ uint16(xReadIb), + /*6913*/ uint16(xArgXmm1), + /*6914*/ uint16(xArgXmm2M64), + /*6915*/ uint16(xArgImm8u), + /*6916*/ uint16(xMatch), + /*6917*/ uint16(xSetOp), uint16(CMPSS), + /*6919*/ uint16(xReadSlashR), + /*6920*/ uint16(xReadIb), + /*6921*/ uint16(xArgXmm1), + /*6922*/ uint16(xArgXmm2M32), + /*6923*/ uint16(xArgImm8u), + /*6924*/ uint16(xMatch), + /*6925*/ uint16(xCondIs64), 6928, 6944, + /*6928*/ uint16(xCondDataSize), 6932, 6938, 0, + /*6932*/ uint16(xSetOp), uint16(MOVNTI), + /*6934*/ uint16(xReadSlashR), + /*6935*/ uint16(xArgM32), + /*6936*/ uint16(xArgR32), + /*6937*/ uint16(xMatch), + /*6938*/ uint16(xSetOp), uint16(MOVNTI), + /*6940*/ uint16(xReadSlashR), + /*6941*/ uint16(xArgM32), + /*6942*/ uint16(xArgR32), + /*6943*/ uint16(xMatch), + /*6944*/ uint16(xCondDataSize), 6932, 6938, 6948, + /*6948*/ uint16(xSetOp), uint16(MOVNTI), + /*6950*/ uint16(xReadSlashR), + /*6951*/ uint16(xArgM64), + /*6952*/ uint16(xArgR64), + /*6953*/ uint16(xMatch), + /*6954*/ uint16(xCondPrefix), 2, + 0x66, 6968, + 0x0, 6960, + /*6960*/ uint16(xSetOp), uint16(PINSRW), + /*6962*/ uint16(xReadSlashR), + /*6963*/ uint16(xReadIb), + /*6964*/ uint16(xArgMm), + /*6965*/ uint16(xArgR32M16), + /*6966*/ uint16(xArgImm8u), + /*6967*/ uint16(xMatch), + /*6968*/ uint16(xSetOp), uint16(PINSRW), + /*6970*/ uint16(xReadSlashR), + /*6971*/ uint16(xReadIb), + /*6972*/ uint16(xArgXmm), + /*6973*/ uint16(xArgR32M16), + /*6974*/ uint16(xArgImm8u), + /*6975*/ uint16(xMatch), + /*6976*/ uint16(xCondPrefix), 2, + 0x66, 6990, + 0x0, 6982, + /*6982*/ uint16(xSetOp), uint16(PEXTRW), + /*6984*/ uint16(xReadSlashR), + /*6985*/ uint16(xReadIb), + /*6986*/ uint16(xArgR32), + /*6987*/ uint16(xArgMm2), + /*6988*/ uint16(xArgImm8u), + /*6989*/ uint16(xMatch), + /*6990*/ uint16(xSetOp), uint16(PEXTRW), + /*6992*/ uint16(xReadSlashR), + /*6993*/ uint16(xReadIb), + /*6994*/ uint16(xArgR32), + /*6995*/ uint16(xArgXmm2), + /*6996*/ uint16(xArgImm8u), + /*6997*/ uint16(xMatch), + /*6998*/ uint16(xCondPrefix), 2, + 0x66, 7012, + 0x0, 7004, + /*7004*/ uint16(xSetOp), uint16(SHUFPS), + /*7006*/ uint16(xReadSlashR), + /*7007*/ uint16(xReadIb), + /*7008*/ uint16(xArgXmm1), + /*7009*/ uint16(xArgXmm2M128), + /*7010*/ uint16(xArgImm8u), + /*7011*/ uint16(xMatch), + /*7012*/ uint16(xSetOp), uint16(SHUFPD), + /*7014*/ uint16(xReadSlashR), + /*7015*/ uint16(xReadIb), + /*7016*/ uint16(xArgXmm1), + /*7017*/ uint16(xArgXmm2M128), + /*7018*/ uint16(xArgImm8u), + /*7019*/ uint16(xMatch), + /*7020*/ uint16(xCondSlashR), + 0, // 0 + 7029, // 1 + 0, // 2 + 7052, // 3 + 7075, // 4 + 7098, // 5 + 7121, // 6 + 0, // 7 + /*7029*/ uint16(xCondIs64), 7032, 7044, + /*7032*/ uint16(xCondDataSize), 7036, 7040, 0, + /*7036*/ uint16(xSetOp), uint16(CMPXCHG8B), + /*7038*/ uint16(xArgM64), + /*7039*/ uint16(xMatch), + /*7040*/ uint16(xSetOp), uint16(CMPXCHG8B), + /*7042*/ uint16(xArgM64), + /*7043*/ uint16(xMatch), + /*7044*/ uint16(xCondDataSize), 7036, 7040, 7048, + /*7048*/ uint16(xSetOp), uint16(CMPXCHG16B), + /*7050*/ uint16(xArgM128), + /*7051*/ uint16(xMatch), + /*7052*/ uint16(xCondIs64), 7055, 7067, + /*7055*/ uint16(xCondDataSize), 7059, 7063, 0, + /*7059*/ uint16(xSetOp), uint16(XRSTORS), + /*7061*/ uint16(xArgMem), + /*7062*/ uint16(xMatch), + /*7063*/ uint16(xSetOp), uint16(XRSTORS), + /*7065*/ uint16(xArgMem), + /*7066*/ uint16(xMatch), + /*7067*/ uint16(xCondDataSize), 7059, 7063, 7071, + /*7071*/ uint16(xSetOp), uint16(XRSTORS64), + /*7073*/ uint16(xArgMem), + /*7074*/ uint16(xMatch), + /*7075*/ uint16(xCondIs64), 7078, 7090, + /*7078*/ uint16(xCondDataSize), 7082, 7086, 0, + /*7082*/ uint16(xSetOp), uint16(XSAVEC), + /*7084*/ uint16(xArgMem), + /*7085*/ uint16(xMatch), + /*7086*/ uint16(xSetOp), uint16(XSAVEC), + /*7088*/ uint16(xArgMem), + /*7089*/ uint16(xMatch), + /*7090*/ uint16(xCondDataSize), 7082, 7086, 7094, + /*7094*/ uint16(xSetOp), uint16(XSAVEC64), + /*7096*/ uint16(xArgMem), + /*7097*/ uint16(xMatch), + /*7098*/ uint16(xCondIs64), 7101, 7113, + /*7101*/ uint16(xCondDataSize), 7105, 7109, 0, + /*7105*/ uint16(xSetOp), uint16(XSAVES), + /*7107*/ uint16(xArgMem), + /*7108*/ uint16(xMatch), + /*7109*/ uint16(xSetOp), uint16(XSAVES), + /*7111*/ uint16(xArgMem), + /*7112*/ uint16(xMatch), + /*7113*/ uint16(xCondDataSize), 7105, 7109, 7117, + /*7117*/ uint16(xSetOp), uint16(XSAVES64), + /*7119*/ uint16(xArgMem), + /*7120*/ uint16(xMatch), + /*7121*/ uint16(xCondIs64), 7124, 7142, + /*7124*/ uint16(xCondDataSize), 7128, 7135, 0, + /*7128*/ uint16(xCondIsMem), 7131, 0, + /*7131*/ uint16(xSetOp), uint16(RDRAND), + /*7133*/ uint16(xArgRmf16), + /*7134*/ uint16(xMatch), + /*7135*/ uint16(xCondIsMem), 7138, 0, + /*7138*/ uint16(xSetOp), uint16(RDRAND), + /*7140*/ uint16(xArgRmf32), + /*7141*/ uint16(xMatch), + /*7142*/ uint16(xCondDataSize), 7128, 7135, 7146, + /*7146*/ uint16(xSetOp), uint16(RDRAND), + /*7148*/ uint16(xMatch), + /*7149*/ uint16(xCondIs64), 7152, 7164, + /*7152*/ uint16(xCondDataSize), 7156, 7160, 0, + /*7156*/ uint16(xSetOp), uint16(BSWAP), + /*7158*/ uint16(xArgR16op), + /*7159*/ uint16(xMatch), + /*7160*/ uint16(xSetOp), uint16(BSWAP), + /*7162*/ uint16(xArgR32op), + /*7163*/ uint16(xMatch), + /*7164*/ uint16(xCondDataSize), 7156, 7160, 7168, + /*7168*/ uint16(xSetOp), uint16(BSWAP), + /*7170*/ uint16(xArgR64op), + /*7171*/ uint16(xMatch), + /*7172*/ uint16(xCondPrefix), 2, + 0xF2, 7184, + 0x66, 7178, + /*7178*/ uint16(xSetOp), uint16(ADDSUBPD), + /*7180*/ uint16(xReadSlashR), + /*7181*/ uint16(xArgXmm1), + /*7182*/ uint16(xArgXmm2M128), + /*7183*/ uint16(xMatch), + /*7184*/ uint16(xSetOp), uint16(ADDSUBPS), + /*7186*/ uint16(xReadSlashR), + /*7187*/ uint16(xArgXmm1), + /*7188*/ uint16(xArgXmm2M128), + /*7189*/ uint16(xMatch), + /*7190*/ uint16(xCondPrefix), 2, + 0x66, 7202, + 0x0, 7196, + /*7196*/ uint16(xSetOp), uint16(PSRLW), + /*7198*/ uint16(xReadSlashR), + /*7199*/ uint16(xArgMm), + /*7200*/ uint16(xArgMmM64), + /*7201*/ uint16(xMatch), + /*7202*/ uint16(xSetOp), uint16(PSRLW), + /*7204*/ uint16(xReadSlashR), + /*7205*/ uint16(xArgXmm1), + /*7206*/ uint16(xArgXmm2M128), + /*7207*/ uint16(xMatch), + /*7208*/ uint16(xCondPrefix), 2, + 0x66, 7220, + 0x0, 7214, + /*7214*/ uint16(xSetOp), uint16(PSRLD), + /*7216*/ uint16(xReadSlashR), + /*7217*/ uint16(xArgMm), + /*7218*/ uint16(xArgMmM64), + /*7219*/ uint16(xMatch), + /*7220*/ uint16(xSetOp), uint16(PSRLD), + /*7222*/ uint16(xReadSlashR), + /*7223*/ uint16(xArgXmm1), + /*7224*/ uint16(xArgXmm2M128), + /*7225*/ uint16(xMatch), + /*7226*/ uint16(xCondPrefix), 2, + 0x66, 7238, + 0x0, 7232, + /*7232*/ uint16(xSetOp), uint16(PSRLQ), + /*7234*/ uint16(xReadSlashR), + /*7235*/ uint16(xArgMm), + /*7236*/ uint16(xArgMmM64), + /*7237*/ uint16(xMatch), + /*7238*/ uint16(xSetOp), uint16(PSRLQ), + /*7240*/ uint16(xReadSlashR), + /*7241*/ uint16(xArgXmm1), + /*7242*/ uint16(xArgXmm2M128), + /*7243*/ uint16(xMatch), + /*7244*/ uint16(xCondPrefix), 2, + 0x66, 7256, + 0x0, 7250, + /*7250*/ uint16(xSetOp), uint16(PADDQ), + /*7252*/ uint16(xReadSlashR), + /*7253*/ uint16(xArgMm1), + /*7254*/ uint16(xArgMm2M64), + /*7255*/ uint16(xMatch), + /*7256*/ uint16(xSetOp), uint16(PADDQ), + /*7258*/ uint16(xReadSlashR), + /*7259*/ uint16(xArgXmm1), + /*7260*/ uint16(xArgXmm2M128), + /*7261*/ uint16(xMatch), + /*7262*/ uint16(xCondPrefix), 2, + 0x66, 7274, + 0x0, 7268, + /*7268*/ uint16(xSetOp), uint16(PMULLW), + /*7270*/ uint16(xReadSlashR), + /*7271*/ uint16(xArgMm), + /*7272*/ uint16(xArgMmM64), + /*7273*/ uint16(xMatch), + /*7274*/ uint16(xSetOp), uint16(PMULLW), + /*7276*/ uint16(xReadSlashR), + /*7277*/ uint16(xArgXmm1), + /*7278*/ uint16(xArgXmm2M128), + /*7279*/ uint16(xMatch), + /*7280*/ uint16(xCondPrefix), 3, + 0xF3, 7300, + 0xF2, 7294, + 0x66, 7288, + /*7288*/ uint16(xSetOp), uint16(MOVQ), + /*7290*/ uint16(xReadSlashR), + /*7291*/ uint16(xArgXmm2M64), + /*7292*/ uint16(xArgXmm1), + /*7293*/ uint16(xMatch), + /*7294*/ uint16(xSetOp), uint16(MOVDQ2Q), + /*7296*/ uint16(xReadSlashR), + /*7297*/ uint16(xArgMm), + /*7298*/ uint16(xArgXmm2), + /*7299*/ uint16(xMatch), + /*7300*/ uint16(xSetOp), uint16(MOVQ2DQ), + /*7302*/ uint16(xReadSlashR), + /*7303*/ uint16(xArgXmm1), + /*7304*/ uint16(xArgMm2), + /*7305*/ uint16(xMatch), + /*7306*/ uint16(xCondPrefix), 2, + 0x66, 7318, + 0x0, 7312, + /*7312*/ uint16(xSetOp), uint16(PMOVMSKB), + /*7314*/ uint16(xReadSlashR), + /*7315*/ uint16(xArgR32), + /*7316*/ uint16(xArgMm2), + /*7317*/ uint16(xMatch), + /*7318*/ uint16(xSetOp), uint16(PMOVMSKB), + /*7320*/ uint16(xReadSlashR), + /*7321*/ uint16(xArgR32), + /*7322*/ uint16(xArgXmm2), + /*7323*/ uint16(xMatch), + /*7324*/ uint16(xCondPrefix), 2, + 0x66, 7336, + 0x0, 7330, + /*7330*/ uint16(xSetOp), uint16(PSUBUSB), + /*7332*/ uint16(xReadSlashR), + /*7333*/ uint16(xArgMm), + /*7334*/ uint16(xArgMmM64), + /*7335*/ uint16(xMatch), + /*7336*/ uint16(xSetOp), uint16(PSUBUSB), + /*7338*/ uint16(xReadSlashR), + /*7339*/ uint16(xArgXmm1), + /*7340*/ uint16(xArgXmm2M128), + /*7341*/ uint16(xMatch), + /*7342*/ uint16(xCondPrefix), 2, + 0x66, 7354, + 0x0, 7348, + /*7348*/ uint16(xSetOp), uint16(PSUBUSW), + /*7350*/ uint16(xReadSlashR), + /*7351*/ uint16(xArgMm), + /*7352*/ uint16(xArgMmM64), + /*7353*/ uint16(xMatch), + /*7354*/ uint16(xSetOp), uint16(PSUBUSW), + /*7356*/ uint16(xReadSlashR), + /*7357*/ uint16(xArgXmm1), + /*7358*/ uint16(xArgXmm2M128), + /*7359*/ uint16(xMatch), + /*7360*/ uint16(xCondPrefix), 2, + 0x66, 7372, + 0x0, 7366, + /*7366*/ uint16(xSetOp), uint16(PMINUB), + /*7368*/ uint16(xReadSlashR), + /*7369*/ uint16(xArgMm1), + /*7370*/ uint16(xArgMm2M64), + /*7371*/ uint16(xMatch), + /*7372*/ uint16(xSetOp), uint16(PMINUB), + /*7374*/ uint16(xReadSlashR), + /*7375*/ uint16(xArgXmm1), + /*7376*/ uint16(xArgXmm2M128), + /*7377*/ uint16(xMatch), + /*7378*/ uint16(xCondPrefix), 2, + 0x66, 7390, + 0x0, 7384, + /*7384*/ uint16(xSetOp), uint16(PAND), + /*7386*/ uint16(xReadSlashR), + /*7387*/ uint16(xArgMm), + /*7388*/ uint16(xArgMmM64), + /*7389*/ uint16(xMatch), + /*7390*/ uint16(xSetOp), uint16(PAND), + /*7392*/ uint16(xReadSlashR), + /*7393*/ uint16(xArgXmm1), + /*7394*/ uint16(xArgXmm2M128), + /*7395*/ uint16(xMatch), + /*7396*/ uint16(xCondPrefix), 2, + 0x66, 7408, + 0x0, 7402, + /*7402*/ uint16(xSetOp), uint16(PADDUSB), + /*7404*/ uint16(xReadSlashR), + /*7405*/ uint16(xArgMm), + /*7406*/ uint16(xArgMmM64), + /*7407*/ uint16(xMatch), + /*7408*/ uint16(xSetOp), uint16(PADDUSB), + /*7410*/ uint16(xReadSlashR), + /*7411*/ uint16(xArgXmm1), + /*7412*/ uint16(xArgXmm2M128), + /*7413*/ uint16(xMatch), + /*7414*/ uint16(xCondPrefix), 2, + 0x66, 7426, + 0x0, 7420, + /*7420*/ uint16(xSetOp), uint16(PADDUSW), + /*7422*/ uint16(xReadSlashR), + /*7423*/ uint16(xArgMm), + /*7424*/ uint16(xArgMmM64), + /*7425*/ uint16(xMatch), + /*7426*/ uint16(xSetOp), uint16(PADDUSW), + /*7428*/ uint16(xReadSlashR), + /*7429*/ uint16(xArgXmm1), + /*7430*/ uint16(xArgXmm2M128), + /*7431*/ uint16(xMatch), + /*7432*/ uint16(xCondPrefix), 2, + 0x66, 7444, + 0x0, 7438, + /*7438*/ uint16(xSetOp), uint16(PMAXUB), + /*7440*/ uint16(xReadSlashR), + /*7441*/ uint16(xArgMm1), + /*7442*/ uint16(xArgMm2M64), + /*7443*/ uint16(xMatch), + /*7444*/ uint16(xSetOp), uint16(PMAXUB), + /*7446*/ uint16(xReadSlashR), + /*7447*/ uint16(xArgXmm1), + /*7448*/ uint16(xArgXmm2M128), + /*7449*/ uint16(xMatch), + /*7450*/ uint16(xCondPrefix), 2, + 0x66, 7462, + 0x0, 7456, + /*7456*/ uint16(xSetOp), uint16(PANDN), + /*7458*/ uint16(xReadSlashR), + /*7459*/ uint16(xArgMm), + /*7460*/ uint16(xArgMmM64), + /*7461*/ uint16(xMatch), + /*7462*/ uint16(xSetOp), uint16(PANDN), + /*7464*/ uint16(xReadSlashR), + /*7465*/ uint16(xArgXmm1), + /*7466*/ uint16(xArgXmm2M128), + /*7467*/ uint16(xMatch), + /*7468*/ uint16(xCondPrefix), 2, + 0x66, 7480, + 0x0, 7474, + /*7474*/ uint16(xSetOp), uint16(PAVGB), + /*7476*/ uint16(xReadSlashR), + /*7477*/ uint16(xArgMm1), + /*7478*/ uint16(xArgMm2M64), + /*7479*/ uint16(xMatch), + /*7480*/ uint16(xSetOp), uint16(PAVGB), + /*7482*/ uint16(xReadSlashR), + /*7483*/ uint16(xArgXmm1), + /*7484*/ uint16(xArgXmm2M128), + /*7485*/ uint16(xMatch), + /*7486*/ uint16(xCondPrefix), 2, + 0x66, 7498, + 0x0, 7492, + /*7492*/ uint16(xSetOp), uint16(PSRAW), + /*7494*/ uint16(xReadSlashR), + /*7495*/ uint16(xArgMm), + /*7496*/ uint16(xArgMmM64), + /*7497*/ uint16(xMatch), + /*7498*/ uint16(xSetOp), uint16(PSRAW), + /*7500*/ uint16(xReadSlashR), + /*7501*/ uint16(xArgXmm1), + /*7502*/ uint16(xArgXmm2M128), + /*7503*/ uint16(xMatch), + /*7504*/ uint16(xCondPrefix), 2, + 0x66, 7516, + 0x0, 7510, + /*7510*/ uint16(xSetOp), uint16(PSRAD), + /*7512*/ uint16(xReadSlashR), + /*7513*/ uint16(xArgMm), + /*7514*/ uint16(xArgMmM64), + /*7515*/ uint16(xMatch), + /*7516*/ uint16(xSetOp), uint16(PSRAD), + /*7518*/ uint16(xReadSlashR), + /*7519*/ uint16(xArgXmm1), + /*7520*/ uint16(xArgXmm2M128), + /*7521*/ uint16(xMatch), + /*7522*/ uint16(xCondPrefix), 2, + 0x66, 7534, + 0x0, 7528, + /*7528*/ uint16(xSetOp), uint16(PAVGW), + /*7530*/ uint16(xReadSlashR), + /*7531*/ uint16(xArgMm1), + /*7532*/ uint16(xArgMm2M64), + /*7533*/ uint16(xMatch), + /*7534*/ uint16(xSetOp), uint16(PAVGW), + /*7536*/ uint16(xReadSlashR), + /*7537*/ uint16(xArgXmm1), + /*7538*/ uint16(xArgXmm2M128), + /*7539*/ uint16(xMatch), + /*7540*/ uint16(xCondPrefix), 2, + 0x66, 7552, + 0x0, 7546, + /*7546*/ uint16(xSetOp), uint16(PMULHUW), + /*7548*/ uint16(xReadSlashR), + /*7549*/ uint16(xArgMm1), + /*7550*/ uint16(xArgMm2M64), + /*7551*/ uint16(xMatch), + /*7552*/ uint16(xSetOp), uint16(PMULHUW), + /*7554*/ uint16(xReadSlashR), + /*7555*/ uint16(xArgXmm1), + /*7556*/ uint16(xArgXmm2M128), + /*7557*/ uint16(xMatch), + /*7558*/ uint16(xCondPrefix), 2, + 0x66, 7570, + 0x0, 7564, + /*7564*/ uint16(xSetOp), uint16(PMULHW), + /*7566*/ uint16(xReadSlashR), + /*7567*/ uint16(xArgMm), + /*7568*/ uint16(xArgMmM64), + /*7569*/ uint16(xMatch), + /*7570*/ uint16(xSetOp), uint16(PMULHW), + /*7572*/ uint16(xReadSlashR), + /*7573*/ uint16(xArgXmm1), + /*7574*/ uint16(xArgXmm2M128), + /*7575*/ uint16(xMatch), + /*7576*/ uint16(xCondPrefix), 3, + 0xF3, 7596, + 0xF2, 7590, + 0x66, 7584, + /*7584*/ uint16(xSetOp), uint16(CVTTPD2DQ), + /*7586*/ uint16(xReadSlashR), + /*7587*/ uint16(xArgXmm1), + /*7588*/ uint16(xArgXmm2M128), + /*7589*/ uint16(xMatch), + /*7590*/ uint16(xSetOp), uint16(CVTPD2DQ), + /*7592*/ uint16(xReadSlashR), + /*7593*/ uint16(xArgXmm1), + /*7594*/ uint16(xArgXmm2M128), + /*7595*/ uint16(xMatch), + /*7596*/ uint16(xSetOp), uint16(CVTDQ2PD), + /*7598*/ uint16(xReadSlashR), + /*7599*/ uint16(xArgXmm1), + /*7600*/ uint16(xArgXmm2M64), + /*7601*/ uint16(xMatch), + /*7602*/ uint16(xCondPrefix), 2, + 0x66, 7614, + 0x0, 7608, + /*7608*/ uint16(xSetOp), uint16(MOVNTQ), + /*7610*/ uint16(xReadSlashR), + /*7611*/ uint16(xArgM64), + /*7612*/ uint16(xArgMm), + /*7613*/ uint16(xMatch), + /*7614*/ uint16(xSetOp), uint16(MOVNTDQ), + /*7616*/ uint16(xReadSlashR), + /*7617*/ uint16(xArgM128), + /*7618*/ uint16(xArgXmm), + /*7619*/ uint16(xMatch), + /*7620*/ uint16(xCondPrefix), 2, + 0x66, 7632, + 0x0, 7626, + /*7626*/ uint16(xSetOp), uint16(PSUBSB), + /*7628*/ uint16(xReadSlashR), + /*7629*/ uint16(xArgMm), + /*7630*/ uint16(xArgMmM64), + /*7631*/ uint16(xMatch), + /*7632*/ uint16(xSetOp), uint16(PSUBSB), + /*7634*/ uint16(xReadSlashR), + /*7635*/ uint16(xArgXmm1), + /*7636*/ uint16(xArgXmm2M128), + /*7637*/ uint16(xMatch), + /*7638*/ uint16(xCondPrefix), 2, + 0x66, 7650, + 0x0, 7644, + /*7644*/ uint16(xSetOp), uint16(PSUBSW), + /*7646*/ uint16(xReadSlashR), + /*7647*/ uint16(xArgMm), + /*7648*/ uint16(xArgMmM64), + /*7649*/ uint16(xMatch), + /*7650*/ uint16(xSetOp), uint16(PSUBSW), + /*7652*/ uint16(xReadSlashR), + /*7653*/ uint16(xArgXmm1), + /*7654*/ uint16(xArgXmm2M128), + /*7655*/ uint16(xMatch), + /*7656*/ uint16(xCondPrefix), 2, + 0x66, 7668, + 0x0, 7662, + /*7662*/ uint16(xSetOp), uint16(PMINSW), + /*7664*/ uint16(xReadSlashR), + /*7665*/ uint16(xArgMm1), + /*7666*/ uint16(xArgMm2M64), + /*7667*/ uint16(xMatch), + /*7668*/ uint16(xSetOp), uint16(PMINSW), + /*7670*/ uint16(xReadSlashR), + /*7671*/ uint16(xArgXmm1), + /*7672*/ uint16(xArgXmm2M128), + /*7673*/ uint16(xMatch), + /*7674*/ uint16(xCondPrefix), 2, + 0x66, 7686, + 0x0, 7680, + /*7680*/ uint16(xSetOp), uint16(POR), + /*7682*/ uint16(xReadSlashR), + /*7683*/ uint16(xArgMm), + /*7684*/ uint16(xArgMmM64), + /*7685*/ uint16(xMatch), + /*7686*/ uint16(xSetOp), uint16(POR), + /*7688*/ uint16(xReadSlashR), + /*7689*/ uint16(xArgXmm1), + /*7690*/ uint16(xArgXmm2M128), + /*7691*/ uint16(xMatch), + /*7692*/ uint16(xCondPrefix), 2, + 0x66, 7704, + 0x0, 7698, + /*7698*/ uint16(xSetOp), uint16(PADDSB), + /*7700*/ uint16(xReadSlashR), + /*7701*/ uint16(xArgMm), + /*7702*/ uint16(xArgMmM64), + /*7703*/ uint16(xMatch), + /*7704*/ uint16(xSetOp), uint16(PADDSB), + /*7706*/ uint16(xReadSlashR), + /*7707*/ uint16(xArgXmm1), + /*7708*/ uint16(xArgXmm2M128), + /*7709*/ uint16(xMatch), + /*7710*/ uint16(xCondPrefix), 2, + 0x66, 7722, + 0x0, 7716, + /*7716*/ uint16(xSetOp), uint16(PADDSW), + /*7718*/ uint16(xReadSlashR), + /*7719*/ uint16(xArgMm), + /*7720*/ uint16(xArgMmM64), + /*7721*/ uint16(xMatch), + /*7722*/ uint16(xSetOp), uint16(PADDSW), + /*7724*/ uint16(xReadSlashR), + /*7725*/ uint16(xArgXmm1), + /*7726*/ uint16(xArgXmm2M128), + /*7727*/ uint16(xMatch), + /*7728*/ uint16(xCondPrefix), 2, + 0x66, 7740, + 0x0, 7734, + /*7734*/ uint16(xSetOp), uint16(PMAXSW), + /*7736*/ uint16(xReadSlashR), + /*7737*/ uint16(xArgMm1), + /*7738*/ uint16(xArgMm2M64), + /*7739*/ uint16(xMatch), + /*7740*/ uint16(xSetOp), uint16(PMAXSW), + /*7742*/ uint16(xReadSlashR), + /*7743*/ uint16(xArgXmm1), + /*7744*/ uint16(xArgXmm2M128), + /*7745*/ uint16(xMatch), + /*7746*/ uint16(xCondPrefix), 2, + 0x66, 7758, + 0x0, 7752, + /*7752*/ uint16(xSetOp), uint16(PXOR), + /*7754*/ uint16(xReadSlashR), + /*7755*/ uint16(xArgMm), + /*7756*/ uint16(xArgMmM64), + /*7757*/ uint16(xMatch), + /*7758*/ uint16(xSetOp), uint16(PXOR), + /*7760*/ uint16(xReadSlashR), + /*7761*/ uint16(xArgXmm1), + /*7762*/ uint16(xArgXmm2M128), + /*7763*/ uint16(xMatch), + /*7764*/ uint16(xCondPrefix), 1, + 0xF2, 7768, + /*7768*/ uint16(xSetOp), uint16(LDDQU), + /*7770*/ uint16(xReadSlashR), + /*7771*/ uint16(xArgXmm1), + /*7772*/ uint16(xArgM128), + /*7773*/ uint16(xMatch), + /*7774*/ uint16(xCondPrefix), 2, + 0x66, 7786, + 0x0, 7780, + /*7780*/ uint16(xSetOp), uint16(PSLLW), + /*7782*/ uint16(xReadSlashR), + /*7783*/ uint16(xArgMm), + /*7784*/ uint16(xArgMmM64), + /*7785*/ uint16(xMatch), + /*7786*/ uint16(xSetOp), uint16(PSLLW), + /*7788*/ uint16(xReadSlashR), + /*7789*/ uint16(xArgXmm1), + /*7790*/ uint16(xArgXmm2M128), + /*7791*/ uint16(xMatch), + /*7792*/ uint16(xCondPrefix), 2, + 0x66, 7804, + 0x0, 7798, + /*7798*/ uint16(xSetOp), uint16(PSLLD), + /*7800*/ uint16(xReadSlashR), + /*7801*/ uint16(xArgMm), + /*7802*/ uint16(xArgMmM64), + /*7803*/ uint16(xMatch), + /*7804*/ uint16(xSetOp), uint16(PSLLD), + /*7806*/ uint16(xReadSlashR), + /*7807*/ uint16(xArgXmm1), + /*7808*/ uint16(xArgXmm2M128), + /*7809*/ uint16(xMatch), + /*7810*/ uint16(xCondPrefix), 2, + 0x66, 7822, + 0x0, 7816, + /*7816*/ uint16(xSetOp), uint16(PSLLQ), + /*7818*/ uint16(xReadSlashR), + /*7819*/ uint16(xArgMm), + /*7820*/ uint16(xArgMmM64), + /*7821*/ uint16(xMatch), + /*7822*/ uint16(xSetOp), uint16(PSLLQ), + /*7824*/ uint16(xReadSlashR), + /*7825*/ uint16(xArgXmm1), + /*7826*/ uint16(xArgXmm2M128), + /*7827*/ uint16(xMatch), + /*7828*/ uint16(xCondPrefix), 2, + 0x66, 7840, + 0x0, 7834, + /*7834*/ uint16(xSetOp), uint16(PMULUDQ), + /*7836*/ uint16(xReadSlashR), + /*7837*/ uint16(xArgMm1), + /*7838*/ uint16(xArgMm2M64), + /*7839*/ uint16(xMatch), + /*7840*/ uint16(xSetOp), uint16(PMULUDQ), + /*7842*/ uint16(xReadSlashR), + /*7843*/ uint16(xArgXmm1), + /*7844*/ uint16(xArgXmm2M128), + /*7845*/ uint16(xMatch), + /*7846*/ uint16(xCondPrefix), 2, + 0x66, 7858, + 0x0, 7852, + /*7852*/ uint16(xSetOp), uint16(PMADDWD), + /*7854*/ uint16(xReadSlashR), + /*7855*/ uint16(xArgMm), + /*7856*/ uint16(xArgMmM64), + /*7857*/ uint16(xMatch), + /*7858*/ uint16(xSetOp), uint16(PMADDWD), + /*7860*/ uint16(xReadSlashR), + /*7861*/ uint16(xArgXmm1), + /*7862*/ uint16(xArgXmm2M128), + /*7863*/ uint16(xMatch), + /*7864*/ uint16(xCondPrefix), 2, + 0x66, 7876, + 0x0, 7870, + /*7870*/ uint16(xSetOp), uint16(PSADBW), + /*7872*/ uint16(xReadSlashR), + /*7873*/ uint16(xArgMm1), + /*7874*/ uint16(xArgMm2M64), + /*7875*/ uint16(xMatch), + /*7876*/ uint16(xSetOp), uint16(PSADBW), + /*7878*/ uint16(xReadSlashR), + /*7879*/ uint16(xArgXmm1), + /*7880*/ uint16(xArgXmm2M128), + /*7881*/ uint16(xMatch), + /*7882*/ uint16(xCondPrefix), 2, + 0x66, 7894, + 0x0, 7888, + /*7888*/ uint16(xSetOp), uint16(MASKMOVQ), + /*7890*/ uint16(xReadSlashR), + /*7891*/ uint16(xArgMm1), + /*7892*/ uint16(xArgMm2), + /*7893*/ uint16(xMatch), + /*7894*/ uint16(xSetOp), uint16(MASKMOVDQU), + /*7896*/ uint16(xReadSlashR), + /*7897*/ uint16(xArgXmm1), + /*7898*/ uint16(xArgXmm2), + /*7899*/ uint16(xMatch), + /*7900*/ uint16(xCondPrefix), 2, + 0x66, 7912, + 0x0, 7906, + /*7906*/ uint16(xSetOp), uint16(PSUBB), + /*7908*/ uint16(xReadSlashR), + /*7909*/ uint16(xArgMm), + /*7910*/ uint16(xArgMmM64), + /*7911*/ uint16(xMatch), + /*7912*/ uint16(xSetOp), uint16(PSUBB), + /*7914*/ uint16(xReadSlashR), + /*7915*/ uint16(xArgXmm1), + /*7916*/ uint16(xArgXmm2M128), + /*7917*/ uint16(xMatch), + /*7918*/ uint16(xCondPrefix), 2, + 0x66, 7930, + 0x0, 7924, + /*7924*/ uint16(xSetOp), uint16(PSUBW), + /*7926*/ uint16(xReadSlashR), + /*7927*/ uint16(xArgMm), + /*7928*/ uint16(xArgMmM64), + /*7929*/ uint16(xMatch), + /*7930*/ uint16(xSetOp), uint16(PSUBW), + /*7932*/ uint16(xReadSlashR), + /*7933*/ uint16(xArgXmm1), + /*7934*/ uint16(xArgXmm2M128), + /*7935*/ uint16(xMatch), + /*7936*/ uint16(xCondPrefix), 2, + 0x66, 7948, + 0x0, 7942, + /*7942*/ uint16(xSetOp), uint16(PSUBD), + /*7944*/ uint16(xReadSlashR), + /*7945*/ uint16(xArgMm), + /*7946*/ uint16(xArgMmM64), + /*7947*/ uint16(xMatch), + /*7948*/ uint16(xSetOp), uint16(PSUBD), + /*7950*/ uint16(xReadSlashR), + /*7951*/ uint16(xArgXmm1), + /*7952*/ uint16(xArgXmm2M128), + /*7953*/ uint16(xMatch), + /*7954*/ uint16(xCondPrefix), 2, + 0x66, 7966, + 0x0, 7960, + /*7960*/ uint16(xSetOp), uint16(PSUBQ), + /*7962*/ uint16(xReadSlashR), + /*7963*/ uint16(xArgMm1), + /*7964*/ uint16(xArgMm2M64), + /*7965*/ uint16(xMatch), + /*7966*/ uint16(xSetOp), uint16(PSUBQ), + /*7968*/ uint16(xReadSlashR), + /*7969*/ uint16(xArgXmm1), + /*7970*/ uint16(xArgXmm2M128), + /*7971*/ uint16(xMatch), + /*7972*/ uint16(xCondPrefix), 2, + 0x66, 7984, + 0x0, 7978, + /*7978*/ uint16(xSetOp), uint16(PADDB), + /*7980*/ uint16(xReadSlashR), + /*7981*/ uint16(xArgMm), + /*7982*/ uint16(xArgMmM64), + /*7983*/ uint16(xMatch), + /*7984*/ uint16(xSetOp), uint16(PADDB), + /*7986*/ uint16(xReadSlashR), + /*7987*/ uint16(xArgXmm1), + /*7988*/ uint16(xArgXmm2M128), + /*7989*/ uint16(xMatch), + /*7990*/ uint16(xCondPrefix), 2, + 0x66, 8002, + 0x0, 7996, + /*7996*/ uint16(xSetOp), uint16(PADDW), + /*7998*/ uint16(xReadSlashR), + /*7999*/ uint16(xArgMm), + /*8000*/ uint16(xArgMmM64), + /*8001*/ uint16(xMatch), + /*8002*/ uint16(xSetOp), uint16(PADDW), + /*8004*/ uint16(xReadSlashR), + /*8005*/ uint16(xArgXmm1), + /*8006*/ uint16(xArgXmm2M128), + /*8007*/ uint16(xMatch), + /*8008*/ uint16(xCondPrefix), 2, + 0x66, 8020, + 0x0, 8014, + /*8014*/ uint16(xSetOp), uint16(PADDD), + /*8016*/ uint16(xReadSlashR), + /*8017*/ uint16(xArgMm), + /*8018*/ uint16(xArgMmM64), + /*8019*/ uint16(xMatch), + /*8020*/ uint16(xSetOp), uint16(PADDD), + /*8022*/ uint16(xReadSlashR), + /*8023*/ uint16(xArgXmm1), + /*8024*/ uint16(xArgXmm2M128), + /*8025*/ uint16(xMatch), + /*8026*/ uint16(xSetOp), uint16(ADC), + /*8028*/ uint16(xReadSlashR), + /*8029*/ uint16(xArgRM8), + /*8030*/ uint16(xArgR8), + /*8031*/ uint16(xMatch), + /*8032*/ uint16(xCondIs64), 8035, 8051, + /*8035*/ uint16(xCondDataSize), 8039, 8045, 0, + /*8039*/ uint16(xSetOp), uint16(ADC), + /*8041*/ uint16(xReadSlashR), + /*8042*/ uint16(xArgRM16), + /*8043*/ uint16(xArgR16), + /*8044*/ uint16(xMatch), + /*8045*/ uint16(xSetOp), uint16(ADC), + /*8047*/ uint16(xReadSlashR), + /*8048*/ uint16(xArgRM32), + /*8049*/ uint16(xArgR32), + /*8050*/ uint16(xMatch), + /*8051*/ uint16(xCondDataSize), 8039, 8045, 8055, + /*8055*/ uint16(xSetOp), uint16(ADC), + /*8057*/ uint16(xReadSlashR), + /*8058*/ uint16(xArgRM64), + /*8059*/ uint16(xArgR64), + /*8060*/ uint16(xMatch), + /*8061*/ uint16(xSetOp), uint16(ADC), + /*8063*/ uint16(xReadSlashR), + /*8064*/ uint16(xArgR8), + /*8065*/ uint16(xArgRM8), + /*8066*/ uint16(xMatch), + /*8067*/ uint16(xCondIs64), 8070, 8086, + /*8070*/ uint16(xCondDataSize), 8074, 8080, 0, + /*8074*/ uint16(xSetOp), uint16(ADC), + /*8076*/ uint16(xReadSlashR), + /*8077*/ uint16(xArgR16), + /*8078*/ uint16(xArgRM16), + /*8079*/ uint16(xMatch), + /*8080*/ uint16(xSetOp), uint16(ADC), + /*8082*/ uint16(xReadSlashR), + /*8083*/ uint16(xArgR32), + /*8084*/ uint16(xArgRM32), + /*8085*/ uint16(xMatch), + /*8086*/ uint16(xCondDataSize), 8074, 8080, 8090, + /*8090*/ uint16(xSetOp), uint16(ADC), + /*8092*/ uint16(xReadSlashR), + /*8093*/ uint16(xArgR64), + /*8094*/ uint16(xArgRM64), + /*8095*/ uint16(xMatch), + /*8096*/ uint16(xSetOp), uint16(ADC), + /*8098*/ uint16(xReadIb), + /*8099*/ uint16(xArgAL), + /*8100*/ uint16(xArgImm8u), + /*8101*/ uint16(xMatch), + /*8102*/ uint16(xCondIs64), 8105, 8121, + /*8105*/ uint16(xCondDataSize), 8109, 8115, 0, + /*8109*/ uint16(xSetOp), uint16(ADC), + /*8111*/ uint16(xReadIw), + /*8112*/ uint16(xArgAX), + /*8113*/ uint16(xArgImm16), + /*8114*/ uint16(xMatch), + /*8115*/ uint16(xSetOp), uint16(ADC), + /*8117*/ uint16(xReadId), + /*8118*/ uint16(xArgEAX), + /*8119*/ uint16(xArgImm32), + /*8120*/ uint16(xMatch), + /*8121*/ uint16(xCondDataSize), 8109, 8115, 8125, + /*8125*/ uint16(xSetOp), uint16(ADC), + /*8127*/ uint16(xReadId), + /*8128*/ uint16(xArgRAX), + /*8129*/ uint16(xArgImm32), + /*8130*/ uint16(xMatch), + /*8131*/ uint16(xCondIs64), 8134, 0, + /*8134*/ uint16(xSetOp), uint16(PUSH), + /*8136*/ uint16(xArgSS), + /*8137*/ uint16(xMatch), + /*8138*/ uint16(xCondIs64), 8141, 0, + /*8141*/ uint16(xSetOp), uint16(POP), + /*8143*/ uint16(xArgSS), + /*8144*/ uint16(xMatch), + /*8145*/ uint16(xSetOp), uint16(SBB), + /*8147*/ uint16(xReadSlashR), + /*8148*/ uint16(xArgRM8), + /*8149*/ uint16(xArgR8), + /*8150*/ uint16(xMatch), + /*8151*/ uint16(xCondIs64), 8154, 8170, + /*8154*/ uint16(xCondDataSize), 8158, 8164, 0, + /*8158*/ uint16(xSetOp), uint16(SBB), + /*8160*/ uint16(xReadSlashR), + /*8161*/ uint16(xArgRM16), + /*8162*/ uint16(xArgR16), + /*8163*/ uint16(xMatch), + /*8164*/ uint16(xSetOp), uint16(SBB), + /*8166*/ uint16(xReadSlashR), + /*8167*/ uint16(xArgRM32), + /*8168*/ uint16(xArgR32), + /*8169*/ uint16(xMatch), + /*8170*/ uint16(xCondDataSize), 8158, 8164, 8174, + /*8174*/ uint16(xSetOp), uint16(SBB), + /*8176*/ uint16(xReadSlashR), + /*8177*/ uint16(xArgRM64), + /*8178*/ uint16(xArgR64), + /*8179*/ uint16(xMatch), + /*8180*/ uint16(xSetOp), uint16(SBB), + /*8182*/ uint16(xReadSlashR), + /*8183*/ uint16(xArgR8), + /*8184*/ uint16(xArgRM8), + /*8185*/ uint16(xMatch), + /*8186*/ uint16(xCondIs64), 8189, 8205, + /*8189*/ uint16(xCondDataSize), 8193, 8199, 0, + /*8193*/ uint16(xSetOp), uint16(SBB), + /*8195*/ uint16(xReadSlashR), + /*8196*/ uint16(xArgR16), + /*8197*/ uint16(xArgRM16), + /*8198*/ uint16(xMatch), + /*8199*/ uint16(xSetOp), uint16(SBB), + /*8201*/ uint16(xReadSlashR), + /*8202*/ uint16(xArgR32), + /*8203*/ uint16(xArgRM32), + /*8204*/ uint16(xMatch), + /*8205*/ uint16(xCondDataSize), 8193, 8199, 8209, + /*8209*/ uint16(xSetOp), uint16(SBB), + /*8211*/ uint16(xReadSlashR), + /*8212*/ uint16(xArgR64), + /*8213*/ uint16(xArgRM64), + /*8214*/ uint16(xMatch), + /*8215*/ uint16(xSetOp), uint16(SBB), + /*8217*/ uint16(xReadIb), + /*8218*/ uint16(xArgAL), + /*8219*/ uint16(xArgImm8u), + /*8220*/ uint16(xMatch), + /*8221*/ uint16(xCondIs64), 8224, 8240, + /*8224*/ uint16(xCondDataSize), 8228, 8234, 0, + /*8228*/ uint16(xSetOp), uint16(SBB), + /*8230*/ uint16(xReadIw), + /*8231*/ uint16(xArgAX), + /*8232*/ uint16(xArgImm16), + /*8233*/ uint16(xMatch), + /*8234*/ uint16(xSetOp), uint16(SBB), + /*8236*/ uint16(xReadId), + /*8237*/ uint16(xArgEAX), + /*8238*/ uint16(xArgImm32), + /*8239*/ uint16(xMatch), + /*8240*/ uint16(xCondDataSize), 8228, 8234, 8244, + /*8244*/ uint16(xSetOp), uint16(SBB), + /*8246*/ uint16(xReadId), + /*8247*/ uint16(xArgRAX), + /*8248*/ uint16(xArgImm32), + /*8249*/ uint16(xMatch), + /*8250*/ uint16(xCondIs64), 8253, 0, + /*8253*/ uint16(xSetOp), uint16(PUSH), + /*8255*/ uint16(xArgDS), + /*8256*/ uint16(xMatch), + /*8257*/ uint16(xCondIs64), 8260, 0, + /*8260*/ uint16(xSetOp), uint16(POP), + /*8262*/ uint16(xArgDS), + /*8263*/ uint16(xMatch), + /*8264*/ uint16(xSetOp), uint16(AND), + /*8266*/ uint16(xReadSlashR), + /*8267*/ uint16(xArgRM8), + /*8268*/ uint16(xArgR8), + /*8269*/ uint16(xMatch), + /*8270*/ uint16(xCondIs64), 8273, 8289, + /*8273*/ uint16(xCondDataSize), 8277, 8283, 0, + /*8277*/ uint16(xSetOp), uint16(AND), + /*8279*/ uint16(xReadSlashR), + /*8280*/ uint16(xArgRM16), + /*8281*/ uint16(xArgR16), + /*8282*/ uint16(xMatch), + /*8283*/ uint16(xSetOp), uint16(AND), + /*8285*/ uint16(xReadSlashR), + /*8286*/ uint16(xArgRM32), + /*8287*/ uint16(xArgR32), + /*8288*/ uint16(xMatch), + /*8289*/ uint16(xCondDataSize), 8277, 8283, 8293, + /*8293*/ uint16(xSetOp), uint16(AND), + /*8295*/ uint16(xReadSlashR), + /*8296*/ uint16(xArgRM64), + /*8297*/ uint16(xArgR64), + /*8298*/ uint16(xMatch), + /*8299*/ uint16(xSetOp), uint16(AND), + /*8301*/ uint16(xReadSlashR), + /*8302*/ uint16(xArgR8), + /*8303*/ uint16(xArgRM8), + /*8304*/ uint16(xMatch), + /*8305*/ uint16(xCondIs64), 8308, 8324, + /*8308*/ uint16(xCondDataSize), 8312, 8318, 0, + /*8312*/ uint16(xSetOp), uint16(AND), + /*8314*/ uint16(xReadSlashR), + /*8315*/ uint16(xArgR16), + /*8316*/ uint16(xArgRM16), + /*8317*/ uint16(xMatch), + /*8318*/ uint16(xSetOp), uint16(AND), + /*8320*/ uint16(xReadSlashR), + /*8321*/ uint16(xArgR32), + /*8322*/ uint16(xArgRM32), + /*8323*/ uint16(xMatch), + /*8324*/ uint16(xCondDataSize), 8312, 8318, 8328, + /*8328*/ uint16(xSetOp), uint16(AND), + /*8330*/ uint16(xReadSlashR), + /*8331*/ uint16(xArgR64), + /*8332*/ uint16(xArgRM64), + /*8333*/ uint16(xMatch), + /*8334*/ uint16(xSetOp), uint16(AND), + /*8336*/ uint16(xReadIb), + /*8337*/ uint16(xArgAL), + /*8338*/ uint16(xArgImm8u), + /*8339*/ uint16(xMatch), + /*8340*/ uint16(xCondIs64), 8343, 8359, + /*8343*/ uint16(xCondDataSize), 8347, 8353, 0, + /*8347*/ uint16(xSetOp), uint16(AND), + /*8349*/ uint16(xReadIw), + /*8350*/ uint16(xArgAX), + /*8351*/ uint16(xArgImm16), + /*8352*/ uint16(xMatch), + /*8353*/ uint16(xSetOp), uint16(AND), + /*8355*/ uint16(xReadId), + /*8356*/ uint16(xArgEAX), + /*8357*/ uint16(xArgImm32), + /*8358*/ uint16(xMatch), + /*8359*/ uint16(xCondDataSize), 8347, 8353, 8363, + /*8363*/ uint16(xSetOp), uint16(AND), + /*8365*/ uint16(xReadId), + /*8366*/ uint16(xArgRAX), + /*8367*/ uint16(xArgImm32), + /*8368*/ uint16(xMatch), + /*8369*/ uint16(xCondIs64), 8372, 0, + /*8372*/ uint16(xSetOp), uint16(DAA), + /*8374*/ uint16(xMatch), + /*8375*/ uint16(xSetOp), uint16(SUB), + /*8377*/ uint16(xReadSlashR), + /*8378*/ uint16(xArgRM8), + /*8379*/ uint16(xArgR8), + /*8380*/ uint16(xMatch), + /*8381*/ uint16(xCondIs64), 8384, 8400, + /*8384*/ uint16(xCondDataSize), 8388, 8394, 0, + /*8388*/ uint16(xSetOp), uint16(SUB), + /*8390*/ uint16(xReadSlashR), + /*8391*/ uint16(xArgRM16), + /*8392*/ uint16(xArgR16), + /*8393*/ uint16(xMatch), + /*8394*/ uint16(xSetOp), uint16(SUB), + /*8396*/ uint16(xReadSlashR), + /*8397*/ uint16(xArgRM32), + /*8398*/ uint16(xArgR32), + /*8399*/ uint16(xMatch), + /*8400*/ uint16(xCondDataSize), 8388, 8394, 8404, + /*8404*/ uint16(xSetOp), uint16(SUB), + /*8406*/ uint16(xReadSlashR), + /*8407*/ uint16(xArgRM64), + /*8408*/ uint16(xArgR64), + /*8409*/ uint16(xMatch), + /*8410*/ uint16(xSetOp), uint16(SUB), + /*8412*/ uint16(xReadSlashR), + /*8413*/ uint16(xArgR8), + /*8414*/ uint16(xArgRM8), + /*8415*/ uint16(xMatch), + /*8416*/ uint16(xCondIs64), 8419, 8435, + /*8419*/ uint16(xCondDataSize), 8423, 8429, 0, + /*8423*/ uint16(xSetOp), uint16(SUB), + /*8425*/ uint16(xReadSlashR), + /*8426*/ uint16(xArgR16), + /*8427*/ uint16(xArgRM16), + /*8428*/ uint16(xMatch), + /*8429*/ uint16(xSetOp), uint16(SUB), + /*8431*/ uint16(xReadSlashR), + /*8432*/ uint16(xArgR32), + /*8433*/ uint16(xArgRM32), + /*8434*/ uint16(xMatch), + /*8435*/ uint16(xCondDataSize), 8423, 8429, 8439, + /*8439*/ uint16(xSetOp), uint16(SUB), + /*8441*/ uint16(xReadSlashR), + /*8442*/ uint16(xArgR64), + /*8443*/ uint16(xArgRM64), + /*8444*/ uint16(xMatch), + /*8445*/ uint16(xSetOp), uint16(SUB), + /*8447*/ uint16(xReadIb), + /*8448*/ uint16(xArgAL), + /*8449*/ uint16(xArgImm8u), + /*8450*/ uint16(xMatch), + /*8451*/ uint16(xCondIs64), 8454, 8470, + /*8454*/ uint16(xCondDataSize), 8458, 8464, 0, + /*8458*/ uint16(xSetOp), uint16(SUB), + /*8460*/ uint16(xReadIw), + /*8461*/ uint16(xArgAX), + /*8462*/ uint16(xArgImm16), + /*8463*/ uint16(xMatch), + /*8464*/ uint16(xSetOp), uint16(SUB), + /*8466*/ uint16(xReadId), + /*8467*/ uint16(xArgEAX), + /*8468*/ uint16(xArgImm32), + /*8469*/ uint16(xMatch), + /*8470*/ uint16(xCondDataSize), 8458, 8464, 8474, + /*8474*/ uint16(xSetOp), uint16(SUB), + /*8476*/ uint16(xReadId), + /*8477*/ uint16(xArgRAX), + /*8478*/ uint16(xArgImm32), + /*8479*/ uint16(xMatch), + /*8480*/ uint16(xCondIs64), 8483, 0, + /*8483*/ uint16(xSetOp), uint16(DAS), + /*8485*/ uint16(xMatch), + /*8486*/ uint16(xSetOp), uint16(XOR), + /*8488*/ uint16(xReadSlashR), + /*8489*/ uint16(xArgRM8), + /*8490*/ uint16(xArgR8), + /*8491*/ uint16(xMatch), + /*8492*/ uint16(xCondIs64), 8495, 8511, + /*8495*/ uint16(xCondDataSize), 8499, 8505, 0, + /*8499*/ uint16(xSetOp), uint16(XOR), + /*8501*/ uint16(xReadSlashR), + /*8502*/ uint16(xArgRM16), + /*8503*/ uint16(xArgR16), + /*8504*/ uint16(xMatch), + /*8505*/ uint16(xSetOp), uint16(XOR), + /*8507*/ uint16(xReadSlashR), + /*8508*/ uint16(xArgRM32), + /*8509*/ uint16(xArgR32), + /*8510*/ uint16(xMatch), + /*8511*/ uint16(xCondDataSize), 8499, 8505, 8515, + /*8515*/ uint16(xSetOp), uint16(XOR), + /*8517*/ uint16(xReadSlashR), + /*8518*/ uint16(xArgRM64), + /*8519*/ uint16(xArgR64), + /*8520*/ uint16(xMatch), + /*8521*/ uint16(xSetOp), uint16(XOR), + /*8523*/ uint16(xReadSlashR), + /*8524*/ uint16(xArgR8), + /*8525*/ uint16(xArgRM8), + /*8526*/ uint16(xMatch), + /*8527*/ uint16(xCondIs64), 8530, 8546, + /*8530*/ uint16(xCondDataSize), 8534, 8540, 0, + /*8534*/ uint16(xSetOp), uint16(XOR), + /*8536*/ uint16(xReadSlashR), + /*8537*/ uint16(xArgR16), + /*8538*/ uint16(xArgRM16), + /*8539*/ uint16(xMatch), + /*8540*/ uint16(xSetOp), uint16(XOR), + /*8542*/ uint16(xReadSlashR), + /*8543*/ uint16(xArgR32), + /*8544*/ uint16(xArgRM32), + /*8545*/ uint16(xMatch), + /*8546*/ uint16(xCondDataSize), 8534, 8540, 8550, + /*8550*/ uint16(xSetOp), uint16(XOR), + /*8552*/ uint16(xReadSlashR), + /*8553*/ uint16(xArgR64), + /*8554*/ uint16(xArgRM64), + /*8555*/ uint16(xMatch), + /*8556*/ uint16(xSetOp), uint16(XOR), + /*8558*/ uint16(xReadIb), + /*8559*/ uint16(xArgAL), + /*8560*/ uint16(xArgImm8u), + /*8561*/ uint16(xMatch), + /*8562*/ uint16(xCondIs64), 8565, 8581, + /*8565*/ uint16(xCondDataSize), 8569, 8575, 0, + /*8569*/ uint16(xSetOp), uint16(XOR), + /*8571*/ uint16(xReadIw), + /*8572*/ uint16(xArgAX), + /*8573*/ uint16(xArgImm16), + /*8574*/ uint16(xMatch), + /*8575*/ uint16(xSetOp), uint16(XOR), + /*8577*/ uint16(xReadId), + /*8578*/ uint16(xArgEAX), + /*8579*/ uint16(xArgImm32), + /*8580*/ uint16(xMatch), + /*8581*/ uint16(xCondDataSize), 8569, 8575, 8585, + /*8585*/ uint16(xSetOp), uint16(XOR), + /*8587*/ uint16(xReadId), + /*8588*/ uint16(xArgRAX), + /*8589*/ uint16(xArgImm32), + /*8590*/ uint16(xMatch), + /*8591*/ uint16(xCondIs64), 8594, 0, + /*8594*/ uint16(xSetOp), uint16(AAA), + /*8596*/ uint16(xMatch), + /*8597*/ uint16(xSetOp), uint16(CMP), + /*8599*/ uint16(xReadSlashR), + /*8600*/ uint16(xArgRM8), + /*8601*/ uint16(xArgR8), + /*8602*/ uint16(xMatch), + /*8603*/ uint16(xCondIs64), 8606, 8622, + /*8606*/ uint16(xCondDataSize), 8610, 8616, 0, + /*8610*/ uint16(xSetOp), uint16(CMP), + /*8612*/ uint16(xReadSlashR), + /*8613*/ uint16(xArgRM16), + /*8614*/ uint16(xArgR16), + /*8615*/ uint16(xMatch), + /*8616*/ uint16(xSetOp), uint16(CMP), + /*8618*/ uint16(xReadSlashR), + /*8619*/ uint16(xArgRM32), + /*8620*/ uint16(xArgR32), + /*8621*/ uint16(xMatch), + /*8622*/ uint16(xCondDataSize), 8610, 8616, 8626, + /*8626*/ uint16(xSetOp), uint16(CMP), + /*8628*/ uint16(xReadSlashR), + /*8629*/ uint16(xArgRM64), + /*8630*/ uint16(xArgR64), + /*8631*/ uint16(xMatch), + /*8632*/ uint16(xSetOp), uint16(CMP), + /*8634*/ uint16(xReadSlashR), + /*8635*/ uint16(xArgR8), + /*8636*/ uint16(xArgRM8), + /*8637*/ uint16(xMatch), + /*8638*/ uint16(xCondIs64), 8641, 8657, + /*8641*/ uint16(xCondDataSize), 8645, 8651, 0, + /*8645*/ uint16(xSetOp), uint16(CMP), + /*8647*/ uint16(xReadSlashR), + /*8648*/ uint16(xArgR16), + /*8649*/ uint16(xArgRM16), + /*8650*/ uint16(xMatch), + /*8651*/ uint16(xSetOp), uint16(CMP), + /*8653*/ uint16(xReadSlashR), + /*8654*/ uint16(xArgR32), + /*8655*/ uint16(xArgRM32), + /*8656*/ uint16(xMatch), + /*8657*/ uint16(xCondDataSize), 8645, 8651, 8661, + /*8661*/ uint16(xSetOp), uint16(CMP), + /*8663*/ uint16(xReadSlashR), + /*8664*/ uint16(xArgR64), + /*8665*/ uint16(xArgRM64), + /*8666*/ uint16(xMatch), + /*8667*/ uint16(xSetOp), uint16(CMP), + /*8669*/ uint16(xReadIb), + /*8670*/ uint16(xArgAL), + /*8671*/ uint16(xArgImm8u), + /*8672*/ uint16(xMatch), + /*8673*/ uint16(xCondIs64), 8676, 8692, + /*8676*/ uint16(xCondDataSize), 8680, 8686, 0, + /*8680*/ uint16(xSetOp), uint16(CMP), + /*8682*/ uint16(xReadIw), + /*8683*/ uint16(xArgAX), + /*8684*/ uint16(xArgImm16), + /*8685*/ uint16(xMatch), + /*8686*/ uint16(xSetOp), uint16(CMP), + /*8688*/ uint16(xReadId), + /*8689*/ uint16(xArgEAX), + /*8690*/ uint16(xArgImm32), + /*8691*/ uint16(xMatch), + /*8692*/ uint16(xCondDataSize), 8680, 8686, 8696, + /*8696*/ uint16(xSetOp), uint16(CMP), + /*8698*/ uint16(xReadId), + /*8699*/ uint16(xArgRAX), + /*8700*/ uint16(xArgImm32), + /*8701*/ uint16(xMatch), + /*8702*/ uint16(xCondIs64), 8705, 0, + /*8705*/ uint16(xSetOp), uint16(AAS), + /*8707*/ uint16(xMatch), + /*8708*/ uint16(xCondIs64), 8711, 0, + /*8711*/ uint16(xCondDataSize), 8715, 8719, 0, + /*8715*/ uint16(xSetOp), uint16(INC), + /*8717*/ uint16(xArgR16op), + /*8718*/ uint16(xMatch), + /*8719*/ uint16(xSetOp), uint16(INC), + /*8721*/ uint16(xArgR32op), + /*8722*/ uint16(xMatch), + /*8723*/ uint16(xCondIs64), 8726, 0, + /*8726*/ uint16(xCondDataSize), 8730, 8734, 0, + /*8730*/ uint16(xSetOp), uint16(DEC), + /*8732*/ uint16(xArgR16op), + /*8733*/ uint16(xMatch), + /*8734*/ uint16(xSetOp), uint16(DEC), + /*8736*/ uint16(xArgR32op), + /*8737*/ uint16(xMatch), + /*8738*/ uint16(xCondIs64), 8741, 8753, + /*8741*/ uint16(xCondDataSize), 8745, 8749, 0, + /*8745*/ uint16(xSetOp), uint16(PUSH), + /*8747*/ uint16(xArgR16op), + /*8748*/ uint16(xMatch), + /*8749*/ uint16(xSetOp), uint16(PUSH), + /*8751*/ uint16(xArgR32op), + /*8752*/ uint16(xMatch), + /*8753*/ uint16(xCondDataSize), 8745, 8757, 8761, + /*8757*/ uint16(xSetOp), uint16(PUSH), + /*8759*/ uint16(xArgR64op), + /*8760*/ uint16(xMatch), + /*8761*/ uint16(xSetOp), uint16(PUSH), + /*8763*/ uint16(xArgR64op), + /*8764*/ uint16(xMatch), + /*8765*/ uint16(xCondIs64), 8768, 8780, + /*8768*/ uint16(xCondDataSize), 8772, 8776, 0, + /*8772*/ uint16(xSetOp), uint16(POP), + /*8774*/ uint16(xArgR16op), + /*8775*/ uint16(xMatch), + /*8776*/ uint16(xSetOp), uint16(POP), + /*8778*/ uint16(xArgR32op), + /*8779*/ uint16(xMatch), + /*8780*/ uint16(xCondDataSize), 8772, 8784, 8788, + /*8784*/ uint16(xSetOp), uint16(POP), + /*8786*/ uint16(xArgR64op), + /*8787*/ uint16(xMatch), + /*8788*/ uint16(xSetOp), uint16(POP), + /*8790*/ uint16(xArgR64op), + /*8791*/ uint16(xMatch), + /*8792*/ uint16(xCondIs64), 8795, 0, + /*8795*/ uint16(xCondDataSize), 8799, 8802, 0, + /*8799*/ uint16(xSetOp), uint16(PUSHA), + /*8801*/ uint16(xMatch), + /*8802*/ uint16(xSetOp), uint16(PUSHAD), + /*8804*/ uint16(xMatch), + /*8805*/ uint16(xCondIs64), 8808, 0, + /*8808*/ uint16(xCondDataSize), 8812, 8815, 0, + /*8812*/ uint16(xSetOp), uint16(POPA), + /*8814*/ uint16(xMatch), + /*8815*/ uint16(xSetOp), uint16(POPAD), + /*8817*/ uint16(xMatch), + /*8818*/ uint16(xCondIs64), 8821, 0, + /*8821*/ uint16(xCondDataSize), 8825, 8831, 0, + /*8825*/ uint16(xSetOp), uint16(BOUND), + /*8827*/ uint16(xReadSlashR), + /*8828*/ uint16(xArgR16), + /*8829*/ uint16(xArgM16and16), + /*8830*/ uint16(xMatch), + /*8831*/ uint16(xSetOp), uint16(BOUND), + /*8833*/ uint16(xReadSlashR), + /*8834*/ uint16(xArgR32), + /*8835*/ uint16(xArgM32and32), + /*8836*/ uint16(xMatch), + /*8837*/ uint16(xCondIs64), 8840, 8846, + /*8840*/ uint16(xSetOp), uint16(ARPL), + /*8842*/ uint16(xReadSlashR), + /*8843*/ uint16(xArgRM16), + /*8844*/ uint16(xArgR16), + /*8845*/ uint16(xMatch), + /*8846*/ uint16(xCondDataSize), 8850, 8856, 8862, + /*8850*/ uint16(xSetOp), uint16(MOVSXD), + /*8852*/ uint16(xReadSlashR), + /*8853*/ uint16(xArgR16), + /*8854*/ uint16(xArgRM32), + /*8855*/ uint16(xMatch), + /*8856*/ uint16(xSetOp), uint16(MOVSXD), + /*8858*/ uint16(xReadSlashR), + /*8859*/ uint16(xArgR32), + /*8860*/ uint16(xArgRM32), + /*8861*/ uint16(xMatch), + /*8862*/ uint16(xSetOp), uint16(MOVSXD), + /*8864*/ uint16(xReadSlashR), + /*8865*/ uint16(xArgR64), + /*8866*/ uint16(xArgRM32), + /*8867*/ uint16(xMatch), + /*8868*/ uint16(xCondDataSize), 8872, 8877, 8882, + /*8872*/ uint16(xSetOp), uint16(PUSH), + /*8874*/ uint16(xReadIw), + /*8875*/ uint16(xArgImm16), + /*8876*/ uint16(xMatch), + /*8877*/ uint16(xSetOp), uint16(PUSH), + /*8879*/ uint16(xReadId), + /*8880*/ uint16(xArgImm32), + /*8881*/ uint16(xMatch), + /*8882*/ uint16(xSetOp), uint16(PUSH), + /*8884*/ uint16(xReadId), + /*8885*/ uint16(xArgImm32), + /*8886*/ uint16(xMatch), + /*8887*/ uint16(xCondIs64), 8890, 8910, + /*8890*/ uint16(xCondDataSize), 8894, 8902, 0, + /*8894*/ uint16(xSetOp), uint16(IMUL), + /*8896*/ uint16(xReadSlashR), + /*8897*/ uint16(xReadIw), + /*8898*/ uint16(xArgR16), + /*8899*/ uint16(xArgRM16), + /*8900*/ uint16(xArgImm16), + /*8901*/ uint16(xMatch), + /*8902*/ uint16(xSetOp), uint16(IMUL), + /*8904*/ uint16(xReadSlashR), + /*8905*/ uint16(xReadId), + /*8906*/ uint16(xArgR32), + /*8907*/ uint16(xArgRM32), + /*8908*/ uint16(xArgImm32), + /*8909*/ uint16(xMatch), + /*8910*/ uint16(xCondDataSize), 8894, 8902, 8914, + /*8914*/ uint16(xSetOp), uint16(IMUL), + /*8916*/ uint16(xReadSlashR), + /*8917*/ uint16(xReadId), + /*8918*/ uint16(xArgR64), + /*8919*/ uint16(xArgRM64), + /*8920*/ uint16(xArgImm32), + /*8921*/ uint16(xMatch), + /*8922*/ uint16(xSetOp), uint16(PUSH), + /*8924*/ uint16(xReadIb), + /*8925*/ uint16(xArgImm8), + /*8926*/ uint16(xMatch), + /*8927*/ uint16(xCondIs64), 8930, 8950, + /*8930*/ uint16(xCondDataSize), 8934, 8942, 0, + /*8934*/ uint16(xSetOp), uint16(IMUL), + /*8936*/ uint16(xReadSlashR), + /*8937*/ uint16(xReadIb), + /*8938*/ uint16(xArgR16), + /*8939*/ uint16(xArgRM16), + /*8940*/ uint16(xArgImm8), + /*8941*/ uint16(xMatch), + /*8942*/ uint16(xSetOp), uint16(IMUL), + /*8944*/ uint16(xReadSlashR), + /*8945*/ uint16(xReadIb), + /*8946*/ uint16(xArgR32), + /*8947*/ uint16(xArgRM32), + /*8948*/ uint16(xArgImm8), + /*8949*/ uint16(xMatch), + /*8950*/ uint16(xCondDataSize), 8934, 8942, 8954, + /*8954*/ uint16(xSetOp), uint16(IMUL), + /*8956*/ uint16(xReadSlashR), + /*8957*/ uint16(xReadIb), + /*8958*/ uint16(xArgR64), + /*8959*/ uint16(xArgRM64), + /*8960*/ uint16(xArgImm8), + /*8961*/ uint16(xMatch), + /*8962*/ uint16(xSetOp), uint16(INSB), + /*8964*/ uint16(xMatch), + /*8965*/ uint16(xCondDataSize), 8969, 8972, 8975, + /*8969*/ uint16(xSetOp), uint16(INSW), + /*8971*/ uint16(xMatch), + /*8972*/ uint16(xSetOp), uint16(INSD), + /*8974*/ uint16(xMatch), + /*8975*/ uint16(xSetOp), uint16(INSD), + /*8977*/ uint16(xMatch), + /*8978*/ uint16(xSetOp), uint16(OUTSB), + /*8980*/ uint16(xMatch), + /*8981*/ uint16(xCondDataSize), 8985, 8988, 8991, + /*8985*/ uint16(xSetOp), uint16(OUTSW), + /*8987*/ uint16(xMatch), + /*8988*/ uint16(xSetOp), uint16(OUTSD), + /*8990*/ uint16(xMatch), + /*8991*/ uint16(xSetOp), uint16(OUTSD), + /*8993*/ uint16(xMatch), + /*8994*/ uint16(xSetOp), uint16(JO), + /*8996*/ uint16(xReadCb), + /*8997*/ uint16(xArgRel8), + /*8998*/ uint16(xMatch), + /*8999*/ uint16(xSetOp), uint16(JNO), + /*9001*/ uint16(xReadCb), + /*9002*/ uint16(xArgRel8), + /*9003*/ uint16(xMatch), + /*9004*/ uint16(xSetOp), uint16(JB), + /*9006*/ uint16(xReadCb), + /*9007*/ uint16(xArgRel8), + /*9008*/ uint16(xMatch), + /*9009*/ uint16(xSetOp), uint16(JAE), + /*9011*/ uint16(xReadCb), + /*9012*/ uint16(xArgRel8), + /*9013*/ uint16(xMatch), + /*9014*/ uint16(xSetOp), uint16(JE), + /*9016*/ uint16(xReadCb), + /*9017*/ uint16(xArgRel8), + /*9018*/ uint16(xMatch), + /*9019*/ uint16(xSetOp), uint16(JNE), + /*9021*/ uint16(xReadCb), + /*9022*/ uint16(xArgRel8), + /*9023*/ uint16(xMatch), + /*9024*/ uint16(xSetOp), uint16(JBE), + /*9026*/ uint16(xReadCb), + /*9027*/ uint16(xArgRel8), + /*9028*/ uint16(xMatch), + /*9029*/ uint16(xSetOp), uint16(JA), + /*9031*/ uint16(xReadCb), + /*9032*/ uint16(xArgRel8), + /*9033*/ uint16(xMatch), + /*9034*/ uint16(xSetOp), uint16(JS), + /*9036*/ uint16(xReadCb), + /*9037*/ uint16(xArgRel8), + /*9038*/ uint16(xMatch), + /*9039*/ uint16(xSetOp), uint16(JNS), + /*9041*/ uint16(xReadCb), + /*9042*/ uint16(xArgRel8), + /*9043*/ uint16(xMatch), + /*9044*/ uint16(xSetOp), uint16(JP), + /*9046*/ uint16(xReadCb), + /*9047*/ uint16(xArgRel8), + /*9048*/ uint16(xMatch), + /*9049*/ uint16(xSetOp), uint16(JNP), + /*9051*/ uint16(xReadCb), + /*9052*/ uint16(xArgRel8), + /*9053*/ uint16(xMatch), + /*9054*/ uint16(xSetOp), uint16(JL), + /*9056*/ uint16(xReadCb), + /*9057*/ uint16(xArgRel8), + /*9058*/ uint16(xMatch), + /*9059*/ uint16(xSetOp), uint16(JGE), + /*9061*/ uint16(xReadCb), + /*9062*/ uint16(xArgRel8), + /*9063*/ uint16(xMatch), + /*9064*/ uint16(xSetOp), uint16(JLE), + /*9066*/ uint16(xReadCb), + /*9067*/ uint16(xArgRel8), + /*9068*/ uint16(xMatch), + /*9069*/ uint16(xSetOp), uint16(JG), + /*9071*/ uint16(xReadCb), + /*9072*/ uint16(xArgRel8), + /*9073*/ uint16(xMatch), + /*9074*/ uint16(xCondSlashR), + 9083, // 0 + 9089, // 1 + 9095, // 2 + 9101, // 3 + 9107, // 4 + 9113, // 5 + 9119, // 6 + 9125, // 7 + /*9083*/ uint16(xSetOp), uint16(ADD), + /*9085*/ uint16(xReadIb), + /*9086*/ uint16(xArgRM8), + /*9087*/ uint16(xArgImm8u), + /*9088*/ uint16(xMatch), + /*9089*/ uint16(xSetOp), uint16(OR), + /*9091*/ uint16(xReadIb), + /*9092*/ uint16(xArgRM8), + /*9093*/ uint16(xArgImm8u), + /*9094*/ uint16(xMatch), + /*9095*/ uint16(xSetOp), uint16(ADC), + /*9097*/ uint16(xReadIb), + /*9098*/ uint16(xArgRM8), + /*9099*/ uint16(xArgImm8u), + /*9100*/ uint16(xMatch), + /*9101*/ uint16(xSetOp), uint16(SBB), + /*9103*/ uint16(xReadIb), + /*9104*/ uint16(xArgRM8), + /*9105*/ uint16(xArgImm8u), + /*9106*/ uint16(xMatch), + /*9107*/ uint16(xSetOp), uint16(AND), + /*9109*/ uint16(xReadIb), + /*9110*/ uint16(xArgRM8), + /*9111*/ uint16(xArgImm8u), + /*9112*/ uint16(xMatch), + /*9113*/ uint16(xSetOp), uint16(SUB), + /*9115*/ uint16(xReadIb), + /*9116*/ uint16(xArgRM8), + /*9117*/ uint16(xArgImm8u), + /*9118*/ uint16(xMatch), + /*9119*/ uint16(xSetOp), uint16(XOR), + /*9121*/ uint16(xReadIb), + /*9122*/ uint16(xArgRM8), + /*9123*/ uint16(xArgImm8u), + /*9124*/ uint16(xMatch), + /*9125*/ uint16(xSetOp), uint16(CMP), + /*9127*/ uint16(xReadIb), + /*9128*/ uint16(xArgRM8), + /*9129*/ uint16(xArgImm8u), + /*9130*/ uint16(xMatch), + /*9131*/ uint16(xCondSlashR), + 9140, // 0 + 9169, // 1 + 9198, // 2 + 9227, // 3 + 9256, // 4 + 9285, // 5 + 9314, // 6 + 9343, // 7 + /*9140*/ uint16(xCondIs64), 9143, 9159, + /*9143*/ uint16(xCondDataSize), 9147, 9153, 0, + /*9147*/ uint16(xSetOp), uint16(ADD), + /*9149*/ uint16(xReadIw), + /*9150*/ uint16(xArgRM16), + /*9151*/ uint16(xArgImm16), + /*9152*/ uint16(xMatch), + /*9153*/ uint16(xSetOp), uint16(ADD), + /*9155*/ uint16(xReadId), + /*9156*/ uint16(xArgRM32), + /*9157*/ uint16(xArgImm32), + /*9158*/ uint16(xMatch), + /*9159*/ uint16(xCondDataSize), 9147, 9153, 9163, + /*9163*/ uint16(xSetOp), uint16(ADD), + /*9165*/ uint16(xReadId), + /*9166*/ uint16(xArgRM64), + /*9167*/ uint16(xArgImm32), + /*9168*/ uint16(xMatch), + /*9169*/ uint16(xCondIs64), 9172, 9188, + /*9172*/ uint16(xCondDataSize), 9176, 9182, 0, + /*9176*/ uint16(xSetOp), uint16(OR), + /*9178*/ uint16(xReadIw), + /*9179*/ uint16(xArgRM16), + /*9180*/ uint16(xArgImm16), + /*9181*/ uint16(xMatch), + /*9182*/ uint16(xSetOp), uint16(OR), + /*9184*/ uint16(xReadId), + /*9185*/ uint16(xArgRM32), + /*9186*/ uint16(xArgImm32), + /*9187*/ uint16(xMatch), + /*9188*/ uint16(xCondDataSize), 9176, 9182, 9192, + /*9192*/ uint16(xSetOp), uint16(OR), + /*9194*/ uint16(xReadId), + /*9195*/ uint16(xArgRM64), + /*9196*/ uint16(xArgImm32), + /*9197*/ uint16(xMatch), + /*9198*/ uint16(xCondIs64), 9201, 9217, + /*9201*/ uint16(xCondDataSize), 9205, 9211, 0, + /*9205*/ uint16(xSetOp), uint16(ADC), + /*9207*/ uint16(xReadIw), + /*9208*/ uint16(xArgRM16), + /*9209*/ uint16(xArgImm16), + /*9210*/ uint16(xMatch), + /*9211*/ uint16(xSetOp), uint16(ADC), + /*9213*/ uint16(xReadId), + /*9214*/ uint16(xArgRM32), + /*9215*/ uint16(xArgImm32), + /*9216*/ uint16(xMatch), + /*9217*/ uint16(xCondDataSize), 9205, 9211, 9221, + /*9221*/ uint16(xSetOp), uint16(ADC), + /*9223*/ uint16(xReadId), + /*9224*/ uint16(xArgRM64), + /*9225*/ uint16(xArgImm32), + /*9226*/ uint16(xMatch), + /*9227*/ uint16(xCondIs64), 9230, 9246, + /*9230*/ uint16(xCondDataSize), 9234, 9240, 0, + /*9234*/ uint16(xSetOp), uint16(SBB), + /*9236*/ uint16(xReadIw), + /*9237*/ uint16(xArgRM16), + /*9238*/ uint16(xArgImm16), + /*9239*/ uint16(xMatch), + /*9240*/ uint16(xSetOp), uint16(SBB), + /*9242*/ uint16(xReadId), + /*9243*/ uint16(xArgRM32), + /*9244*/ uint16(xArgImm32), + /*9245*/ uint16(xMatch), + /*9246*/ uint16(xCondDataSize), 9234, 9240, 9250, + /*9250*/ uint16(xSetOp), uint16(SBB), + /*9252*/ uint16(xReadId), + /*9253*/ uint16(xArgRM64), + /*9254*/ uint16(xArgImm32), + /*9255*/ uint16(xMatch), + /*9256*/ uint16(xCondIs64), 9259, 9275, + /*9259*/ uint16(xCondDataSize), 9263, 9269, 0, + /*9263*/ uint16(xSetOp), uint16(AND), + /*9265*/ uint16(xReadIw), + /*9266*/ uint16(xArgRM16), + /*9267*/ uint16(xArgImm16), + /*9268*/ uint16(xMatch), + /*9269*/ uint16(xSetOp), uint16(AND), + /*9271*/ uint16(xReadId), + /*9272*/ uint16(xArgRM32), + /*9273*/ uint16(xArgImm32), + /*9274*/ uint16(xMatch), + /*9275*/ uint16(xCondDataSize), 9263, 9269, 9279, + /*9279*/ uint16(xSetOp), uint16(AND), + /*9281*/ uint16(xReadId), + /*9282*/ uint16(xArgRM64), + /*9283*/ uint16(xArgImm32), + /*9284*/ uint16(xMatch), + /*9285*/ uint16(xCondIs64), 9288, 9304, + /*9288*/ uint16(xCondDataSize), 9292, 9298, 0, + /*9292*/ uint16(xSetOp), uint16(SUB), + /*9294*/ uint16(xReadIw), + /*9295*/ uint16(xArgRM16), + /*9296*/ uint16(xArgImm16), + /*9297*/ uint16(xMatch), + /*9298*/ uint16(xSetOp), uint16(SUB), + /*9300*/ uint16(xReadId), + /*9301*/ uint16(xArgRM32), + /*9302*/ uint16(xArgImm32), + /*9303*/ uint16(xMatch), + /*9304*/ uint16(xCondDataSize), 9292, 9298, 9308, + /*9308*/ uint16(xSetOp), uint16(SUB), + /*9310*/ uint16(xReadId), + /*9311*/ uint16(xArgRM64), + /*9312*/ uint16(xArgImm32), + /*9313*/ uint16(xMatch), + /*9314*/ uint16(xCondIs64), 9317, 9333, + /*9317*/ uint16(xCondDataSize), 9321, 9327, 0, + /*9321*/ uint16(xSetOp), uint16(XOR), + /*9323*/ uint16(xReadIw), + /*9324*/ uint16(xArgRM16), + /*9325*/ uint16(xArgImm16), + /*9326*/ uint16(xMatch), + /*9327*/ uint16(xSetOp), uint16(XOR), + /*9329*/ uint16(xReadId), + /*9330*/ uint16(xArgRM32), + /*9331*/ uint16(xArgImm32), + /*9332*/ uint16(xMatch), + /*9333*/ uint16(xCondDataSize), 9321, 9327, 9337, + /*9337*/ uint16(xSetOp), uint16(XOR), + /*9339*/ uint16(xReadId), + /*9340*/ uint16(xArgRM64), + /*9341*/ uint16(xArgImm32), + /*9342*/ uint16(xMatch), + /*9343*/ uint16(xCondIs64), 9346, 9362, + /*9346*/ uint16(xCondDataSize), 9350, 9356, 0, + /*9350*/ uint16(xSetOp), uint16(CMP), + /*9352*/ uint16(xReadIw), + /*9353*/ uint16(xArgRM16), + /*9354*/ uint16(xArgImm16), + /*9355*/ uint16(xMatch), + /*9356*/ uint16(xSetOp), uint16(CMP), + /*9358*/ uint16(xReadId), + /*9359*/ uint16(xArgRM32), + /*9360*/ uint16(xArgImm32), + /*9361*/ uint16(xMatch), + /*9362*/ uint16(xCondDataSize), 9350, 9356, 9366, + /*9366*/ uint16(xSetOp), uint16(CMP), + /*9368*/ uint16(xReadId), + /*9369*/ uint16(xArgRM64), + /*9370*/ uint16(xArgImm32), + /*9371*/ uint16(xMatch), + /*9372*/ uint16(xCondSlashR), + 9381, // 0 + 9410, // 1 + 9439, // 2 + 9468, // 3 + 9497, // 4 + 9526, // 5 + 9555, // 6 + 9584, // 7 + /*9381*/ uint16(xCondIs64), 9384, 9400, + /*9384*/ uint16(xCondDataSize), 9388, 9394, 0, + /*9388*/ uint16(xSetOp), uint16(ADD), + /*9390*/ uint16(xReadIb), + /*9391*/ uint16(xArgRM16), + /*9392*/ uint16(xArgImm8), + /*9393*/ uint16(xMatch), + /*9394*/ uint16(xSetOp), uint16(ADD), + /*9396*/ uint16(xReadIb), + /*9397*/ uint16(xArgRM32), + /*9398*/ uint16(xArgImm8), + /*9399*/ uint16(xMatch), + /*9400*/ uint16(xCondDataSize), 9388, 9394, 9404, + /*9404*/ uint16(xSetOp), uint16(ADD), + /*9406*/ uint16(xReadIb), + /*9407*/ uint16(xArgRM64), + /*9408*/ uint16(xArgImm8), + /*9409*/ uint16(xMatch), + /*9410*/ uint16(xCondIs64), 9413, 9429, + /*9413*/ uint16(xCondDataSize), 9417, 9423, 0, + /*9417*/ uint16(xSetOp), uint16(OR), + /*9419*/ uint16(xReadIb), + /*9420*/ uint16(xArgRM16), + /*9421*/ uint16(xArgImm8), + /*9422*/ uint16(xMatch), + /*9423*/ uint16(xSetOp), uint16(OR), + /*9425*/ uint16(xReadIb), + /*9426*/ uint16(xArgRM32), + /*9427*/ uint16(xArgImm8), + /*9428*/ uint16(xMatch), + /*9429*/ uint16(xCondDataSize), 9417, 9423, 9433, + /*9433*/ uint16(xSetOp), uint16(OR), + /*9435*/ uint16(xReadIb), + /*9436*/ uint16(xArgRM64), + /*9437*/ uint16(xArgImm8), + /*9438*/ uint16(xMatch), + /*9439*/ uint16(xCondIs64), 9442, 9458, + /*9442*/ uint16(xCondDataSize), 9446, 9452, 0, + /*9446*/ uint16(xSetOp), uint16(ADC), + /*9448*/ uint16(xReadIb), + /*9449*/ uint16(xArgRM16), + /*9450*/ uint16(xArgImm8), + /*9451*/ uint16(xMatch), + /*9452*/ uint16(xSetOp), uint16(ADC), + /*9454*/ uint16(xReadIb), + /*9455*/ uint16(xArgRM32), + /*9456*/ uint16(xArgImm8), + /*9457*/ uint16(xMatch), + /*9458*/ uint16(xCondDataSize), 9446, 9452, 9462, + /*9462*/ uint16(xSetOp), uint16(ADC), + /*9464*/ uint16(xReadIb), + /*9465*/ uint16(xArgRM64), + /*9466*/ uint16(xArgImm8), + /*9467*/ uint16(xMatch), + /*9468*/ uint16(xCondIs64), 9471, 9487, + /*9471*/ uint16(xCondDataSize), 9475, 9481, 0, + /*9475*/ uint16(xSetOp), uint16(SBB), + /*9477*/ uint16(xReadIb), + /*9478*/ uint16(xArgRM16), + /*9479*/ uint16(xArgImm8), + /*9480*/ uint16(xMatch), + /*9481*/ uint16(xSetOp), uint16(SBB), + /*9483*/ uint16(xReadIb), + /*9484*/ uint16(xArgRM32), + /*9485*/ uint16(xArgImm8), + /*9486*/ uint16(xMatch), + /*9487*/ uint16(xCondDataSize), 9475, 9481, 9491, + /*9491*/ uint16(xSetOp), uint16(SBB), + /*9493*/ uint16(xReadIb), + /*9494*/ uint16(xArgRM64), + /*9495*/ uint16(xArgImm8), + /*9496*/ uint16(xMatch), + /*9497*/ uint16(xCondIs64), 9500, 9516, + /*9500*/ uint16(xCondDataSize), 9504, 9510, 0, + /*9504*/ uint16(xSetOp), uint16(AND), + /*9506*/ uint16(xReadIb), + /*9507*/ uint16(xArgRM16), + /*9508*/ uint16(xArgImm8), + /*9509*/ uint16(xMatch), + /*9510*/ uint16(xSetOp), uint16(AND), + /*9512*/ uint16(xReadIb), + /*9513*/ uint16(xArgRM32), + /*9514*/ uint16(xArgImm8), + /*9515*/ uint16(xMatch), + /*9516*/ uint16(xCondDataSize), 9504, 9510, 9520, + /*9520*/ uint16(xSetOp), uint16(AND), + /*9522*/ uint16(xReadIb), + /*9523*/ uint16(xArgRM64), + /*9524*/ uint16(xArgImm8), + /*9525*/ uint16(xMatch), + /*9526*/ uint16(xCondIs64), 9529, 9545, + /*9529*/ uint16(xCondDataSize), 9533, 9539, 0, + /*9533*/ uint16(xSetOp), uint16(SUB), + /*9535*/ uint16(xReadIb), + /*9536*/ uint16(xArgRM16), + /*9537*/ uint16(xArgImm8), + /*9538*/ uint16(xMatch), + /*9539*/ uint16(xSetOp), uint16(SUB), + /*9541*/ uint16(xReadIb), + /*9542*/ uint16(xArgRM32), + /*9543*/ uint16(xArgImm8), + /*9544*/ uint16(xMatch), + /*9545*/ uint16(xCondDataSize), 9533, 9539, 9549, + /*9549*/ uint16(xSetOp), uint16(SUB), + /*9551*/ uint16(xReadIb), + /*9552*/ uint16(xArgRM64), + /*9553*/ uint16(xArgImm8), + /*9554*/ uint16(xMatch), + /*9555*/ uint16(xCondIs64), 9558, 9574, + /*9558*/ uint16(xCondDataSize), 9562, 9568, 0, + /*9562*/ uint16(xSetOp), uint16(XOR), + /*9564*/ uint16(xReadIb), + /*9565*/ uint16(xArgRM16), + /*9566*/ uint16(xArgImm8), + /*9567*/ uint16(xMatch), + /*9568*/ uint16(xSetOp), uint16(XOR), + /*9570*/ uint16(xReadIb), + /*9571*/ uint16(xArgRM32), + /*9572*/ uint16(xArgImm8), + /*9573*/ uint16(xMatch), + /*9574*/ uint16(xCondDataSize), 9562, 9568, 9578, + /*9578*/ uint16(xSetOp), uint16(XOR), + /*9580*/ uint16(xReadIb), + /*9581*/ uint16(xArgRM64), + /*9582*/ uint16(xArgImm8), + /*9583*/ uint16(xMatch), + /*9584*/ uint16(xCondIs64), 9587, 9603, + /*9587*/ uint16(xCondDataSize), 9591, 9597, 0, + /*9591*/ uint16(xSetOp), uint16(CMP), + /*9593*/ uint16(xReadIb), + /*9594*/ uint16(xArgRM16), + /*9595*/ uint16(xArgImm8), + /*9596*/ uint16(xMatch), + /*9597*/ uint16(xSetOp), uint16(CMP), + /*9599*/ uint16(xReadIb), + /*9600*/ uint16(xArgRM32), + /*9601*/ uint16(xArgImm8), + /*9602*/ uint16(xMatch), + /*9603*/ uint16(xCondDataSize), 9591, 9597, 9607, + /*9607*/ uint16(xSetOp), uint16(CMP), + /*9609*/ uint16(xReadIb), + /*9610*/ uint16(xArgRM64), + /*9611*/ uint16(xArgImm8), + /*9612*/ uint16(xMatch), + /*9613*/ uint16(xSetOp), uint16(TEST), + /*9615*/ uint16(xReadSlashR), + /*9616*/ uint16(xArgRM8), + /*9617*/ uint16(xArgR8), + /*9618*/ uint16(xMatch), + /*9619*/ uint16(xCondIs64), 9622, 9638, + /*9622*/ uint16(xCondDataSize), 9626, 9632, 0, + /*9626*/ uint16(xSetOp), uint16(TEST), + /*9628*/ uint16(xReadSlashR), + /*9629*/ uint16(xArgRM16), + /*9630*/ uint16(xArgR16), + /*9631*/ uint16(xMatch), + /*9632*/ uint16(xSetOp), uint16(TEST), + /*9634*/ uint16(xReadSlashR), + /*9635*/ uint16(xArgRM32), + /*9636*/ uint16(xArgR32), + /*9637*/ uint16(xMatch), + /*9638*/ uint16(xCondDataSize), 9626, 9632, 9642, + /*9642*/ uint16(xSetOp), uint16(TEST), + /*9644*/ uint16(xReadSlashR), + /*9645*/ uint16(xArgRM64), + /*9646*/ uint16(xArgR64), + /*9647*/ uint16(xMatch), + /*9648*/ uint16(xSetOp), uint16(XCHG), + /*9650*/ uint16(xReadSlashR), + /*9651*/ uint16(xArgRM8), + /*9652*/ uint16(xArgR8), + /*9653*/ uint16(xMatch), + /*9654*/ uint16(xCondIs64), 9657, 9673, + /*9657*/ uint16(xCondDataSize), 9661, 9667, 0, + /*9661*/ uint16(xSetOp), uint16(XCHG), + /*9663*/ uint16(xReadSlashR), + /*9664*/ uint16(xArgRM16), + /*9665*/ uint16(xArgR16), + /*9666*/ uint16(xMatch), + /*9667*/ uint16(xSetOp), uint16(XCHG), + /*9669*/ uint16(xReadSlashR), + /*9670*/ uint16(xArgRM32), + /*9671*/ uint16(xArgR32), + /*9672*/ uint16(xMatch), + /*9673*/ uint16(xCondDataSize), 9661, 9667, 9677, + /*9677*/ uint16(xSetOp), uint16(XCHG), + /*9679*/ uint16(xReadSlashR), + /*9680*/ uint16(xArgRM64), + /*9681*/ uint16(xArgR64), + /*9682*/ uint16(xMatch), + /*9683*/ uint16(xSetOp), uint16(MOV), + /*9685*/ uint16(xReadSlashR), + /*9686*/ uint16(xArgRM8), + /*9687*/ uint16(xArgR8), + /*9688*/ uint16(xMatch), + /*9689*/ uint16(xCondDataSize), 9693, 9699, 9705, + /*9693*/ uint16(xSetOp), uint16(MOV), + /*9695*/ uint16(xReadSlashR), + /*9696*/ uint16(xArgRM16), + /*9697*/ uint16(xArgR16), + /*9698*/ uint16(xMatch), + /*9699*/ uint16(xSetOp), uint16(MOV), + /*9701*/ uint16(xReadSlashR), + /*9702*/ uint16(xArgRM32), + /*9703*/ uint16(xArgR32), + /*9704*/ uint16(xMatch), + /*9705*/ uint16(xSetOp), uint16(MOV), + /*9707*/ uint16(xReadSlashR), + /*9708*/ uint16(xArgRM64), + /*9709*/ uint16(xArgR64), + /*9710*/ uint16(xMatch), + /*9711*/ uint16(xSetOp), uint16(MOV), + /*9713*/ uint16(xReadSlashR), + /*9714*/ uint16(xArgR8), + /*9715*/ uint16(xArgRM8), + /*9716*/ uint16(xMatch), + /*9717*/ uint16(xCondDataSize), 9721, 9727, 9733, + /*9721*/ uint16(xSetOp), uint16(MOV), + /*9723*/ uint16(xReadSlashR), + /*9724*/ uint16(xArgR16), + /*9725*/ uint16(xArgRM16), + /*9726*/ uint16(xMatch), + /*9727*/ uint16(xSetOp), uint16(MOV), + /*9729*/ uint16(xReadSlashR), + /*9730*/ uint16(xArgR32), + /*9731*/ uint16(xArgRM32), + /*9732*/ uint16(xMatch), + /*9733*/ uint16(xSetOp), uint16(MOV), + /*9735*/ uint16(xReadSlashR), + /*9736*/ uint16(xArgR64), + /*9737*/ uint16(xArgRM64), + /*9738*/ uint16(xMatch), + /*9739*/ uint16(xCondIs64), 9742, 9758, + /*9742*/ uint16(xCondDataSize), 9746, 9752, 0, + /*9746*/ uint16(xSetOp), uint16(MOV), + /*9748*/ uint16(xReadSlashR), + /*9749*/ uint16(xArgRM16), + /*9750*/ uint16(xArgSreg), + /*9751*/ uint16(xMatch), + /*9752*/ uint16(xSetOp), uint16(MOV), + /*9754*/ uint16(xReadSlashR), + /*9755*/ uint16(xArgR32M16), + /*9756*/ uint16(xArgSreg), + /*9757*/ uint16(xMatch), + /*9758*/ uint16(xCondDataSize), 9746, 9752, 9762, + /*9762*/ uint16(xSetOp), uint16(MOV), + /*9764*/ uint16(xReadSlashR), + /*9765*/ uint16(xArgR64M16), + /*9766*/ uint16(xArgSreg), + /*9767*/ uint16(xMatch), + /*9768*/ uint16(xCondIs64), 9771, 9787, + /*9771*/ uint16(xCondDataSize), 9775, 9781, 0, + /*9775*/ uint16(xSetOp), uint16(LEA), + /*9777*/ uint16(xReadSlashR), + /*9778*/ uint16(xArgR16), + /*9779*/ uint16(xArgM), + /*9780*/ uint16(xMatch), + /*9781*/ uint16(xSetOp), uint16(LEA), + /*9783*/ uint16(xReadSlashR), + /*9784*/ uint16(xArgR32), + /*9785*/ uint16(xArgM), + /*9786*/ uint16(xMatch), + /*9787*/ uint16(xCondDataSize), 9775, 9781, 9791, + /*9791*/ uint16(xSetOp), uint16(LEA), + /*9793*/ uint16(xReadSlashR), + /*9794*/ uint16(xArgR64), + /*9795*/ uint16(xArgM), + /*9796*/ uint16(xMatch), + /*9797*/ uint16(xCondIs64), 9800, 9816, + /*9800*/ uint16(xCondDataSize), 9804, 9810, 0, + /*9804*/ uint16(xSetOp), uint16(MOV), + /*9806*/ uint16(xReadSlashR), + /*9807*/ uint16(xArgSreg), + /*9808*/ uint16(xArgRM16), + /*9809*/ uint16(xMatch), + /*9810*/ uint16(xSetOp), uint16(MOV), + /*9812*/ uint16(xReadSlashR), + /*9813*/ uint16(xArgSreg), + /*9814*/ uint16(xArgR32M16), + /*9815*/ uint16(xMatch), + /*9816*/ uint16(xCondDataSize), 9804, 9810, 9820, + /*9820*/ uint16(xSetOp), uint16(MOV), + /*9822*/ uint16(xReadSlashR), + /*9823*/ uint16(xArgSreg), + /*9824*/ uint16(xArgR64M16), + /*9825*/ uint16(xMatch), + /*9826*/ uint16(xCondSlashR), + 9835, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*9835*/ uint16(xCondIs64), 9838, 9850, + /*9838*/ uint16(xCondDataSize), 9842, 9846, 0, + /*9842*/ uint16(xSetOp), uint16(POP), + /*9844*/ uint16(xArgRM16), + /*9845*/ uint16(xMatch), + /*9846*/ uint16(xSetOp), uint16(POP), + /*9848*/ uint16(xArgRM32), + /*9849*/ uint16(xMatch), + /*9850*/ uint16(xCondDataSize), 9842, 9854, 9858, + /*9854*/ uint16(xSetOp), uint16(POP), + /*9856*/ uint16(xArgRM64), + /*9857*/ uint16(xMatch), + /*9858*/ uint16(xSetOp), uint16(POP), + /*9860*/ uint16(xArgRM64), + /*9861*/ uint16(xMatch), + /*9862*/ uint16(xCondIs64), 9865, 9879, + /*9865*/ uint16(xCondDataSize), 9869, 9874, 0, + /*9869*/ uint16(xSetOp), uint16(XCHG), + /*9871*/ uint16(xArgR16op), + /*9872*/ uint16(xArgAX), + /*9873*/ uint16(xMatch), + /*9874*/ uint16(xSetOp), uint16(XCHG), + /*9876*/ uint16(xArgR32op), + /*9877*/ uint16(xArgEAX), + /*9878*/ uint16(xMatch), + /*9879*/ uint16(xCondDataSize), 9869, 9874, 9883, + /*9883*/ uint16(xSetOp), uint16(XCHG), + /*9885*/ uint16(xArgR64op), + /*9886*/ uint16(xArgRAX), + /*9887*/ uint16(xMatch), + /*9888*/ uint16(xCondIs64), 9891, 9901, + /*9891*/ uint16(xCondDataSize), 9895, 9898, 0, + /*9895*/ uint16(xSetOp), uint16(CBW), + /*9897*/ uint16(xMatch), + /*9898*/ uint16(xSetOp), uint16(CWDE), + /*9900*/ uint16(xMatch), + /*9901*/ uint16(xCondDataSize), 9895, 9898, 9905, + /*9905*/ uint16(xSetOp), uint16(CDQE), + /*9907*/ uint16(xMatch), + /*9908*/ uint16(xCondIs64), 9911, 9921, + /*9911*/ uint16(xCondDataSize), 9915, 9918, 0, + /*9915*/ uint16(xSetOp), uint16(CWD), + /*9917*/ uint16(xMatch), + /*9918*/ uint16(xSetOp), uint16(CDQ), + /*9920*/ uint16(xMatch), + /*9921*/ uint16(xCondDataSize), 9915, 9918, 9925, + /*9925*/ uint16(xSetOp), uint16(CQO), + /*9927*/ uint16(xMatch), + /*9928*/ uint16(xCondIs64), 9931, 0, + /*9931*/ uint16(xCondDataSize), 9935, 9940, 0, + /*9935*/ uint16(xSetOp), uint16(LCALL), + /*9937*/ uint16(xReadCd), + /*9938*/ uint16(xArgPtr16colon16), + /*9939*/ uint16(xMatch), + /*9940*/ uint16(xSetOp), uint16(LCALL), + /*9942*/ uint16(xReadCp), + /*9943*/ uint16(xArgPtr16colon32), + /*9944*/ uint16(xMatch), + /*9945*/ uint16(xSetOp), uint16(FWAIT), + /*9947*/ uint16(xMatch), + /*9948*/ uint16(xCondIs64), 9951, 9961, + /*9951*/ uint16(xCondDataSize), 9955, 9958, 0, + /*9955*/ uint16(xSetOp), uint16(PUSHF), + /*9957*/ uint16(xMatch), + /*9958*/ uint16(xSetOp), uint16(PUSHFD), + /*9960*/ uint16(xMatch), + /*9961*/ uint16(xCondDataSize), 9955, 9965, 9968, + /*9965*/ uint16(xSetOp), uint16(PUSHFQ), + /*9967*/ uint16(xMatch), + /*9968*/ uint16(xSetOp), uint16(PUSHFQ), + /*9970*/ uint16(xMatch), + /*9971*/ uint16(xCondIs64), 9974, 9984, + /*9974*/ uint16(xCondDataSize), 9978, 9981, 0, + /*9978*/ uint16(xSetOp), uint16(POPF), + /*9980*/ uint16(xMatch), + /*9981*/ uint16(xSetOp), uint16(POPFD), + /*9983*/ uint16(xMatch), + /*9984*/ uint16(xCondDataSize), 9978, 9988, 9991, + /*9988*/ uint16(xSetOp), uint16(POPFQ), + /*9990*/ uint16(xMatch), + /*9991*/ uint16(xSetOp), uint16(POPFQ), + /*9993*/ uint16(xMatch), + /*9994*/ uint16(xSetOp), uint16(SAHF), + /*9996*/ uint16(xMatch), + /*9997*/ uint16(xSetOp), uint16(LAHF), + /*9999*/ uint16(xMatch), + /*10000*/ uint16(xCondIs64), 10003, 10009, + /*10003*/ uint16(xSetOp), uint16(MOV), + /*10005*/ uint16(xReadCm), + /*10006*/ uint16(xArgAL), + /*10007*/ uint16(xArgMoffs8), + /*10008*/ uint16(xMatch), + /*10009*/ uint16(xCondDataSize), 10003, 10003, 10013, + /*10013*/ uint16(xSetOp), uint16(MOV), + /*10015*/ uint16(xReadCm), + /*10016*/ uint16(xArgAL), + /*10017*/ uint16(xArgMoffs8), + /*10018*/ uint16(xMatch), + /*10019*/ uint16(xCondDataSize), 10023, 10029, 10035, + /*10023*/ uint16(xSetOp), uint16(MOV), + /*10025*/ uint16(xReadCm), + /*10026*/ uint16(xArgAX), + /*10027*/ uint16(xArgMoffs16), + /*10028*/ uint16(xMatch), + /*10029*/ uint16(xSetOp), uint16(MOV), + /*10031*/ uint16(xReadCm), + /*10032*/ uint16(xArgEAX), + /*10033*/ uint16(xArgMoffs32), + /*10034*/ uint16(xMatch), + /*10035*/ uint16(xSetOp), uint16(MOV), + /*10037*/ uint16(xReadCm), + /*10038*/ uint16(xArgRAX), + /*10039*/ uint16(xArgMoffs64), + /*10040*/ uint16(xMatch), + /*10041*/ uint16(xCondIs64), 10044, 10050, + /*10044*/ uint16(xSetOp), uint16(MOV), + /*10046*/ uint16(xReadCm), + /*10047*/ uint16(xArgMoffs8), + /*10048*/ uint16(xArgAL), + /*10049*/ uint16(xMatch), + /*10050*/ uint16(xCondDataSize), 10044, 10044, 10054, + /*10054*/ uint16(xSetOp), uint16(MOV), + /*10056*/ uint16(xReadCm), + /*10057*/ uint16(xArgMoffs8), + /*10058*/ uint16(xArgAL), + /*10059*/ uint16(xMatch), + /*10060*/ uint16(xCondDataSize), 10064, 10070, 10076, + /*10064*/ uint16(xSetOp), uint16(MOV), + /*10066*/ uint16(xReadCm), + /*10067*/ uint16(xArgMoffs16), + /*10068*/ uint16(xArgAX), + /*10069*/ uint16(xMatch), + /*10070*/ uint16(xSetOp), uint16(MOV), + /*10072*/ uint16(xReadCm), + /*10073*/ uint16(xArgMoffs32), + /*10074*/ uint16(xArgEAX), + /*10075*/ uint16(xMatch), + /*10076*/ uint16(xSetOp), uint16(MOV), + /*10078*/ uint16(xReadCm), + /*10079*/ uint16(xArgMoffs64), + /*10080*/ uint16(xArgRAX), + /*10081*/ uint16(xMatch), + /*10082*/ uint16(xSetOp), uint16(MOVSB), + /*10084*/ uint16(xMatch), + /*10085*/ uint16(xCondIs64), 10088, 10098, + /*10088*/ uint16(xCondDataSize), 10092, 10095, 0, + /*10092*/ uint16(xSetOp), uint16(MOVSW), + /*10094*/ uint16(xMatch), + /*10095*/ uint16(xSetOp), uint16(MOVSD), + /*10097*/ uint16(xMatch), + /*10098*/ uint16(xCondDataSize), 10092, 10095, 10102, + /*10102*/ uint16(xSetOp), uint16(MOVSQ), + /*10104*/ uint16(xMatch), + /*10105*/ uint16(xSetOp), uint16(CMPSB), + /*10107*/ uint16(xMatch), + /*10108*/ uint16(xCondIs64), 10111, 10121, + /*10111*/ uint16(xCondDataSize), 10115, 10118, 0, + /*10115*/ uint16(xSetOp), uint16(CMPSW), + /*10117*/ uint16(xMatch), + /*10118*/ uint16(xSetOp), uint16(CMPSD), + /*10120*/ uint16(xMatch), + /*10121*/ uint16(xCondDataSize), 10115, 10118, 10125, + /*10125*/ uint16(xSetOp), uint16(CMPSQ), + /*10127*/ uint16(xMatch), + /*10128*/ uint16(xSetOp), uint16(TEST), + /*10130*/ uint16(xReadIb), + /*10131*/ uint16(xArgAL), + /*10132*/ uint16(xArgImm8u), + /*10133*/ uint16(xMatch), + /*10134*/ uint16(xCondIs64), 10137, 10153, + /*10137*/ uint16(xCondDataSize), 10141, 10147, 0, + /*10141*/ uint16(xSetOp), uint16(TEST), + /*10143*/ uint16(xReadIw), + /*10144*/ uint16(xArgAX), + /*10145*/ uint16(xArgImm16), + /*10146*/ uint16(xMatch), + /*10147*/ uint16(xSetOp), uint16(TEST), + /*10149*/ uint16(xReadId), + /*10150*/ uint16(xArgEAX), + /*10151*/ uint16(xArgImm32), + /*10152*/ uint16(xMatch), + /*10153*/ uint16(xCondDataSize), 10141, 10147, 10157, + /*10157*/ uint16(xSetOp), uint16(TEST), + /*10159*/ uint16(xReadId), + /*10160*/ uint16(xArgRAX), + /*10161*/ uint16(xArgImm32), + /*10162*/ uint16(xMatch), + /*10163*/ uint16(xSetOp), uint16(STOSB), + /*10165*/ uint16(xMatch), + /*10166*/ uint16(xCondIs64), 10169, 10179, + /*10169*/ uint16(xCondDataSize), 10173, 10176, 0, + /*10173*/ uint16(xSetOp), uint16(STOSW), + /*10175*/ uint16(xMatch), + /*10176*/ uint16(xSetOp), uint16(STOSD), + /*10178*/ uint16(xMatch), + /*10179*/ uint16(xCondDataSize), 10173, 10176, 10183, + /*10183*/ uint16(xSetOp), uint16(STOSQ), + /*10185*/ uint16(xMatch), + /*10186*/ uint16(xSetOp), uint16(LODSB), + /*10188*/ uint16(xMatch), + /*10189*/ uint16(xCondIs64), 10192, 10202, + /*10192*/ uint16(xCondDataSize), 10196, 10199, 0, + /*10196*/ uint16(xSetOp), uint16(LODSW), + /*10198*/ uint16(xMatch), + /*10199*/ uint16(xSetOp), uint16(LODSD), + /*10201*/ uint16(xMatch), + /*10202*/ uint16(xCondDataSize), 10196, 10199, 10206, + /*10206*/ uint16(xSetOp), uint16(LODSQ), + /*10208*/ uint16(xMatch), + /*10209*/ uint16(xSetOp), uint16(SCASB), + /*10211*/ uint16(xMatch), + /*10212*/ uint16(xCondIs64), 10215, 10225, + /*10215*/ uint16(xCondDataSize), 10219, 10222, 0, + /*10219*/ uint16(xSetOp), uint16(SCASW), + /*10221*/ uint16(xMatch), + /*10222*/ uint16(xSetOp), uint16(SCASD), + /*10224*/ uint16(xMatch), + /*10225*/ uint16(xCondDataSize), 10219, 10222, 10229, + /*10229*/ uint16(xSetOp), uint16(SCASQ), + /*10231*/ uint16(xMatch), + /*10232*/ uint16(xSetOp), uint16(MOV), + /*10234*/ uint16(xReadIb), + /*10235*/ uint16(xArgR8op), + /*10236*/ uint16(xArgImm8u), + /*10237*/ uint16(xMatch), + /*10238*/ uint16(xCondIs64), 10241, 10257, + /*10241*/ uint16(xCondDataSize), 10245, 10251, 0, + /*10245*/ uint16(xSetOp), uint16(MOV), + /*10247*/ uint16(xReadIw), + /*10248*/ uint16(xArgR16op), + /*10249*/ uint16(xArgImm16), + /*10250*/ uint16(xMatch), + /*10251*/ uint16(xSetOp), uint16(MOV), + /*10253*/ uint16(xReadId), + /*10254*/ uint16(xArgR32op), + /*10255*/ uint16(xArgImm32), + /*10256*/ uint16(xMatch), + /*10257*/ uint16(xCondDataSize), 10245, 10251, 10261, + /*10261*/ uint16(xSetOp), uint16(MOV), + /*10263*/ uint16(xReadIo), + /*10264*/ uint16(xArgR64op), + /*10265*/ uint16(xArgImm64), + /*10266*/ uint16(xMatch), + /*10267*/ uint16(xCondSlashR), + 10276, // 0 + 10282, // 1 + 10288, // 2 + 10294, // 3 + 10300, // 4 + 10306, // 5 + 0, // 6 + 10312, // 7 + /*10276*/ uint16(xSetOp), uint16(ROL), + /*10278*/ uint16(xReadIb), + /*10279*/ uint16(xArgRM8), + /*10280*/ uint16(xArgImm8u), + /*10281*/ uint16(xMatch), + /*10282*/ uint16(xSetOp), uint16(ROR), + /*10284*/ uint16(xReadIb), + /*10285*/ uint16(xArgRM8), + /*10286*/ uint16(xArgImm8u), + /*10287*/ uint16(xMatch), + /*10288*/ uint16(xSetOp), uint16(RCL), + /*10290*/ uint16(xReadIb), + /*10291*/ uint16(xArgRM8), + /*10292*/ uint16(xArgImm8u), + /*10293*/ uint16(xMatch), + /*10294*/ uint16(xSetOp), uint16(RCR), + /*10296*/ uint16(xReadIb), + /*10297*/ uint16(xArgRM8), + /*10298*/ uint16(xArgImm8u), + /*10299*/ uint16(xMatch), + /*10300*/ uint16(xSetOp), uint16(SHL), + /*10302*/ uint16(xReadIb), + /*10303*/ uint16(xArgRM8), + /*10304*/ uint16(xArgImm8u), + /*10305*/ uint16(xMatch), + /*10306*/ uint16(xSetOp), uint16(SHR), + /*10308*/ uint16(xReadIb), + /*10309*/ uint16(xArgRM8), + /*10310*/ uint16(xArgImm8u), + /*10311*/ uint16(xMatch), + /*10312*/ uint16(xSetOp), uint16(SAR), + /*10314*/ uint16(xReadIb), + /*10315*/ uint16(xArgRM8), + /*10316*/ uint16(xArgImm8u), + /*10317*/ uint16(xMatch), + /*10318*/ uint16(xCondSlashR), + 10327, // 0 + 10349, // 1 + 10371, // 2 + 10400, // 3 + 10429, // 4 + 10458, // 5 + 0, // 6 + 10487, // 7 + /*10327*/ uint16(xCondDataSize), 10331, 10337, 10343, + /*10331*/ uint16(xSetOp), uint16(ROL), + /*10333*/ uint16(xReadIb), + /*10334*/ uint16(xArgRM16), + /*10335*/ uint16(xArgImm8u), + /*10336*/ uint16(xMatch), + /*10337*/ uint16(xSetOp), uint16(ROL), + /*10339*/ uint16(xReadIb), + /*10340*/ uint16(xArgRM32), + /*10341*/ uint16(xArgImm8u), + /*10342*/ uint16(xMatch), + /*10343*/ uint16(xSetOp), uint16(ROL), + /*10345*/ uint16(xReadIb), + /*10346*/ uint16(xArgRM64), + /*10347*/ uint16(xArgImm8u), + /*10348*/ uint16(xMatch), + /*10349*/ uint16(xCondDataSize), 10353, 10359, 10365, + /*10353*/ uint16(xSetOp), uint16(ROR), + /*10355*/ uint16(xReadIb), + /*10356*/ uint16(xArgRM16), + /*10357*/ uint16(xArgImm8u), + /*10358*/ uint16(xMatch), + /*10359*/ uint16(xSetOp), uint16(ROR), + /*10361*/ uint16(xReadIb), + /*10362*/ uint16(xArgRM32), + /*10363*/ uint16(xArgImm8u), + /*10364*/ uint16(xMatch), + /*10365*/ uint16(xSetOp), uint16(ROR), + /*10367*/ uint16(xReadIb), + /*10368*/ uint16(xArgRM64), + /*10369*/ uint16(xArgImm8u), + /*10370*/ uint16(xMatch), + /*10371*/ uint16(xCondIs64), 10374, 10390, + /*10374*/ uint16(xCondDataSize), 10378, 10384, 0, + /*10378*/ uint16(xSetOp), uint16(RCL), + /*10380*/ uint16(xReadIb), + /*10381*/ uint16(xArgRM16), + /*10382*/ uint16(xArgImm8u), + /*10383*/ uint16(xMatch), + /*10384*/ uint16(xSetOp), uint16(RCL), + /*10386*/ uint16(xReadIb), + /*10387*/ uint16(xArgRM32), + /*10388*/ uint16(xArgImm8u), + /*10389*/ uint16(xMatch), + /*10390*/ uint16(xCondDataSize), 10378, 10384, 10394, + /*10394*/ uint16(xSetOp), uint16(RCL), + /*10396*/ uint16(xReadIb), + /*10397*/ uint16(xArgRM64), + /*10398*/ uint16(xArgImm8u), + /*10399*/ uint16(xMatch), + /*10400*/ uint16(xCondIs64), 10403, 10419, + /*10403*/ uint16(xCondDataSize), 10407, 10413, 0, + /*10407*/ uint16(xSetOp), uint16(RCR), + /*10409*/ uint16(xReadIb), + /*10410*/ uint16(xArgRM16), + /*10411*/ uint16(xArgImm8u), + /*10412*/ uint16(xMatch), + /*10413*/ uint16(xSetOp), uint16(RCR), + /*10415*/ uint16(xReadIb), + /*10416*/ uint16(xArgRM32), + /*10417*/ uint16(xArgImm8u), + /*10418*/ uint16(xMatch), + /*10419*/ uint16(xCondDataSize), 10407, 10413, 10423, + /*10423*/ uint16(xSetOp), uint16(RCR), + /*10425*/ uint16(xReadIb), + /*10426*/ uint16(xArgRM64), + /*10427*/ uint16(xArgImm8u), + /*10428*/ uint16(xMatch), + /*10429*/ uint16(xCondIs64), 10432, 10448, + /*10432*/ uint16(xCondDataSize), 10436, 10442, 0, + /*10436*/ uint16(xSetOp), uint16(SHL), + /*10438*/ uint16(xReadIb), + /*10439*/ uint16(xArgRM16), + /*10440*/ uint16(xArgImm8u), + /*10441*/ uint16(xMatch), + /*10442*/ uint16(xSetOp), uint16(SHL), + /*10444*/ uint16(xReadIb), + /*10445*/ uint16(xArgRM32), + /*10446*/ uint16(xArgImm8u), + /*10447*/ uint16(xMatch), + /*10448*/ uint16(xCondDataSize), 10436, 10442, 10452, + /*10452*/ uint16(xSetOp), uint16(SHL), + /*10454*/ uint16(xReadIb), + /*10455*/ uint16(xArgRM64), + /*10456*/ uint16(xArgImm8u), + /*10457*/ uint16(xMatch), + /*10458*/ uint16(xCondIs64), 10461, 10477, + /*10461*/ uint16(xCondDataSize), 10465, 10471, 0, + /*10465*/ uint16(xSetOp), uint16(SHR), + /*10467*/ uint16(xReadIb), + /*10468*/ uint16(xArgRM16), + /*10469*/ uint16(xArgImm8u), + /*10470*/ uint16(xMatch), + /*10471*/ uint16(xSetOp), uint16(SHR), + /*10473*/ uint16(xReadIb), + /*10474*/ uint16(xArgRM32), + /*10475*/ uint16(xArgImm8u), + /*10476*/ uint16(xMatch), + /*10477*/ uint16(xCondDataSize), 10465, 10471, 10481, + /*10481*/ uint16(xSetOp), uint16(SHR), + /*10483*/ uint16(xReadIb), + /*10484*/ uint16(xArgRM64), + /*10485*/ uint16(xArgImm8u), + /*10486*/ uint16(xMatch), + /*10487*/ uint16(xCondIs64), 10490, 10506, + /*10490*/ uint16(xCondDataSize), 10494, 10500, 0, + /*10494*/ uint16(xSetOp), uint16(SAR), + /*10496*/ uint16(xReadIb), + /*10497*/ uint16(xArgRM16), + /*10498*/ uint16(xArgImm8u), + /*10499*/ uint16(xMatch), + /*10500*/ uint16(xSetOp), uint16(SAR), + /*10502*/ uint16(xReadIb), + /*10503*/ uint16(xArgRM32), + /*10504*/ uint16(xArgImm8u), + /*10505*/ uint16(xMatch), + /*10506*/ uint16(xCondDataSize), 10494, 10500, 10510, + /*10510*/ uint16(xSetOp), uint16(SAR), + /*10512*/ uint16(xReadIb), + /*10513*/ uint16(xArgRM64), + /*10514*/ uint16(xArgImm8u), + /*10515*/ uint16(xMatch), + /*10516*/ uint16(xSetOp), uint16(RET), + /*10518*/ uint16(xReadIw), + /*10519*/ uint16(xArgImm16u), + /*10520*/ uint16(xMatch), + /*10521*/ uint16(xSetOp), uint16(RET), + /*10523*/ uint16(xMatch), + /*10524*/ uint16(xCondIs64), 10527, 0, + /*10527*/ uint16(xCondDataSize), 10531, 10537, 0, + /*10531*/ uint16(xSetOp), uint16(LES), + /*10533*/ uint16(xReadSlashR), + /*10534*/ uint16(xArgR16), + /*10535*/ uint16(xArgM16colon16), + /*10536*/ uint16(xMatch), + /*10537*/ uint16(xSetOp), uint16(LES), + /*10539*/ uint16(xReadSlashR), + /*10540*/ uint16(xArgR32), + /*10541*/ uint16(xArgM16colon32), + /*10542*/ uint16(xMatch), + /*10543*/ uint16(xCondIs64), 10546, 0, + /*10546*/ uint16(xCondDataSize), 10550, 10556, 0, + /*10550*/ uint16(xSetOp), uint16(LDS), + /*10552*/ uint16(xReadSlashR), + /*10553*/ uint16(xArgR16), + /*10554*/ uint16(xArgM16colon16), + /*10555*/ uint16(xMatch), + /*10556*/ uint16(xSetOp), uint16(LDS), + /*10558*/ uint16(xReadSlashR), + /*10559*/ uint16(xArgR32), + /*10560*/ uint16(xArgM16colon32), + /*10561*/ uint16(xMatch), + /*10562*/ uint16(xCondByte), 1, + 0xF8, 10581, + /*10566*/ uint16(xCondSlashR), + 10575, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*10575*/ uint16(xSetOp), uint16(MOV), + /*10577*/ uint16(xReadIb), + /*10578*/ uint16(xArgRM8), + /*10579*/ uint16(xArgImm8u), + /*10580*/ uint16(xMatch), + /*10581*/ uint16(xSetOp), uint16(XABORT), + /*10583*/ uint16(xReadIb), + /*10584*/ uint16(xArgImm8u), + /*10585*/ uint16(xMatch), + /*10586*/ uint16(xCondByte), 1, + 0xF8, 10628, + /*10590*/ uint16(xCondSlashR), + 10599, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*10599*/ uint16(xCondIs64), 10602, 10618, + /*10602*/ uint16(xCondDataSize), 10606, 10612, 0, + /*10606*/ uint16(xSetOp), uint16(MOV), + /*10608*/ uint16(xReadIw), + /*10609*/ uint16(xArgRM16), + /*10610*/ uint16(xArgImm16), + /*10611*/ uint16(xMatch), + /*10612*/ uint16(xSetOp), uint16(MOV), + /*10614*/ uint16(xReadId), + /*10615*/ uint16(xArgRM32), + /*10616*/ uint16(xArgImm32), + /*10617*/ uint16(xMatch), + /*10618*/ uint16(xCondDataSize), 10606, 10612, 10622, + /*10622*/ uint16(xSetOp), uint16(MOV), + /*10624*/ uint16(xReadId), + /*10625*/ uint16(xArgRM64), + /*10626*/ uint16(xArgImm32), + /*10627*/ uint16(xMatch), + /*10628*/ uint16(xCondDataSize), 10632, 10637, 10642, + /*10632*/ uint16(xSetOp), uint16(XBEGIN), + /*10634*/ uint16(xReadCw), + /*10635*/ uint16(xArgRel16), + /*10636*/ uint16(xMatch), + /*10637*/ uint16(xSetOp), uint16(XBEGIN), + /*10639*/ uint16(xReadCd), + /*10640*/ uint16(xArgRel32), + /*10641*/ uint16(xMatch), + /*10642*/ uint16(xSetOp), uint16(XBEGIN), + /*10644*/ uint16(xReadCd), + /*10645*/ uint16(xArgRel32), + /*10646*/ uint16(xMatch), + /*10647*/ uint16(xSetOp), uint16(ENTER), + /*10649*/ uint16(xReadIw), + /*10650*/ uint16(xReadIb), + /*10651*/ uint16(xArgImm16u), + /*10652*/ uint16(xArgImm8u), + /*10653*/ uint16(xMatch), + /*10654*/ uint16(xCondIs64), 10657, 10667, + /*10657*/ uint16(xCondDataSize), 10661, 10664, 0, + /*10661*/ uint16(xSetOp), uint16(LEAVE), + /*10663*/ uint16(xMatch), + /*10664*/ uint16(xSetOp), uint16(LEAVE), + /*10666*/ uint16(xMatch), + /*10667*/ uint16(xCondDataSize), 10661, 10671, 10674, + /*10671*/ uint16(xSetOp), uint16(LEAVE), + /*10673*/ uint16(xMatch), + /*10674*/ uint16(xSetOp), uint16(LEAVE), + /*10676*/ uint16(xMatch), + /*10677*/ uint16(xSetOp), uint16(LRET), + /*10679*/ uint16(xReadIw), + /*10680*/ uint16(xArgImm16u), + /*10681*/ uint16(xMatch), + /*10682*/ uint16(xSetOp), uint16(LRET), + /*10684*/ uint16(xMatch), + /*10685*/ uint16(xSetOp), uint16(INT), + /*10687*/ uint16(xArg3), + /*10688*/ uint16(xMatch), + /*10689*/ uint16(xSetOp), uint16(INT), + /*10691*/ uint16(xReadIb), + /*10692*/ uint16(xArgImm8u), + /*10693*/ uint16(xMatch), + /*10694*/ uint16(xCondIs64), 10697, 0, + /*10697*/ uint16(xSetOp), uint16(INTO), + /*10699*/ uint16(xMatch), + /*10700*/ uint16(xCondIs64), 10703, 10713, + /*10703*/ uint16(xCondDataSize), 10707, 10710, 0, + /*10707*/ uint16(xSetOp), uint16(IRET), + /*10709*/ uint16(xMatch), + /*10710*/ uint16(xSetOp), uint16(IRETD), + /*10712*/ uint16(xMatch), + /*10713*/ uint16(xCondDataSize), 10707, 10710, 10717, + /*10717*/ uint16(xSetOp), uint16(IRETQ), + /*10719*/ uint16(xMatch), + /*10720*/ uint16(xCondSlashR), + 10729, // 0 + 10734, // 1 + 10739, // 2 + 10744, // 3 + 10749, // 4 + 10754, // 5 + 0, // 6 + 10759, // 7 + /*10729*/ uint16(xSetOp), uint16(ROL), + /*10731*/ uint16(xArgRM8), + /*10732*/ uint16(xArg1), + /*10733*/ uint16(xMatch), + /*10734*/ uint16(xSetOp), uint16(ROR), + /*10736*/ uint16(xArgRM8), + /*10737*/ uint16(xArg1), + /*10738*/ uint16(xMatch), + /*10739*/ uint16(xSetOp), uint16(RCL), + /*10741*/ uint16(xArgRM8), + /*10742*/ uint16(xArg1), + /*10743*/ uint16(xMatch), + /*10744*/ uint16(xSetOp), uint16(RCR), + /*10746*/ uint16(xArgRM8), + /*10747*/ uint16(xArg1), + /*10748*/ uint16(xMatch), + /*10749*/ uint16(xSetOp), uint16(SHL), + /*10751*/ uint16(xArgRM8), + /*10752*/ uint16(xArg1), + /*10753*/ uint16(xMatch), + /*10754*/ uint16(xSetOp), uint16(SHR), + /*10756*/ uint16(xArgRM8), + /*10757*/ uint16(xArg1), + /*10758*/ uint16(xMatch), + /*10759*/ uint16(xSetOp), uint16(SAR), + /*10761*/ uint16(xArgRM8), + /*10762*/ uint16(xArg1), + /*10763*/ uint16(xMatch), + /*10764*/ uint16(xCondSlashR), + 10773, // 0 + 10799, // 1 + 10825, // 2 + 10851, // 3 + 10877, // 4 + 10903, // 5 + 0, // 6 + 10929, // 7 + /*10773*/ uint16(xCondIs64), 10776, 10790, + /*10776*/ uint16(xCondDataSize), 10780, 10785, 0, + /*10780*/ uint16(xSetOp), uint16(ROL), + /*10782*/ uint16(xArgRM16), + /*10783*/ uint16(xArg1), + /*10784*/ uint16(xMatch), + /*10785*/ uint16(xSetOp), uint16(ROL), + /*10787*/ uint16(xArgRM32), + /*10788*/ uint16(xArg1), + /*10789*/ uint16(xMatch), + /*10790*/ uint16(xCondDataSize), 10780, 10785, 10794, + /*10794*/ uint16(xSetOp), uint16(ROL), + /*10796*/ uint16(xArgRM64), + /*10797*/ uint16(xArg1), + /*10798*/ uint16(xMatch), + /*10799*/ uint16(xCondIs64), 10802, 10816, + /*10802*/ uint16(xCondDataSize), 10806, 10811, 0, + /*10806*/ uint16(xSetOp), uint16(ROR), + /*10808*/ uint16(xArgRM16), + /*10809*/ uint16(xArg1), + /*10810*/ uint16(xMatch), + /*10811*/ uint16(xSetOp), uint16(ROR), + /*10813*/ uint16(xArgRM32), + /*10814*/ uint16(xArg1), + /*10815*/ uint16(xMatch), + /*10816*/ uint16(xCondDataSize), 10806, 10811, 10820, + /*10820*/ uint16(xSetOp), uint16(ROR), + /*10822*/ uint16(xArgRM64), + /*10823*/ uint16(xArg1), + /*10824*/ uint16(xMatch), + /*10825*/ uint16(xCondIs64), 10828, 10842, + /*10828*/ uint16(xCondDataSize), 10832, 10837, 0, + /*10832*/ uint16(xSetOp), uint16(RCL), + /*10834*/ uint16(xArgRM16), + /*10835*/ uint16(xArg1), + /*10836*/ uint16(xMatch), + /*10837*/ uint16(xSetOp), uint16(RCL), + /*10839*/ uint16(xArgRM32), + /*10840*/ uint16(xArg1), + /*10841*/ uint16(xMatch), + /*10842*/ uint16(xCondDataSize), 10832, 10837, 10846, + /*10846*/ uint16(xSetOp), uint16(RCL), + /*10848*/ uint16(xArgRM64), + /*10849*/ uint16(xArg1), + /*10850*/ uint16(xMatch), + /*10851*/ uint16(xCondIs64), 10854, 10868, + /*10854*/ uint16(xCondDataSize), 10858, 10863, 0, + /*10858*/ uint16(xSetOp), uint16(RCR), + /*10860*/ uint16(xArgRM16), + /*10861*/ uint16(xArg1), + /*10862*/ uint16(xMatch), + /*10863*/ uint16(xSetOp), uint16(RCR), + /*10865*/ uint16(xArgRM32), + /*10866*/ uint16(xArg1), + /*10867*/ uint16(xMatch), + /*10868*/ uint16(xCondDataSize), 10858, 10863, 10872, + /*10872*/ uint16(xSetOp), uint16(RCR), + /*10874*/ uint16(xArgRM64), + /*10875*/ uint16(xArg1), + /*10876*/ uint16(xMatch), + /*10877*/ uint16(xCondIs64), 10880, 10894, + /*10880*/ uint16(xCondDataSize), 10884, 10889, 0, + /*10884*/ uint16(xSetOp), uint16(SHL), + /*10886*/ uint16(xArgRM16), + /*10887*/ uint16(xArg1), + /*10888*/ uint16(xMatch), + /*10889*/ uint16(xSetOp), uint16(SHL), + /*10891*/ uint16(xArgRM32), + /*10892*/ uint16(xArg1), + /*10893*/ uint16(xMatch), + /*10894*/ uint16(xCondDataSize), 10884, 10889, 10898, + /*10898*/ uint16(xSetOp), uint16(SHL), + /*10900*/ uint16(xArgRM64), + /*10901*/ uint16(xArg1), + /*10902*/ uint16(xMatch), + /*10903*/ uint16(xCondIs64), 10906, 10920, + /*10906*/ uint16(xCondDataSize), 10910, 10915, 0, + /*10910*/ uint16(xSetOp), uint16(SHR), + /*10912*/ uint16(xArgRM16), + /*10913*/ uint16(xArg1), + /*10914*/ uint16(xMatch), + /*10915*/ uint16(xSetOp), uint16(SHR), + /*10917*/ uint16(xArgRM32), + /*10918*/ uint16(xArg1), + /*10919*/ uint16(xMatch), + /*10920*/ uint16(xCondDataSize), 10910, 10915, 10924, + /*10924*/ uint16(xSetOp), uint16(SHR), + /*10926*/ uint16(xArgRM64), + /*10927*/ uint16(xArg1), + /*10928*/ uint16(xMatch), + /*10929*/ uint16(xCondIs64), 10932, 10946, + /*10932*/ uint16(xCondDataSize), 10936, 10941, 0, + /*10936*/ uint16(xSetOp), uint16(SAR), + /*10938*/ uint16(xArgRM16), + /*10939*/ uint16(xArg1), + /*10940*/ uint16(xMatch), + /*10941*/ uint16(xSetOp), uint16(SAR), + /*10943*/ uint16(xArgRM32), + /*10944*/ uint16(xArg1), + /*10945*/ uint16(xMatch), + /*10946*/ uint16(xCondDataSize), 10936, 10941, 10950, + /*10950*/ uint16(xSetOp), uint16(SAR), + /*10952*/ uint16(xArgRM64), + /*10953*/ uint16(xArg1), + /*10954*/ uint16(xMatch), + /*10955*/ uint16(xCondSlashR), + 10964, // 0 + 10969, // 1 + 10974, // 2 + 10979, // 3 + 10984, // 4 + 10989, // 5 + 0, // 6 + 10994, // 7 + /*10964*/ uint16(xSetOp), uint16(ROL), + /*10966*/ uint16(xArgRM8), + /*10967*/ uint16(xArgCL), + /*10968*/ uint16(xMatch), + /*10969*/ uint16(xSetOp), uint16(ROR), + /*10971*/ uint16(xArgRM8), + /*10972*/ uint16(xArgCL), + /*10973*/ uint16(xMatch), + /*10974*/ uint16(xSetOp), uint16(RCL), + /*10976*/ uint16(xArgRM8), + /*10977*/ uint16(xArgCL), + /*10978*/ uint16(xMatch), + /*10979*/ uint16(xSetOp), uint16(RCR), + /*10981*/ uint16(xArgRM8), + /*10982*/ uint16(xArgCL), + /*10983*/ uint16(xMatch), + /*10984*/ uint16(xSetOp), uint16(SHL), + /*10986*/ uint16(xArgRM8), + /*10987*/ uint16(xArgCL), + /*10988*/ uint16(xMatch), + /*10989*/ uint16(xSetOp), uint16(SHR), + /*10991*/ uint16(xArgRM8), + /*10992*/ uint16(xArgCL), + /*10993*/ uint16(xMatch), + /*10994*/ uint16(xSetOp), uint16(SAR), + /*10996*/ uint16(xArgRM8), + /*10997*/ uint16(xArgCL), + /*10998*/ uint16(xMatch), + /*10999*/ uint16(xCondSlashR), + 11008, // 0 + 11034, // 1 + 11060, // 2 + 11086, // 3 + 11112, // 4 + 11138, // 5 + 0, // 6 + 11164, // 7 + /*11008*/ uint16(xCondIs64), 11011, 11025, + /*11011*/ uint16(xCondDataSize), 11015, 11020, 0, + /*11015*/ uint16(xSetOp), uint16(ROL), + /*11017*/ uint16(xArgRM16), + /*11018*/ uint16(xArgCL), + /*11019*/ uint16(xMatch), + /*11020*/ uint16(xSetOp), uint16(ROL), + /*11022*/ uint16(xArgRM32), + /*11023*/ uint16(xArgCL), + /*11024*/ uint16(xMatch), + /*11025*/ uint16(xCondDataSize), 11015, 11020, 11029, + /*11029*/ uint16(xSetOp), uint16(ROL), + /*11031*/ uint16(xArgRM64), + /*11032*/ uint16(xArgCL), + /*11033*/ uint16(xMatch), + /*11034*/ uint16(xCondIs64), 11037, 11051, + /*11037*/ uint16(xCondDataSize), 11041, 11046, 0, + /*11041*/ uint16(xSetOp), uint16(ROR), + /*11043*/ uint16(xArgRM16), + /*11044*/ uint16(xArgCL), + /*11045*/ uint16(xMatch), + /*11046*/ uint16(xSetOp), uint16(ROR), + /*11048*/ uint16(xArgRM32), + /*11049*/ uint16(xArgCL), + /*11050*/ uint16(xMatch), + /*11051*/ uint16(xCondDataSize), 11041, 11046, 11055, + /*11055*/ uint16(xSetOp), uint16(ROR), + /*11057*/ uint16(xArgRM64), + /*11058*/ uint16(xArgCL), + /*11059*/ uint16(xMatch), + /*11060*/ uint16(xCondIs64), 11063, 11077, + /*11063*/ uint16(xCondDataSize), 11067, 11072, 0, + /*11067*/ uint16(xSetOp), uint16(RCL), + /*11069*/ uint16(xArgRM16), + /*11070*/ uint16(xArgCL), + /*11071*/ uint16(xMatch), + /*11072*/ uint16(xSetOp), uint16(RCL), + /*11074*/ uint16(xArgRM32), + /*11075*/ uint16(xArgCL), + /*11076*/ uint16(xMatch), + /*11077*/ uint16(xCondDataSize), 11067, 11072, 11081, + /*11081*/ uint16(xSetOp), uint16(RCL), + /*11083*/ uint16(xArgRM64), + /*11084*/ uint16(xArgCL), + /*11085*/ uint16(xMatch), + /*11086*/ uint16(xCondIs64), 11089, 11103, + /*11089*/ uint16(xCondDataSize), 11093, 11098, 0, + /*11093*/ uint16(xSetOp), uint16(RCR), + /*11095*/ uint16(xArgRM16), + /*11096*/ uint16(xArgCL), + /*11097*/ uint16(xMatch), + /*11098*/ uint16(xSetOp), uint16(RCR), + /*11100*/ uint16(xArgRM32), + /*11101*/ uint16(xArgCL), + /*11102*/ uint16(xMatch), + /*11103*/ uint16(xCondDataSize), 11093, 11098, 11107, + /*11107*/ uint16(xSetOp), uint16(RCR), + /*11109*/ uint16(xArgRM64), + /*11110*/ uint16(xArgCL), + /*11111*/ uint16(xMatch), + /*11112*/ uint16(xCondIs64), 11115, 11129, + /*11115*/ uint16(xCondDataSize), 11119, 11124, 0, + /*11119*/ uint16(xSetOp), uint16(SHL), + /*11121*/ uint16(xArgRM16), + /*11122*/ uint16(xArgCL), + /*11123*/ uint16(xMatch), + /*11124*/ uint16(xSetOp), uint16(SHL), + /*11126*/ uint16(xArgRM32), + /*11127*/ uint16(xArgCL), + /*11128*/ uint16(xMatch), + /*11129*/ uint16(xCondDataSize), 11119, 11124, 11133, + /*11133*/ uint16(xSetOp), uint16(SHL), + /*11135*/ uint16(xArgRM64), + /*11136*/ uint16(xArgCL), + /*11137*/ uint16(xMatch), + /*11138*/ uint16(xCondIs64), 11141, 11155, + /*11141*/ uint16(xCondDataSize), 11145, 11150, 0, + /*11145*/ uint16(xSetOp), uint16(SHR), + /*11147*/ uint16(xArgRM16), + /*11148*/ uint16(xArgCL), + /*11149*/ uint16(xMatch), + /*11150*/ uint16(xSetOp), uint16(SHR), + /*11152*/ uint16(xArgRM32), + /*11153*/ uint16(xArgCL), + /*11154*/ uint16(xMatch), + /*11155*/ uint16(xCondDataSize), 11145, 11150, 11159, + /*11159*/ uint16(xSetOp), uint16(SHR), + /*11161*/ uint16(xArgRM64), + /*11162*/ uint16(xArgCL), + /*11163*/ uint16(xMatch), + /*11164*/ uint16(xCondIs64), 11167, 11181, + /*11167*/ uint16(xCondDataSize), 11171, 11176, 0, + /*11171*/ uint16(xSetOp), uint16(SAR), + /*11173*/ uint16(xArgRM16), + /*11174*/ uint16(xArgCL), + /*11175*/ uint16(xMatch), + /*11176*/ uint16(xSetOp), uint16(SAR), + /*11178*/ uint16(xArgRM32), + /*11179*/ uint16(xArgCL), + /*11180*/ uint16(xMatch), + /*11181*/ uint16(xCondDataSize), 11171, 11176, 11185, + /*11185*/ uint16(xSetOp), uint16(SAR), + /*11187*/ uint16(xArgRM64), + /*11188*/ uint16(xArgCL), + /*11189*/ uint16(xMatch), + /*11190*/ uint16(xCondIs64), 11193, 0, + /*11193*/ uint16(xSetOp), uint16(AAM), + /*11195*/ uint16(xReadIb), + /*11196*/ uint16(xArgImm8u), + /*11197*/ uint16(xMatch), + /*11198*/ uint16(xCondIs64), 11201, 0, + /*11201*/ uint16(xSetOp), uint16(AAD), + /*11203*/ uint16(xReadIb), + /*11204*/ uint16(xArgImm8u), + /*11205*/ uint16(xMatch), + /*11206*/ uint16(xCondIs64), 11209, 11212, + /*11209*/ uint16(xSetOp), uint16(XLATB), + /*11211*/ uint16(xMatch), + /*11212*/ uint16(xCondDataSize), 11209, 11209, 11216, + /*11216*/ uint16(xSetOp), uint16(XLATB), + /*11218*/ uint16(xMatch), + /*11219*/ uint16(xCondByte), 64, + 0xc0, 11390, + 0xc1, 11390, + 0xc2, 11390, + 0xc3, 11390, + 0xc4, 11390, + 0xc5, 11390, + 0xc6, 11390, + 0xc7, 11390, + 0xc8, 11395, + 0xc9, 11395, + 0xca, 11395, + 0xcb, 11395, + 0xcc, 11395, + 0xcd, 11395, + 0xce, 11395, + 0xcf, 11395, + 0xd0, 11400, + 0xd1, 11400, + 0xd2, 11400, + 0xd3, 11400, + 0xd4, 11400, + 0xd5, 11400, + 0xd6, 11400, + 0xd7, 11400, + 0xd8, 11404, + 0xd9, 11404, + 0xda, 11404, + 0xdb, 11404, + 0xdc, 11404, + 0xdd, 11404, + 0xde, 11404, + 0xdf, 11404, + 0xe0, 11408, + 0xe1, 11408, + 0xe2, 11408, + 0xe3, 11408, + 0xe4, 11408, + 0xe5, 11408, + 0xe6, 11408, + 0xe7, 11408, + 0xe8, 11413, + 0xe9, 11413, + 0xea, 11413, + 0xeb, 11413, + 0xec, 11413, + 0xed, 11413, + 0xee, 11413, + 0xef, 11413, + 0xf0, 11418, + 0xf1, 11418, + 0xf2, 11418, + 0xf3, 11418, + 0xf4, 11418, + 0xf5, 11418, + 0xf6, 11418, + 0xf7, 11418, + 0xf8, 11423, + 0xf9, 11423, + 0xfa, 11423, + 0xfb, 11423, + 0xfc, 11423, + 0xfd, 11423, + 0xfe, 11423, + 0xff, 11423, + /*11349*/ uint16(xCondSlashR), + 11358, // 0 + 11362, // 1 + 11366, // 2 + 11370, // 3 + 11374, // 4 + 11378, // 5 + 11382, // 6 + 11386, // 7 + /*11358*/ uint16(xSetOp), uint16(FADD), + /*11360*/ uint16(xArgM32fp), + /*11361*/ uint16(xMatch), + /*11362*/ uint16(xSetOp), uint16(FMUL), + /*11364*/ uint16(xArgM32fp), + /*11365*/ uint16(xMatch), + /*11366*/ uint16(xSetOp), uint16(FCOM), + /*11368*/ uint16(xArgM32fp), + /*11369*/ uint16(xMatch), + /*11370*/ uint16(xSetOp), uint16(FCOMP), + /*11372*/ uint16(xArgM32fp), + /*11373*/ uint16(xMatch), + /*11374*/ uint16(xSetOp), uint16(FSUB), + /*11376*/ uint16(xArgM32fp), + /*11377*/ uint16(xMatch), + /*11378*/ uint16(xSetOp), uint16(FSUBR), + /*11380*/ uint16(xArgM32fp), + /*11381*/ uint16(xMatch), + /*11382*/ uint16(xSetOp), uint16(FDIV), + /*11384*/ uint16(xArgM32fp), + /*11385*/ uint16(xMatch), + /*11386*/ uint16(xSetOp), uint16(FDIVR), + /*11388*/ uint16(xArgM32fp), + /*11389*/ uint16(xMatch), + /*11390*/ uint16(xSetOp), uint16(FADD), + /*11392*/ uint16(xArgST), + /*11393*/ uint16(xArgSTi), + /*11394*/ uint16(xMatch), + /*11395*/ uint16(xSetOp), uint16(FMUL), + /*11397*/ uint16(xArgST), + /*11398*/ uint16(xArgSTi), + /*11399*/ uint16(xMatch), + /*11400*/ uint16(xSetOp), uint16(FCOM), + /*11402*/ uint16(xArgSTi), + /*11403*/ uint16(xMatch), + /*11404*/ uint16(xSetOp), uint16(FCOMP), + /*11406*/ uint16(xArgSTi), + /*11407*/ uint16(xMatch), + /*11408*/ uint16(xSetOp), uint16(FSUB), + /*11410*/ uint16(xArgST), + /*11411*/ uint16(xArgSTi), + /*11412*/ uint16(xMatch), + /*11413*/ uint16(xSetOp), uint16(FSUBR), + /*11415*/ uint16(xArgST), + /*11416*/ uint16(xArgSTi), + /*11417*/ uint16(xMatch), + /*11418*/ uint16(xSetOp), uint16(FDIV), + /*11420*/ uint16(xArgST), + /*11421*/ uint16(xArgSTi), + /*11422*/ uint16(xMatch), + /*11423*/ uint16(xSetOp), uint16(FDIVR), + /*11425*/ uint16(xArgST), + /*11426*/ uint16(xArgSTi), + /*11427*/ uint16(xMatch), + /*11428*/ uint16(xCondByte), 42, + 0xc0, 11551, + 0xc1, 11551, + 0xc2, 11551, + 0xc3, 11551, + 0xc4, 11551, + 0xc5, 11551, + 0xc6, 11551, + 0xc7, 11551, + 0xc8, 11555, + 0xc9, 11555, + 0xca, 11555, + 0xcb, 11555, + 0xcc, 11555, + 0xcd, 11555, + 0xce, 11555, + 0xcf, 11555, + 0xD0, 11559, + 0xE0, 11562, + 0xE1, 11565, + 0xE4, 11568, + 0xE5, 11571, + 0xE8, 11574, + 0xE9, 11577, + 0xEA, 11580, + 0xEB, 11583, + 0xEC, 11586, + 0xF0, 11589, + 0xF1, 11592, + 0xF2, 11595, + 0xF3, 11598, + 0xF4, 11601, + 0xF5, 11604, + 0xF6, 11607, + 0xF7, 11610, + 0xF8, 11613, + 0xF9, 11616, + 0xFA, 11619, + 0xFB, 11622, + 0xFC, 11625, + 0xFD, 11628, + 0xFE, 11631, + 0xFF, 11634, + /*11514*/ uint16(xCondSlashR), + 11523, // 0 + 0, // 1 + 11527, // 2 + 11531, // 3 + 11535, // 4 + 11539, // 5 + 11543, // 6 + 11547, // 7 + /*11523*/ uint16(xSetOp), uint16(FLD), + /*11525*/ uint16(xArgM32fp), + /*11526*/ uint16(xMatch), + /*11527*/ uint16(xSetOp), uint16(FST), + /*11529*/ uint16(xArgM32fp), + /*11530*/ uint16(xMatch), + /*11531*/ uint16(xSetOp), uint16(FSTP), + /*11533*/ uint16(xArgM32fp), + /*11534*/ uint16(xMatch), + /*11535*/ uint16(xSetOp), uint16(FLDENV), + /*11537*/ uint16(xArgM1428byte), + /*11538*/ uint16(xMatch), + /*11539*/ uint16(xSetOp), uint16(FLDCW), + /*11541*/ uint16(xArgM2byte), + /*11542*/ uint16(xMatch), + /*11543*/ uint16(xSetOp), uint16(FNSTENV), + /*11545*/ uint16(xArgM1428byte), + /*11546*/ uint16(xMatch), + /*11547*/ uint16(xSetOp), uint16(FNSTCW), + /*11549*/ uint16(xArgM2byte), + /*11550*/ uint16(xMatch), + /*11551*/ uint16(xSetOp), uint16(FLD), + /*11553*/ uint16(xArgSTi), + /*11554*/ uint16(xMatch), + /*11555*/ uint16(xSetOp), uint16(FXCH), + /*11557*/ uint16(xArgSTi), + /*11558*/ uint16(xMatch), + /*11559*/ uint16(xSetOp), uint16(FNOP), + /*11561*/ uint16(xMatch), + /*11562*/ uint16(xSetOp), uint16(FCHS), + /*11564*/ uint16(xMatch), + /*11565*/ uint16(xSetOp), uint16(FABS), + /*11567*/ uint16(xMatch), + /*11568*/ uint16(xSetOp), uint16(FTST), + /*11570*/ uint16(xMatch), + /*11571*/ uint16(xSetOp), uint16(FXAM), + /*11573*/ uint16(xMatch), + /*11574*/ uint16(xSetOp), uint16(FLD1), + /*11576*/ uint16(xMatch), + /*11577*/ uint16(xSetOp), uint16(FLDL2T), + /*11579*/ uint16(xMatch), + /*11580*/ uint16(xSetOp), uint16(FLDL2E), + /*11582*/ uint16(xMatch), + /*11583*/ uint16(xSetOp), uint16(FLDPI), + /*11585*/ uint16(xMatch), + /*11586*/ uint16(xSetOp), uint16(FLDLG2), + /*11588*/ uint16(xMatch), + /*11589*/ uint16(xSetOp), uint16(F2XM1), + /*11591*/ uint16(xMatch), + /*11592*/ uint16(xSetOp), uint16(FYL2X), + /*11594*/ uint16(xMatch), + /*11595*/ uint16(xSetOp), uint16(FPTAN), + /*11597*/ uint16(xMatch), + /*11598*/ uint16(xSetOp), uint16(FPATAN), + /*11600*/ uint16(xMatch), + /*11601*/ uint16(xSetOp), uint16(FXTRACT), + /*11603*/ uint16(xMatch), + /*11604*/ uint16(xSetOp), uint16(FPREM1), + /*11606*/ uint16(xMatch), + /*11607*/ uint16(xSetOp), uint16(FDECSTP), + /*11609*/ uint16(xMatch), + /*11610*/ uint16(xSetOp), uint16(FINCSTP), + /*11612*/ uint16(xMatch), + /*11613*/ uint16(xSetOp), uint16(FPREM), + /*11615*/ uint16(xMatch), + /*11616*/ uint16(xSetOp), uint16(FYL2XP1), + /*11618*/ uint16(xMatch), + /*11619*/ uint16(xSetOp), uint16(FSQRT), + /*11621*/ uint16(xMatch), + /*11622*/ uint16(xSetOp), uint16(FSINCOS), + /*11624*/ uint16(xMatch), + /*11625*/ uint16(xSetOp), uint16(FRNDINT), + /*11627*/ uint16(xMatch), + /*11628*/ uint16(xSetOp), uint16(FSCALE), + /*11630*/ uint16(xMatch), + /*11631*/ uint16(xSetOp), uint16(FSIN), + /*11633*/ uint16(xMatch), + /*11634*/ uint16(xSetOp), uint16(FCOS), + /*11636*/ uint16(xMatch), + /*11637*/ uint16(xCondByte), 33, + 0xc0, 11746, + 0xc1, 11746, + 0xc2, 11746, + 0xc3, 11746, + 0xc4, 11746, + 0xc5, 11746, + 0xc6, 11746, + 0xc7, 11746, + 0xc8, 11751, + 0xc9, 11751, + 0xca, 11751, + 0xcb, 11751, + 0xcc, 11751, + 0xcd, 11751, + 0xce, 11751, + 0xcf, 11751, + 0xd0, 11756, + 0xd1, 11756, + 0xd2, 11756, + 0xd3, 11756, + 0xd4, 11756, + 0xd5, 11756, + 0xd6, 11756, + 0xd7, 11756, + 0xd8, 11761, + 0xd9, 11761, + 0xda, 11761, + 0xdb, 11761, + 0xdc, 11761, + 0xdd, 11761, + 0xde, 11761, + 0xdf, 11761, + 0xE9, 11766, + /*11705*/ uint16(xCondSlashR), + 11714, // 0 + 11718, // 1 + 11722, // 2 + 11726, // 3 + 11730, // 4 + 11734, // 5 + 11738, // 6 + 11742, // 7 + /*11714*/ uint16(xSetOp), uint16(FIADD), + /*11716*/ uint16(xArgM32int), + /*11717*/ uint16(xMatch), + /*11718*/ uint16(xSetOp), uint16(FIMUL), + /*11720*/ uint16(xArgM32int), + /*11721*/ uint16(xMatch), + /*11722*/ uint16(xSetOp), uint16(FICOM), + /*11724*/ uint16(xArgM32int), + /*11725*/ uint16(xMatch), + /*11726*/ uint16(xSetOp), uint16(FICOMP), + /*11728*/ uint16(xArgM32int), + /*11729*/ uint16(xMatch), + /*11730*/ uint16(xSetOp), uint16(FISUB), + /*11732*/ uint16(xArgM32int), + /*11733*/ uint16(xMatch), + /*11734*/ uint16(xSetOp), uint16(FISUBR), + /*11736*/ uint16(xArgM32int), + /*11737*/ uint16(xMatch), + /*11738*/ uint16(xSetOp), uint16(FIDIV), + /*11740*/ uint16(xArgM32int), + /*11741*/ uint16(xMatch), + /*11742*/ uint16(xSetOp), uint16(FIDIVR), + /*11744*/ uint16(xArgM32int), + /*11745*/ uint16(xMatch), + /*11746*/ uint16(xSetOp), uint16(FCMOVB), + /*11748*/ uint16(xArgST), + /*11749*/ uint16(xArgSTi), + /*11750*/ uint16(xMatch), + /*11751*/ uint16(xSetOp), uint16(FCMOVE), + /*11753*/ uint16(xArgST), + /*11754*/ uint16(xArgSTi), + /*11755*/ uint16(xMatch), + /*11756*/ uint16(xSetOp), uint16(FCMOVBE), + /*11758*/ uint16(xArgST), + /*11759*/ uint16(xArgSTi), + /*11760*/ uint16(xMatch), + /*11761*/ uint16(xSetOp), uint16(FCMOVU), + /*11763*/ uint16(xArgST), + /*11764*/ uint16(xArgSTi), + /*11765*/ uint16(xMatch), + /*11766*/ uint16(xSetOp), uint16(FUCOMPP), + /*11768*/ uint16(xMatch), + /*11769*/ uint16(xCondByte), 50, + 0xc0, 11904, + 0xc1, 11904, + 0xc2, 11904, + 0xc3, 11904, + 0xc4, 11904, + 0xc5, 11904, + 0xc6, 11904, + 0xc7, 11904, + 0xc8, 11909, + 0xc9, 11909, + 0xca, 11909, + 0xcb, 11909, + 0xcc, 11909, + 0xcd, 11909, + 0xce, 11909, + 0xcf, 11909, + 0xd0, 11914, + 0xd1, 11914, + 0xd2, 11914, + 0xd3, 11914, + 0xd4, 11914, + 0xd5, 11914, + 0xd6, 11914, + 0xd7, 11914, + 0xd8, 11919, + 0xd9, 11919, + 0xda, 11919, + 0xdb, 11919, + 0xdc, 11919, + 0xdd, 11919, + 0xde, 11919, + 0xdf, 11919, + 0xE2, 11924, + 0xE3, 11927, + 0xe8, 11930, + 0xe9, 11930, + 0xea, 11930, + 0xeb, 11930, + 0xec, 11930, + 0xed, 11930, + 0xee, 11930, + 0xef, 11930, + 0xf0, 11935, + 0xf1, 11935, + 0xf2, 11935, + 0xf3, 11935, + 0xf4, 11935, + 0xf5, 11935, + 0xf6, 11935, + 0xf7, 11935, + /*11871*/ uint16(xCondSlashR), + 11880, // 0 + 11884, // 1 + 11888, // 2 + 11892, // 3 + 0, // 4 + 11896, // 5 + 0, // 6 + 11900, // 7 + /*11880*/ uint16(xSetOp), uint16(FILD), + /*11882*/ uint16(xArgM32int), + /*11883*/ uint16(xMatch), + /*11884*/ uint16(xSetOp), uint16(FISTTP), + /*11886*/ uint16(xArgM32int), + /*11887*/ uint16(xMatch), + /*11888*/ uint16(xSetOp), uint16(FIST), + /*11890*/ uint16(xArgM32int), + /*11891*/ uint16(xMatch), + /*11892*/ uint16(xSetOp), uint16(FISTP), + /*11894*/ uint16(xArgM32int), + /*11895*/ uint16(xMatch), + /*11896*/ uint16(xSetOp), uint16(FLD), + /*11898*/ uint16(xArgM80fp), + /*11899*/ uint16(xMatch), + /*11900*/ uint16(xSetOp), uint16(FSTP), + /*11902*/ uint16(xArgM80fp), + /*11903*/ uint16(xMatch), + /*11904*/ uint16(xSetOp), uint16(FCMOVNB), + /*11906*/ uint16(xArgST), + /*11907*/ uint16(xArgSTi), + /*11908*/ uint16(xMatch), + /*11909*/ uint16(xSetOp), uint16(FCMOVNE), + /*11911*/ uint16(xArgST), + /*11912*/ uint16(xArgSTi), + /*11913*/ uint16(xMatch), + /*11914*/ uint16(xSetOp), uint16(FCMOVNBE), + /*11916*/ uint16(xArgST), + /*11917*/ uint16(xArgSTi), + /*11918*/ uint16(xMatch), + /*11919*/ uint16(xSetOp), uint16(FCMOVNU), + /*11921*/ uint16(xArgST), + /*11922*/ uint16(xArgSTi), + /*11923*/ uint16(xMatch), + /*11924*/ uint16(xSetOp), uint16(FNCLEX), + /*11926*/ uint16(xMatch), + /*11927*/ uint16(xSetOp), uint16(FNINIT), + /*11929*/ uint16(xMatch), + /*11930*/ uint16(xSetOp), uint16(FUCOMI), + /*11932*/ uint16(xArgST), + /*11933*/ uint16(xArgSTi), + /*11934*/ uint16(xMatch), + /*11935*/ uint16(xSetOp), uint16(FCOMI), + /*11937*/ uint16(xArgST), + /*11938*/ uint16(xArgSTi), + /*11939*/ uint16(xMatch), + /*11940*/ uint16(xCondByte), 48, + 0xc0, 12079, + 0xc1, 12079, + 0xc2, 12079, + 0xc3, 12079, + 0xc4, 12079, + 0xc5, 12079, + 0xc6, 12079, + 0xc7, 12079, + 0xc8, 12084, + 0xc9, 12084, + 0xca, 12084, + 0xcb, 12084, + 0xcc, 12084, + 0xcd, 12084, + 0xce, 12084, + 0xcf, 12084, + 0xe0, 12089, + 0xe1, 12089, + 0xe2, 12089, + 0xe3, 12089, + 0xe4, 12089, + 0xe5, 12089, + 0xe6, 12089, + 0xe7, 12089, + 0xe8, 12094, + 0xe9, 12094, + 0xea, 12094, + 0xeb, 12094, + 0xec, 12094, + 0xed, 12094, + 0xee, 12094, + 0xef, 12094, + 0xf0, 12099, + 0xf1, 12099, + 0xf2, 12099, + 0xf3, 12099, + 0xf4, 12099, + 0xf5, 12099, + 0xf6, 12099, + 0xf7, 12099, + 0xf8, 12104, + 0xf9, 12104, + 0xfa, 12104, + 0xfb, 12104, + 0xfc, 12104, + 0xfd, 12104, + 0xfe, 12104, + 0xff, 12104, + /*12038*/ uint16(xCondSlashR), + 12047, // 0 + 12051, // 1 + 12055, // 2 + 12059, // 3 + 12063, // 4 + 12067, // 5 + 12071, // 6 + 12075, // 7 + /*12047*/ uint16(xSetOp), uint16(FADD), + /*12049*/ uint16(xArgM64fp), + /*12050*/ uint16(xMatch), + /*12051*/ uint16(xSetOp), uint16(FMUL), + /*12053*/ uint16(xArgM64fp), + /*12054*/ uint16(xMatch), + /*12055*/ uint16(xSetOp), uint16(FCOM), + /*12057*/ uint16(xArgM64fp), + /*12058*/ uint16(xMatch), + /*12059*/ uint16(xSetOp), uint16(FCOMP), + /*12061*/ uint16(xArgM64fp), + /*12062*/ uint16(xMatch), + /*12063*/ uint16(xSetOp), uint16(FSUB), + /*12065*/ uint16(xArgM64fp), + /*12066*/ uint16(xMatch), + /*12067*/ uint16(xSetOp), uint16(FSUBR), + /*12069*/ uint16(xArgM64fp), + /*12070*/ uint16(xMatch), + /*12071*/ uint16(xSetOp), uint16(FDIV), + /*12073*/ uint16(xArgM64fp), + /*12074*/ uint16(xMatch), + /*12075*/ uint16(xSetOp), uint16(FDIVR), + /*12077*/ uint16(xArgM64fp), + /*12078*/ uint16(xMatch), + /*12079*/ uint16(xSetOp), uint16(FADD), + /*12081*/ uint16(xArgSTi), + /*12082*/ uint16(xArgST), + /*12083*/ uint16(xMatch), + /*12084*/ uint16(xSetOp), uint16(FMUL), + /*12086*/ uint16(xArgSTi), + /*12087*/ uint16(xArgST), + /*12088*/ uint16(xMatch), + /*12089*/ uint16(xSetOp), uint16(FSUBR), + /*12091*/ uint16(xArgSTi), + /*12092*/ uint16(xArgST), + /*12093*/ uint16(xMatch), + /*12094*/ uint16(xSetOp), uint16(FSUB), + /*12096*/ uint16(xArgSTi), + /*12097*/ uint16(xArgST), + /*12098*/ uint16(xMatch), + /*12099*/ uint16(xSetOp), uint16(FDIVR), + /*12101*/ uint16(xArgSTi), + /*12102*/ uint16(xArgST), + /*12103*/ uint16(xMatch), + /*12104*/ uint16(xSetOp), uint16(FDIV), + /*12106*/ uint16(xArgSTi), + /*12107*/ uint16(xArgST), + /*12108*/ uint16(xMatch), + /*12109*/ uint16(xCondByte), 40, + 0xc0, 12228, + 0xc1, 12228, + 0xc2, 12228, + 0xc3, 12228, + 0xc4, 12228, + 0xc5, 12228, + 0xc6, 12228, + 0xc7, 12228, + 0xd0, 12232, + 0xd1, 12232, + 0xd2, 12232, + 0xd3, 12232, + 0xd4, 12232, + 0xd5, 12232, + 0xd6, 12232, + 0xd7, 12232, + 0xd8, 12236, + 0xd9, 12236, + 0xda, 12236, + 0xdb, 12236, + 0xdc, 12236, + 0xdd, 12236, + 0xde, 12236, + 0xdf, 12236, + 0xe0, 12240, + 0xe1, 12240, + 0xe2, 12240, + 0xe3, 12240, + 0xe4, 12240, + 0xe5, 12240, + 0xe6, 12240, + 0xe7, 12240, + 0xe8, 12244, + 0xe9, 12244, + 0xea, 12244, + 0xeb, 12244, + 0xec, 12244, + 0xed, 12244, + 0xee, 12244, + 0xef, 12244, + /*12191*/ uint16(xCondSlashR), + 12200, // 0 + 12204, // 1 + 12208, // 2 + 12212, // 3 + 12216, // 4 + 0, // 5 + 12220, // 6 + 12224, // 7 + /*12200*/ uint16(xSetOp), uint16(FLD), + /*12202*/ uint16(xArgM64fp), + /*12203*/ uint16(xMatch), + /*12204*/ uint16(xSetOp), uint16(FISTTP), + /*12206*/ uint16(xArgM64int), + /*12207*/ uint16(xMatch), + /*12208*/ uint16(xSetOp), uint16(FST), + /*12210*/ uint16(xArgM64fp), + /*12211*/ uint16(xMatch), + /*12212*/ uint16(xSetOp), uint16(FSTP), + /*12214*/ uint16(xArgM64fp), + /*12215*/ uint16(xMatch), + /*12216*/ uint16(xSetOp), uint16(FRSTOR), + /*12218*/ uint16(xArgM94108byte), + /*12219*/ uint16(xMatch), + /*12220*/ uint16(xSetOp), uint16(FNSAVE), + /*12222*/ uint16(xArgM94108byte), + /*12223*/ uint16(xMatch), + /*12224*/ uint16(xSetOp), uint16(FNSTSW), + /*12226*/ uint16(xArgM2byte), + /*12227*/ uint16(xMatch), + /*12228*/ uint16(xSetOp), uint16(FFREE), + /*12230*/ uint16(xArgSTi), + /*12231*/ uint16(xMatch), + /*12232*/ uint16(xSetOp), uint16(FST), + /*12234*/ uint16(xArgSTi), + /*12235*/ uint16(xMatch), + /*12236*/ uint16(xSetOp), uint16(FSTP), + /*12238*/ uint16(xArgSTi), + /*12239*/ uint16(xMatch), + /*12240*/ uint16(xSetOp), uint16(FUCOM), + /*12242*/ uint16(xArgSTi), + /*12243*/ uint16(xMatch), + /*12244*/ uint16(xSetOp), uint16(FUCOMP), + /*12246*/ uint16(xArgSTi), + /*12247*/ uint16(xMatch), + /*12248*/ uint16(xCondByte), 49, + 0xc0, 12389, + 0xc1, 12389, + 0xc2, 12389, + 0xc3, 12389, + 0xc4, 12389, + 0xc5, 12389, + 0xc6, 12389, + 0xc7, 12389, + 0xc8, 12394, + 0xc9, 12394, + 0xca, 12394, + 0xcb, 12394, + 0xcc, 12394, + 0xcd, 12394, + 0xce, 12394, + 0xcf, 12394, + 0xD9, 12399, + 0xe0, 12402, + 0xe1, 12402, + 0xe2, 12402, + 0xe3, 12402, + 0xe4, 12402, + 0xe5, 12402, + 0xe6, 12402, + 0xe7, 12402, + 0xe8, 12407, + 0xe9, 12407, + 0xea, 12407, + 0xeb, 12407, + 0xec, 12407, + 0xed, 12407, + 0xee, 12407, + 0xef, 12407, + 0xf0, 12412, + 0xf1, 12412, + 0xf2, 12412, + 0xf3, 12412, + 0xf4, 12412, + 0xf5, 12412, + 0xf6, 12412, + 0xf7, 12412, + 0xf8, 12417, + 0xf9, 12417, + 0xfa, 12417, + 0xfb, 12417, + 0xfc, 12417, + 0xfd, 12417, + 0xfe, 12417, + 0xff, 12417, + /*12348*/ uint16(xCondSlashR), + 12357, // 0 + 12361, // 1 + 12365, // 2 + 12369, // 3 + 12373, // 4 + 12377, // 5 + 12381, // 6 + 12385, // 7 + /*12357*/ uint16(xSetOp), uint16(FIADD), + /*12359*/ uint16(xArgM16int), + /*12360*/ uint16(xMatch), + /*12361*/ uint16(xSetOp), uint16(FIMUL), + /*12363*/ uint16(xArgM16int), + /*12364*/ uint16(xMatch), + /*12365*/ uint16(xSetOp), uint16(FICOM), + /*12367*/ uint16(xArgM16int), + /*12368*/ uint16(xMatch), + /*12369*/ uint16(xSetOp), uint16(FICOMP), + /*12371*/ uint16(xArgM16int), + /*12372*/ uint16(xMatch), + /*12373*/ uint16(xSetOp), uint16(FISUB), + /*12375*/ uint16(xArgM16int), + /*12376*/ uint16(xMatch), + /*12377*/ uint16(xSetOp), uint16(FISUBR), + /*12379*/ uint16(xArgM16int), + /*12380*/ uint16(xMatch), + /*12381*/ uint16(xSetOp), uint16(FIDIV), + /*12383*/ uint16(xArgM16int), + /*12384*/ uint16(xMatch), + /*12385*/ uint16(xSetOp), uint16(FIDIVR), + /*12387*/ uint16(xArgM16int), + /*12388*/ uint16(xMatch), + /*12389*/ uint16(xSetOp), uint16(FADDP), + /*12391*/ uint16(xArgSTi), + /*12392*/ uint16(xArgST), + /*12393*/ uint16(xMatch), + /*12394*/ uint16(xSetOp), uint16(FMULP), + /*12396*/ uint16(xArgSTi), + /*12397*/ uint16(xArgST), + /*12398*/ uint16(xMatch), + /*12399*/ uint16(xSetOp), uint16(FCOMPP), + /*12401*/ uint16(xMatch), + /*12402*/ uint16(xSetOp), uint16(FSUBRP), + /*12404*/ uint16(xArgSTi), + /*12405*/ uint16(xArgST), + /*12406*/ uint16(xMatch), + /*12407*/ uint16(xSetOp), uint16(FSUBP), + /*12409*/ uint16(xArgSTi), + /*12410*/ uint16(xArgST), + /*12411*/ uint16(xMatch), + /*12412*/ uint16(xSetOp), uint16(FDIVRP), + /*12414*/ uint16(xArgSTi), + /*12415*/ uint16(xArgST), + /*12416*/ uint16(xMatch), + /*12417*/ uint16(xSetOp), uint16(FDIVP), + /*12419*/ uint16(xArgSTi), + /*12420*/ uint16(xArgST), + /*12421*/ uint16(xMatch), + /*12422*/ uint16(xCondByte), 25, + 0xc0, 12515, + 0xc1, 12515, + 0xc2, 12515, + 0xc3, 12515, + 0xc4, 12515, + 0xc5, 12515, + 0xc6, 12515, + 0xc7, 12515, + 0xE0, 12519, + 0xe8, 12523, + 0xe9, 12523, + 0xea, 12523, + 0xeb, 12523, + 0xec, 12523, + 0xed, 12523, + 0xee, 12523, + 0xef, 12523, + 0xf0, 12528, + 0xf1, 12528, + 0xf2, 12528, + 0xf3, 12528, + 0xf4, 12528, + 0xf5, 12528, + 0xf6, 12528, + 0xf7, 12528, + /*12474*/ uint16(xCondSlashR), + 12483, // 0 + 12487, // 1 + 12491, // 2 + 12495, // 3 + 12499, // 4 + 12503, // 5 + 12507, // 6 + 12511, // 7 + /*12483*/ uint16(xSetOp), uint16(FILD), + /*12485*/ uint16(xArgM16int), + /*12486*/ uint16(xMatch), + /*12487*/ uint16(xSetOp), uint16(FISTTP), + /*12489*/ uint16(xArgM16int), + /*12490*/ uint16(xMatch), + /*12491*/ uint16(xSetOp), uint16(FIST), + /*12493*/ uint16(xArgM16int), + /*12494*/ uint16(xMatch), + /*12495*/ uint16(xSetOp), uint16(FISTP), + /*12497*/ uint16(xArgM16int), + /*12498*/ uint16(xMatch), + /*12499*/ uint16(xSetOp), uint16(FBLD), + /*12501*/ uint16(xArgM80dec), + /*12502*/ uint16(xMatch), + /*12503*/ uint16(xSetOp), uint16(FILD), + /*12505*/ uint16(xArgM64int), + /*12506*/ uint16(xMatch), + /*12507*/ uint16(xSetOp), uint16(FBSTP), + /*12509*/ uint16(xArgM80bcd), + /*12510*/ uint16(xMatch), + /*12511*/ uint16(xSetOp), uint16(FISTP), + /*12513*/ uint16(xArgM64int), + /*12514*/ uint16(xMatch), + /*12515*/ uint16(xSetOp), uint16(FFREEP), + /*12517*/ uint16(xArgSTi), + /*12518*/ uint16(xMatch), + /*12519*/ uint16(xSetOp), uint16(FNSTSW), + /*12521*/ uint16(xArgAX), + /*12522*/ uint16(xMatch), + /*12523*/ uint16(xSetOp), uint16(FUCOMIP), + /*12525*/ uint16(xArgST), + /*12526*/ uint16(xArgSTi), + /*12527*/ uint16(xMatch), + /*12528*/ uint16(xSetOp), uint16(FCOMIP), + /*12530*/ uint16(xArgST), + /*12531*/ uint16(xArgSTi), + /*12532*/ uint16(xMatch), + /*12533*/ uint16(xSetOp), uint16(LOOPNE), + /*12535*/ uint16(xReadCb), + /*12536*/ uint16(xArgRel8), + /*12537*/ uint16(xMatch), + /*12538*/ uint16(xSetOp), uint16(LOOPE), + /*12540*/ uint16(xReadCb), + /*12541*/ uint16(xArgRel8), + /*12542*/ uint16(xMatch), + /*12543*/ uint16(xSetOp), uint16(LOOP), + /*12545*/ uint16(xReadCb), + /*12546*/ uint16(xArgRel8), + /*12547*/ uint16(xMatch), + /*12548*/ uint16(xCondIs64), 12551, 12565, + /*12551*/ uint16(xCondAddrSize), 12555, 12560, 0, + /*12555*/ uint16(xSetOp), uint16(JCXZ), + /*12557*/ uint16(xReadCb), + /*12558*/ uint16(xArgRel8), + /*12559*/ uint16(xMatch), + /*12560*/ uint16(xSetOp), uint16(JECXZ), + /*12562*/ uint16(xReadCb), + /*12563*/ uint16(xArgRel8), + /*12564*/ uint16(xMatch), + /*12565*/ uint16(xCondAddrSize), 0, 12560, 12569, + /*12569*/ uint16(xSetOp), uint16(JRCXZ), + /*12571*/ uint16(xReadCb), + /*12572*/ uint16(xArgRel8), + /*12573*/ uint16(xMatch), + /*12574*/ uint16(xSetOp), uint16(IN), + /*12576*/ uint16(xReadIb), + /*12577*/ uint16(xArgAL), + /*12578*/ uint16(xArgImm8u), + /*12579*/ uint16(xMatch), + /*12580*/ uint16(xCondDataSize), 12584, 12590, 12596, + /*12584*/ uint16(xSetOp), uint16(IN), + /*12586*/ uint16(xReadIb), + /*12587*/ uint16(xArgAX), + /*12588*/ uint16(xArgImm8u), + /*12589*/ uint16(xMatch), + /*12590*/ uint16(xSetOp), uint16(IN), + /*12592*/ uint16(xReadIb), + /*12593*/ uint16(xArgEAX), + /*12594*/ uint16(xArgImm8u), + /*12595*/ uint16(xMatch), + /*12596*/ uint16(xSetOp), uint16(IN), + /*12598*/ uint16(xReadIb), + /*12599*/ uint16(xArgEAX), + /*12600*/ uint16(xArgImm8u), + /*12601*/ uint16(xMatch), + /*12602*/ uint16(xSetOp), uint16(OUT), + /*12604*/ uint16(xReadIb), + /*12605*/ uint16(xArgImm8u), + /*12606*/ uint16(xArgAL), + /*12607*/ uint16(xMatch), + /*12608*/ uint16(xCondDataSize), 12612, 12618, 12624, + /*12612*/ uint16(xSetOp), uint16(OUT), + /*12614*/ uint16(xReadIb), + /*12615*/ uint16(xArgImm8u), + /*12616*/ uint16(xArgAX), + /*12617*/ uint16(xMatch), + /*12618*/ uint16(xSetOp), uint16(OUT), + /*12620*/ uint16(xReadIb), + /*12621*/ uint16(xArgImm8u), + /*12622*/ uint16(xArgEAX), + /*12623*/ uint16(xMatch), + /*12624*/ uint16(xSetOp), uint16(OUT), + /*12626*/ uint16(xReadIb), + /*12627*/ uint16(xArgImm8u), + /*12628*/ uint16(xArgEAX), + /*12629*/ uint16(xMatch), + /*12630*/ uint16(xCondIs64), 12633, 12647, + /*12633*/ uint16(xCondDataSize), 12637, 12642, 0, + /*12637*/ uint16(xSetOp), uint16(CALL), + /*12639*/ uint16(xReadCw), + /*12640*/ uint16(xArgRel16), + /*12641*/ uint16(xMatch), + /*12642*/ uint16(xSetOp), uint16(CALL), + /*12644*/ uint16(xReadCd), + /*12645*/ uint16(xArgRel32), + /*12646*/ uint16(xMatch), + /*12647*/ uint16(xCondDataSize), 12651, 12642, 12656, + /*12651*/ uint16(xSetOp), uint16(CALL), + /*12653*/ uint16(xReadCd), + /*12654*/ uint16(xArgRel32), + /*12655*/ uint16(xMatch), + /*12656*/ uint16(xSetOp), uint16(CALL), + /*12658*/ uint16(xReadCd), + /*12659*/ uint16(xArgRel32), + /*12660*/ uint16(xMatch), + /*12661*/ uint16(xCondIs64), 12664, 12678, + /*12664*/ uint16(xCondDataSize), 12668, 12673, 0, + /*12668*/ uint16(xSetOp), uint16(JMP), + /*12670*/ uint16(xReadCw), + /*12671*/ uint16(xArgRel16), + /*12672*/ uint16(xMatch), + /*12673*/ uint16(xSetOp), uint16(JMP), + /*12675*/ uint16(xReadCd), + /*12676*/ uint16(xArgRel32), + /*12677*/ uint16(xMatch), + /*12678*/ uint16(xCondDataSize), 12682, 12673, 12687, + /*12682*/ uint16(xSetOp), uint16(JMP), + /*12684*/ uint16(xReadCd), + /*12685*/ uint16(xArgRel32), + /*12686*/ uint16(xMatch), + /*12687*/ uint16(xSetOp), uint16(JMP), + /*12689*/ uint16(xReadCd), + /*12690*/ uint16(xArgRel32), + /*12691*/ uint16(xMatch), + /*12692*/ uint16(xCondIs64), 12695, 0, + /*12695*/ uint16(xCondDataSize), 12699, 12704, 0, + /*12699*/ uint16(xSetOp), uint16(LJMP), + /*12701*/ uint16(xReadCd), + /*12702*/ uint16(xArgPtr16colon16), + /*12703*/ uint16(xMatch), + /*12704*/ uint16(xSetOp), uint16(LJMP), + /*12706*/ uint16(xReadCp), + /*12707*/ uint16(xArgPtr16colon32), + /*12708*/ uint16(xMatch), + /*12709*/ uint16(xSetOp), uint16(JMP), + /*12711*/ uint16(xReadCb), + /*12712*/ uint16(xArgRel8), + /*12713*/ uint16(xMatch), + /*12714*/ uint16(xSetOp), uint16(IN), + /*12716*/ uint16(xArgAL), + /*12717*/ uint16(xArgDX), + /*12718*/ uint16(xMatch), + /*12719*/ uint16(xCondDataSize), 12723, 12728, 12733, + /*12723*/ uint16(xSetOp), uint16(IN), + /*12725*/ uint16(xArgAX), + /*12726*/ uint16(xArgDX), + /*12727*/ uint16(xMatch), + /*12728*/ uint16(xSetOp), uint16(IN), + /*12730*/ uint16(xArgEAX), + /*12731*/ uint16(xArgDX), + /*12732*/ uint16(xMatch), + /*12733*/ uint16(xSetOp), uint16(IN), + /*12735*/ uint16(xArgEAX), + /*12736*/ uint16(xArgDX), + /*12737*/ uint16(xMatch), + /*12738*/ uint16(xSetOp), uint16(OUT), + /*12740*/ uint16(xArgDX), + /*12741*/ uint16(xArgAL), + /*12742*/ uint16(xMatch), + /*12743*/ uint16(xCondDataSize), 12747, 12752, 12757, + /*12747*/ uint16(xSetOp), uint16(OUT), + /*12749*/ uint16(xArgDX), + /*12750*/ uint16(xArgAX), + /*12751*/ uint16(xMatch), + /*12752*/ uint16(xSetOp), uint16(OUT), + /*12754*/ uint16(xArgDX), + /*12755*/ uint16(xArgEAX), + /*12756*/ uint16(xMatch), + /*12757*/ uint16(xSetOp), uint16(OUT), + /*12759*/ uint16(xArgDX), + /*12760*/ uint16(xArgEAX), + /*12761*/ uint16(xMatch), + /*12762*/ uint16(xSetOp), uint16(ICEBP), + /*12764*/ uint16(xMatch), + /*12765*/ uint16(xSetOp), uint16(HLT), + /*12767*/ uint16(xMatch), + /*12768*/ uint16(xSetOp), uint16(CMC), + /*12770*/ uint16(xMatch), + /*12771*/ uint16(xCondSlashR), + 12780, // 0 + 0, // 1 + 12786, // 2 + 12790, // 3 + 12794, // 4 + 12798, // 5 + 12802, // 6 + 12806, // 7 + /*12780*/ uint16(xSetOp), uint16(TEST), + /*12782*/ uint16(xReadIb), + /*12783*/ uint16(xArgRM8), + /*12784*/ uint16(xArgImm8u), + /*12785*/ uint16(xMatch), + /*12786*/ uint16(xSetOp), uint16(NOT), + /*12788*/ uint16(xArgRM8), + /*12789*/ uint16(xMatch), + /*12790*/ uint16(xSetOp), uint16(NEG), + /*12792*/ uint16(xArgRM8), + /*12793*/ uint16(xMatch), + /*12794*/ uint16(xSetOp), uint16(MUL), + /*12796*/ uint16(xArgRM8), + /*12797*/ uint16(xMatch), + /*12798*/ uint16(xSetOp), uint16(IMUL), + /*12800*/ uint16(xArgRM8), + /*12801*/ uint16(xMatch), + /*12802*/ uint16(xSetOp), uint16(DIV), + /*12804*/ uint16(xArgRM8), + /*12805*/ uint16(xMatch), + /*12806*/ uint16(xSetOp), uint16(IDIV), + /*12808*/ uint16(xArgRM8), + /*12809*/ uint16(xMatch), + /*12810*/ uint16(xCondSlashR), + 12819, // 0 + 0, // 1 + 12848, // 2 + 12871, // 3 + 12894, // 4 + 12917, // 5 + 12940, // 6 + 12963, // 7 + /*12819*/ uint16(xCondIs64), 12822, 12838, + /*12822*/ uint16(xCondDataSize), 12826, 12832, 0, + /*12826*/ uint16(xSetOp), uint16(TEST), + /*12828*/ uint16(xReadIw), + /*12829*/ uint16(xArgRM16), + /*12830*/ uint16(xArgImm16), + /*12831*/ uint16(xMatch), + /*12832*/ uint16(xSetOp), uint16(TEST), + /*12834*/ uint16(xReadId), + /*12835*/ uint16(xArgRM32), + /*12836*/ uint16(xArgImm32), + /*12837*/ uint16(xMatch), + /*12838*/ uint16(xCondDataSize), 12826, 12832, 12842, + /*12842*/ uint16(xSetOp), uint16(TEST), + /*12844*/ uint16(xReadId), + /*12845*/ uint16(xArgRM64), + /*12846*/ uint16(xArgImm32), + /*12847*/ uint16(xMatch), + /*12848*/ uint16(xCondIs64), 12851, 12863, + /*12851*/ uint16(xCondDataSize), 12855, 12859, 0, + /*12855*/ uint16(xSetOp), uint16(NOT), + /*12857*/ uint16(xArgRM16), + /*12858*/ uint16(xMatch), + /*12859*/ uint16(xSetOp), uint16(NOT), + /*12861*/ uint16(xArgRM32), + /*12862*/ uint16(xMatch), + /*12863*/ uint16(xCondDataSize), 12855, 12859, 12867, + /*12867*/ uint16(xSetOp), uint16(NOT), + /*12869*/ uint16(xArgRM64), + /*12870*/ uint16(xMatch), + /*12871*/ uint16(xCondIs64), 12874, 12886, + /*12874*/ uint16(xCondDataSize), 12878, 12882, 0, + /*12878*/ uint16(xSetOp), uint16(NEG), + /*12880*/ uint16(xArgRM16), + /*12881*/ uint16(xMatch), + /*12882*/ uint16(xSetOp), uint16(NEG), + /*12884*/ uint16(xArgRM32), + /*12885*/ uint16(xMatch), + /*12886*/ uint16(xCondDataSize), 12878, 12882, 12890, + /*12890*/ uint16(xSetOp), uint16(NEG), + /*12892*/ uint16(xArgRM64), + /*12893*/ uint16(xMatch), + /*12894*/ uint16(xCondIs64), 12897, 12909, + /*12897*/ uint16(xCondDataSize), 12901, 12905, 0, + /*12901*/ uint16(xSetOp), uint16(MUL), + /*12903*/ uint16(xArgRM16), + /*12904*/ uint16(xMatch), + /*12905*/ uint16(xSetOp), uint16(MUL), + /*12907*/ uint16(xArgRM32), + /*12908*/ uint16(xMatch), + /*12909*/ uint16(xCondDataSize), 12901, 12905, 12913, + /*12913*/ uint16(xSetOp), uint16(MUL), + /*12915*/ uint16(xArgRM64), + /*12916*/ uint16(xMatch), + /*12917*/ uint16(xCondIs64), 12920, 12932, + /*12920*/ uint16(xCondDataSize), 12924, 12928, 0, + /*12924*/ uint16(xSetOp), uint16(IMUL), + /*12926*/ uint16(xArgRM16), + /*12927*/ uint16(xMatch), + /*12928*/ uint16(xSetOp), uint16(IMUL), + /*12930*/ uint16(xArgRM32), + /*12931*/ uint16(xMatch), + /*12932*/ uint16(xCondDataSize), 12924, 12928, 12936, + /*12936*/ uint16(xSetOp), uint16(IMUL), + /*12938*/ uint16(xArgRM64), + /*12939*/ uint16(xMatch), + /*12940*/ uint16(xCondIs64), 12943, 12955, + /*12943*/ uint16(xCondDataSize), 12947, 12951, 0, + /*12947*/ uint16(xSetOp), uint16(DIV), + /*12949*/ uint16(xArgRM16), + /*12950*/ uint16(xMatch), + /*12951*/ uint16(xSetOp), uint16(DIV), + /*12953*/ uint16(xArgRM32), + /*12954*/ uint16(xMatch), + /*12955*/ uint16(xCondDataSize), 12947, 12951, 12959, + /*12959*/ uint16(xSetOp), uint16(DIV), + /*12961*/ uint16(xArgRM64), + /*12962*/ uint16(xMatch), + /*12963*/ uint16(xCondIs64), 12966, 12978, + /*12966*/ uint16(xCondDataSize), 12970, 12974, 0, + /*12970*/ uint16(xSetOp), uint16(IDIV), + /*12972*/ uint16(xArgRM16), + /*12973*/ uint16(xMatch), + /*12974*/ uint16(xSetOp), uint16(IDIV), + /*12976*/ uint16(xArgRM32), + /*12977*/ uint16(xMatch), + /*12978*/ uint16(xCondDataSize), 12970, 12974, 12982, + /*12982*/ uint16(xSetOp), uint16(IDIV), + /*12984*/ uint16(xArgRM64), + /*12985*/ uint16(xMatch), + /*12986*/ uint16(xSetOp), uint16(CLC), + /*12988*/ uint16(xMatch), + /*12989*/ uint16(xSetOp), uint16(STC), + /*12991*/ uint16(xMatch), + /*12992*/ uint16(xSetOp), uint16(CLI), + /*12994*/ uint16(xMatch), + /*12995*/ uint16(xSetOp), uint16(STI), + /*12997*/ uint16(xMatch), + /*12998*/ uint16(xSetOp), uint16(CLD), + /*13000*/ uint16(xMatch), + /*13001*/ uint16(xSetOp), uint16(STD), + /*13003*/ uint16(xMatch), + /*13004*/ uint16(xCondSlashR), + 13013, // 0 + 13017, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + /*13013*/ uint16(xSetOp), uint16(INC), + /*13015*/ uint16(xArgRM8), + /*13016*/ uint16(xMatch), + /*13017*/ uint16(xSetOp), uint16(DEC), + /*13019*/ uint16(xArgRM8), + /*13020*/ uint16(xMatch), + /*13021*/ uint16(xCondSlashR), + 13030, // 0 + 13053, // 1 + 13076, // 2 + 13095, // 3 + 13118, // 4 + 13137, // 5 + 13160, // 6 + 0, // 7 + /*13030*/ uint16(xCondIs64), 13033, 13045, + /*13033*/ uint16(xCondDataSize), 13037, 13041, 0, + /*13037*/ uint16(xSetOp), uint16(INC), + /*13039*/ uint16(xArgRM16), + /*13040*/ uint16(xMatch), + /*13041*/ uint16(xSetOp), uint16(INC), + /*13043*/ uint16(xArgRM32), + /*13044*/ uint16(xMatch), + /*13045*/ uint16(xCondDataSize), 13037, 13041, 13049, + /*13049*/ uint16(xSetOp), uint16(INC), + /*13051*/ uint16(xArgRM64), + /*13052*/ uint16(xMatch), + /*13053*/ uint16(xCondIs64), 13056, 13068, + /*13056*/ uint16(xCondDataSize), 13060, 13064, 0, + /*13060*/ uint16(xSetOp), uint16(DEC), + /*13062*/ uint16(xArgRM16), + /*13063*/ uint16(xMatch), + /*13064*/ uint16(xSetOp), uint16(DEC), + /*13066*/ uint16(xArgRM32), + /*13067*/ uint16(xMatch), + /*13068*/ uint16(xCondDataSize), 13060, 13064, 13072, + /*13072*/ uint16(xSetOp), uint16(DEC), + /*13074*/ uint16(xArgRM64), + /*13075*/ uint16(xMatch), + /*13076*/ uint16(xCondIs64), 13079, 13091, + /*13079*/ uint16(xCondDataSize), 13083, 13087, 0, + /*13083*/ uint16(xSetOp), uint16(CALL), + /*13085*/ uint16(xArgRM16), + /*13086*/ uint16(xMatch), + /*13087*/ uint16(xSetOp), uint16(CALL), + /*13089*/ uint16(xArgRM32), + /*13090*/ uint16(xMatch), + /*13091*/ uint16(xSetOp), uint16(CALL), + /*13093*/ uint16(xArgRM64), + /*13094*/ uint16(xMatch), + /*13095*/ uint16(xCondIs64), 13098, 13110, + /*13098*/ uint16(xCondDataSize), 13102, 13106, 0, + /*13102*/ uint16(xSetOp), uint16(LCALL), + /*13104*/ uint16(xArgM16colon16), + /*13105*/ uint16(xMatch), + /*13106*/ uint16(xSetOp), uint16(LCALL), + /*13108*/ uint16(xArgM16colon32), + /*13109*/ uint16(xMatch), + /*13110*/ uint16(xCondDataSize), 13102, 13106, 13114, + /*13114*/ uint16(xSetOp), uint16(LCALL), + /*13116*/ uint16(xArgM16colon64), + /*13117*/ uint16(xMatch), + /*13118*/ uint16(xCondIs64), 13121, 13133, + /*13121*/ uint16(xCondDataSize), 13125, 13129, 0, + /*13125*/ uint16(xSetOp), uint16(JMP), + /*13127*/ uint16(xArgRM16), + /*13128*/ uint16(xMatch), + /*13129*/ uint16(xSetOp), uint16(JMP), + /*13131*/ uint16(xArgRM32), + /*13132*/ uint16(xMatch), + /*13133*/ uint16(xSetOp), uint16(JMP), + /*13135*/ uint16(xArgRM64), + /*13136*/ uint16(xMatch), + /*13137*/ uint16(xCondIs64), 13140, 13152, + /*13140*/ uint16(xCondDataSize), 13144, 13148, 0, + /*13144*/ uint16(xSetOp), uint16(LJMP), + /*13146*/ uint16(xArgM16colon16), + /*13147*/ uint16(xMatch), + /*13148*/ uint16(xSetOp), uint16(LJMP), + /*13150*/ uint16(xArgM16colon32), + /*13151*/ uint16(xMatch), + /*13152*/ uint16(xCondDataSize), 13144, 13148, 13156, + /*13156*/ uint16(xSetOp), uint16(LJMP), + /*13158*/ uint16(xArgM16colon64), + /*13159*/ uint16(xMatch), + /*13160*/ uint16(xCondIs64), 13163, 13175, + /*13163*/ uint16(xCondDataSize), 13167, 13171, 0, + /*13167*/ uint16(xSetOp), uint16(PUSH), + /*13169*/ uint16(xArgRM16), + /*13170*/ uint16(xMatch), + /*13171*/ uint16(xSetOp), uint16(PUSH), + /*13173*/ uint16(xArgRM32), + /*13174*/ uint16(xMatch), + /*13175*/ uint16(xCondDataSize), 13167, 13179, 13183, + /*13179*/ uint16(xSetOp), uint16(PUSH), + /*13181*/ uint16(xArgRM64), + /*13182*/ uint16(xMatch), + /*13183*/ uint16(xSetOp), uint16(PUSH), + /*13185*/ uint16(xArgRM64), + /*13186*/ uint16(xMatch), +} + +const ( + _ Op = iota + + AAA + AAD + AAM + AAS + ADC + ADD + ADDPD + ADDPS + ADDSD + ADDSS + ADDSUBPD + ADDSUBPS + AESDEC + AESDECLAST + AESENC + AESENCLAST + AESIMC + AESKEYGENASSIST + AND + ANDNPD + ANDNPS + ANDPD + ANDPS + ARPL + BLENDPD + BLENDPS + BLENDVPD + BLENDVPS + BOUND + BSF + BSR + BSWAP + BT + BTC + BTR + BTS + CALL + CBW + CDQ + CDQE + CLC + CLD + CLFLUSH + CLI + CLTS + CMC + CMOVA + CMOVAE + CMOVB + CMOVBE + CMOVE + CMOVG + CMOVGE + CMOVL + CMOVLE + CMOVNE + CMOVNO + CMOVNP + CMOVNS + CMOVO + CMOVP + CMOVS + CMP + CMPPD + CMPPS + CMPSB + CMPSD + CMPSD_XMM + CMPSQ + CMPSS + CMPSW + CMPXCHG + CMPXCHG16B + CMPXCHG8B + COMISD + COMISS + CPUID + CQO + CRC32 + CVTDQ2PD + CVTDQ2PS + CVTPD2DQ + CVTPD2PI + CVTPD2PS + CVTPI2PD + CVTPI2PS + CVTPS2DQ + CVTPS2PD + CVTPS2PI + CVTSD2SI + CVTSD2SS + CVTSI2SD + CVTSI2SS + CVTSS2SD + CVTSS2SI + CVTTPD2DQ + CVTTPD2PI + CVTTPS2DQ + CVTTPS2PI + CVTTSD2SI + CVTTSS2SI + CWD + CWDE + DAA + DAS + DEC + DIV + DIVPD + DIVPS + DIVSD + DIVSS + DPPD + DPPS + EMMS + ENTER + EXTRACTPS + F2XM1 + FABS + FADD + FADDP + FBLD + FBSTP + FCHS + FCMOVB + FCMOVBE + FCMOVE + FCMOVNB + FCMOVNBE + FCMOVNE + FCMOVNU + FCMOVU + FCOM + FCOMI + FCOMIP + FCOMP + FCOMPP + FCOS + FDECSTP + FDIV + FDIVP + FDIVR + FDIVRP + FFREE + FFREEP + FIADD + FICOM + FICOMP + FIDIV + FIDIVR + FILD + FIMUL + FINCSTP + FIST + FISTP + FISTTP + FISUB + FISUBR + FLD + FLD1 + FLDCW + FLDENV + FLDL2E + FLDL2T + FLDLG2 + FLDPI + FMUL + FMULP + FNCLEX + FNINIT + FNOP + FNSAVE + FNSTCW + FNSTENV + FNSTSW + FPATAN + FPREM + FPREM1 + FPTAN + FRNDINT + FRSTOR + FSCALE + FSIN + FSINCOS + FSQRT + FST + FSTP + FSUB + FSUBP + FSUBR + FSUBRP + FTST + FUCOM + FUCOMI + FUCOMIP + FUCOMP + FUCOMPP + FWAIT + FXAM + FXCH + FXRSTOR + FXRSTOR64 + FXSAVE + FXSAVE64 + FXTRACT + FYL2X + FYL2XP1 + HADDPD + HADDPS + HLT + HSUBPD + HSUBPS + ICEBP + IDIV + IMUL + IN + INC + INSB + INSD + INSERTPS + INSW + INT + INTO + INVD + INVLPG + INVPCID + IRET + IRETD + IRETQ + JA + JAE + JB + JBE + JCXZ + JE + JECXZ + JG + JGE + JL + JLE + JMP + JNE + JNO + JNP + JNS + JO + JP + JRCXZ + JS + LAHF + LAR + LCALL + LDDQU + LDMXCSR + LDS + LEA + LEAVE + LES + LFENCE + LFS + LGDT + LGS + LIDT + LJMP + LLDT + LMSW + LODSB + LODSD + LODSQ + LODSW + LOOP + LOOPE + LOOPNE + LRET + LSL + LSS + LTR + LZCNT + MASKMOVDQU + MASKMOVQ + MAXPD + MAXPS + MAXSD + MAXSS + MFENCE + MINPD + MINPS + MINSD + MINSS + MONITOR + MOV + MOVAPD + MOVAPS + MOVBE + MOVD + MOVDDUP + MOVDQ2Q + MOVDQA + MOVDQU + MOVHLPS + MOVHPD + MOVHPS + MOVLHPS + MOVLPD + MOVLPS + MOVMSKPD + MOVMSKPS + MOVNTDQ + MOVNTDQA + MOVNTI + MOVNTPD + MOVNTPS + MOVNTQ + MOVNTSD + MOVNTSS + MOVQ + MOVQ2DQ + MOVSB + MOVSD + MOVSD_XMM + MOVSHDUP + MOVSLDUP + MOVSQ + MOVSS + MOVSW + MOVSX + MOVSXD + MOVUPD + MOVUPS + MOVZX + MPSADBW + MUL + MULPD + MULPS + MULSD + MULSS + MWAIT + NEG + NOP + NOT + OR + ORPD + ORPS + OUT + OUTSB + OUTSD + OUTSW + PABSB + PABSD + PABSW + PACKSSDW + PACKSSWB + PACKUSDW + PACKUSWB + PADDB + PADDD + PADDQ + PADDSB + PADDSW + PADDUSB + PADDUSW + PADDW + PALIGNR + PAND + PANDN + PAUSE + PAVGB + PAVGW + PBLENDVB + PBLENDW + PCLMULQDQ + PCMPEQB + PCMPEQD + PCMPEQQ + PCMPEQW + PCMPESTRI + PCMPESTRM + PCMPGTB + PCMPGTD + PCMPGTQ + PCMPGTW + PCMPISTRI + PCMPISTRM + PEXTRB + PEXTRD + PEXTRQ + PEXTRW + PHADDD + PHADDSW + PHADDW + PHMINPOSUW + PHSUBD + PHSUBSW + PHSUBW + PINSRB + PINSRD + PINSRQ + PINSRW + PMADDUBSW + PMADDWD + PMAXSB + PMAXSD + PMAXSW + PMAXUB + PMAXUD + PMAXUW + PMINSB + PMINSD + PMINSW + PMINUB + PMINUD + PMINUW + PMOVMSKB + PMOVSXBD + PMOVSXBQ + PMOVSXBW + PMOVSXDQ + PMOVSXWD + PMOVSXWQ + PMOVZXBD + PMOVZXBQ + PMOVZXBW + PMOVZXDQ + PMOVZXWD + PMOVZXWQ + PMULDQ + PMULHRSW + PMULHUW + PMULHW + PMULLD + PMULLW + PMULUDQ + POP + POPA + POPAD + POPCNT + POPF + POPFD + POPFQ + POR + PREFETCHNTA + PREFETCHT0 + PREFETCHT1 + PREFETCHT2 + PREFETCHW + PSADBW + PSHUFB + PSHUFD + PSHUFHW + PSHUFLW + PSHUFW + PSIGNB + PSIGND + PSIGNW + PSLLD + PSLLDQ + PSLLQ + PSLLW + PSRAD + PSRAW + PSRLD + PSRLDQ + PSRLQ + PSRLW + PSUBB + PSUBD + PSUBQ + PSUBSB + PSUBSW + PSUBUSB + PSUBUSW + PSUBW + PTEST + PUNPCKHBW + PUNPCKHDQ + PUNPCKHQDQ + PUNPCKHWD + PUNPCKLBW + PUNPCKLDQ + PUNPCKLQDQ + PUNPCKLWD + PUSH + PUSHA + PUSHAD + PUSHF + PUSHFD + PUSHFQ + PXOR + RCL + RCPPS + RCPSS + RCR + RDFSBASE + RDGSBASE + RDMSR + RDPMC + RDRAND + RDTSC + RDTSCP + RET + ROL + ROR + ROUNDPD + ROUNDPS + ROUNDSD + ROUNDSS + RSM + RSQRTPS + RSQRTSS + SAHF + SAR + SBB + SCASB + SCASD + SCASQ + SCASW + SETA + SETAE + SETB + SETBE + SETE + SETG + SETGE + SETL + SETLE + SETNE + SETNO + SETNP + SETNS + SETO + SETP + SETS + SFENCE + SGDT + SHL + SHLD + SHR + SHRD + SHUFPD + SHUFPS + SIDT + SLDT + SMSW + SQRTPD + SQRTPS + SQRTSD + SQRTSS + STC + STD + STI + STMXCSR + STOSB + STOSD + STOSQ + STOSW + STR + SUB + SUBPD + SUBPS + SUBSD + SUBSS + SWAPGS + SYSCALL + SYSENTER + SYSEXIT + SYSRET + TEST + TZCNT + UCOMISD + UCOMISS + UD1 + UD2 + UNPCKHPD + UNPCKHPS + UNPCKLPD + UNPCKLPS + VERR + VERW + WBINVD + WRFSBASE + WRGSBASE + WRMSR + XABORT + XADD + XBEGIN + XCHG + XEND + XGETBV + XLATB + XOR + XORPD + XORPS + XRSTOR + XRSTOR64 + XRSTORS + XRSTORS64 + XSAVE + XSAVE64 + XSAVEC + XSAVEC64 + XSAVEOPT + XSAVEOPT64 + XSAVES + XSAVES64 + XSETBV + XTEST +) + +const maxOp = XTEST + +var opNames = [...]string{ + AAA: "AAA", + AAD: "AAD", + AAM: "AAM", + AAS: "AAS", + ADC: "ADC", + ADD: "ADD", + ADDPD: "ADDPD", + ADDPS: "ADDPS", + ADDSD: "ADDSD", + ADDSS: "ADDSS", + ADDSUBPD: "ADDSUBPD", + ADDSUBPS: "ADDSUBPS", + AESDEC: "AESDEC", + AESDECLAST: "AESDECLAST", + AESENC: "AESENC", + AESENCLAST: "AESENCLAST", + AESIMC: "AESIMC", + AESKEYGENASSIST: "AESKEYGENASSIST", + AND: "AND", + ANDNPD: "ANDNPD", + ANDNPS: "ANDNPS", + ANDPD: "ANDPD", + ANDPS: "ANDPS", + ARPL: "ARPL", + BLENDPD: "BLENDPD", + BLENDPS: "BLENDPS", + BLENDVPD: "BLENDVPD", + BLENDVPS: "BLENDVPS", + BOUND: "BOUND", + BSF: "BSF", + BSR: "BSR", + BSWAP: "BSWAP", + BT: "BT", + BTC: "BTC", + BTR: "BTR", + BTS: "BTS", + CALL: "CALL", + CBW: "CBW", + CDQ: "CDQ", + CDQE: "CDQE", + CLC: "CLC", + CLD: "CLD", + CLFLUSH: "CLFLUSH", + CLI: "CLI", + CLTS: "CLTS", + CMC: "CMC", + CMOVA: "CMOVA", + CMOVAE: "CMOVAE", + CMOVB: "CMOVB", + CMOVBE: "CMOVBE", + CMOVE: "CMOVE", + CMOVG: "CMOVG", + CMOVGE: "CMOVGE", + CMOVL: "CMOVL", + CMOVLE: "CMOVLE", + CMOVNE: "CMOVNE", + CMOVNO: "CMOVNO", + CMOVNP: "CMOVNP", + CMOVNS: "CMOVNS", + CMOVO: "CMOVO", + CMOVP: "CMOVP", + CMOVS: "CMOVS", + CMP: "CMP", + CMPPD: "CMPPD", + CMPPS: "CMPPS", + CMPSB: "CMPSB", + CMPSD: "CMPSD", + CMPSD_XMM: "CMPSD_XMM", + CMPSQ: "CMPSQ", + CMPSS: "CMPSS", + CMPSW: "CMPSW", + CMPXCHG: "CMPXCHG", + CMPXCHG16B: "CMPXCHG16B", + CMPXCHG8B: "CMPXCHG8B", + COMISD: "COMISD", + COMISS: "COMISS", + CPUID: "CPUID", + CQO: "CQO", + CRC32: "CRC32", + CVTDQ2PD: "CVTDQ2PD", + CVTDQ2PS: "CVTDQ2PS", + CVTPD2DQ: "CVTPD2DQ", + CVTPD2PI: "CVTPD2PI", + CVTPD2PS: "CVTPD2PS", + CVTPI2PD: "CVTPI2PD", + CVTPI2PS: "CVTPI2PS", + CVTPS2DQ: "CVTPS2DQ", + CVTPS2PD: "CVTPS2PD", + CVTPS2PI: "CVTPS2PI", + CVTSD2SI: "CVTSD2SI", + CVTSD2SS: "CVTSD2SS", + CVTSI2SD: "CVTSI2SD", + CVTSI2SS: "CVTSI2SS", + CVTSS2SD: "CVTSS2SD", + CVTSS2SI: "CVTSS2SI", + CVTTPD2DQ: "CVTTPD2DQ", + CVTTPD2PI: "CVTTPD2PI", + CVTTPS2DQ: "CVTTPS2DQ", + CVTTPS2PI: "CVTTPS2PI", + CVTTSD2SI: "CVTTSD2SI", + CVTTSS2SI: "CVTTSS2SI", + CWD: "CWD", + CWDE: "CWDE", + DAA: "DAA", + DAS: "DAS", + DEC: "DEC", + DIV: "DIV", + DIVPD: "DIVPD", + DIVPS: "DIVPS", + DIVSD: "DIVSD", + DIVSS: "DIVSS", + DPPD: "DPPD", + DPPS: "DPPS", + EMMS: "EMMS", + ENTER: "ENTER", + EXTRACTPS: "EXTRACTPS", + F2XM1: "F2XM1", + FABS: "FABS", + FADD: "FADD", + FADDP: "FADDP", + FBLD: "FBLD", + FBSTP: "FBSTP", + FCHS: "FCHS", + FCMOVB: "FCMOVB", + FCMOVBE: "FCMOVBE", + FCMOVE: "FCMOVE", + FCMOVNB: "FCMOVNB", + FCMOVNBE: "FCMOVNBE", + FCMOVNE: "FCMOVNE", + FCMOVNU: "FCMOVNU", + FCMOVU: "FCMOVU", + FCOM: "FCOM", + FCOMI: "FCOMI", + FCOMIP: "FCOMIP", + FCOMP: "FCOMP", + FCOMPP: "FCOMPP", + FCOS: "FCOS", + FDECSTP: "FDECSTP", + FDIV: "FDIV", + FDIVP: "FDIVP", + FDIVR: "FDIVR", + FDIVRP: "FDIVRP", + FFREE: "FFREE", + FFREEP: "FFREEP", + FIADD: "FIADD", + FICOM: "FICOM", + FICOMP: "FICOMP", + FIDIV: "FIDIV", + FIDIVR: "FIDIVR", + FILD: "FILD", + FIMUL: "FIMUL", + FINCSTP: "FINCSTP", + FIST: "FIST", + FISTP: "FISTP", + FISTTP: "FISTTP", + FISUB: "FISUB", + FISUBR: "FISUBR", + FLD: "FLD", + FLD1: "FLD1", + FLDCW: "FLDCW", + FLDENV: "FLDENV", + FLDL2E: "FLDL2E", + FLDL2T: "FLDL2T", + FLDLG2: "FLDLG2", + FLDPI: "FLDPI", + FMUL: "FMUL", + FMULP: "FMULP", + FNCLEX: "FNCLEX", + FNINIT: "FNINIT", + FNOP: "FNOP", + FNSAVE: "FNSAVE", + FNSTCW: "FNSTCW", + FNSTENV: "FNSTENV", + FNSTSW: "FNSTSW", + FPATAN: "FPATAN", + FPREM: "FPREM", + FPREM1: "FPREM1", + FPTAN: "FPTAN", + FRNDINT: "FRNDINT", + FRSTOR: "FRSTOR", + FSCALE: "FSCALE", + FSIN: "FSIN", + FSINCOS: "FSINCOS", + FSQRT: "FSQRT", + FST: "FST", + FSTP: "FSTP", + FSUB: "FSUB", + FSUBP: "FSUBP", + FSUBR: "FSUBR", + FSUBRP: "FSUBRP", + FTST: "FTST", + FUCOM: "FUCOM", + FUCOMI: "FUCOMI", + FUCOMIP: "FUCOMIP", + FUCOMP: "FUCOMP", + FUCOMPP: "FUCOMPP", + FWAIT: "FWAIT", + FXAM: "FXAM", + FXCH: "FXCH", + FXRSTOR: "FXRSTOR", + FXRSTOR64: "FXRSTOR64", + FXSAVE: "FXSAVE", + FXSAVE64: "FXSAVE64", + FXTRACT: "FXTRACT", + FYL2X: "FYL2X", + FYL2XP1: "FYL2XP1", + HADDPD: "HADDPD", + HADDPS: "HADDPS", + HLT: "HLT", + HSUBPD: "HSUBPD", + HSUBPS: "HSUBPS", + ICEBP: "ICEBP", + IDIV: "IDIV", + IMUL: "IMUL", + IN: "IN", + INC: "INC", + INSB: "INSB", + INSD: "INSD", + INSERTPS: "INSERTPS", + INSW: "INSW", + INT: "INT", + INTO: "INTO", + INVD: "INVD", + INVLPG: "INVLPG", + INVPCID: "INVPCID", + IRET: "IRET", + IRETD: "IRETD", + IRETQ: "IRETQ", + JA: "JA", + JAE: "JAE", + JB: "JB", + JBE: "JBE", + JCXZ: "JCXZ", + JE: "JE", + JECXZ: "JECXZ", + JG: "JG", + JGE: "JGE", + JL: "JL", + JLE: "JLE", + JMP: "JMP", + JNE: "JNE", + JNO: "JNO", + JNP: "JNP", + JNS: "JNS", + JO: "JO", + JP: "JP", + JRCXZ: "JRCXZ", + JS: "JS", + LAHF: "LAHF", + LAR: "LAR", + LCALL: "LCALL", + LDDQU: "LDDQU", + LDMXCSR: "LDMXCSR", + LDS: "LDS", + LEA: "LEA", + LEAVE: "LEAVE", + LES: "LES", + LFENCE: "LFENCE", + LFS: "LFS", + LGDT: "LGDT", + LGS: "LGS", + LIDT: "LIDT", + LJMP: "LJMP", + LLDT: "LLDT", + LMSW: "LMSW", + LODSB: "LODSB", + LODSD: "LODSD", + LODSQ: "LODSQ", + LODSW: "LODSW", + LOOP: "LOOP", + LOOPE: "LOOPE", + LOOPNE: "LOOPNE", + LRET: "LRET", + LSL: "LSL", + LSS: "LSS", + LTR: "LTR", + LZCNT: "LZCNT", + MASKMOVDQU: "MASKMOVDQU", + MASKMOVQ: "MASKMOVQ", + MAXPD: "MAXPD", + MAXPS: "MAXPS", + MAXSD: "MAXSD", + MAXSS: "MAXSS", + MFENCE: "MFENCE", + MINPD: "MINPD", + MINPS: "MINPS", + MINSD: "MINSD", + MINSS: "MINSS", + MONITOR: "MONITOR", + MOV: "MOV", + MOVAPD: "MOVAPD", + MOVAPS: "MOVAPS", + MOVBE: "MOVBE", + MOVD: "MOVD", + MOVDDUP: "MOVDDUP", + MOVDQ2Q: "MOVDQ2Q", + MOVDQA: "MOVDQA", + MOVDQU: "MOVDQU", + MOVHLPS: "MOVHLPS", + MOVHPD: "MOVHPD", + MOVHPS: "MOVHPS", + MOVLHPS: "MOVLHPS", + MOVLPD: "MOVLPD", + MOVLPS: "MOVLPS", + MOVMSKPD: "MOVMSKPD", + MOVMSKPS: "MOVMSKPS", + MOVNTDQ: "MOVNTDQ", + MOVNTDQA: "MOVNTDQA", + MOVNTI: "MOVNTI", + MOVNTPD: "MOVNTPD", + MOVNTPS: "MOVNTPS", + MOVNTQ: "MOVNTQ", + MOVNTSD: "MOVNTSD", + MOVNTSS: "MOVNTSS", + MOVQ: "MOVQ", + MOVQ2DQ: "MOVQ2DQ", + MOVSB: "MOVSB", + MOVSD: "MOVSD", + MOVSD_XMM: "MOVSD_XMM", + MOVSHDUP: "MOVSHDUP", + MOVSLDUP: "MOVSLDUP", + MOVSQ: "MOVSQ", + MOVSS: "MOVSS", + MOVSW: "MOVSW", + MOVSX: "MOVSX", + MOVSXD: "MOVSXD", + MOVUPD: "MOVUPD", + MOVUPS: "MOVUPS", + MOVZX: "MOVZX", + MPSADBW: "MPSADBW", + MUL: "MUL", + MULPD: "MULPD", + MULPS: "MULPS", + MULSD: "MULSD", + MULSS: "MULSS", + MWAIT: "MWAIT", + NEG: "NEG", + NOP: "NOP", + NOT: "NOT", + OR: "OR", + ORPD: "ORPD", + ORPS: "ORPS", + OUT: "OUT", + OUTSB: "OUTSB", + OUTSD: "OUTSD", + OUTSW: "OUTSW", + PABSB: "PABSB", + PABSD: "PABSD", + PABSW: "PABSW", + PACKSSDW: "PACKSSDW", + PACKSSWB: "PACKSSWB", + PACKUSDW: "PACKUSDW", + PACKUSWB: "PACKUSWB", + PADDB: "PADDB", + PADDD: "PADDD", + PADDQ: "PADDQ", + PADDSB: "PADDSB", + PADDSW: "PADDSW", + PADDUSB: "PADDUSB", + PADDUSW: "PADDUSW", + PADDW: "PADDW", + PALIGNR: "PALIGNR", + PAND: "PAND", + PANDN: "PANDN", + PAUSE: "PAUSE", + PAVGB: "PAVGB", + PAVGW: "PAVGW", + PBLENDVB: "PBLENDVB", + PBLENDW: "PBLENDW", + PCLMULQDQ: "PCLMULQDQ", + PCMPEQB: "PCMPEQB", + PCMPEQD: "PCMPEQD", + PCMPEQQ: "PCMPEQQ", + PCMPEQW: "PCMPEQW", + PCMPESTRI: "PCMPESTRI", + PCMPESTRM: "PCMPESTRM", + PCMPGTB: "PCMPGTB", + PCMPGTD: "PCMPGTD", + PCMPGTQ: "PCMPGTQ", + PCMPGTW: "PCMPGTW", + PCMPISTRI: "PCMPISTRI", + PCMPISTRM: "PCMPISTRM", + PEXTRB: "PEXTRB", + PEXTRD: "PEXTRD", + PEXTRQ: "PEXTRQ", + PEXTRW: "PEXTRW", + PHADDD: "PHADDD", + PHADDSW: "PHADDSW", + PHADDW: "PHADDW", + PHMINPOSUW: "PHMINPOSUW", + PHSUBD: "PHSUBD", + PHSUBSW: "PHSUBSW", + PHSUBW: "PHSUBW", + PINSRB: "PINSRB", + PINSRD: "PINSRD", + PINSRQ: "PINSRQ", + PINSRW: "PINSRW", + PMADDUBSW: "PMADDUBSW", + PMADDWD: "PMADDWD", + PMAXSB: "PMAXSB", + PMAXSD: "PMAXSD", + PMAXSW: "PMAXSW", + PMAXUB: "PMAXUB", + PMAXUD: "PMAXUD", + PMAXUW: "PMAXUW", + PMINSB: "PMINSB", + PMINSD: "PMINSD", + PMINSW: "PMINSW", + PMINUB: "PMINUB", + PMINUD: "PMINUD", + PMINUW: "PMINUW", + PMOVMSKB: "PMOVMSKB", + PMOVSXBD: "PMOVSXBD", + PMOVSXBQ: "PMOVSXBQ", + PMOVSXBW: "PMOVSXBW", + PMOVSXDQ: "PMOVSXDQ", + PMOVSXWD: "PMOVSXWD", + PMOVSXWQ: "PMOVSXWQ", + PMOVZXBD: "PMOVZXBD", + PMOVZXBQ: "PMOVZXBQ", + PMOVZXBW: "PMOVZXBW", + PMOVZXDQ: "PMOVZXDQ", + PMOVZXWD: "PMOVZXWD", + PMOVZXWQ: "PMOVZXWQ", + PMULDQ: "PMULDQ", + PMULHRSW: "PMULHRSW", + PMULHUW: "PMULHUW", + PMULHW: "PMULHW", + PMULLD: "PMULLD", + PMULLW: "PMULLW", + PMULUDQ: "PMULUDQ", + POP: "POP", + POPA: "POPA", + POPAD: "POPAD", + POPCNT: "POPCNT", + POPF: "POPF", + POPFD: "POPFD", + POPFQ: "POPFQ", + POR: "POR", + PREFETCHNTA: "PREFETCHNTA", + PREFETCHT0: "PREFETCHT0", + PREFETCHT1: "PREFETCHT1", + PREFETCHT2: "PREFETCHT2", + PREFETCHW: "PREFETCHW", + PSADBW: "PSADBW", + PSHUFB: "PSHUFB", + PSHUFD: "PSHUFD", + PSHUFHW: "PSHUFHW", + PSHUFLW: "PSHUFLW", + PSHUFW: "PSHUFW", + PSIGNB: "PSIGNB", + PSIGND: "PSIGND", + PSIGNW: "PSIGNW", + PSLLD: "PSLLD", + PSLLDQ: "PSLLDQ", + PSLLQ: "PSLLQ", + PSLLW: "PSLLW", + PSRAD: "PSRAD", + PSRAW: "PSRAW", + PSRLD: "PSRLD", + PSRLDQ: "PSRLDQ", + PSRLQ: "PSRLQ", + PSRLW: "PSRLW", + PSUBB: "PSUBB", + PSUBD: "PSUBD", + PSUBQ: "PSUBQ", + PSUBSB: "PSUBSB", + PSUBSW: "PSUBSW", + PSUBUSB: "PSUBUSB", + PSUBUSW: "PSUBUSW", + PSUBW: "PSUBW", + PTEST: "PTEST", + PUNPCKHBW: "PUNPCKHBW", + PUNPCKHDQ: "PUNPCKHDQ", + PUNPCKHQDQ: "PUNPCKHQDQ", + PUNPCKHWD: "PUNPCKHWD", + PUNPCKLBW: "PUNPCKLBW", + PUNPCKLDQ: "PUNPCKLDQ", + PUNPCKLQDQ: "PUNPCKLQDQ", + PUNPCKLWD: "PUNPCKLWD", + PUSH: "PUSH", + PUSHA: "PUSHA", + PUSHAD: "PUSHAD", + PUSHF: "PUSHF", + PUSHFD: "PUSHFD", + PUSHFQ: "PUSHFQ", + PXOR: "PXOR", + RCL: "RCL", + RCPPS: "RCPPS", + RCPSS: "RCPSS", + RCR: "RCR", + RDFSBASE: "RDFSBASE", + RDGSBASE: "RDGSBASE", + RDMSR: "RDMSR", + RDPMC: "RDPMC", + RDRAND: "RDRAND", + RDTSC: "RDTSC", + RDTSCP: "RDTSCP", + RET: "RET", + ROL: "ROL", + ROR: "ROR", + ROUNDPD: "ROUNDPD", + ROUNDPS: "ROUNDPS", + ROUNDSD: "ROUNDSD", + ROUNDSS: "ROUNDSS", + RSM: "RSM", + RSQRTPS: "RSQRTPS", + RSQRTSS: "RSQRTSS", + SAHF: "SAHF", + SAR: "SAR", + SBB: "SBB", + SCASB: "SCASB", + SCASD: "SCASD", + SCASQ: "SCASQ", + SCASW: "SCASW", + SETA: "SETA", + SETAE: "SETAE", + SETB: "SETB", + SETBE: "SETBE", + SETE: "SETE", + SETG: "SETG", + SETGE: "SETGE", + SETL: "SETL", + SETLE: "SETLE", + SETNE: "SETNE", + SETNO: "SETNO", + SETNP: "SETNP", + SETNS: "SETNS", + SETO: "SETO", + SETP: "SETP", + SETS: "SETS", + SFENCE: "SFENCE", + SGDT: "SGDT", + SHL: "SHL", + SHLD: "SHLD", + SHR: "SHR", + SHRD: "SHRD", + SHUFPD: "SHUFPD", + SHUFPS: "SHUFPS", + SIDT: "SIDT", + SLDT: "SLDT", + SMSW: "SMSW", + SQRTPD: "SQRTPD", + SQRTPS: "SQRTPS", + SQRTSD: "SQRTSD", + SQRTSS: "SQRTSS", + STC: "STC", + STD: "STD", + STI: "STI", + STMXCSR: "STMXCSR", + STOSB: "STOSB", + STOSD: "STOSD", + STOSQ: "STOSQ", + STOSW: "STOSW", + STR: "STR", + SUB: "SUB", + SUBPD: "SUBPD", + SUBPS: "SUBPS", + SUBSD: "SUBSD", + SUBSS: "SUBSS", + SWAPGS: "SWAPGS", + SYSCALL: "SYSCALL", + SYSENTER: "SYSENTER", + SYSEXIT: "SYSEXIT", + SYSRET: "SYSRET", + TEST: "TEST", + TZCNT: "TZCNT", + UCOMISD: "UCOMISD", + UCOMISS: "UCOMISS", + UD1: "UD1", + UD2: "UD2", + UNPCKHPD: "UNPCKHPD", + UNPCKHPS: "UNPCKHPS", + UNPCKLPD: "UNPCKLPD", + UNPCKLPS: "UNPCKLPS", + VERR: "VERR", + VERW: "VERW", + WBINVD: "WBINVD", + WRFSBASE: "WRFSBASE", + WRGSBASE: "WRGSBASE", + WRMSR: "WRMSR", + XABORT: "XABORT", + XADD: "XADD", + XBEGIN: "XBEGIN", + XCHG: "XCHG", + XEND: "XEND", + XGETBV: "XGETBV", + XLATB: "XLATB", + XOR: "XOR", + XORPD: "XORPD", + XORPS: "XORPS", + XRSTOR: "XRSTOR", + XRSTOR64: "XRSTOR64", + XRSTORS: "XRSTORS", + XRSTORS64: "XRSTORS64", + XSAVE: "XSAVE", + XSAVE64: "XSAVE64", + XSAVEC: "XSAVEC", + XSAVEC64: "XSAVEC64", + XSAVEOPT: "XSAVEOPT", + XSAVEOPT64: "XSAVEOPT64", + XSAVES: "XSAVES", + XSAVES64: "XSAVES64", + XSETBV: "XSETBV", + XTEST: "XTEST", +} diff --git a/vendor/vendor.json b/vendor/vendor.json index e2eb847..9f40335 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -14,6 +14,102 @@ "revision": "323a1c4214101331a4b71922c23d19b7409ac71f", "revisionTime": "2017-03-06T13:59:04Z" }, + { + "checksumSHA1": "Ay6dg3VVgggBHMsytbc+U4Wutyc=", + "path": "github.com/derekparker/delve/pkg/config", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "i4N90QPS76SMH2GjkJKjuS+z4xI=", + "path": "github.com/derekparker/delve/pkg/dwarf/frame", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "3pNKXngpbU4tnDOZc1ez6ywk7GA=", + "path": "github.com/derekparker/delve/pkg/dwarf/line", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "mOPdy13ztM3W5WMt3vVUq00AXfg=", + "path": "github.com/derekparker/delve/pkg/dwarf/op", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "hqg+xjH/qCO0CQokj5L1qD5lBmE=", + "path": "github.com/derekparker/delve/pkg/dwarf/reader", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "QkHSoN99PlCYaEgChgPaEBmUWbk=", + "path": "github.com/derekparker/delve/pkg/dwarf/util", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "KH9MVb6MX5iPgRjySRZHQa324Sw=", + "path": "github.com/derekparker/delve/pkg/proc", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "9dbHlIWbcf3jXVu6zRjZvJnDq4c=", + "path": "github.com/derekparker/delve/pkg/target", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "nqWjcE4SeTBNSuYlh6MJ8akB0cM=", + "path": "github.com/derekparker/delve/pkg/terminal", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "xRa64kuzCXVktmGscs1vCz9jIHs=", + "path": "github.com/derekparker/delve/pkg/version", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "BPHre0My8iszpkoNcX4ljtrz1dA=", + "path": "github.com/derekparker/delve/service", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "xMPjvGhTumLbAUApyLI/7UnC7sQ=", + "path": "github.com/derekparker/delve/service/api", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "/EXcw7FytgML9fdbMV0pxDBJJE0=", + "path": "github.com/derekparker/delve/service/debugger", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "d73mTsiCuYYpDaVs9QtozhzMDU0=", + "path": "github.com/derekparker/delve/service/rpc1", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "B+J0KRNuX0anRlif3mWXhBQhnVo=", + "path": "github.com/derekparker/delve/service/rpc2", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "PsNfnfv8GS79AG225Q/h57q/6F4=", + "path": "github.com/derekparker/delve/service/rpccommon", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, { "checksumSHA1": "hveFTNQ9YEyYRs6SWuXM+XU9qRI=", "path": "github.com/fsnotify/fsnotify", @@ -44,17 +140,73 @@ "revision": "80f8150043c80fb52dee6bc863a709cdac7ec8f8", "revisionTime": "2016-08-06T14:40:29Z" }, + { + "checksumSHA1": "rCffFCN6TpDAN3Jylyo8RFzhQ9E=", + "origin": "github.com/derekparker/delve/vendor/github.com/mattn/go-colorable", + "path": "github.com/mattn/go-colorable", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "NkbetqlpWBi3gP08JDneC+axTKw=", + "origin": "github.com/derekparker/delve/vendor/github.com/mattn/go-isatty", + "path": "github.com/mattn/go-isatty", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "i8KS96zyCztA4003YeqcAmpcXXs=", + "origin": "github.com/derekparker/delve/vendor/github.com/peterh/liner", + "path": "github.com/peterh/liner", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "1TxpZhEa9Ez1pq+kffwve9VUMug=", + "origin": "github.com/derekparker/delve/vendor/golang.org/x/debug/dwarf", + "path": "golang.org/x/debug/dwarf", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "dVu8Q/oko6zBz5UkwkrDyPHR8fU=", + "origin": "github.com/derekparker/delve/vendor/golang.org/x/debug/elf", + "path": "golang.org/x/debug/elf", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, + { + "checksumSHA1": "OktQbhBwXQo+frEBu9j+mbSn2T8=", + "origin": "github.com/derekparker/delve/vendor/golang.org/x/debug/macho", + "path": "golang.org/x/debug/macho", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, { "checksumSHA1": "NIg5qnKx/D8Th7YX882++siXTDY=", "path": "golang.org/x/sys/unix", "revision": "131454b5606f5f11f6926156504d8ec772484f1d", "revisionTime": "2015-09-10T19:29:23Z" }, + { + "checksumSHA1": "K/B/XoWtkUDe+j1yIR8JPbpPW7Y=", + "origin": "github.com/derekparker/delve/vendor/golang.org/x/sys/windows", + "path": "golang.org/x/sys/windows", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" + }, { "checksumSHA1": "+OgOXBoiQ+X+C2dsAeiOHwBIEH0=", "path": "gopkg.in/yaml.v2", "revision": "a83829b6f1293c91addabc89d0571c246397bbf4", "revisionTime": "2016-03-01T20:40:22Z" + }, + { + "checksumSHA1": "AfKaQYT0TjxxZewjMk36e3GsVV4=", + "origin": "github.com/derekparker/delve/vendor/rsc.io/x86/x86asm", + "path": "rsc.io/x86/x86asm", + "revision": "ab7367ed2bf15044f7bca97147a802f77b875797", + "revisionTime": "2017-03-13T17:59:34Z" } ], "rootPath": "github.com/beego/bee"