From 6da499c2c2ca89f12c2eda6b0e3a32b0e62b5352 Mon Sep 17 00:00:00 2001 From: Django Date: Fri, 11 Jan 2019 17:35:48 +0800 Subject: [PATCH] Fix issue that derekparker renamed to go-delve --- cmd/commands/dlv/dlv_amd64.go | 10 +- vendor/github.com/delve | 1 + vendor/github.com/derekparker/delve/LICENSE | 20 - .../derekparker/delve/config/config.go | 134 -- .../derekparker/delve/dwarf/frame/entries.go | 95 - .../delve/dwarf/frame/expression_constants.go | 164 -- .../derekparker/delve/dwarf/frame/parser.go | 125 -- .../derekparker/delve/dwarf/frame/table.go | 429 ----- .../delve/dwarf/line/line_parser.go | 122 -- .../delve/dwarf/line/state_machine.go | 252 --- .../derekparker/delve/dwarf/op/op.go | 84 - .../derekparker/delve/dwarf/reader/reader.go | 345 ---- .../derekparker/delve/dwarf/util/util.go | 81 - .../github.com/derekparker/delve/proc/arch.go | 79 - .../derekparker/delve/proc/breakpoints.go | 163 -- .../derekparker/delve/proc/disasm.go | 67 - .../derekparker/delve/proc/disasm_amd64.go | 183 -- .../github.com/derekparker/delve/proc/doc.go | 9 - .../github.com/derekparker/delve/proc/eval.go | 1121 ------------ .../github.com/derekparker/delve/proc/exc.h | 283 --- .../derekparker/delve/proc/exc_user_darwin.c | 768 -------- .../derekparker/delve/proc/exec_darwin.c | 112 -- .../derekparker/delve/proc/exec_darwin.h | 10 - .../derekparker/delve/proc/go_version.go | 113 -- .../derekparker/delve/proc/mach_exc.defs | 119 -- .../derekparker/delve/proc/mach_exc.h | 283 --- .../delve/proc/mach_exc_user_darwin.c | 768 -------- .../github.com/derekparker/delve/proc/mem.go | 57 - .../derekparker/delve/proc/moduledata.go | 189 -- .../github.com/derekparker/delve/proc/proc.go | 942 ---------- .../derekparker/delve/proc/proc_darwin.c | 231 --- .../derekparker/delve/proc/proc_darwin.go | 511 ------ .../derekparker/delve/proc/proc_darwin.h | 54 - .../derekparker/delve/proc/proc_linux.go | 482 ----- .../derekparker/delve/proc/proc_windows.go | 643 ------- .../derekparker/delve/proc/ptrace_darwin.go | 28 - .../derekparker/delve/proc/ptrace_linux.go | 96 - .../derekparker/delve/proc/ptrace_windows.go | 13 - .../derekparker/delve/proc/registers.go | 230 --- .../delve/proc/registers_darwin_amd64.go | 363 ---- .../delve/proc/registers_linux_amd64.go | 325 ---- .../delve/proc/registers_windows_amd64.go | 347 ---- .../derekparker/delve/proc/stack.go | 211 --- .../derekparker/delve/proc/syscall_windows.go | 112 -- .../delve/proc/syscall_windows_amd64.go | 114 -- .../derekparker/delve/proc/threads.go | 504 ------ .../derekparker/delve/proc/threads_darwin.c | 177 -- .../derekparker/delve/proc/threads_darwin.go | 136 -- .../derekparker/delve/proc/threads_darwin.h | 41 - .../derekparker/delve/proc/threads_linux.go | 108 -- .../derekparker/delve/proc/threads_windows.go | 151 -- .../derekparker/delve/proc/types.go | 715 -------- .../derekparker/delve/proc/variables.go | 1572 ----------------- .../delve/proc/zsyscall_windows.go | 181 -- .../delve/service/api/conversions.go | 264 --- .../delve/service/api/prettyprint.go | 321 ---- .../derekparker/delve/service/api/types.go | 320 ---- .../derekparker/delve/service/client.go | 115 -- .../derekparker/delve/service/config.go | 28 - .../delve/service/debugger/debugger.go | 833 --------- .../delve/service/debugger/debugger_darwin.go | 15 - .../delve/service/debugger/debugger_linux.go | 35 - .../service/debugger/debugger_windows.go | 16 - .../delve/service/debugger/locations.go | 411 ----- .../derekparker/delve/service/rpc1/client.go | 312 ---- .../delve/service/rpc1/readme.txtr | 5 - .../derekparker/delve/service/rpc1/server.go | 318 ---- .../derekparker/delve/service/rpc2/client.go | 308 ---- .../derekparker/delve/service/rpc2/server.go | 575 ------ .../derekparker/delve/service/rpccallback.go | 6 - .../delve/service/rpccommon/server.go | 409 ----- .../derekparker/delve/service/server.go | 8 - .../derekparker/delve/terminal/command.go | 1426 --------------- .../derekparker/delve/terminal/disasmprint.go | 31 - .../derekparker/delve/terminal/docgen.go | 54 - .../derekparker/delve/terminal/terminal.go | 251 --- .../delve/terminal/terminal_other.go | 14 - .../delve/terminal/terminal_windows.go | 35 - .../derekparker/delve/version/version.go | 25 - 79 files changed, 6 insertions(+), 20602 deletions(-) create mode 160000 vendor/github.com/delve delete mode 100644 vendor/github.com/derekparker/delve/LICENSE delete mode 100644 vendor/github.com/derekparker/delve/config/config.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/frame/entries.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/frame/expression_constants.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/frame/parser.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/frame/table.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/line/line_parser.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/line/state_machine.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/op/op.go delete mode 100755 vendor/github.com/derekparker/delve/dwarf/reader/reader.go delete mode 100644 vendor/github.com/derekparker/delve/dwarf/util/util.go delete mode 100644 vendor/github.com/derekparker/delve/proc/arch.go delete mode 100644 vendor/github.com/derekparker/delve/proc/breakpoints.go delete mode 100644 vendor/github.com/derekparker/delve/proc/disasm.go delete mode 100644 vendor/github.com/derekparker/delve/proc/disasm_amd64.go delete mode 100644 vendor/github.com/derekparker/delve/proc/doc.go delete mode 100644 vendor/github.com/derekparker/delve/proc/eval.go delete mode 100644 vendor/github.com/derekparker/delve/proc/exc.h delete mode 100644 vendor/github.com/derekparker/delve/proc/exc_user_darwin.c delete mode 100644 vendor/github.com/derekparker/delve/proc/exec_darwin.c delete mode 100644 vendor/github.com/derekparker/delve/proc/exec_darwin.h delete mode 100644 vendor/github.com/derekparker/delve/proc/go_version.go delete mode 100644 vendor/github.com/derekparker/delve/proc/mach_exc.defs delete mode 100644 vendor/github.com/derekparker/delve/proc/mach_exc.h delete mode 100644 vendor/github.com/derekparker/delve/proc/mach_exc_user_darwin.c delete mode 100644 vendor/github.com/derekparker/delve/proc/mem.go delete mode 100644 vendor/github.com/derekparker/delve/proc/moduledata.go delete mode 100644 vendor/github.com/derekparker/delve/proc/proc.go delete mode 100644 vendor/github.com/derekparker/delve/proc/proc_darwin.c delete mode 100644 vendor/github.com/derekparker/delve/proc/proc_darwin.go delete mode 100644 vendor/github.com/derekparker/delve/proc/proc_darwin.h delete mode 100644 vendor/github.com/derekparker/delve/proc/proc_linux.go delete mode 100644 vendor/github.com/derekparker/delve/proc/proc_windows.go delete mode 100644 vendor/github.com/derekparker/delve/proc/ptrace_darwin.go delete mode 100644 vendor/github.com/derekparker/delve/proc/ptrace_linux.go delete mode 100644 vendor/github.com/derekparker/delve/proc/ptrace_windows.go delete mode 100644 vendor/github.com/derekparker/delve/proc/registers.go delete mode 100644 vendor/github.com/derekparker/delve/proc/registers_darwin_amd64.go delete mode 100644 vendor/github.com/derekparker/delve/proc/registers_linux_amd64.go delete mode 100644 vendor/github.com/derekparker/delve/proc/registers_windows_amd64.go delete mode 100644 vendor/github.com/derekparker/delve/proc/stack.go delete mode 100644 vendor/github.com/derekparker/delve/proc/syscall_windows.go delete mode 100644 vendor/github.com/derekparker/delve/proc/syscall_windows_amd64.go delete mode 100644 vendor/github.com/derekparker/delve/proc/threads.go delete mode 100644 vendor/github.com/derekparker/delve/proc/threads_darwin.c delete mode 100644 vendor/github.com/derekparker/delve/proc/threads_darwin.go delete mode 100644 vendor/github.com/derekparker/delve/proc/threads_darwin.h delete mode 100644 vendor/github.com/derekparker/delve/proc/threads_linux.go delete mode 100644 vendor/github.com/derekparker/delve/proc/threads_windows.go delete mode 100644 vendor/github.com/derekparker/delve/proc/types.go delete mode 100644 vendor/github.com/derekparker/delve/proc/variables.go delete mode 100644 vendor/github.com/derekparker/delve/proc/zsyscall_windows.go delete mode 100644 vendor/github.com/derekparker/delve/service/api/conversions.go delete mode 100644 vendor/github.com/derekparker/delve/service/api/prettyprint.go delete mode 100644 vendor/github.com/derekparker/delve/service/api/types.go delete mode 100644 vendor/github.com/derekparker/delve/service/client.go delete mode 100644 vendor/github.com/derekparker/delve/service/config.go delete mode 100644 vendor/github.com/derekparker/delve/service/debugger/debugger.go delete mode 100644 vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go delete mode 100644 vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go delete mode 100644 vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go delete mode 100644 vendor/github.com/derekparker/delve/service/debugger/locations.go delete mode 100644 vendor/github.com/derekparker/delve/service/rpc1/client.go delete mode 100644 vendor/github.com/derekparker/delve/service/rpc1/readme.txtr delete mode 100644 vendor/github.com/derekparker/delve/service/rpc1/server.go delete mode 100644 vendor/github.com/derekparker/delve/service/rpc2/client.go delete mode 100644 vendor/github.com/derekparker/delve/service/rpc2/server.go delete mode 100644 vendor/github.com/derekparker/delve/service/rpccallback.go delete mode 100644 vendor/github.com/derekparker/delve/service/rpccommon/server.go delete mode 100644 vendor/github.com/derekparker/delve/service/server.go delete mode 100644 vendor/github.com/derekparker/delve/terminal/command.go delete mode 100644 vendor/github.com/derekparker/delve/terminal/disasmprint.go delete mode 100644 vendor/github.com/derekparker/delve/terminal/docgen.go delete mode 100644 vendor/github.com/derekparker/delve/terminal/terminal.go delete mode 100644 vendor/github.com/derekparker/delve/terminal/terminal_other.go delete mode 100644 vendor/github.com/derekparker/delve/terminal/terminal_windows.go delete mode 100644 vendor/github.com/derekparker/delve/version/version.go diff --git a/cmd/commands/dlv/dlv_amd64.go b/cmd/commands/dlv/dlv_amd64.go index a61a5fa..21b5fa4 100644 --- a/cmd/commands/dlv/dlv_amd64.go +++ b/cmd/commands/dlv/dlv_amd64.go @@ -28,10 +28,10 @@ import ( "github.com/beego/bee/cmd/commands/version" beeLogger "github.com/beego/bee/logger" "github.com/beego/bee/utils" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/rpc2" - "github.com/derekparker/delve/service/rpccommon" - "github.com/derekparker/delve/terminal" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/rpc2" + "github.com/go-delve/delve/service/rpccommon" + "github.com/go-delve/delve/terminal" "github.com/fsnotify/fsnotify" ) @@ -43,7 +43,7 @@ var cmdDlv = &commands.Command{ To debug your application using Delve, use: {{"$ bee dlv" | bold}} - For more information on Delve: https://github.com/derekparker/delve + For more information on Delve: https://github.com/go-delve/delve `, PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() }, Run: runDlv, diff --git a/vendor/github.com/delve b/vendor/github.com/delve new file mode 160000 index 0000000..a86711f --- /dev/null +++ b/vendor/github.com/delve @@ -0,0 +1 @@ +Subproject commit a86711f547fdfef6a2c1bc5755569f9b25b64323 diff --git a/vendor/github.com/derekparker/delve/LICENSE b/vendor/github.com/derekparker/delve/LICENSE deleted file mode 100644 index 5ee9d2f..0000000 --- a/vendor/github.com/derekparker/delve/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -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/config/config.go b/vendor/github.com/derekparker/delve/config/config.go deleted file mode 100644 index 3abb485..0000000 --- a/vendor/github.com/derekparker/delve/config/config.go +++ /dev/null @@ -1,134 +0,0 @@ -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/dwarf/frame/entries.go b/vendor/github.com/derekparker/delve/dwarf/frame/entries.go deleted file mode 100644 index caca2ce..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/frame/entries.go +++ /dev/null @@ -1,95 +0,0 @@ -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/dwarf/frame/expression_constants.go b/vendor/github.com/derekparker/delve/dwarf/frame/expression_constants.go deleted file mode 100644 index 95240cf..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/frame/expression_constants.go +++ /dev/null @@ -1,164 +0,0 @@ -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/dwarf/frame/parser.go b/vendor/github.com/derekparker/delve/dwarf/frame/parser.go deleted file mode 100644 index 08018a6..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/frame/parser.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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/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/dwarf/frame/table.go b/vendor/github.com/derekparker/delve/dwarf/frame/table.go deleted file mode 100644 index 6b99965..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/frame/table.go +++ /dev/null @@ -1,429 +0,0 @@ -package frame - -import ( - "bytes" - "encoding/binary" - "fmt" - - "github.com/derekparker/delve/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/dwarf/line/line_parser.go b/vendor/github.com/derekparker/delve/dwarf/line/line_parser.go deleted file mode 100644 index def5a11..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/line/line_parser.go +++ /dev/null @@ -1,122 +0,0 @@ -package line - -import ( - "bytes" - "encoding/binary" - - "github.com/derekparker/delve/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/dwarf/line/state_machine.go b/vendor/github.com/derekparker/delve/dwarf/line/state_machine.go deleted file mode 100644 index 1e2051a..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/line/state_machine.go +++ /dev/null @@ -1,252 +0,0 @@ -package line - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - - "github.com/derekparker/delve/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 -} - -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 - 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.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) - sm.basicBlock = false - sm.lastWasStandard = false -} - -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 - - 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 - - fn(sm, buf) -} - -func copyfn(sm *StateMachine, buf *bytes.Buffer) { - sm.basicBlock = false -} - -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 += (255 / uint64(sm.dbl.Prologue.LineRange)) -} - -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 -} - -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/dwarf/op/op.go b/vendor/github.com/derekparker/delve/dwarf/op/op.go deleted file mode 100644 index 82f0683..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/op/op.go +++ /dev/null @@ -1,84 +0,0 @@ -package op - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - - "github.com/derekparker/delve/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/dwarf/reader/reader.go b/vendor/github.com/derekparker/delve/dwarf/reader/reader.go deleted file mode 100755 index 339c278..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/reader/reader.go +++ /dev/null @@ -1,345 +0,0 @@ -package reader - -import ( - "errors" - "fmt" - - "golang.org/x/debug/dwarf" - "github.com/derekparker/delve/dwarf/op" -) - -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/dwarf/util/util.go b/vendor/github.com/derekparker/delve/dwarf/util/util.go deleted file mode 100644 index f60c203..0000000 --- a/vendor/github.com/derekparker/delve/dwarf/util/util.go +++ /dev/null @@ -1,81 +0,0 @@ -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/proc/arch.go b/vendor/github.com/derekparker/delve/proc/arch.go deleted file mode 100644 index 4031fd8..0000000 --- a/vendor/github.com/derekparker/delve/proc/arch.go +++ /dev/null @@ -1,79 +0,0 @@ -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/proc/breakpoints.go b/vendor/github.com/derekparker/delve/proc/breakpoints.go deleted file mode 100644 index 8f13d47..0000000 --- a/vendor/github.com/derekparker/delve/proc/breakpoints.go +++ /dev/null @@ -1,163 +0,0 @@ -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/proc/disasm.go b/vendor/github.com/derekparker/delve/proc/disasm.go deleted file mode 100644 index be2db19..0000000 --- a/vendor/github.com/derekparker/delve/proc/disasm.go +++ /dev/null @@ -1,67 +0,0 @@ -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/proc/disasm_amd64.go b/vendor/github.com/derekparker/delve/proc/disasm_amd64.go deleted file mode 100644 index cebf51b..0000000 --- a/vendor/github.com/derekparker/delve/proc/disasm_amd64.go +++ /dev/null @@ -1,183 +0,0 @@ -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/proc/doc.go b/vendor/github.com/derekparker/delve/proc/doc.go deleted file mode 100644 index 6079887..0000000 --- a/vendor/github.com/derekparker/delve/proc/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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/proc/eval.go b/vendor/github.com/derekparker/delve/proc/eval.go deleted file mode 100644 index 01213fa..0000000 --- a/vendor/github.com/derekparker/delve/proc/eval.go +++ /dev/null @@ -1,1121 +0,0 @@ -package proc - -import ( - "bytes" - "encoding/binary" - "fmt" - "go/ast" - "go/constant" - "go/parser" - "go/printer" - "go/token" - "reflect" - - "github.com/derekparker/delve/dwarf/reader" - "golang.org/x/debug/dwarf" -) - -// 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.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 - } - - 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/proc/exc.h b/vendor/github.com/derekparker/delve/proc/exc.h deleted file mode 100644 index c5c4386..0000000 --- a/vendor/github.com/derekparker/delve/proc/exc.h +++ /dev/null @@ -1,283 +0,0 @@ -#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/proc/exc_user_darwin.c b/vendor/github.com/derekparker/delve/proc/exc_user_darwin.c deleted file mode 100644 index bd2e689..0000000 --- a/vendor/github.com/derekparker/delve/proc/exc_user_darwin.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * 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/proc/exec_darwin.c b/vendor/github.com/derekparker/delve/proc/exec_darwin.c deleted file mode 100644 index 67409e3..0000000 --- a/vendor/github.com/derekparker/delve/proc/exec_darwin.c +++ /dev/null @@ -1,112 +0,0 @@ -#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/proc/exec_darwin.h b/vendor/github.com/derekparker/delve/proc/exec_darwin.h deleted file mode 100644 index 995e7e8..0000000 --- a/vendor/github.com/derekparker/delve/proc/exec_darwin.h +++ /dev/null @@ -1,10 +0,0 @@ -#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/proc/go_version.go b/vendor/github.com/derekparker/delve/proc/go_version.go deleted file mode 100644 index 21afab8..0000000 --- a/vendor/github.com/derekparker/delve/proc/go_version.go +++ /dev/null @@ -1,113 +0,0 @@ -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 -} - -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/proc/mach_exc.defs b/vendor/github.com/derekparker/delve/proc/mach_exc.defs deleted file mode 100644 index 00fae28..0000000 --- a/vendor/github.com/derekparker/delve/proc/mach_exc.defs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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/proc/mach_exc.h b/vendor/github.com/derekparker/delve/proc/mach_exc.h deleted file mode 100644 index b5f6dfc..0000000 --- a/vendor/github.com/derekparker/delve/proc/mach_exc.h +++ /dev/null @@ -1,283 +0,0 @@ -#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/proc/mach_exc_user_darwin.c b/vendor/github.com/derekparker/delve/proc/mach_exc_user_darwin.c deleted file mode 100644 index e475808..0000000 --- a/vendor/github.com/derekparker/delve/proc/mach_exc_user_darwin.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * 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/proc/mem.go b/vendor/github.com/derekparker/delve/proc/mem.go deleted file mode 100644 index ea45360..0000000 --- a/vendor/github.com/derekparker/delve/proc/mem.go +++ /dev/null @@ -1,57 +0,0 @@ -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/proc/moduledata.go b/vendor/github.com/derekparker/delve/proc/moduledata.go deleted file mode 100644 index 8652a5a..0000000 --- a/vendor/github.com/derekparker/delve/proc/moduledata.go +++ /dev/null @@ -1,189 +0,0 @@ -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/proc/proc.go b/vendor/github.com/derekparker/delve/proc/proc.go deleted file mode 100644 index c059ade..0000000 --- a/vendor/github.com/derekparker/delve/proc/proc.go +++ /dev/null @@ -1,942 +0,0 @@ -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/dwarf/frame" - "github.com/derekparker/delve/dwarf/line" - "github.com/derekparker/delve/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 - - loadModuleDataOnce sync.Once - moduleData []moduleData - nameOfRuntimeType map[uintptr]nameOfRuntimeTypeEntry -} - -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.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 -} - -// 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.loadTypeMap(&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() { - for i := 0; i < 2; i++ { - if err = dbp.CurrentThread.StepInstruction(); err != nil { - return err - } - } - } - 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 && dbp.SelectedGoroutine.DeferPC != 0 { - _, _, deferfn := dbp.goSymTable.PCToLine(dbp.SelectedGoroutine.DeferPC) - 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/proc/proc_darwin.c b/vendor/github.com/derekparker/delve/proc/proc_darwin.c deleted file mode 100644 index 24a6084..0000000 --- a/vendor/github.com/derekparker/delve/proc/proc_darwin.c +++ /dev/null @@ -1,231 +0,0 @@ -#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/proc/proc_darwin.go b/vendor/github.com/derekparker/delve/proc/proc_darwin.go deleted file mode 100644 index 50b3968..0000000 --- a/vendor/github.com/derekparker/delve/proc/proc_darwin.go +++ /dev/null @@ -1,511 +0,0 @@ -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/dwarf/frame" - "github.com/derekparker/delve/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/proc/proc_darwin.h b/vendor/github.com/derekparker/delve/proc/proc_darwin.h deleted file mode 100644 index 022ab14..0000000 --- a/vendor/github.com/derekparker/delve/proc/proc_darwin.h +++ /dev/null @@ -1,54 +0,0 @@ -#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/proc/proc_linux.go b/vendor/github.com/derekparker/delve/proc/proc_linux.go deleted file mode 100644 index 7b9df75..0000000 --- a/vendor/github.com/derekparker/delve/proc/proc_linux.go +++ /dev/null @@ -1,482 +0,0 @@ -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/dwarf/frame" - "github.com/derekparker/delve/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 -} - -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/proc/proc_windows.go b/vendor/github.com/derekparker/delve/proc/proc_windows.go deleted file mode 100644 index aa5518e..0000000 --- a/vendor/github.com/derekparker/delve/proc/proc_windows.go +++ /dev/null @@ -1,643 +0,0 @@ -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/dwarf/frame" - "github.com/derekparker/delve/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) - if code := exception.ExceptionRecord.ExceptionCode; code == _EXCEPTION_BREAKPOINT || code == _EXCEPTION_SINGLE_STEP { - tid := int(debugEvent.ThreadId) - dbp.os.breakThread = tid - return tid, 0, nil - } else { - 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/proc/ptrace_darwin.go b/vendor/github.com/derekparker/delve/proc/ptrace_darwin.go deleted file mode 100644 index c9ed435..0000000 --- a/vendor/github.com/derekparker/delve/proc/ptrace_darwin.go +++ /dev/null @@ -1,28 +0,0 @@ -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/proc/ptrace_linux.go b/vendor/github.com/derekparker/delve/proc/ptrace_linux.go deleted file mode 100644 index 402dbb9..0000000 --- a/vendor/github.com/derekparker/delve/proc/ptrace_linux.go +++ /dev/null @@ -1,96 +0,0 @@ -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/proc/ptrace_windows.go b/vendor/github.com/derekparker/delve/proc/ptrace_windows.go deleted file mode 100644 index 96e347b..0000000 --- a/vendor/github.com/derekparker/delve/proc/ptrace_windows.go +++ /dev/null @@ -1,13 +0,0 @@ -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/proc/registers.go b/vendor/github.com/derekparker/delve/proc/registers.go deleted file mode 100644 index d1032fa..0000000 --- a/vendor/github.com/derekparker/delve/proc/registers.go +++ /dev/null @@ -1,230 +0,0 @@ -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 - 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/proc/registers_darwin_amd64.go b/vendor/github.com/derekparker/delve/proc/registers_darwin_amd64.go deleted file mode 100644 index 0357c91..0000000 --- a/vendor/github.com/derekparker/delve/proc/registers_darwin_amd64.go +++ /dev/null @@ -1,363 +0,0 @@ -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 -} - -// 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.rax >> 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/proc/registers_linux_amd64.go b/vendor/github.com/derekparker/delve/proc/registers_linux_amd64.go deleted file mode 100644 index 07b79e2..0000000 --- a/vendor/github.com/derekparker/delve/proc/registers_linux_amd64.go +++ /dev/null @@ -1,325 +0,0 @@ -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 -} - -// 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.Rax >> 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/proc/registers_windows_amd64.go b/vendor/github.com/derekparker/delve/proc/registers_windows_amd64.go deleted file mode 100644 index ac4ed7c..0000000 --- a/vendor/github.com/derekparker/delve/proc/registers_windows_amd64.go +++ /dev/null @@ -1,347 +0,0 @@ -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 -} - -// 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.rax >> 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/proc/stack.go b/vendor/github.com/derekparker/delve/proc/stack.go deleted file mode 100644 index 878e90f..0000000 --- a/vendor/github.com/derekparker/delve/proc/stack.go +++ /dev/null @@ -1,211 +0,0 @@ -package proc - -import ( - "encoding/binary" - "errors" - "fmt" - "github.com/derekparker/delve/dwarf/frame" -) - -// 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 -} - -// 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() (*stackIterator, error) { - regs, err := t.Registers(false) - if err != nil { - return nil, err - } - return newStackIterator(t.dbp, regs.PC(), regs.SP()), 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() - if err != nil { - return nil, err - } - return it.stacktrace(depth) -} - -func (g *G) stackIterator() (*stackIterator, error) { - if g.thread != nil { - return g.thread.stackIterator() - } - return newStackIterator(g.dbp, g.PC, g.SP), 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 uint64 - top bool - atend bool - frame Stackframe - dbp *Process - err error -} - -func newStackIterator(dbp *Process, pc, sp uint64) *stackIterator { - return &stackIterator{pc: pc, sp: sp, top: true, dbp: dbp, err: nil, atend: false} -} - -// 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.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.Current.Fn == nil { - if it.top { - it.err = fmt.Errorf("PC not associated to any function") - } - return false - } - - if it.frame.Ret <= 0 { - it.atend = true - return true - } - // Look for "top of stack" functions. - if 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) - 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 uint64, top bool) (Stackframe, error) { - f, l, fn := dbp.PCToLine(pc) - fde, err := dbp.frameEntries.FDEForPC(pc) - if err != nil { - return Stackframe{}, err - } - spoffset, retoffset := fde.ReturnAddressOffset(pc) - cfa := int64(sp) + spoffset - - retaddr := uintptr(cfa + retoffset) - if retaddr == 0 { - return Stackframe{}, NullAddrError{} - } - data, err := dbp.CurrentThread.readMemory(retaddr, 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: binary.LittleEndian.Uint64(data)} - if !top { - r.Call.File, r.Call.Line, r.Call.Fn = dbp.PCToLine(pc - 1) - r.Call.PC, _, _ = dbp.goSymTable.LineToPC(r.Call.File, r.Call.Line) - } 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/proc/syscall_windows.go b/vendor/github.com/derekparker/delve/proc/syscall_windows.go deleted file mode 100644 index 770a789..0000000 --- a/vendor/github.com/derekparker/delve/proc/syscall_windows.go +++ /dev/null @@ -1,112 +0,0 @@ -//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/proc/syscall_windows_amd64.go b/vendor/github.com/derekparker/delve/proc/syscall_windows_amd64.go deleted file mode 100644 index 1ce592e..0000000 --- a/vendor/github.com/derekparker/delve/proc/syscall_windows_amd64.go +++ /dev/null @@ -1,114 +0,0 @@ -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/proc/threads.go b/vendor/github.com/derekparker/delve/proc/threads.go deleted file mode 100644 index 1552fd2..0000000 --- a/vendor/github.com/derekparker/delve/proc/threads.go +++ /dev/null @@ -1,504 +0,0 @@ -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 && dbp.SelectedGoroutine.DeferPC != 0 { - _, _, deferfn := dbp.goSymTable.PCToLine(dbp.SelectedGoroutine.DeferPC) - 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 CurrentThread 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 - } - 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/proc/threads_darwin.c b/vendor/github.com/derekparker/delve/proc/threads_darwin.c deleted file mode 100644 index 88a92f4..0000000 --- a/vendor/github.com/derekparker/delve/proc/threads_darwin.c +++ /dev/null @@ -1,177 +0,0 @@ -#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/proc/threads_darwin.go b/vendor/github.com/derekparker/delve/proc/threads_darwin.go deleted file mode 100644 index 0c80b17..0000000 --- a/vendor/github.com/derekparker/delve/proc/threads_darwin.go +++ /dev/null @@ -1,136 +0,0 @@ -package proc - -// #include "threads_darwin.h" -// #include "proc_darwin.h" -import "C" -import ( - "fmt" - sys "golang.org/x/sys/unix" - "unsafe" -) - -// 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/proc/threads_darwin.h b/vendor/github.com/derekparker/delve/proc/threads_darwin.h deleted file mode 100644 index 75a82b8..0000000 --- a/vendor/github.com/derekparker/delve/proc/threads_darwin.h +++ /dev/null @@ -1,41 +0,0 @@ -#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/proc/threads_linux.go b/vendor/github.com/derekparker/delve/proc/threads_linux.go deleted file mode 100644 index 6f0a8b3..0000000 --- a/vendor/github.com/derekparker/delve/proc/threads_linux.go +++ /dev/null @@ -1,108 +0,0 @@ -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.wait(t.ID, 0) - 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/proc/threads_windows.go b/vendor/github.com/derekparker/delve/proc/threads_windows.go deleted file mode 100644 index e0452e7..0000000 --- a/vendor/github.com/derekparker/delve/proc/threads_windows.go +++ /dev/null @@ -1,151 +0,0 @@ -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/proc/types.go b/vendor/github.com/derekparker/delve/proc/types.go deleted file mode 100644 index 50ee054..0000000 --- a/vendor/github.com/derekparker/delve/proc/types.go +++ /dev/null @@ -1,715 +0,0 @@ -package proc - -import ( - "bytes" - "errors" - "fmt" - "go/ast" - "go/constant" - "go/token" - "reflect" - "strconv" - "strings" - "sync" - "unsafe" - - "github.com/derekparker/delve/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 -} - -func (dbp *Process) loadTypeMap(wg *sync.WaitGroup) { - defer wg.Done() - dbp.types = make(map[string]dwarf.Offset) - reader := dbp.DwarfReader() - for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() { - if err != nil { - break - } - name, ok := entry.Val(dwarf.AttrName).(string) - if !ok { - continue - } - if _, exists := dbp.types[name]; !exists { - dbp.types[name] = entry.Offset - } - } -} - -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.toFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil { - tflag, _ = constant.Int64Val(tflagField.Value) - } - if kindField := _type.toFieldNamed("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.toFieldNamed("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.toFieldNamed("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.toFieldNamed("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.toFieldNamed("inCount"); inCountField != nil && inCountField.Value != nil { - inCount, _ = constant.Int64Val(inCountField.Value) - } - if outCountField := _type.toFieldNamed("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.toFieldNamed("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/proc/variables.go b/vendor/github.com/derekparker/delve/proc/variables.go deleted file mode 100644 index 0734422..0000000 --- a/vendor/github.com/derekparker/delve/proc/variables.go +++ /dev/null @@ -1,1572 +0,0 @@ -package proc - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "go/constant" - "go/parser" - "go/token" - "reflect" - "strings" - "unsafe" - - "github.com/derekparker/delve/dwarf/op" - "github.com/derekparker/delve/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 -) - -// 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 - - 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 - - // Information on goroutine location - CurrentLoc Location - - // PC of entry to top-most deferred function. - DeferPC uint64 - - // Thread that this goroutine is currently allocated to - thread *Thread - - 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} - } - gvar.loadValue(loadFullValue) - if gvar.Unreadable != nil { - return nil, gvar.Unreadable - } - schedVar := gvar.toFieldNamed("sched") - pc, _ := constant.Int64Val(schedVar.toFieldNamed("pc").Value) - sp, _ := constant.Int64Val(schedVar.toFieldNamed("sp").Value) - id, _ := constant.Int64Val(gvar.toFieldNamed("goid").Value) - gopc, _ := constant.Int64Val(gvar.toFieldNamed("gopc").Value) - waitReason := constant.StringVal(gvar.toFieldNamed("waitreason").Value) - d := gvar.toFieldNamed("_defer") - deferPC := int64(0) - fnvar := d.toFieldNamed("fn") - if fnvar != nil { - fnvalvar := fnvar.toFieldNamed("fn") - deferPC, _ = constant.Int64Val(fnvalvar.Value) - } - status, _ := constant.Int64Val(gvar.toFieldNamed("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, - DeferPC: uint64(deferPC), - Status: uint64(status), - CurrentLoc: Location{PC: uint64(pc), File: f, Line: l, Fn: fn}, - dbp: gvar.dbp, - } - return g, nil -} - -func (v *Variable) toFieldNamed(name string) *Variable { - v, err := v.structMember(name) - if err != nil { - return nil - } - v.loadValue(loadFullValue) - if v.Unreadable != nil { - return nil - } - return v -} - -// 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} -} - -// 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 - } - v.loadValue(cfg) - return v, nil -} - -func (scope *EvalScope) extractVarInfo(varName string) (*Variable, error) { - reader := scope.DwarfReader() - - _, err := reader.SeekToFunction(scope.PC) - if err != nil { - return nil, err - } - - for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() { - if err != nil { - return nil, err - } - - 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 - } - 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 - v.Children[0].loadValueInternal(recurseLevel, 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) - 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 - } - } - - return it -} - -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 = fmt.Errorf("malformed map type: keys, values or tophash of a bucket is not an array") - return false - } - - if it.tophashes.Len != it.keys.Len || it.tophashes.Len != it.values.Len { - it.v.Unreadable = fmt.Errorf("malformed map type: inconsistent array length in bucket") - 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 { - 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() - - _, err := reader.SeekToFunction(scope.PC) - if err != nil { - return nil, err - } - - var vars []*Variable - for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() { - if err != nil { - return nil, err - } - - 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) - } - } - - return vars, nil -} diff --git a/vendor/github.com/derekparker/delve/proc/zsyscall_windows.go b/vendor/github.com/derekparker/delve/proc/zsyscall_windows.go deleted file mode 100644 index ee2b33c..0000000 --- a/vendor/github.com/derekparker/delve/proc/zsyscall_windows.go +++ /dev/null @@ -1,181 +0,0 @@ -// 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/service/api/conversions.go b/vendor/github.com/derekparker/delve/service/api/conversions.go deleted file mode 100644 index 61a15f7..0000000 --- a/vendor/github.com/derekparker/delve/service/api/conversions.go +++ /dev/null @@ -1,264 +0,0 @@ -package api - -import ( - "bytes" - "debug/gosym" - "go/constant" - "go/printer" - "go/token" - "reflect" - "strconv" - - "github.com/derekparker/delve/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 -} - -// 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: - f, _ := constant.Float64Val(v.Value) - r.Value = strconv.FormatFloat(f, 'f', -1, 32) - case reflect.Float64: - f, _ := constant.Float64Val(v.Value) - r.Value = strconv.FormatFloat(f, 'f', -1, 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 deleted file mode 100644 index 3afb359..0000000 --- a/vendor/github.com/derekparker/delve/service/api/prettyprint.go +++ /dev/null @@ -1,321 +0,0 @@ -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 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 deleted file mode 100644 index 4a64c56..0000000 --- a/vendor/github.com/derekparker/delve/service/api/types.go +++ /dev/null @@ -1,320 +0,0 @@ -package api - -import ( - "bytes" - "errors" - "fmt" - "reflect" - "strconv" - "unicode" - - "github.com/derekparker/delve/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 deleted file mode 100644 index fe06a94..0000000 --- a/vendor/github.com/derekparker/delve/service/client.go +++ /dev/null @@ -1,115 +0,0 @@ -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 deleted file mode 100644 index dd2991c..0000000 --- a/vendor/github.com/derekparker/delve/service/config.go +++ /dev/null @@ -1,28 +0,0 @@ -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 deleted file mode 100644 index 41fa767..0000000 --- a/vendor/github.com/derekparker/delve/service/debugger/debugger.go +++ /dev/null @@ -1,833 +0,0 @@ -package debugger - -import ( - "debug/gosym" - "errors" - "fmt" - "go/parser" - "log" - "path/filepath" - "regexp" - "runtime" - "strings" - "sync" - "time" - - "github.com/derekparker/delve/proc" - "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 - processMutex sync.Mutex - process *proc.Process -} - -// 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.process = 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.process = p - } - return d, nil -} - -// ProcessPid returns the PID of the process -// the debugger is debugging. -func (d *Debugger) ProcessPid() int { - return d.process.Pid -} - -// LastModified returns the time that the process' executable was last -// modified. -func (d *Debugger) LastModified() time.Time { - return d.process.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.process.Detach(kill) - } - return d.process.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.process.Exited() { - if d.process.Running() { - d.process.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.process = 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.process.Exited() { - return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} - } - - var ( - state *api.DebuggerState - goroutine *api.Goroutine - ) - - if d.process.SelectedGoroutine != nil { - goroutine = api.ConvertGoroutine(d.process.SelectedGoroutine) - } - - state = &api.DebuggerState{ - SelectedGoroutine: goroutine, - Exited: d.process.Exited(), - } - - for i := range d.process.Threads { - th := api.ConvertThread(d.process.Threads[i]) - state.Threads = append(state.Threads, th) - if i == d.process.CurrentThread.ID { - state.CurrentThread = th - } - } - - for _, bp := range d.process.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.process.Sources() { - if fileNameNormalized == strings.ToLower(filepath.ToSlash(symFile)) { - fileName = symFile - break - } - } - } - addr, err = d.process.FindFileLocation(fileName, requestedBp.Line) - case len(requestedBp.FunctionName) > 0: - if requestedBp.Line >= 0 { - addr, err = d.process.FindFunctionLocation(requestedBp.FunctionName, false, requestedBp.Line) - } else { - addr, err = d.process.FindFunctionLocation(requestedBp.FunctionName, true, 0) - } - default: - addr = requestedBp.Addr - } - - if err != nil { - return nil, err - } - - bp, err := d.process.SetBreakpoint(addr, proc.UserBreakpoint, nil) - if err != nil { - return nil, err - } - if err := copyBreakpointInfo(bp, requestedBp); err != nil { - if _, err1 := d.process.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.process.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.process.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.process.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.process.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.process.Exited() { - return nil, &proc.ProcessExitedError{} - } - threads := []*api.Thread{} - for _, th := range d.process.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.process.Exited() { - return nil, &proc.ProcessExitedError{} - } - - for _, th := range d.process.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.process.RequestManualStop() - } - - d.processMutex.Lock() - defer d.processMutex.Unlock() - - switch command.Name { - case api.Continue: - log.Print("continuing") - err = d.process.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.process.Next() - case api.Step: - log.Print("stepping") - err = d.process.Step() - case api.StepInstruction: - log.Print("single stepping") - err = d.process.StepInstruction() - case api.StepOut: - log.Print("step out") - err = d.process.StepOut() - case api.SwitchThread: - log.Printf("switching to thread %d", command.ThreadID) - err = d.process.SwitchThread(command.ThreadID) - case api.SwitchGoroutine: - log.Printf("switching to goroutine %d", command.GoroutineID) - err = d.process.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.process.CurrentThread.GetG() - if err != nil { - return err - } - bpi.Goroutine = api.ConvertGoroutine(g) - } - - if bp.Stacktrace > 0 { - rawlocs, err := d.process.CurrentThread.Stacktrace(bp.Stacktrace) - if err != nil { - return err - } - bpi.Stacktrace, err = d.convertStacktrace(rawlocs, nil) - if err != nil { - return err - } - } - - s, err := d.process.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.process.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.process.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.process.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.process.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.process.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.process.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.process.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.process.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.process.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.process.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.process.FindGoroutine(goroutineID) - if err != nil { - return nil, err - } - - if g == nil { - rawlocs, err = d.process.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 { - var err error - scope := rawlocs[i].Scope(d.process.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.process.ConvertEvalScope(scope.GoroutineID, scope.Frame) - - locs, err := loc.Find(d, s, locStr) - for i := range locs { - file, line, fn := d.process.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.process.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.process.CurrentThread - - if s, err := d.process.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 deleted file mode 100644 index c317718..0000000 --- a/vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go +++ /dev/null @@ -1,15 +0,0 @@ -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 deleted file mode 100644 index 1d567c0..0000000 --- a/vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go +++ /dev/null @@ -1,35 +0,0 @@ -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 deleted file mode 100644 index c80ce2a..0000000 --- a/vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index 0c85ae5..0000000 --- a/vendor/github.com/derekparker/delve/service/debugger/locations.go +++ /dev/null @@ -1,411 +0,0 @@ -package debugger - -import ( - "debug/gosym" - "fmt" - "go/constant" - "path/filepath" - "reflect" - "runtime" - "strconv" - "strings" - - "github.com/derekparker/delve/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.process.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.process.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.process.PCToLine(uint64(v.Base)) - pc, err := d.process.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.process.Funcs() - files := d.process.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.process.FindFileLocation(candidates[0], loc.LineOffset) - } else { - if loc.LineOffset < 0 { - addr, err = d.process.FindFunctionLocation(candidates[0], true, 0) - } else { - addr, err = d.process.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.process.PCToLine(scope.PC) - if fn == nil { - return nil, fmt.Errorf("could not determine current location") - } - addr, err := d.process.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.process.PCToLine(scope.PC) - if fn == nil { - return nil, fmt.Errorf("could not determine current location") - } - addr, err := d.process.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 deleted file mode 100644 index 43c76c4..0000000 --- a/vendor/github.com/derekparker/delve/service/rpc1/client.go +++ /dev/null @@ -1,312 +0,0 @@ -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 deleted file mode 100644 index c25192d..0000000 --- a/vendor/github.com/derekparker/delve/service/rpc1/readme.txtr +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index af233be..0000000 --- a/vendor/github.com/derekparker/delve/service/rpc1/server.go +++ /dev/null @@ -1,318 +0,0 @@ -package rpc1 - -import ( - "errors" - "fmt" - - "github.com/derekparker/delve/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 deleted file mode 100644 index 1489044..0000000 --- a/vendor/github.com/derekparker/delve/service/rpc2/client.go +++ /dev/null @@ -1,308 +0,0 @@ -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 deleted file mode 100644 index 51c5954..0000000 --- a/vendor/github.com/derekparker/delve/service/rpc2/server.go +++ /dev/null @@ -1,575 +0,0 @@ -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 deleted file mode 100644 index 9b04782..0000000 --- a/vendor/github.com/derekparker/delve/service/rpccallback.go +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 40f2646..0000000 --- a/vendor/github.com/derekparker/delve/service/rpccommon/server.go +++ /dev/null @@ -1,409 +0,0 @@ -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/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" - "github.com/derekparker/delve/version" -) - -// 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 deleted file mode 100644 index 20a364b..0000000 --- a/vendor/github.com/derekparker/delve/service/server.go +++ /dev/null @@ -1,8 +0,0 @@ -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/derekparker/delve/terminal/command.go b/vendor/github.com/derekparker/delve/terminal/command.go deleted file mode 100644 index 764c3e8..0000000 --- a/vendor/github.com/derekparker/delve/terminal/command.go +++ /dev/null @@ -1,1426 +0,0 @@ -// 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/terminal/disasmprint.go b/vendor/github.com/derekparker/delve/terminal/disasmprint.go deleted file mode 100644 index 7c27374..0000000 --- a/vendor/github.com/derekparker/delve/terminal/disasmprint.go +++ /dev/null @@ -1,31 +0,0 @@ -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/terminal/docgen.go b/vendor/github.com/derekparker/delve/terminal/docgen.go deleted file mode 100644 index a9632d9..0000000 --- a/vendor/github.com/derekparker/delve/terminal/docgen.go +++ /dev/null @@ -1,54 +0,0 @@ -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/terminal/terminal.go b/vendor/github.com/derekparker/delve/terminal/terminal.go deleted file mode 100644 index b6bb7e9..0000000 --- a/vendor/github.com/derekparker/delve/terminal/terminal.go +++ /dev/null @@ -1,251 +0,0 @@ -package terminal - -import ( - "fmt" - "io" - "os" - "os/signal" - "runtime" - "strings" - - "syscall" - - "github.com/peterh/liner" - - "github.com/derekparker/delve/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/terminal/terminal_other.go b/vendor/github.com/derekparker/delve/terminal/terminal_other.go deleted file mode 100644 index 70a8fee..0000000 --- a/vendor/github.com/derekparker/delve/terminal/terminal_other.go +++ /dev/null @@ -1,14 +0,0 @@ -// +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/terminal/terminal_windows.go b/vendor/github.com/derekparker/delve/terminal/terminal_windows.go deleted file mode 100644 index 1d525be..0000000 --- a/vendor/github.com/derekparker/delve/terminal/terminal_windows.go +++ /dev/null @@ -1,35 +0,0 @@ -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/version/version.go b/vendor/github.com/derekparker/delve/version/version.go deleted file mode 100644 index f89e9df..0000000 --- a/vendor/github.com/derekparker/delve/version/version.go +++ /dev/null @@ -1,25 +0,0 @@ -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) -}