From da91d50ab8d5d2bb25bae8f48e694be50d3d77b8 Mon Sep 17 00:00:00 2001 From: Ruben Cid Date: Mon, 15 Apr 2019 16:43:01 +0200 Subject: [PATCH] Updated vendor --- cmd/commands/dlv/dlv_amd64.go | 2 +- cmd/commands/run/watch.go | 2 +- generate/swaggergen/g_docs.go | 2 +- utils/utils.go | 2 +- vendor/github.com/astaxie/beego/LICENSE | 13 + vendor/github.com/cosiner/argv/README.md | 31 + .../delve/pkg/logflags/logflags.go | 83 --- .../delve/pkg/proc/native/mach_exc.defs | 119 --- .../pkg/proc/native/registers_linux_amd64.go | 342 --------- .../pkg/proc/native/syscall_windows_amd64.go | 114 --- .../{derekparker => go-delve}/delve/LICENSE | 0 .../delve/pkg/config/config.go | 129 +++- .../delve/pkg/config/split.go | 2 +- .../delve/pkg/dwarf/frame/entries.go | 0 .../pkg/dwarf/frame/expression_constants.go | 0 .../delve/pkg/dwarf/frame/parser.go | 2 +- .../delve/pkg/dwarf/frame/table.go | 2 +- .../delve/pkg/dwarf/godwarf/sections.go | 0 .../delve/pkg/dwarf/godwarf/type.go | 197 ++++- .../delve/pkg/dwarf/line/line_parser.go | 2 +- .../delve/pkg/dwarf/line/state_machine.go | 2 +- .../delve/pkg/dwarf/op/op.go | 2 +- .../delve/pkg/dwarf/op/opcodes.go | 0 .../delve/pkg/dwarf/op/opcodes.table | 0 .../delve/pkg/dwarf/op/regs.go | 0 .../delve/pkg/dwarf/reader/reader.go | 2 +- .../delve/pkg/dwarf/reader/variables.go | 0 .../delve/pkg/dwarf/util/buf.go | 0 .../delve/pkg/dwarf/util/util.go | 0 .../delve/pkg/goversion/go_version.go | 0 .../go-delve/delve/pkg/logflags/logflags.go | 227 ++++++ .../delve/pkg/proc/arch.go | 6 +- .../delve/pkg/proc/bininfo.go | 233 ++++-- .../delve/pkg/proc/breakpoints.go | 27 +- .../delve/pkg/proc/core/core.go | 172 ++--- .../delve/pkg/proc/core/linux_amd64_core.go | 291 ++------ .../proc/core/minidump/fileflags_string.go | 154 ++++ .../delve/pkg/proc/core/minidump/minidump.go | 686 ++++++++++++++++++ .../pkg/proc/core/windows_amd64_minidump.go | 59 ++ .../delve/pkg/proc/disasm.go | 0 .../delve/pkg/proc/disasm_amd64.go | 10 +- .../delve/pkg/proc/doc.go | 0 .../delve/pkg/proc/eval.go | 52 +- .../delve/pkg/proc/fncall.go | 38 +- .../delve/pkg/proc/gdbserial/gdbserver.go | 281 +++---- .../pkg/proc/gdbserial/gdbserver_conn.go | 7 +- .../pkg/proc/gdbserial/gdbserver_unix.go | 0 .../pkg/proc/gdbserial/gdbserver_windows.go | 0 .../delve/pkg/proc/gdbserial/rr.go | 8 +- .../delve/pkg/proc/interface.go | 2 + .../delve/pkg/proc/linutil/auxv.go | 0 .../delve/pkg/proc/linutil/doc.go | 0 .../delve/pkg/proc/linutil/dynamic.go | 172 +++++ .../go-delve/delve/pkg/proc/linutil/regs.go | 399 ++++++++++ .../delve/pkg/proc/mem.go | 10 +- .../delve/pkg/proc/moduledata.go | 2 +- .../delve/pkg/proc/native/exc.h | 0 .../delve/pkg/proc/native/exc_user_darwin.c | 0 .../delve/pkg/proc/native/exec_darwin.c | 0 .../delve/pkg/proc/native/exec_darwin.h | 0 .../delve/pkg/proc/native/mach_exc.h | 0 .../pkg/proc/native/mach_exc_user_darwin.c | 0 .../delve/pkg/proc/native/nonative_darwin.go | 18 +- .../delve/pkg/proc/native/proc.go | 63 +- .../delve/pkg/proc/native/proc_darwin.c | 0 .../delve/pkg/proc/native/proc_darwin.go | 19 +- .../delve/pkg/proc/native/proc_darwin.h | 0 .../delve/pkg/proc/native/proc_linux.go | 92 ++- .../delve/pkg/proc/native/proc_windows.go | 48 +- .../delve/pkg/proc/native/ptrace_darwin.go | 0 .../delve/pkg/proc/native/ptrace_linux.go | 13 +- .../pkg/proc/native/registers_darwin_amd64.go | 8 +- .../pkg/proc/native/registers_linux_amd64.go | 87 +++ .../proc/native/registers_windows_amd64.go | 71 ++ .../delve/pkg/proc/native/syscall_windows.go | 7 + .../pkg/proc/native/syscall_windows_amd64.go | 24 + .../delve/pkg/proc/native/threads.go | 2 +- .../delve/pkg/proc/native/threads_darwin.c | 0 .../delve/pkg/proc/native/threads_darwin.go | 2 +- .../delve/pkg/proc/native/threads_darwin.h | 0 .../delve/pkg/proc/native/threads_linux.go | 13 +- .../delve/pkg/proc/native/threads_windows.go | 7 +- .../delve/pkg/proc/native/zsyscall_windows.go | 0 .../delve/pkg/proc/proc.go | 206 +++++- .../delve/pkg/proc/registers.go | 98 +-- .../delve/pkg/proc/registers_amd64.go | 2 +- .../delve/pkg/proc/stack.go | 82 ++- .../delve/pkg/proc/threads.go | 58 +- .../delve/pkg/proc/types.go | 79 +- .../delve/pkg/proc/variables.go | 178 ++++- .../delve/pkg/proc/winutil/regs.go} | 266 ++++--- .../delve/pkg/terminal/command.go | 219 ++++-- .../delve/pkg/terminal/config.go | 2 +- .../delve/pkg/terminal/disasmprint.go | 2 +- .../delve/pkg/terminal/docgen.go | 4 +- .../delve/pkg/terminal/terminal.go | 32 +- .../delve/pkg/terminal/terminal_other.go | 0 .../delve/pkg/terminal/terminal_windows.go | 0 .../delve/pkg/version/version.go | 4 +- .../delve/service/api/conversions.go | 16 +- .../delve/service/api/prettyprint.go | 21 +- .../delve/service/api/types.go | 31 +- .../delve/service/client.go | 12 +- .../delve/service/config.go | 4 + .../delve/service/debugger/debugger.go | 143 +++- .../delve/service/debugger/debugger_darwin.go | 0 .../delve/service/debugger/debugger_linux.go | 0 .../service/debugger/debugger_windows.go | 0 .../delve/service/debugger/locations.go | 13 +- .../delve/service/listenerpipe.go | 0 .../delve/service/rpc1/client.go | 2 +- .../delve/service/rpc1/readme.txtr | 0 .../delve/service/rpc1/server.go | 12 +- .../delve/service/rpc2/client.go | 38 +- .../delve/service/rpc2/server.go | 85 ++- .../delve/service/rpccallback.go | 0 .../delve/service/rpccommon/server.go | 34 +- .../delve/service/server.go | 0 vendor/github.com/lib/pq/oid/gen.go | 74 -- .../github.com/mattn/go-colorable/README.md | 48 ++ vendor/github.com/mattn/go-isatty/README.md | 50 ++ vendor/github.com/peterh/liner/README.md | 100 +++ .../github.com/sirupsen/logrus/CHANGELOG.md | 123 ++++ vendor/github.com/sirupsen/logrus/README.md | 461 ++++++++++++ .../github.com/sirupsen/logrus/appveyor.yml | 14 + vendor/golang.org/x/arch/x86/x86asm/Makefile | 3 + vendor/golang.org/x/sys/windows/aliases.go | 13 - .../x/sys/windows/asm_windows_arm.s | 11 - vendor/golang.org/x/sys/windows/service.go | 18 - .../x/sys/windows/syscall_windows.go | 60 +- .../golang.org/x/sys/windows/types_windows.go | 176 +---- .../x/sys/windows/types_windows_arm.go | 22 - .../x/sys/windows/zsyscall_windows.go | 2 +- vendor/vendor.json | 340 ++++----- 134 files changed, 4988 insertions(+), 2530 deletions(-) create mode 100644 vendor/github.com/astaxie/beego/LICENSE create mode 100644 vendor/github.com/cosiner/argv/README.md delete mode 100644 vendor/github.com/derekparker/delve/pkg/logflags/logflags.go delete mode 100644 vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.defs delete mode 100644 vendor/github.com/derekparker/delve/pkg/proc/native/registers_linux_amd64.go delete mode 100644 vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows_amd64.go rename vendor/github.com/{derekparker => go-delve}/delve/LICENSE (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/config/config.go (57%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/config/split.go (92%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/frame/entries.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/frame/expression_constants.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/frame/parser.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/frame/table.go (99%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/godwarf/sections.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/godwarf/type.go (80%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/line/line_parser.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/line/state_machine.go (99%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/op/op.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/op/opcodes.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/op/opcodes.table (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/op/regs.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/reader/reader.go (99%) mode change 100755 => 100644 rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/reader/variables.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/util/buf.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/dwarf/util/util.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/goversion/go_version.go (100%) create mode 100644 vendor/github.com/go-delve/delve/pkg/logflags/logflags.go rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/arch.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/bininfo.go (83%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/breakpoints.go (95%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/core/core.go (85%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/core/linux_amd64_core.go (59%) create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/core/minidump/fileflags_string.go create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/core/minidump/minidump.go create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/core/windows_amd64_minidump.go rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/disasm.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/disasm_amd64.go (95%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/doc.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/eval.go (96%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/fncall.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/gdbserial/gdbserver.go (92%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/gdbserial/gdbserver_conn.go (99%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/gdbserial/gdbserver_unix.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/gdbserial/gdbserver_windows.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/gdbserial/rr.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/interface.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/linutil/auxv.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/linutil/doc.go (100%) create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/linutil/dynamic.go create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/linutil/regs.go rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/mem.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/moduledata.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/exc.h (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/exc_user_darwin.c (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/exec_darwin.c (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/exec_darwin.h (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/mach_exc.h (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/mach_exc_user_darwin.c (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/nonative_darwin.go (84%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/proc.go (89%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/proc_darwin.c (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/proc_darwin.go (96%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/proc_darwin.h (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/proc_linux.go (90%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/proc_windows.go (93%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/ptrace_darwin.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/ptrace_linux.go (84%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/registers_darwin_amd64.go (98%) create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/native/registers_linux_amd64.go create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/native/registers_windows_amd64.go rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/syscall_windows.go (93%) create mode 100644 vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows_amd64.go rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/threads.go (99%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/threads_darwin.c (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/threads_darwin.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/threads_darwin.h (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/threads_linux.go (88%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/threads_windows.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/native/zsyscall_windows.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/proc.go (74%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/registers.go (70%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/registers_amd64.go (98%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/stack.go (89%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/threads.go (91%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/types.go (95%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/proc/variables.go (90%) rename vendor/github.com/{derekparker/delve/pkg/proc/native/registers_windows_amd64.go => go-delve/delve/pkg/proc/winutil/regs.go} (68%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/command.go (89%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/config.go (99%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/disasmprint.go (93%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/docgen.go (85%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/terminal.go (92%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/terminal_other.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/terminal/terminal_windows.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/pkg/version/version.go (81%) rename vendor/github.com/{derekparker => go-delve}/delve/service/api/conversions.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/service/api/prettyprint.go (93%) rename vendor/github.com/{derekparker => go-delve}/delve/service/api/types.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/service/client.go (94%) rename vendor/github.com/{derekparker => go-delve}/delve/service/config.go (90%) rename vendor/github.com/{derekparker => go-delve}/delve/service/debugger/debugger.go (88%) rename vendor/github.com/{derekparker => go-delve}/delve/service/debugger/debugger_darwin.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/service/debugger/debugger_linux.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/service/debugger/debugger_windows.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/service/debugger/locations.go (96%) rename vendor/github.com/{derekparker => go-delve}/delve/service/listenerpipe.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpc1/client.go (99%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpc1/readme.txtr (100%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpc1/server.go (96%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpc2/client.go (88%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpc2/server.go (86%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpccallback.go (100%) rename vendor/github.com/{derekparker => go-delve}/delve/service/rpccommon/server.go (93%) rename vendor/github.com/{derekparker => go-delve}/delve/service/server.go (100%) delete mode 100644 vendor/github.com/lib/pq/oid/gen.go create mode 100644 vendor/github.com/mattn/go-colorable/README.md create mode 100644 vendor/github.com/mattn/go-isatty/README.md create mode 100644 vendor/github.com/peterh/liner/README.md create mode 100644 vendor/github.com/sirupsen/logrus/CHANGELOG.md create mode 100644 vendor/github.com/sirupsen/logrus/README.md create mode 100644 vendor/github.com/sirupsen/logrus/appveyor.yml create mode 100644 vendor/golang.org/x/arch/x86/x86asm/Makefile delete mode 100644 vendor/golang.org/x/sys/windows/aliases.go delete mode 100644 vendor/golang.org/x/sys/windows/asm_windows_arm.s delete mode 100644 vendor/golang.org/x/sys/windows/types_windows_arm.go diff --git a/cmd/commands/dlv/dlv_amd64.go b/cmd/commands/dlv/dlv_amd64.go index 27870f9..328ef82 100644 --- a/cmd/commands/dlv/dlv_amd64.go +++ b/cmd/commands/dlv/dlv_amd64.go @@ -228,7 +228,7 @@ func startWatcher(paths []string, ch chan int) { // Wait 1s before re-build until there is no file change scheduleTime := time.Now().Add(1 * time.Second) - time.Sleep(scheduleTime.Sub(time.Now())) + time.Sleep(time.Until(scheduleTime)) _, err := buildDebug() if err != nil { utils.Notify("Build Failed: "+err.Error(), "bee") diff --git a/cmd/commands/run/watch.go b/cmd/commands/run/watch.go index be547cb..9c810cc 100644 --- a/cmd/commands/run/watch.go +++ b/cmd/commands/run/watch.go @@ -85,7 +85,7 @@ func NewWatcher(paths []string, files []string, isgenerate bool) { go func() { // Wait 1s before autobuild until there is no file change. scheduleTime = time.Now().Add(1 * time.Second) - time.Sleep(scheduleTime.Sub(time.Now())) + time.Sleep(time.Until(scheduleTime)) AutoBuild(files, isgenerate) if config.Conf.EnableReload { diff --git a/generate/swaggergen/g_docs.go b/generate/swaggergen/g_docs.go index 351a289..9d77b62 100644 --- a/generate/swaggergen/g_docs.go +++ b/generate/swaggergen/g_docs.go @@ -116,7 +116,7 @@ func ParsePackagesFromDir(dirpath string) { err = parsePackageFromDir(fpath) if err != nil { // Send the error to through the channel and continue walking - c <- fmt.Errorf("Error while parsing directory: %s", err.Error()) + c <- fmt.Errorf("error while parsing directory: %s", err.Error()) return nil } } diff --git a/utils/utils.go b/utils/utils.go index 13e50b1..75b6898 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -328,7 +328,7 @@ func CheckEnv(appname string) (apppath, packpath string, err error) { apppath = filepath.Join(gosrcpath, appname) if _, e := os.Stat(apppath); !os.IsNotExist(e) { - err = fmt.Errorf("Cannot create application without removing '%s' first", apppath) + err = fmt.Errorf("cannot create application without removing '%s' first", apppath) beeLogger.Log.Errorf("Path '%s' already exists", apppath) return } diff --git a/vendor/github.com/astaxie/beego/LICENSE b/vendor/github.com/astaxie/beego/LICENSE new file mode 100644 index 0000000..5dbd424 --- /dev/null +++ b/vendor/github.com/astaxie/beego/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 astaxie + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/cosiner/argv/README.md b/vendor/github.com/cosiner/argv/README.md new file mode 100644 index 0000000..7f2f8d2 --- /dev/null +++ b/vendor/github.com/cosiner/argv/README.md @@ -0,0 +1,31 @@ +# Argv + +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/cosiner/argv) +[![Build Status](https://travis-ci.org/cosiner/argv.svg?branch=master&style=flat)](https://travis-ci.org/cosiner/argv) +[![Coverage Status](https://coveralls.io/repos/github/cosiner/argv/badge.svg?style=flat)](https://coveralls.io/github/cosiner/argv) +[![Go Report Card](https://goreportcard.com/badge/github.com/cosiner/argv?style=flat)](https://goreportcard.com/report/github.com/cosiner/argv) + +Argv is a library for [Go](https://golang.org) to split command line string into arguments array. + +# Documentation +Documentation can be found at [Godoc](https://godoc.org/github.com/cosiner/argv) + +# Example +```Go +func TestArgv(t *testing.T) { + args, err := argv.Argv([]rune(" ls `echo /` | wc -l "), os.Environ(), argv.Run) + if err != nil { + t.Fatal(err) + } + expects := [][]string{ + []string{"ls", "/"}, + []string{"wc", "-l"}, + } + if !reflect.DeepDqual(args, expects) { + t.Fatal(args) + } +} +``` + +# LICENSE +MIT. diff --git a/vendor/github.com/derekparker/delve/pkg/logflags/logflags.go b/vendor/github.com/derekparker/delve/pkg/logflags/logflags.go deleted file mode 100644 index 9a99898..0000000 --- a/vendor/github.com/derekparker/delve/pkg/logflags/logflags.go +++ /dev/null @@ -1,83 +0,0 @@ -package logflags - -import ( - "errors" - "io/ioutil" - "log" - "strings" -) - -var debugger = false -var gdbWire = false -var lldbServerOutput = false -var debugLineErrors = false -var rpc = false -var fnCall = false - -// GdbWire returns true if the gdbserial package should log all the packets -// exchanged with the stub. -func GdbWire() bool { - return gdbWire -} - -// Debugger returns true if the debugger package should log. -func Debugger() bool { - return debugger -} - -// LLDBServerOutput returns true if the output of the LLDB server should be -// redirected to standard output instead of suppressed. -func LLDBServerOutput() bool { - return lldbServerOutput -} - -// DebugLineErrors returns true if pkg/dwarf/line should log its recoverable -// errors. -func DebugLineErrors() bool { - return debugLineErrors -} - -// RPC returns true if rpc messages should be logged. -func RPC() bool { - return rpc -} - -// FnCall returns true if the function call protocol should be logged. -func FnCall() bool { - return fnCall -} - -var errLogstrWithoutLog = errors.New("--log-output specified without --log") - -// Setup sets debugger flags based on the contents of logstr. -func Setup(logFlag bool, logstr string) error { - log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) - if !logFlag { - log.SetOutput(ioutil.Discard) - if logstr != "" { - return errLogstrWithoutLog - } - return nil - } - if logstr == "" { - logstr = "debugger" - } - v := strings.Split(logstr, ",") - for _, logcmd := range v { - switch logcmd { - case "debugger": - debugger = true - case "gdbwire": - gdbWire = true - case "lldbout": - lldbServerOutput = true - case "debuglineerr": - debugLineErrors = true - case "rpc": - rpc = true - case "fncall": - fnCall = true - } - } - return nil -} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.defs b/vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.defs deleted file mode 100644 index 00fae28..0000000 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/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/pkg/proc/native/registers_linux_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/native/registers_linux_amd64.go deleted file mode 100644 index eb3715a..0000000 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/registers_linux_amd64.go +++ /dev/null @@ -1,342 +0,0 @@ -package native - -import ( - "fmt" - - "golang.org/x/arch/x86/x86asm" - sys "golang.org/x/sys/unix" - - "github.com/derekparker/delve/pkg/proc" -) - -// Regs is a wrapper for sys.PtraceRegs. -type Regs struct { - regs *sys.PtraceRegs - fpregs []proc.Register - fpregset *proc.LinuxX86Xstate -} - -func (r *Regs) Slice() []proc.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([]proc.Register, 0, len(regs)+len(r.fpregs)) - for _, reg := range regs { - if reg.k == "Eflags" { - out = proc.AppendEflagReg(out, reg.k, reg.v) - } else { - out = proc.AppendQwordReg(out, reg.k, reg.v) - } - } - out = append(out, r.fpregs...) - return out -} - -// PC returns the value of RIP register. -func (r *Regs) PC() uint64 { - return r.regs.PC() -} - -// SP returns the value of RSP register. -func (r *Regs) SP() uint64 { - return r.regs.Rsp -} - -func (r *Regs) BP() uint64 { - return r.regs.Rbp -} - -// CX returns the value of RCX register. -func (r *Regs) CX() uint64 { - return r.regs.Rcx -} - -// TLS returns the address of the thread -// local storage memory segment. -func (r *Regs) TLS() uint64 { - return r.regs.Fs_base -} - -func (r *Regs) GAddr() (uint64, bool) { - return 0, false -} - -// SetPC sets RIP to the value specified by 'pc'. -func (thread *Thread) SetPC(pc uint64) error { - ir, err := registers(thread, false) - if err != nil { - return err - } - r := ir.(*Regs) - r.regs.SetPC(pc) - thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, r.regs) }) - return err -} - -// SetSP sets RSP to the value specified by 'sp' -func (thread *Thread) SetSP(sp uint64) (err error) { - var ir proc.Registers - ir, err = registers(thread, false) - if err != nil { - return err - } - r := ir.(*Regs) - r.regs.Rsp = sp - thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, r.regs) }) - return -} - -func (thread *Thread) SetDX(dx uint64) (err error) { - var ir proc.Registers - ir, err = registers(thread, false) - if err != nil { - return err - } - r := ir.(*Regs) - r.regs.Rdx = dx - thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, r.regs) }) - return -} - -func (r *Regs) Get(n int) (uint64, error) { - reg := x86asm.Reg(n) - const ( - mask8 = 0x000f - mask16 = 0x00ff - mask32 = 0xffff - ) - - switch reg { - // 8-bit - case x86asm.AL: - return r.regs.Rax & mask8, nil - case x86asm.CL: - return r.regs.Rcx & mask8, nil - case x86asm.DL: - return r.regs.Rdx & mask8, nil - case x86asm.BL: - return r.regs.Rbx & mask8, nil - case x86asm.AH: - return (r.regs.Rax >> 8) & mask8, nil - case x86asm.CH: - return (r.regs.Rcx >> 8) & mask8, nil - case x86asm.DH: - return (r.regs.Rdx >> 8) & mask8, nil - case x86asm.BH: - return (r.regs.Rbx >> 8) & mask8, nil - case x86asm.SPB: - return r.regs.Rsp & mask8, nil - case x86asm.BPB: - return r.regs.Rbp & mask8, nil - case x86asm.SIB: - return r.regs.Rsi & mask8, nil - case x86asm.DIB: - return r.regs.Rdi & mask8, nil - case x86asm.R8B: - return r.regs.R8 & mask8, nil - case x86asm.R9B: - return r.regs.R9 & mask8, nil - case x86asm.R10B: - return r.regs.R10 & mask8, nil - case x86asm.R11B: - return r.regs.R11 & mask8, nil - case x86asm.R12B: - return r.regs.R12 & mask8, nil - case x86asm.R13B: - return r.regs.R13 & mask8, nil - case x86asm.R14B: - return r.regs.R14 & mask8, nil - case x86asm.R15B: - return r.regs.R15 & mask8, nil - - // 16-bit - case x86asm.AX: - return r.regs.Rax & mask16, nil - case x86asm.CX: - return r.regs.Rcx & mask16, nil - case x86asm.DX: - return r.regs.Rdx & mask16, nil - case x86asm.BX: - return r.regs.Rbx & mask16, nil - case x86asm.SP: - return r.regs.Rsp & mask16, nil - case x86asm.BP: - return r.regs.Rbp & mask16, nil - case x86asm.SI: - return r.regs.Rsi & mask16, nil - case x86asm.DI: - return r.regs.Rdi & mask16, nil - case x86asm.R8W: - return r.regs.R8 & mask16, nil - case x86asm.R9W: - return r.regs.R9 & mask16, nil - case x86asm.R10W: - return r.regs.R10 & mask16, nil - case x86asm.R11W: - return r.regs.R11 & mask16, nil - case x86asm.R12W: - return r.regs.R12 & mask16, nil - case x86asm.R13W: - return r.regs.R13 & mask16, nil - case x86asm.R14W: - return r.regs.R14 & mask16, nil - case x86asm.R15W: - return r.regs.R15 & mask16, nil - - // 32-bit - case x86asm.EAX: - return r.regs.Rax & mask32, nil - case x86asm.ECX: - return r.regs.Rcx & mask32, nil - case x86asm.EDX: - return r.regs.Rdx & mask32, nil - case x86asm.EBX: - return r.regs.Rbx & mask32, nil - case x86asm.ESP: - return r.regs.Rsp & mask32, nil - case x86asm.EBP: - return r.regs.Rbp & mask32, nil - case x86asm.ESI: - return r.regs.Rsi & mask32, nil - case x86asm.EDI: - return r.regs.Rdi & mask32, nil - case x86asm.R8L: - return r.regs.R8 & mask32, nil - case x86asm.R9L: - return r.regs.R9 & mask32, nil - case x86asm.R10L: - return r.regs.R10 & mask32, nil - case x86asm.R11L: - return r.regs.R11 & mask32, nil - case x86asm.R12L: - return r.regs.R12 & mask32, nil - case x86asm.R13L: - return r.regs.R13 & mask32, nil - case x86asm.R14L: - return r.regs.R14 & mask32, nil - case x86asm.R15L: - return r.regs.R15 & mask32, nil - - // 64-bit - case x86asm.RAX: - return r.regs.Rax, nil - case x86asm.RCX: - return r.regs.Rcx, nil - case x86asm.RDX: - return r.regs.Rdx, nil - case x86asm.RBX: - return r.regs.Rbx, nil - case x86asm.RSP: - return r.regs.Rsp, nil - case x86asm.RBP: - return r.regs.Rbp, nil - case x86asm.RSI: - return r.regs.Rsi, nil - case x86asm.RDI: - return r.regs.Rdi, nil - case x86asm.R8: - return r.regs.R8, nil - case x86asm.R9: - return r.regs.R9, nil - case x86asm.R10: - return r.regs.R10, nil - case x86asm.R11: - return r.regs.R11, nil - case x86asm.R12: - return r.regs.R12, nil - case x86asm.R13: - return r.regs.R13, nil - case x86asm.R14: - return r.regs.R14, nil - case x86asm.R15: - return r.regs.R15, nil - } - - return 0, proc.ErrUnknownRegister -} - -func registers(thread *Thread, floatingPoint bool) (proc.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, nil} - if floatingPoint { - var fpregset proc.LinuxX86Xstate - r.fpregs, fpregset, err = thread.fpRegisters() - r.fpregset = &fpregset - if err != nil { - return nil, err - } - } - return r, nil -} - -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 []proc.Register, fpregs proc.LinuxX86Xstate, err error) { - thread.dbp.execPtraceFunc(func() { fpregs, err = PtraceGetRegset(thread.ID) }) - regs = fpregs.Decode() - if err != nil { - err = fmt.Errorf("could not get floating point registers: %v", err.Error()) - } - return -} - -// Copy returns a copy of these registers that is -// guarenteed not to change. -func (r *Regs) Copy() proc.Registers { - var rr Regs - rr.regs = &sys.PtraceRegs{} - rr.fpregset = &proc.LinuxX86Xstate{} - *(rr.regs) = *(r.regs) - if r.fpregset != nil { - *(rr.fpregset) = *(r.fpregset) - } - if r.fpregs != nil { - rr.fpregs = make([]proc.Register, len(r.fpregs)) - copy(rr.fpregs, r.fpregs) - } - return &rr -} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows_amd64.go b/vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows_amd64.go deleted file mode 100644 index 9740326..0000000 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows_amd64.go +++ /dev/null @@ -1,114 +0,0 @@ -package native - -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/LICENSE b/vendor/github.com/go-delve/delve/LICENSE similarity index 100% rename from vendor/github.com/derekparker/delve/LICENSE rename to vendor/github.com/go-delve/delve/LICENSE diff --git a/vendor/github.com/derekparker/delve/pkg/config/config.go b/vendor/github.com/go-delve/delve/pkg/config/config.go similarity index 57% rename from vendor/github.com/derekparker/delve/pkg/config/config.go rename to vendor/github.com/go-delve/delve/pkg/config/config.go index 297abac..59b9273 100644 --- a/vendor/github.com/derekparker/delve/pkg/config/config.go +++ b/vendor/github.com/go-delve/delve/pkg/config/config.go @@ -2,20 +2,23 @@ package config import ( "fmt" + "io" "io/ioutil" "os" "os/user" "path" + "runtime" "gopkg.in/yaml.v2" ) const ( - configDir string = ".dlv" - configFile string = "config.yml" + configDir string = "dlv" + configDirHidden string = ".dlv" + configFile string = "config.yml" ) -// Describes a rule for substitution of path to source code file. +// SubstitutePathRule 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 @@ -23,7 +26,7 @@ type SubstitutePathRule struct { To string } -// Slice of source code path substitution rules. +// SubstitutePathRules is a slice of source code path substitution rules. type SubstitutePathRules []SubstitutePathRule // Config defines all configuration options available to be set through the config file. @@ -43,10 +46,14 @@ type Config struct { // If ShowLocationExpr is true whatis will print the DWARF location // expression for its argument. ShowLocationExpr bool `yaml:"show-location-expr"` - + // Source list line-number color (3/4 bit color codes as defined // here: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) SourceListLineColor int `yaml:"source-list-line-color"` + + // DebugFileDirectories is the list of directories Delve will use + // in order to resolve external debug info files. + DebugInfoDirectories []string `yaml:"debug-info-directories"` } // LoadConfig attempts to populate a Config object from the config.yml file. @@ -54,12 +61,32 @@ func LoadConfig() *Config { err := createConfigPath() if err != nil { fmt.Printf("Could not create config directory: %v.", err) - return nil + return &Config{} } fullConfigFile, err := GetConfigFilePath(configFile) if err != nil { fmt.Printf("Unable to get config file path: %v.", err) - return nil + return &Config{} + } + + hasOldConfig, err := hasOldConfig() + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to determine if old config exists: %v\n", err) + } + + if hasOldConfig { + userHomeDir := getUserHomeDir() + oldLocation := path.Join(userHomeDir, configDirHidden) + if err := moveOldConfig(); err != nil { + fmt.Fprintf(os.Stderr, "Unable to move old config: %v\n", err) + return &Config{} + } + + if err := os.RemoveAll(oldLocation); err != nil { + fmt.Fprintf(os.Stderr, "Unable to remove old config location: %v\n", err) + return &Config{} + } + fmt.Fprintf(os.Stderr, "Successfully moved config from: %s to: %s\n", oldLocation, fullConfigFile) } f, err := os.Open(fullConfigFile) @@ -67,7 +94,7 @@ func LoadConfig() *Config { f, err = createDefaultConfig(fullConfigFile) if err != nil { fmt.Printf("Error creating default config file: %v", err) - return nil + return &Config{} } } defer func() { @@ -80,19 +107,25 @@ func LoadConfig() *Config { data, err := ioutil.ReadAll(f) if err != nil { fmt.Printf("Unable to read config data: %v.", err) - return nil + return &Config{} } var c Config err = yaml.Unmarshal(data, &c) if err != nil { fmt.Printf("Unable to decode config file: %v.", err) - return nil + return &Config{} + } + + if len(c.DebugInfoDirectories) == 0 { + c.DebugInfoDirectories = []string{"/usr/lib/debug/.build-id"} } return &c } +// SaveConfig will marshal and save the config struct +// to disk. func SaveConfig(conf *Config) error { fullConfigFile, err := GetConfigFilePath(configFile) if err != nil { @@ -114,15 +147,42 @@ func SaveConfig(conf *Config) error { return err } +// moveOldConfig attempts to move config to new location +// $HOME/.dlv to $XDG_CONFIG_HOME/dlv +func moveOldConfig() error { + if os.Getenv("XDG_CONFIG_HOME") == "" && runtime.GOOS != "linux" { + return nil + } + + userHomeDir := getUserHomeDir() + + p := path.Join(userHomeDir, configDirHidden, configFile) + _, err := os.Stat(p) + if err != nil { + return fmt.Errorf("unable to read config file located at: %s", p) + } + + newFile, err := GetConfigFilePath(configFile) + if err != nil { + return fmt.Errorf("unable to read config file located at: %s", err) + } + + if err := os.Rename(p, newFile); err != nil { + return fmt.Errorf("unable to move %s to %s", p, newFile) + } + return nil +} + func createDefaultConfig(path string) (*os.File, error) { f, err := os.Create(path) if err != nil { - return nil, fmt.Errorf("Unable to create config file: %v.", err) + return nil, fmt.Errorf("unable to create config file: %v", err) } err = writeDefaultConfig(f) if err != nil { - return nil, fmt.Errorf("Unable to write default configuration: %v.", err) + return nil, fmt.Errorf("unable to write default configuration: %v", err) } + f.Seek(0, io.SeekStart) return f, nil } @@ -158,6 +218,9 @@ substitute-path: # Uncomment the following line to make the whatis command also print the DWARF location expression of its argument. # show-location-expr: true + +# List of directories to use when searching for separate debug info files. +debug-info-directories: ["/usr/lib/debug/.build-id"] `) return err } @@ -173,9 +236,43 @@ func createConfigPath() error { // 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 + if configPath := os.Getenv("XDG_CONFIG_HOME"); configPath != "" { + return path.Join(configPath, configDir, file), nil } - return path.Join(usr.HomeDir, configDir, file), nil + + userHomeDir := getUserHomeDir() + + if runtime.GOOS == "linux" { + return path.Join(userHomeDir, ".config", configDir, file), nil + } + return path.Join(userHomeDir, configDirHidden, file), nil +} + +// Checks if the user has a config at the old location: $HOME/.dlv +func hasOldConfig() (bool, error) { + // If you don't have XDG_CONFIG_HOME set and aren't on Linux you have nothing to move + if os.Getenv("XDG_CONFIG_HOME") == "" && runtime.GOOS != "linux" { + return false, nil + } + + userHomeDir := getUserHomeDir() + + o := path.Join(userHomeDir, configDirHidden, configFile) + _, err := os.Stat(o) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + return true, nil +} + +func getUserHomeDir() string { + userHomeDir := "." + usr, err := user.Current() + if err == nil { + userHomeDir = usr.HomeDir + } + return userHomeDir } diff --git a/vendor/github.com/derekparker/delve/pkg/config/split.go b/vendor/github.com/go-delve/delve/pkg/config/split.go similarity index 92% rename from vendor/github.com/derekparker/delve/pkg/config/split.go rename to vendor/github.com/go-delve/delve/pkg/config/split.go index 6ab0e06..8279f22 100644 --- a/vendor/github.com/derekparker/delve/pkg/config/split.go +++ b/vendor/github.com/go-delve/delve/pkg/config/split.go @@ -5,7 +5,7 @@ import ( "unicode" ) -// Like strings.Fields but ignores spaces inside areas surrounded +// SplitQuotedFields is like strings.Fields but ignores spaces inside areas surrounded // by the specified quote character. // To specify a single quote use backslash to escape it: '\'' func SplitQuotedFields(in string, quote rune) []string { diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go b/vendor/github.com/go-delve/delve/pkg/dwarf/frame/entries.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/frame/entries.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go b/vendor/github.com/go-delve/delve/pkg/dwarf/frame/expression_constants.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/frame/expression_constants.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go b/vendor/github.com/go-delve/delve/pkg/dwarf/frame/parser.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/frame/parser.go index 550f412..122092c 100644 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/frame/parser.go @@ -7,7 +7,7 @@ import ( "bytes" "encoding/binary" - "github.com/derekparker/delve/pkg/dwarf/util" + "github.com/go-delve/delve/pkg/dwarf/util" ) type parsefunc func(*parseContext) parsefunc diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go b/vendor/github.com/go-delve/delve/pkg/dwarf/frame/table.go similarity index 99% rename from vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/frame/table.go index ff6621a..4857c37 100644 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/frame/table.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "fmt" - "github.com/derekparker/delve/pkg/dwarf/util" + "github.com/go-delve/delve/pkg/dwarf/util" ) type DWRule struct { diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/sections.go b/vendor/github.com/go-delve/delve/pkg/dwarf/godwarf/sections.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/sections.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/godwarf/sections.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/type.go b/vendor/github.com/go-delve/delve/pkg/dwarf/godwarf/type.go similarity index 80% rename from vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/type.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/godwarf/type.go index f46d7ba..631c6a5 100644 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/type.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/godwarf/type.go @@ -16,8 +16,8 @@ import ( "reflect" "strconv" - "github.com/derekparker/delve/pkg/dwarf/op" - "github.com/derekparker/delve/pkg/dwarf/util" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/util" ) const ( @@ -41,6 +41,20 @@ const ( encImaginaryFloat = 0x09 ) +const cyclicalTypeStop = "" // guard value printed for types with a cyclical definition, to avoid inifinite recursion in Type.String + +type recCheck map[dwarf.Offset]struct{} + +func (recCheck recCheck) acquire(off dwarf.Offset) (release func()) { + if _, rec := recCheck[off]; rec { + return nil + } + recCheck[off] = struct{}{} + return func() { + delete(recCheck, off) + } +} + // A Type conventionally represents a pointer to any of the // specific Type structures (CharType, StructType, etc.). //TODO: remove this use dwarf.Type @@ -48,6 +62,9 @@ type Type interface { Common() *CommonType String() string Size() int64 + + stringIntl(recCheck) string + sizeIntl(recCheck) int64 } // A CommonType holds fields common to multiple types. @@ -62,7 +79,8 @@ type CommonType struct { func (c *CommonType) Common() *CommonType { return c } -func (c *CommonType) Size() int64 { return c.ByteSize } +func (c *CommonType) Size() int64 { return c.ByteSize } +func (c *CommonType) sizeIntl(recCheck) int64 { return c.ByteSize } // Basic types @@ -75,7 +93,9 @@ type BasicType struct { func (b *BasicType) Basic() *BasicType { return b } -func (t *BasicType) String() string { +func (t *BasicType) String() string { return t.stringIntl(nil) } + +func (t *BasicType) stringIntl(recCheck) string { if t.Name != "" { return t.Name } @@ -136,9 +156,27 @@ type QualType struct { Type Type } -func (t *QualType) String() string { return t.Qual + " " + t.Type.String() } +func (t *QualType) String() string { return t.stringIntl(make(recCheck)) } -func (t *QualType) Size() int64 { return t.Type.Size() } +func (t *QualType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() + return t.Qual + " " + t.Type.stringIntl(recCheck) +} + +func (t *QualType) Size() int64 { return t.sizeIntl(make(recCheck)) } + +func (t *QualType) sizeIntl(recCheck recCheck) int64 { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return t.CommonType.ByteSize + } + defer release() + return t.Type.sizeIntl(recCheck) +} // An ArrayType represents a fixed size array type. type ArrayType struct { @@ -148,18 +186,36 @@ type ArrayType struct { Count int64 // if == -1, an incomplete array, like char x[]. } -func (t *ArrayType) String() string { - return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String() +func (t *ArrayType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *ArrayType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() + return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.stringIntl(recCheck) } -func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() } +func (t *ArrayType) Size() int64 { return t.sizeIntl(make(recCheck)) } + +func (t *ArrayType) sizeIntl(recCheck recCheck) int64 { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return t.CommonType.ByteSize + } + defer release() + return t.Count * t.Type.sizeIntl(recCheck) +} // A VoidType represents the C void type. type VoidType struct { CommonType } -func (t *VoidType) String() string { return "void" } +func (t *VoidType) String() string { return t.stringIntl(nil) } + +func (t *VoidType) stringIntl(recCheck) string { return "void" } // A PtrType represents a pointer type. type PtrType struct { @@ -167,7 +223,16 @@ type PtrType struct { Type Type } -func (t *PtrType) String() string { return "*" + t.Type.String() } +func (t *PtrType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *PtrType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() + return "*" + t.Type.stringIntl(recCheck) +} // A StructType represents a struct, union, or C++ class type. type StructType struct { @@ -189,14 +254,21 @@ type StructField struct { Embedded bool } -func (t *StructType) String() string { +func (t *StructType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *StructType) stringIntl(recCheck recCheck) string { if t.StructName != "" { return t.Kind + " " + t.StructName } - return t.Defn() + return t.Defn(recCheck) } -func (t *StructType) Defn() string { +func (t *StructType) Defn(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() s := t.Kind if t.StructName != "" { s += " " + t.StructName @@ -210,7 +282,7 @@ func (t *StructType) Defn() string { if i > 0 { s += "; " } - s += f.Name + " " + f.Type.String() + s += f.Name + " " + f.Type.stringIntl(recCheck) s += "@" + strconv.FormatInt(f.ByteOffset, 10) if f.BitSize > 0 { s += " : " + strconv.FormatInt(f.BitSize, 10) @@ -228,11 +300,18 @@ type SliceType struct { ElemType Type } -func (t *SliceType) String() string { +func (t *SliceType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *SliceType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() if t.Name != "" { return t.Name } - return "[]" + t.ElemType.String() + return "[]" + t.ElemType.stringIntl(recCheck) } // A StringType represents a Go string type. It looks like a StructType, describing @@ -241,7 +320,9 @@ type StringType struct { StructType } -func (t *StringType) String() string { +func (t *StringType) String() string { return t.stringIntl(nil) } + +func (t *StringType) stringIntl(recCheck recCheck) string { if t.Name != "" { return t.Name } @@ -253,7 +334,9 @@ type InterfaceType struct { TypedefType } -func (t *InterfaceType) String() string { +func (t *InterfaceType) String() string { return t.stringIntl(nil) } + +func (t *InterfaceType) stringIntl(recCheck recCheck) string { if t.Name != "" { return t.Name } @@ -275,7 +358,9 @@ type EnumValue struct { Val int64 } -func (t *EnumType) String() string { +func (t *EnumType) String() string { return t.stringIntl(nil) } + +func (t *EnumType) stringIntl(recCheck recCheck) string { s := "enum" if t.EnumName != "" { s += " " + t.EnumName @@ -298,17 +383,24 @@ type FuncType struct { ParamType []Type } -func (t *FuncType) String() string { +func (t *FuncType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *FuncType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() s := "func(" for i, t := range t.ParamType { if i > 0 { s += ", " } - s += t.String() + s += t.stringIntl(recCheck) } s += ")" if t.ReturnType != nil { - s += " " + t.ReturnType.String() + s += " " + t.ReturnType.stringIntl(recCheck) } return s } @@ -318,7 +410,9 @@ type DotDotDotType struct { CommonType } -func (t *DotDotDotType) String() string { return "..." } +func (t *DotDotDotType) String() string { return t.stringIntl(nil) } + +func (t *DotDotDotType) stringIntl(recCheck recCheck) string { return "..." } // A TypedefType represents a named type. type TypedefType struct { @@ -326,9 +420,20 @@ type TypedefType struct { Type Type } -func (t *TypedefType) String() string { return t.Name } +func (t *TypedefType) String() string { return t.stringIntl(nil) } -func (t *TypedefType) Size() int64 { return t.Type.Size() } +func (t *TypedefType) stringIntl(recCheck recCheck) string { return t.Name } + +func (t *TypedefType) Size() int64 { return t.sizeIntl(make(recCheck)) } + +func (t *TypedefType) sizeIntl(recCheck recCheck) int64 { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return t.CommonType.ByteSize + } + defer release() + return t.Type.sizeIntl(recCheck) +} // A MapType represents a Go map type. It looks like a TypedefType, describing // the runtime-internal structure, with extra fields. @@ -338,7 +443,14 @@ type MapType struct { ElemType Type } -func (t *MapType) String() string { +func (t *MapType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *MapType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() if t.Name != "" { return t.Name } @@ -351,7 +463,14 @@ type ChanType struct { ElemType Type } -func (t *ChanType) String() string { +func (t *ChanType) String() string { return t.stringIntl(make(recCheck)) } + +func (t *ChanType) stringIntl(recCheck recCheck) string { + release := recCheck.acquire(t.CommonType.Offset) + if release == nil { + return cyclicalTypeStop + } + defer release() if t.Name != "" { return t.Name } @@ -586,9 +705,10 @@ func readType(d *dwarf.Data, name string, r *dwarf.Reader, off dwarf.Offset, typ switch t.ReflectKind { case reflect.Slice: slice := new(SliceType) + typ = slice + typeCache[off] = slice slice.ElemType = typeOf(e, AttrGoElem) t = &slice.StructType - typ = slice case reflect.String: str := new(StringType) t = &str.StructType @@ -798,19 +918,22 @@ func readType(d *dwarf.Data, name string, r *dwarf.Reader, off dwarf.Offset, typ switch t.ReflectKind { case reflect.Map: m := new(MapType) + typ = m + typeCache[off] = typ m.KeyType = typeOf(e, AttrGoKey) m.ElemType = typeOf(e, AttrGoElem) t = &m.TypedefType - typ = m case reflect.Chan: c := new(ChanType) + typ = c + typeCache[off] = typ c.ElemType = typeOf(e, AttrGoElem) t = &c.TypedefType - typ = c case reflect.Interface: it := new(InterfaceType) - t = &it.TypedefType typ = it + typeCache[off] = it + t = &it.TypedefType default: typ = t } @@ -876,3 +999,13 @@ func zeroArray(t Type) { t = at.Type } } + +func resolveTypedef(typ Type) Type { + for { + if tt, ok := typ.(*TypedefType); ok { + typ = tt.Type + } else { + return typ + } + } +} diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go b/vendor/github.com/go-delve/delve/pkg/dwarf/line/line_parser.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/line/line_parser.go index 92554ff..b69c502 100644 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/line/line_parser.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "path/filepath" - "github.com/derekparker/delve/pkg/dwarf/util" + "github.com/go-delve/delve/pkg/dwarf/util" ) type DebugLinePrologue struct { diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go b/vendor/github.com/go-delve/delve/pkg/dwarf/line/state_machine.go similarity index 99% rename from vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/line/state_machine.go index 30b77a8..da92487 100644 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/line/state_machine.go @@ -7,7 +7,7 @@ import ( "fmt" "io" - "github.com/derekparker/delve/pkg/dwarf/util" + "github.com/go-delve/delve/pkg/dwarf/util" ) type Location struct { diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go b/vendor/github.com/go-delve/delve/pkg/dwarf/op/op.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/op/op.go index 7cc4fe3..89af5a6 100644 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/op/op.go @@ -7,7 +7,7 @@ import ( "fmt" "io" - "github.com/derekparker/delve/pkg/dwarf/util" + "github.com/go-delve/delve/pkg/dwarf/util" ) type Opcode byte diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/op/opcodes.go b/vendor/github.com/go-delve/delve/pkg/dwarf/op/opcodes.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/op/opcodes.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/op/opcodes.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/op/opcodes.table b/vendor/github.com/go-delve/delve/pkg/dwarf/op/opcodes.table similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/op/opcodes.table rename to vendor/github.com/go-delve/delve/pkg/dwarf/op/opcodes.table diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/op/regs.go b/vendor/github.com/go-delve/delve/pkg/dwarf/op/regs.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/op/regs.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/op/regs.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go b/vendor/github.com/go-delve/delve/pkg/dwarf/reader/reader.go old mode 100755 new mode 100644 similarity index 99% rename from vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/reader/reader.go index bf17b3e..4f19b08 --- a/vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go +++ b/vendor/github.com/go-delve/delve/pkg/dwarf/reader/reader.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/derekparker/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/op" ) type Reader struct { diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/reader/variables.go b/vendor/github.com/go-delve/delve/pkg/dwarf/reader/variables.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/reader/variables.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/reader/variables.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/util/buf.go b/vendor/github.com/go-delve/delve/pkg/dwarf/util/buf.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/util/buf.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/util/buf.go diff --git a/vendor/github.com/derekparker/delve/pkg/dwarf/util/util.go b/vendor/github.com/go-delve/delve/pkg/dwarf/util/util.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/dwarf/util/util.go rename to vendor/github.com/go-delve/delve/pkg/dwarf/util/util.go diff --git a/vendor/github.com/derekparker/delve/pkg/goversion/go_version.go b/vendor/github.com/go-delve/delve/pkg/goversion/go_version.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/goversion/go_version.go rename to vendor/github.com/go-delve/delve/pkg/goversion/go_version.go diff --git a/vendor/github.com/go-delve/delve/pkg/logflags/logflags.go b/vendor/github.com/go-delve/delve/pkg/logflags/logflags.go new file mode 100644 index 0000000..0e1aad7 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/logflags/logflags.go @@ -0,0 +1,227 @@ +package logflags + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "sort" + "strconv" + "strings" + "time" + + "github.com/sirupsen/logrus" +) + +var debugger = false +var gdbWire = false +var lldbServerOutput = false +var debugLineErrors = false +var rpc = false +var fnCall = false +var minidump = false + +var logOut io.WriteCloser + +func makeLogger(flag bool, fields logrus.Fields) *logrus.Entry { + logger := logrus.New().WithFields(fields) + logger.Logger.Formatter = &textFormatter{} + if logOut != nil { + logger.Logger.Out = logOut + } + logger.Logger.Level = logrus.DebugLevel + if !flag { + logger.Logger.Level = logrus.PanicLevel + } + return logger +} + +// GdbWire returns true if the gdbserial package should log all the packets +// exchanged with the stub. +func GdbWire() bool { + return gdbWire +} + +// GdbWireLogger returns a configured logger for the gdbserial wire protocol. +func GdbWireLogger() *logrus.Entry { + return makeLogger(gdbWire, logrus.Fields{"layer": "gdbconn"}) +} + +// Debugger returns true if the debugger package should log. +func Debugger() bool { + return debugger +} + +// DebuggerLogger returns a logger for the debugger package. +func DebuggerLogger() *logrus.Entry { + return makeLogger(debugger, logrus.Fields{"layer": "debugger"}) +} + +// LLDBServerOutput returns true if the output of the LLDB server should be +// redirected to standard output instead of suppressed. +func LLDBServerOutput() bool { + return lldbServerOutput +} + +// DebugLineErrors returns true if pkg/dwarf/line should log its recoverable +// errors. +func DebugLineErrors() bool { + return debugLineErrors +} + +// RPC returns true if RPC messages should be logged. +func RPC() bool { + return rpc +} + +// RPCLogger returns a logger for RPC messages. +func RPCLogger() *logrus.Entry { + return makeLogger(rpc, logrus.Fields{"layer": "rpc"}) +} + +// FnCall returns true if the function call protocol should be logged. +func FnCall() bool { + return fnCall +} + +func FnCallLogger() *logrus.Entry { + return makeLogger(fnCall, logrus.Fields{"layer": "proc", "kind": "fncall"}) +} + +// Minidump returns true if the minidump loader should be logged. +func Minidump() bool { + return minidump +} + +func MinidumpLogger() *logrus.Entry { + return makeLogger(minidump, logrus.Fields{"layer": "core", "kind": "minidump"}) +} + +// WriteAPIListeningMessage writes the "API server listening" message in headless mode. +func WriteAPIListeningMessage(addr string) { + if logOut != nil { + fmt.Fprintf(logOut, "API server listening at: %s\n", addr) + } else { + fmt.Printf("API server listening at: %s\n", addr) + } +} + +var errLogstrWithoutLog = errors.New("--log-output specified without --log") + +// Setup sets debugger flags based on the contents of logstr. +// If logDest is not empty logs will be redirected to the file descriptor or +// file path specified by logDest. +func Setup(logFlag bool, logstr string, logDest string) error { + if logDest != "" { + n, err := strconv.Atoi(logDest) + if err == nil { + logOut = os.NewFile(uintptr(n), "delve-logs") + } else { + fh, err := os.Create(logDest) + if err != nil { + return fmt.Errorf("could not create log file: %v", err) + } + logOut = fh + } + } + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + if !logFlag { + log.SetOutput(ioutil.Discard) + if logstr != "" { + return errLogstrWithoutLog + } + return nil + } + if logstr == "" { + logstr = "debugger" + } + v := strings.Split(logstr, ",") + for _, logcmd := range v { + switch logcmd { + case "debugger": + debugger = true + case "gdbwire": + gdbWire = true + case "lldbout": + lldbServerOutput = true + case "debuglineerr": + debugLineErrors = true + case "rpc": + rpc = true + case "fncall": + fnCall = true + case "minidump": + minidump = true + } + } + return nil +} + +// Close closes the logger output. +func Close() { + if logOut != nil { + logOut.Close() + } +} + +// textFormatter is a simplified version of logrus.TextFormatter that +// doesn't make logs unreadable when they are output to a text file or to a +// terminal that doesn't support colors. +type textFormatter struct { +} + +func (f *textFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + keys := make([]string, 0, len(entry.Data)) + for k := range entry.Data { + keys = append(keys, k) + } + sort.Strings(keys) + + b.WriteString(entry.Time.Format(time.RFC3339)) + b.WriteByte(' ') + b.WriteString(entry.Level.String()) + b.WriteByte(' ') + for i, key := range keys { + b.WriteString(key) + b.WriteByte('=') + stringVal, ok := entry.Data[key].(string) + if !ok { + stringVal = fmt.Sprint(entry.Data[key]) + } + if f.needsQuoting(stringVal) { + fmt.Fprintf(b, "%q", stringVal) + } else { + b.WriteString(stringVal) + } + if i != len(keys)-1 { + b.WriteByte(',') + } else { + b.WriteByte(' ') + } + } + b.WriteString(entry.Message) + b.WriteByte('\n') + return b.Bytes(), nil +} + +func (f *textFormatter) needsQuoting(text string) bool { + for _, ch := range text { + if !((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') { + return true + } + } + return false +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/arch.go b/vendor/github.com/go-delve/delve/pkg/proc/arch.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/proc/arch.go rename to vendor/github.com/go-delve/delve/pkg/proc/arch.go index 5d92463..cdb20e7 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/arch.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/arch.go @@ -3,8 +3,8 @@ package proc import ( "encoding/binary" - "github.com/derekparker/delve/pkg/dwarf/frame" - "github.com/derekparker/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/frame" + "github.com/go-delve/delve/pkg/dwarf/op" "golang.org/x/arch/x86/x86asm" ) @@ -284,7 +284,7 @@ func (a *AMD64) RegistersToDwarfRegisters(regs Registers, staticBase uint64) op. } } - for _, reg := range regs.Slice() { + for _, reg := range regs.Slice(true) { for dwarfReg, regName := range amd64DwarfToName { if regName == reg.Name { dregs[dwarfReg] = op.DwarfRegisterFromBytes(reg.Bytes) diff --git a/vendor/github.com/derekparker/delve/pkg/proc/bininfo.go b/vendor/github.com/go-delve/delve/pkg/proc/bininfo.go similarity index 83% rename from vendor/github.com/derekparker/delve/pkg/proc/bininfo.go rename to vendor/github.com/go-delve/delve/pkg/proc/bininfo.go index d5d3f96..fbc4f2e 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/bininfo.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/bininfo.go @@ -12,40 +12,30 @@ import ( "fmt" "io" "os" + "path/filepath" "sort" "strings" "sync" "time" - "github.com/derekparker/delve/pkg/dwarf/frame" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/dwarf/line" - "github.com/derekparker/delve/pkg/dwarf/op" - "github.com/derekparker/delve/pkg/dwarf/reader" - "github.com/derekparker/delve/pkg/goversion" + "github.com/go-delve/delve/pkg/dwarf/frame" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/line" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/goversion" ) -// BinaryInfo holds information on the binary being executed. +// BinaryInfo holds information on the binaries being executed (this +// includes both the executable and also any loaded libraries). type BinaryInfo struct { - lastModified time.Time // Time the executable of this process was last modified + // Path on disk of the binary being executed. + Path string + // Architecture of this binary. + Arch Arch - GOOS string - closer io.Closer - sepDebugCloser io.Closer - - staticBase uint64 - - // Maps package names to package paths, needed to lookup types inside DWARF info - packageMap map[string]string - - Arch Arch - dwarf *dwarf.Data - frameEntries frame.FrameDescriptionEntries - loclist loclistReader - compileUnits []*compileUnit - types map[string]dwarf.Offset - packageVars []packageVar // packageVars is a list of all global/package variables in debug_info, sorted by address - gStructOffset uint64 + // GOOS operating system this binary is executing on. + GOOS string // Functions is a list of all DW_TAG_subprogram entries in debug_info, sorted by entry point Functions []Function @@ -54,7 +44,32 @@ type BinaryInfo struct { // LookupFunc maps function names to a description of the function. LookupFunc map[string]*Function - typeCache map[dwarf.Offset]godwarf.Type + // Images is a list of loaded shared libraries (also known as + // shared objects on linux or DLLs on windws). + Images []*Image + + ElfDynamicSection ElfDynamicSection + + lastModified time.Time // Time the executable of this process was last modified + + closer io.Closer + sepDebugCloser io.Closer + + staticBase uint64 + + // Maps package names to package paths, needed to lookup types inside DWARF info + packageMap map[string]string + + dwarf *dwarf.Data + dwarfReader *dwarf.Reader + frameEntries frame.FrameDescriptionEntries + loclist loclistReader + compileUnits []*compileUnit + types map[string]dwarf.Offset + packageVars []packageVar // packageVars is a list of all global/package variables in debug_info, sorted by address + typeCache map[dwarf.Offset]godwarf.Type + + gStructOffset uint64 loadModuleDataOnce sync.Once moduleData []moduleData @@ -71,8 +86,6 @@ type BinaryInfo struct { loadErrMu sync.Mutex loadErr error - - dwarfReader *dwarf.Reader } // ErrUnsupportedLinuxArch is returned when attempting to debug a binary compiled for an unsupported architecture. @@ -84,14 +97,20 @@ var ErrUnsupportedWindowsArch = errors.New("unsupported architecture of windows/ // ErrUnsupportedDarwinArch is returned when attempting to debug a binary compiled for an unsupported architecture. var ErrUnsupportedDarwinArch = errors.New("unsupported architecture - only darwin/amd64 is supported") +// ErrCouldNotDetermineRelocation is an error returned when Delve could not determine the base address of a +// position independant executable. var ErrCouldNotDetermineRelocation = errors.New("could not determine the base address of a PIE") +// ErrNoDebugInfoFound is returned when Delve cannot open the debug_info +// section or find an external debug info file. +var ErrNoDebugInfoFound = errors.New("could not open debug info") + const dwarfGoLanguage = 22 // DW_LANG_Go (from DWARF v5, section 7.12, page 231) type compileUnit struct { - Name string // univocal name for non-go compile units - LowPC uint64 - Ranges [][2]uint64 + name string // univocal name for non-go compile units + lowPC uint64 + ranges [][2]uint64 entry *dwarf.Entry // debug_info entry describing this compile unit isgo bool // true if this is the go compile unit @@ -277,6 +296,12 @@ type buildIDHeader struct { Type uint32 } +// ElfDynamicSection describes the .dynamic section of an ELF executable. +type ElfDynamicSection struct { + Addr uint64 // relocated address of where the .dynamic section is mapped in memory + Size uint64 // size of the .dynamic section of the executable +} + // NewBinaryInfo returns an initialized but unloaded BinaryInfo struct. func NewBinaryInfo(goos, goarch string) *BinaryInfo { r := &BinaryInfo{GOOS: goos, nameOfRuntimeType: make(map[uintptr]nameOfRuntimeTypeEntry), typeCache: make(map[dwarf.Offset]godwarf.Type)} @@ -293,22 +318,24 @@ func NewBinaryInfo(goos, goarch string) *BinaryInfo { // LoadBinaryInfo will load and store the information from the binary at 'path'. // It is expected this will be called in parallel with other initialization steps // so a sync.WaitGroup must be provided. -func (bi *BinaryInfo) LoadBinaryInfo(path string, entryPoint uint64, wg *sync.WaitGroup) error { +func (bi *BinaryInfo) LoadBinaryInfo(path string, entryPoint uint64, debugInfoDirs []string) error { fi, err := os.Stat(path) if err == nil { bi.lastModified = fi.ModTime() } + var wg sync.WaitGroup + defer wg.Wait() + bi.Path = path switch bi.GOOS { case "linux": - return bi.LoadBinaryInfoElf(path, entryPoint, wg) + return bi.LoadBinaryInfoElf(path, entryPoint, debugInfoDirs, &wg) case "windows": - return bi.LoadBinaryInfoPE(path, entryPoint, wg) + return bi.LoadBinaryInfoPE(path, entryPoint, &wg) case "darwin": - return bi.LoadBinaryInfoMacho(path, entryPoint, wg) + return bi.LoadBinaryInfoMacho(path, entryPoint, &wg) } return errors.New("unsupported operating system") - return nil } // GStructOffset returns the offset of the G @@ -398,12 +425,35 @@ func (bi *BinaryInfo) PCToFunc(pc uint64) *Function { return nil } +// Image represents a loaded library file (shared object on linux, DLL on windows). +type Image struct { + Path string + addr uint64 +} + +// AddImage adds the specified image to bi. +func (bi *BinaryInfo) AddImage(path string, addr uint64) { + if !strings.HasPrefix(path, "/") { + return + } + for _, image := range bi.Images { + if image.Path == path && image.addr == addr { + return + } + } + //TODO(aarzilli): actually load informations about the image here + bi.Images = append(bi.Images, &Image{Path: path, addr: addr}) +} + // Close closes all internal readers. func (bi *BinaryInfo) Close() error { if bi.sepDebugCloser != nil { bi.sepDebugCloser.Close() } - return bi.closer.Close() + if bi.closer != nil { + return bi.closer.Close() + } + return nil } func (bi *BinaryInfo) setLoadError(fmtstr string, args ...interface{}) { @@ -488,7 +538,7 @@ func (bi *BinaryInfo) Location(entry reader.Entry, attr dwarf.Attr, pc uint64, r func (bi *BinaryInfo) loclistEntry(off int64, pc uint64) []byte { var base uint64 if cu := bi.findCompileUnit(pc); cu != nil { - base = cu.LowPC + base = cu.lowPC } bi.loclist.Seek(int(off)) @@ -509,7 +559,7 @@ func (bi *BinaryInfo) loclistEntry(off int64, pc uint64) []byte { // findCompileUnit returns the compile unit containing address pc. func (bi *BinaryInfo) findCompileUnit(pc uint64) *compileUnit { for _, cu := range bi.compileUnits { - for _, rng := range cu.Ranges { + for _, rng := range cu.ranges { if pc >= rng[0] && pc < rng[1] { return cu } @@ -558,35 +608,32 @@ func (e *ErrNoBuildIDNote) Error() string { // in GDB's documentation [1], and if found returns two handles, one // for the bare file, and another for its corresponding elf.File. // [1] https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html -func (bi *BinaryInfo) openSeparateDebugInfo(exe *elf.File) (*os.File, *elf.File, error) { - buildid := exe.Section(".note.gnu.build-id") - if buildid == nil { - return nil, nil, &ErrNoBuildIDNote{} +// +// Alternatively, if the debug file cannot be found be the build-id, Delve +// will look in directories specified by the debug-info-directories config value. +func (bi *BinaryInfo) openSeparateDebugInfo(exe *elf.File, debugInfoDirectories []string) (*os.File, *elf.File, error) { + var debugFilePath string + for _, dir := range debugInfoDirectories { + var potentialDebugFilePath string + if strings.Contains(dir, "build-id") { + desc1, desc2, err := parseBuildID(exe) + if err != nil { + continue + } + potentialDebugFilePath = fmt.Sprintf("%s/%s/%s.debug", dir, desc1, desc2) + } else { + potentialDebugFilePath = fmt.Sprintf("%s/%s.debug", dir, filepath.Base(bi.Path)) + } + _, err := os.Stat(potentialDebugFilePath) + if err == nil { + debugFilePath = potentialDebugFilePath + break + } } - - br := buildid.Open() - bh := new(buildIDHeader) - if err := binary.Read(br, binary.LittleEndian, bh); err != nil { - return nil, nil, errors.New("can't read build-id header: " + err.Error()) + if debugFilePath == "" { + return nil, nil, ErrNoDebugInfoFound } - - name := make([]byte, bh.Namesz) - if err := binary.Read(br, binary.LittleEndian, name); err != nil { - return nil, nil, errors.New("can't read build-id name: " + err.Error()) - } - - if strings.TrimSpace(string(name)) != "GNU\x00" { - return nil, nil, errors.New("invalid build-id signature") - } - - descBinary := make([]byte, bh.Descsz) - if err := binary.Read(br, binary.LittleEndian, descBinary); err != nil { - return nil, nil, errors.New("can't read build-id desc: " + err.Error()) - } - desc := hex.EncodeToString(descBinary) - - debugPath := fmt.Sprintf("/usr/lib/debug/.build-id/%s/%s.debug", desc[:2], desc[2:]) - sepFile, err := os.OpenFile(debugPath, 0, os.ModePerm) + sepFile, err := os.OpenFile(debugFilePath, 0, os.ModePerm) if err != nil { return nil, nil, errors.New("can't open separate debug file: " + err.Error()) } @@ -594,19 +641,48 @@ func (bi *BinaryInfo) openSeparateDebugInfo(exe *elf.File) (*os.File, *elf.File, elfFile, err := elf.NewFile(sepFile) if err != nil { sepFile.Close() - return nil, nil, fmt.Errorf("can't open separate debug file %q: %v", debugPath, err.Error()) + return nil, nil, fmt.Errorf("can't open separate debug file %q: %v", debugFilePath, err.Error()) } if elfFile.Machine != elf.EM_X86_64 { sepFile.Close() - return nil, nil, fmt.Errorf("can't open separate debug file %q: %v", debugPath, ErrUnsupportedLinuxArch.Error()) + return nil, nil, fmt.Errorf("can't open separate debug file %q: %v", debugFilePath, ErrUnsupportedLinuxArch.Error()) } return sepFile, elfFile, nil } +func parseBuildID(exe *elf.File) (string, string, error) { + buildid := exe.Section(".note.gnu.build-id") + if buildid == nil { + return "", "", &ErrNoBuildIDNote{} + } + + br := buildid.Open() + bh := new(buildIDHeader) + if err := binary.Read(br, binary.LittleEndian, bh); err != nil { + return "", "", errors.New("can't read build-id header: " + err.Error()) + } + + name := make([]byte, bh.Namesz) + if err := binary.Read(br, binary.LittleEndian, name); err != nil { + return "", "", errors.New("can't read build-id name: " + err.Error()) + } + + if strings.TrimSpace(string(name)) != "GNU\x00" { + return "", "", errors.New("invalid build-id signature") + } + + descBinary := make([]byte, bh.Descsz) + if err := binary.Read(br, binary.LittleEndian, descBinary); err != nil { + return "", "", errors.New("can't read build-id desc: " + err.Error()) + } + desc := hex.EncodeToString(descBinary) + return desc[:2], desc[2:], nil +} + // LoadBinaryInfoElf specifically loads information from an ELF binary. -func (bi *BinaryInfo) LoadBinaryInfoElf(path string, entryPoint uint64, wg *sync.WaitGroup) error { +func (bi *BinaryInfo) LoadBinaryInfoElf(path string, entryPoint uint64, debugInfoDirectories []string, wg *sync.WaitGroup) error { exe, err := os.OpenFile(path, 0, os.ModePerm) if err != nil { return err @@ -628,17 +704,19 @@ func (bi *BinaryInfo) LoadBinaryInfoElf(path string, entryPoint uint64, wg *sync } } + if dynsec := elfFile.Section(".dynamic"); dynsec != nil { + bi.ElfDynamicSection.Addr = dynsec.Addr + bi.staticBase + bi.ElfDynamicSection.Size = dynsec.Size + } + dwarfFile := elfFile bi.dwarf, err = elfFile.DWARF() if err != nil { var sepFile *os.File var serr error - sepFile, dwarfFile, serr = bi.openSeparateDebugInfo(elfFile) + sepFile, dwarfFile, serr = bi.openSeparateDebugInfo(elfFile, debugInfoDirectories) if serr != nil { - if _, ok := serr.(*ErrNoBuildIDNote); ok { - return err - } return serr } bi.sepDebugCloser = sepFile @@ -714,9 +792,16 @@ func (bi *BinaryInfo) setGStructOffsetElf(exe *elf.File, wg *sync.WaitGroup) { break } } + if tls == nil { + bi.gStructOffset = ^uint64(8) + 1 // -8 + return + } + memsz := tls.Memsz + + memsz = (memsz + uint64(bi.Arch.PtrSize()) - 1) & ^uint64(bi.Arch.PtrSize()-1) // align to pointer-sized-boundary // The TLS register points to the end of the TLS block, which is // tls.Memsz long. runtime.tlsg is an offset from the beginning of that block. - bi.gStructOffset = ^(tls.Memsz) + 1 + tlsg.Value // -tls.Memsz + tlsg.Value + bi.gStructOffset = ^(memsz) + 1 + tlsg.Value // -tls.Memsz + tlsg.Value } // PE //////////////////////////////////////////////////////////////// diff --git a/vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go b/vendor/github.com/go-delve/delve/pkg/proc/breakpoints.go similarity index 95% rename from vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go rename to vendor/github.com/go-delve/delve/pkg/proc/breakpoints.go index a374152..6623072 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/breakpoints.go @@ -30,7 +30,8 @@ type Breakpoint struct { Kind BreakpointKind // Breakpoint information - Tracepoint bool // Tracepoint flag + Tracepoint bool // Tracepoint flag + TraceReturn bool Goroutine bool // Retrieve goroutine information Stacktrace int // Number of stack frames to retrieve Variables []string // Variables to evaluate @@ -45,7 +46,7 @@ type Breakpoint struct { // 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. This ensures 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 @@ -220,13 +221,16 @@ func (bpmap *BreakpointMap) ResetBreakpointIDCounter() { bpmap.breakpointIDCounter = 0 } -type writeBreakpointFn func(addr uint64) (file string, line int, fn *Function, originalData []byte, err error) +// WriteBreakpointFn is a type that represents a function to be used for +// writting breakpoings into the target. +type WriteBreakpointFn func(addr uint64) (file string, line int, fn *Function, originalData []byte, err error) + type clearBreakpointFn func(*Breakpoint) error // Set creates a breakpoint at addr calling writeBreakpoint. Do not call this // function, call proc.Process.SetBreakpoint instead, this function exists // to implement proc.Process.SetBreakpoint. -func (bpmap *BreakpointMap) Set(addr uint64, kind BreakpointKind, cond ast.Expr, writeBreakpoint writeBreakpointFn) (*Breakpoint, error) { +func (bpmap *BreakpointMap) Set(addr uint64, kind BreakpointKind, cond ast.Expr, writeBreakpoint WriteBreakpointFn) (*Breakpoint, error) { if bp, ok := bpmap.M[addr]; ok { // We can overlap one internal breakpoint with one user breakpoint, we // need to support this otherwise a conditional breakpoint can mask a @@ -248,8 +252,13 @@ func (bpmap *BreakpointMap) Set(addr uint64, kind BreakpointKind, cond ast.Expr, return nil, err } + fnName := "" + if fn != nil { + fnName = fn.Name + } + newBreakpoint := &Breakpoint{ - FunctionName: fn.Name, + FunctionName: fnName, File: f, Line: l, Addr: addr, @@ -274,7 +283,7 @@ func (bpmap *BreakpointMap) Set(addr uint64, kind BreakpointKind, cond ast.Expr, } // SetWithID creates a breakpoint at addr, with the specified ID. -func (bpmap *BreakpointMap) SetWithID(id int, addr uint64, writeBreakpoint writeBreakpointFn) (*Breakpoint, error) { +func (bpmap *BreakpointMap) SetWithID(id int, addr uint64, writeBreakpoint WriteBreakpointFn) (*Breakpoint, error) { bp, err := bpmap.Set(addr, UserBreakpoint, nil, writeBreakpoint) if err == nil { bp.ID = id @@ -421,12 +430,6 @@ func (rbpi *returnBreakpointInfo) Collect(thread Thread) []*Variable { return (v.Flags & VariableReturnArgument) != 0 }) - // Go saves the return variables in the opposite order that the user - // specifies them so here we reverse the slice to make it easier to - // understand. - for i := 0; i < len(vars)/2; i++ { - vars[i], vars[len(vars)-i-1] = vars[len(vars)-i-1], vars[i] - } return vars } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/core/core.go b/vendor/github.com/go-delve/delve/pkg/proc/core/core.go similarity index 85% rename from vendor/github.com/derekparker/delve/pkg/proc/core/core.go rename to vendor/github.com/go-delve/delve/pkg/proc/core/core.go index 60043ee..52c685d 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/core/core.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/core/core.go @@ -5,9 +5,8 @@ import ( "fmt" "go/ast" "io" - "sync" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // A SplicedMemory represents a memory space formed from multiple regions, @@ -144,8 +143,13 @@ func (r *OffsetReaderAt) ReadMemory(buf []byte, addr uintptr) (n int, err error) // Process represents a core file. type Process struct { + mem proc.MemoryReader + Threads map[int]*Thread + pid int + + entryPoint uint64 + bi *proc.BinaryInfo - core *Core breakpoints proc.BreakpointMap currentThread *Thread selectedGoroutine *proc.G @@ -154,12 +158,16 @@ type Process struct { // Thread represents a thread in the core file being debugged. type Thread struct { - th *LinuxPrStatus - fpregs []proc.Register + th osThread p *Process common proc.CommonThread } +type osThread interface { + registers(floatingPoint bool) (proc.Registers, error) + pid() int +} + var ( // ErrWriteCore is returned when attempting to write to the core // process memory. @@ -175,45 +183,66 @@ var ( ErrChangeRegisterCore = errors.New("can not change register values of core process") ) +type openFn func(string, string) (*Process, error) + +var openFns = []openFn{readLinuxAMD64Core, readAMD64Minidump} + +// ErrUnrecognizedFormat is returned when the core file is not recognized as +// any of the supported formats. +var ErrUnrecognizedFormat = errors.New("unrecognized core format") + // OpenCore will open the core file and return a Process struct. -func OpenCore(corePath, exePath string) (*Process, error) { - core, err := readCore(corePath, exePath) - if err != nil { - return nil, err - } - p := &Process{ - core: core, - breakpoints: proc.NewBreakpointMap(), - bi: proc.NewBinaryInfo("linux", "amd64"), - } - for _, thread := range core.Threads { - thread.p = p - } - - var wg sync.WaitGroup - err = p.bi.LoadBinaryInfo(exePath, core.entryPoint, &wg) - wg.Wait() - if err == nil { - err = p.bi.LoadError() +// If the DWARF information cannot be found in the binary, Delve will look +// for external debug files in the directories passed in. +func OpenCore(corePath, exePath string, debugInfoDirs []string) (*Process, error) { + var p *Process + var err error + for _, openFn := range openFns { + p, err = openFn(corePath, exePath) + if err != ErrUnrecognizedFormat { + break + } } if err != nil { return nil, err } - for _, th := range p.core.Threads { - p.currentThread = th - break + if err := p.initialize(exePath, debugInfoDirs); err != nil { + return nil, err } - p.selectedGoroutine, _ = proc.GetG(p.CurrentThread()) return p, nil } +// initialize for core files doesn't do much +// aside from call the post initialization setup. +func (p *Process) initialize(path string, debugInfoDirs []string) error { + return proc.PostInitializationSetup(p, path, debugInfoDirs, p.writeBreakpoint) +} + // BinInfo will return the binary info. func (p *Process) BinInfo() *proc.BinaryInfo { return p.bi } +// SetSelectedGoroutine will set internally the goroutine that should be +// the default for any command executed, the goroutine being actively +// followed. +func (p *Process) SetSelectedGoroutine(g *proc.G) { + p.selectedGoroutine = g +} + +// EntryPoint will return the entry point address for this core file. +func (p *Process) EntryPoint() (uint64, error) { + return p.entryPoint, nil +} + +// writeBreakpoint is a noop function since you +// cannot write breakpoints into core files. +func (p *Process) writeBreakpoint(addr uint64) (file string, line int, fn *proc.Function, originalData []byte, err error) { + return "", 0, nil, nil, errors.New("cannot write a breakpoint to a core file") +} + // Recorded returns whether this is a live or recorded process. Always returns true for core files. func (p *Process) Recorded() (bool, string) { return true, "" } @@ -239,7 +268,7 @@ func (p *Process) ClearCheckpoint(int) error { return errors.New("checkpoint not // read memory into `data`, returning the length read, and returning an error if // the length read is shorter than the length of the `data` buffer. func (t *Thread) ReadMemory(data []byte, addr uintptr) (n int, err error) { - n, err = t.p.core.ReadMemory(data, addr) + n, err = t.p.mem.ReadMemory(data, addr) if err == nil && n != len(data) { err = ErrShortRead } @@ -255,8 +284,13 @@ func (t *Thread) WriteMemory(addr uintptr, data []byte) (int, error) { // Location returns the location of this thread based on // the value of the instruction pointer register. func (t *Thread) Location() (*proc.Location, error) { - f, l, fn := t.p.bi.PCToLine(t.th.Reg.Rip) - return &proc.Location{PC: t.th.Reg.Rip, File: f, Line: l, Fn: fn}, nil + regs, err := t.th.registers(false) + if err != nil { + return nil, err + } + pc := regs.PC() + f, l, fn := t.p.bi.PCToLine(pc) + return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil } // Breakpoint returns the current breakpoint this thread is stopped at. @@ -268,16 +302,12 @@ func (t *Thread) Breakpoint() proc.BreakpointState { // ThreadID returns the ID for this thread. func (t *Thread) ThreadID() int { - return int(t.th.Pid) + return int(t.th.pid()) } // Registers returns the current value of the registers for this thread. func (t *Thread) Registers(floatingPoint bool) (proc.Registers, error) { - r := &Registers{&t.th.Reg, nil} - if floatingPoint { - r.fpregs = t.fpregs - } - return r, nil + return t.th.registers(floatingPoint) } // RestoreRegisters will only return an error for core files, @@ -406,7 +436,7 @@ func (p *Process) Common() *proc.CommonProcess { // Pid returns the process ID of this process. func (p *Process) Pid() int { - return p.core.Pid + return p.pid } // ResumeNotify is a no-op on core files as we cannot @@ -444,7 +474,7 @@ func (p *Process) SwitchGoroutine(gid int) error { // SwitchThread will change the selected and active thread. func (p *Process) SwitchThread(tid int) error { - if th, ok := p.core.Threads[tid]; ok { + if th, ok := p.Threads[tid]; ok { p.currentThread = th p.selectedGoroutine, _ = proc.GetG(p.CurrentThread()) return nil @@ -454,8 +484,8 @@ func (p *Process) SwitchThread(tid int) error { // ThreadList will return a list of all threads currently in the process. func (p *Process) ThreadList() []proc.Thread { - r := make([]proc.Thread, 0, len(p.core.Threads)) - for _, v := range p.core.Threads { + r := make([]proc.Thread, 0, len(p.Threads)) + for _, v := range p.Threads { r = append(r, v) } return r @@ -463,64 +493,6 @@ func (p *Process) ThreadList() []proc.Thread { // FindThread will return the thread with the corresponding thread ID. func (p *Process) FindThread(threadID int) (proc.Thread, bool) { - t, ok := p.core.Threads[threadID] + t, ok := p.Threads[threadID] return t, ok } - -// Registers represents the CPU registers. -type Registers struct { - *LinuxCoreRegisters - fpregs []proc.Register -} - -// Slice will return a slice containing all registers and their values. -func (r *Registers) Slice() []proc.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}, - {"Orig_rax", r.Orig_rax}, - {"Cs", r.Cs}, - {"Eflags", r.Eflags}, - {"Ss", r.Ss}, - {"Fs_base", r.Fs_base}, - {"Gs_base", r.Gs_base}, - {"Ds", r.Ds}, - {"Es", r.Es}, - {"Fs", r.Fs}, - {"Gs", r.Gs}, - } - out := make([]proc.Register, 0, len(regs)) - for _, reg := range regs { - if reg.k == "Eflags" { - out = proc.AppendEflagReg(out, reg.k, reg.v) - } else { - out = proc.AppendQwordReg(out, reg.k, reg.v) - } - } - out = append(out, r.fpregs...) - return out -} - -// Copy will return a copy of the registers that is guarenteed -// not to change. -func (r *Registers) Copy() proc.Registers { - return r -} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/core/linux_amd64_core.go b/vendor/github.com/go-delve/delve/pkg/proc/core/linux_amd64_core.go similarity index 59% rename from vendor/github.com/derekparker/delve/pkg/proc/core/linux_amd64_core.go rename to vendor/github.com/go-delve/delve/pkg/proc/core/linux_amd64_core.go index 482a8a6..09b8dcc 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/core/linux_amd64_core.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/core/linux_amd64_core.go @@ -7,45 +7,12 @@ import ( "fmt" "io" "os" + "strings" - "golang.org/x/arch/x86/x86asm" - - "github.com/derekparker/delve/pkg/proc" - "github.com/derekparker/delve/pkg/proc/linutil" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" ) -// Copied from golang.org/x/sys/unix.PtraceRegs since it's not available on -// all systems. -type LinuxCoreRegisters struct { - R15 uint64 - R14 uint64 - R13 uint64 - R12 uint64 - Rbp uint64 - Rbx uint64 - R11 uint64 - R10 uint64 - R9 uint64 - R8 uint64 - Rax uint64 - Rcx uint64 - Rdx uint64 - Rsi uint64 - Rdi uint64 - Orig_rax uint64 - Rip uint64 - Cs uint64 - Eflags uint64 - Rsp uint64 - Ss uint64 - Fs_base uint64 - Gs_base uint64 - Ds uint64 - Es uint64 - Fs uint64 - Gs uint64 -} - // Copied from golang.org/x/sys/unix.Timeval since it's not available on all // systems. type LinuxCoreTimeval struct { @@ -62,207 +29,21 @@ const NT_X86_XSTATE elf.NType = 0x202 // Note type for notes containing X86 XSAV // NT_AUXV is the note type for notes containing a copy of the Auxv array const NT_AUXV elf.NType = 0x6 -// PC returns the value of RIP. -func (r *LinuxCoreRegisters) PC() uint64 { - return r.Rip -} +const elfErrorBadMagicNumber = "bad magic number" -// SP returns the value of RSP. -func (r *LinuxCoreRegisters) SP() uint64 { - return r.Rsp -} - -// BP returns the value of RBP. -func (r *LinuxCoreRegisters) BP() uint64 { - return r.Rbp -} - -// CX returns the value of RCX. -func (r *LinuxCoreRegisters) CX() uint64 { - return r.Rcx -} - -// TLS returns the location of the thread local storate, -// which will be the value of Fs_base. -func (r *LinuxCoreRegisters) TLS() uint64 { - return r.Fs_base -} - -// GAddr returns the address of the G struct. Always returns 0 -// and false for core files. -func (r *LinuxCoreRegisters) GAddr() (uint64, bool) { - return 0, false -} - -// Get returns the value of the register requested via the -// register number, returning an error if that register -// could not be found. -func (r *LinuxCoreRegisters) Get(n int) (uint64, error) { - reg := x86asm.Reg(n) - const ( - mask8 = 0x000f - mask16 = 0x00ff - mask32 = 0xffff - ) - - switch reg { - // 8-bit - case x86asm.AL: - return r.Rax & mask8, nil - case x86asm.CL: - return r.Rcx & mask8, nil - case x86asm.DL: - return r.Rdx & mask8, nil - case x86asm.BL: - return r.Rbx & mask8, nil - case x86asm.AH: - return (r.Rax >> 8) & mask8, nil - case x86asm.CH: - return (r.Rcx >> 8) & mask8, nil - case x86asm.DH: - return (r.Rdx >> 8) & mask8, nil - case x86asm.BH: - return (r.Rbx >> 8) & mask8, nil - case x86asm.SPB: - return r.Rsp & mask8, nil - case x86asm.BPB: - return r.Rbp & mask8, nil - case x86asm.SIB: - return r.Rsi & mask8, nil - case x86asm.DIB: - return r.Rdi & mask8, nil - case x86asm.R8B: - return r.R8 & mask8, nil - case x86asm.R9B: - return r.R9 & mask8, nil - case x86asm.R10B: - return r.R10 & mask8, nil - case x86asm.R11B: - return r.R11 & mask8, nil - case x86asm.R12B: - return r.R12 & mask8, nil - case x86asm.R13B: - return r.R13 & mask8, nil - case x86asm.R14B: - return r.R14 & mask8, nil - case x86asm.R15B: - return r.R15 & mask8, nil - - // 16-bit - case x86asm.AX: - return r.Rax & mask16, nil - case x86asm.CX: - return r.Rcx & mask16, nil - case x86asm.DX: - return r.Rdx & mask16, nil - case x86asm.BX: - return r.Rbx & mask16, nil - case x86asm.SP: - return r.Rsp & mask16, nil - case x86asm.BP: - return r.Rbp & mask16, nil - case x86asm.SI: - return r.Rsi & mask16, nil - case x86asm.DI: - return r.Rdi & mask16, nil - case x86asm.R8W: - return r.R8 & mask16, nil - case x86asm.R9W: - return r.R9 & mask16, nil - case x86asm.R10W: - return r.R10 & mask16, nil - case x86asm.R11W: - return r.R11 & mask16, nil - case x86asm.R12W: - return r.R12 & mask16, nil - case x86asm.R13W: - return r.R13 & mask16, nil - case x86asm.R14W: - return r.R14 & mask16, nil - case x86asm.R15W: - return r.R15 & mask16, nil - - // 32-bit - case x86asm.EAX: - return r.Rax & mask32, nil - case x86asm.ECX: - return r.Rcx & mask32, nil - case x86asm.EDX: - return r.Rdx & mask32, nil - case x86asm.EBX: - return r.Rbx & mask32, nil - case x86asm.ESP: - return r.Rsp & mask32, nil - case x86asm.EBP: - return r.Rbp & mask32, nil - case x86asm.ESI: - return r.Rsi & mask32, nil - case x86asm.EDI: - return r.Rdi & mask32, nil - case x86asm.R8L: - return r.R8 & mask32, nil - case x86asm.R9L: - return r.R9 & mask32, nil - case x86asm.R10L: - return r.R10 & mask32, nil - case x86asm.R11L: - return r.R11 & mask32, nil - case x86asm.R12L: - return r.R12 & mask32, nil - case x86asm.R13L: - return r.R13 & mask32, nil - case x86asm.R14L: - return r.R14 & mask32, nil - case x86asm.R15L: - return r.R15 & mask32, nil - - // 64-bit - case x86asm.RAX: - return r.Rax, nil - case x86asm.RCX: - return r.Rcx, nil - case x86asm.RDX: - return r.Rdx, nil - case x86asm.RBX: - return r.Rbx, nil - case x86asm.RSP: - return r.Rsp, nil - case x86asm.RBP: - return r.Rbp, nil - case x86asm.RSI: - return r.Rsi, nil - case x86asm.RDI: - return r.Rdi, nil - case x86asm.R8: - return r.R8, nil - case x86asm.R9: - return r.R9, nil - case x86asm.R10: - return r.R10, nil - case x86asm.R11: - return r.R11, nil - case x86asm.R12: - return r.R12, nil - case x86asm.R13: - return r.R13, nil - case x86asm.R14: - return r.R14, nil - case x86asm.R15: - return r.R15, nil - } - - return 0, proc.ErrUnknownRegister -} - -// readCore reads a core file from corePath corresponding to the executable at +// readLinuxAMD64Core reads a core file from corePath corresponding to the executable at // exePath. For details on the Linux ELF core format, see: // http://www.gabriel.urdhr.fr/2015/05/29/core-file/, // http://uhlo.blogspot.fr/2012/05/brief-look-into-core-dumps.html, // elf_core_dump in http://lxr.free-electrons.com/source/fs/binfmt_elf.c, // and, if absolutely desperate, readelf.c from the binutils source. -func readCore(corePath, exePath string) (*Core, error) { +func readLinuxAMD64Core(corePath, exePath string) (*Process, error) { coreFile, err := elf.Open(corePath) if err != nil { + if _, isfmterr := err.(*elf.FormatError); isfmterr && (strings.Contains(err.Error(), elfErrorBadMagicNumber) || strings.Contains(err.Error(), " at offset 0x0: too short")) { + // Go >=1.11 and <1.11 produce different errors when reading a non-elf file. + return nil, ErrUnrecognizedFormat + } return nil, err } exe, err := os.Open(exePath) @@ -288,37 +69,51 @@ func readCore(corePath, exePath string) (*Core, error) { memory := buildMemory(coreFile, exeELF, exe, notes) entryPoint := findEntryPoint(notes) - core := &Core{ - MemoryReader: memory, - Threads: map[int]*Thread{}, - entryPoint: entryPoint, + p := &Process{ + mem: memory, + Threads: map[int]*Thread{}, + entryPoint: entryPoint, + bi: proc.NewBinaryInfo("linux", "amd64"), + breakpoints: proc.NewBreakpointMap(), } - var lastThread *Thread + var lastThread *linuxAMD64Thread for _, note := range notes { switch note.Type { case elf.NT_PRSTATUS: t := note.Desc.(*LinuxPrStatus) - lastThread = &Thread{t, nil, nil, proc.CommonThread{}} - core.Threads[int(t.Pid)] = lastThread + lastThread = &linuxAMD64Thread{linutil.AMD64Registers{Regs: &t.Reg}, t} + p.Threads[int(t.Pid)] = &Thread{lastThread, p, proc.CommonThread{}} + if p.currentThread == nil { + p.currentThread = p.Threads[int(t.Pid)] + } case NT_X86_XSTATE: if lastThread != nil { - lastThread.fpregs = note.Desc.(*proc.LinuxX86Xstate).Decode() + lastThread.regs.Fpregs = note.Desc.(*linutil.AMD64Xstate).Decode() } case elf.NT_PRPSINFO: - core.Pid = int(note.Desc.(*LinuxPrPsInfo).Pid) + p.pid = int(note.Desc.(*LinuxPrPsInfo).Pid) } } - return core, nil + return p, nil } -// Core represents a core file. -type Core struct { - proc.MemoryReader - Threads map[int]*Thread - Pid int +type linuxAMD64Thread struct { + regs linutil.AMD64Registers + t *LinuxPrStatus +} - entryPoint uint64 +func (t *linuxAMD64Thread) registers(floatingPoint bool) (proc.Registers, error) { + var r linutil.AMD64Registers + r.Regs = t.regs.Regs + if floatingPoint { + r.Fpregs = t.regs.Fpregs + } + return &r, nil +} + +func (t *linuxAMD64Thread) pid() int { + return int(t.t.Pid) } // Note is a note from the PT_NOTE prog. @@ -415,8 +210,8 @@ func readNote(r io.ReadSeeker) (*Note, error) { } note.Desc = data case NT_X86_XSTATE: - var fpregs proc.LinuxX86Xstate - if err := proc.LinuxX86XstateRead(desc, true, &fpregs); err != nil { + var fpregs linutil.AMD64Xstate + if err := linutil.AMD64XstateRead(desc, true, &fpregs); err != nil { return nil, err } note.Desc = &fpregs @@ -516,7 +311,7 @@ type LinuxPrStatus struct { Sighold uint64 Pid, Ppid, Pgrp, Sid int32 Utime, Stime, CUtime, CStime LinuxCoreTimeval - Reg LinuxCoreRegisters + Reg linutil.AMD64PtraceRegs Fpvalid int32 } diff --git a/vendor/github.com/go-delve/delve/pkg/proc/core/minidump/fileflags_string.go b/vendor/github.com/go-delve/delve/pkg/proc/core/minidump/fileflags_string.go new file mode 100644 index 0000000..b69969e --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/core/minidump/fileflags_string.go @@ -0,0 +1,154 @@ +// Code generated by "stringer -type FileFlags,StreamType,Arch,MemoryState,MemoryType,MemoryProtection"; DO NOT EDIT. + +package minidump + +import "strconv" + +const _FileFlags_name = "FileNormalFileWithDataSegsFileWithFullMemoryFileWithHandleDataFileFilterMemoryFileScanMemoryFileWithUnloadedModulesFileWithIncorrectlyReferencedMemoryFileFilterModulePathsFileWithProcessThreadDataFileWithPrivateReadWriteMemoryFileWithoutOptionalDataFileWithFullMemoryInfoFileWithThreadInfoFileWithCodeSegsFileWithoutAuxilliarySegsFileWithFullAuxilliaryStateFileWithPrivateCopyMemoryFileIgnoreInaccessibleMemoryFileWithTokenInformation" + +var _FileFlags_map = map[FileFlags]string{ + 0: _FileFlags_name[0:10], + 1: _FileFlags_name[10:26], + 2: _FileFlags_name[26:44], + 4: _FileFlags_name[44:62], + 8: _FileFlags_name[62:78], + 16: _FileFlags_name[78:92], + 32: _FileFlags_name[92:115], + 64: _FileFlags_name[115:150], + 128: _FileFlags_name[150:171], + 256: _FileFlags_name[171:196], + 512: _FileFlags_name[196:226], + 1024: _FileFlags_name[226:249], + 2048: _FileFlags_name[249:271], + 4096: _FileFlags_name[271:289], + 8192: _FileFlags_name[289:305], + 16384: _FileFlags_name[305:330], + 32768: _FileFlags_name[330:357], + 65536: _FileFlags_name[357:382], + 131072: _FileFlags_name[382:410], + 262144: _FileFlags_name[410:434], +} + +func (i FileFlags) String() string { + if str, ok := _FileFlags_map[i]; ok { + return str + } + return "FileFlags(" + strconv.FormatInt(int64(i), 10) + ")" +} + +const _StreamType_name = "UnusedStreamReservedStream0ReservedStream1ThreadListStreamModuleListStreamMemoryListStreamExceptionStreamSystemInfoStreamThreadExListStreamMemory64ListStreamCommentStreamACommentStreamWHandleDataStreamFunctionTableStreamUnloadedModuleStreamMiscInfoStreamMemoryInfoListStreamThreadInfoListStreamHandleOperationListStreamTokenStreamJavascriptDataStreamSystemMemoryInfoStreamProcessVMCounterStream" + +var _StreamType_index = [...]uint16{0, 12, 27, 42, 58, 74, 90, 105, 121, 139, 157, 171, 185, 201, 220, 240, 254, 274, 294, 319, 330, 350, 372, 394} + +func (i StreamType) String() string { + if i >= StreamType(len(_StreamType_index)-1) { + return "StreamType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _StreamType_name[_StreamType_index[i]:_StreamType_index[i+1]] +} + +const ( + _Arch_name_0 = "CpuArchitectureX86CpuArchitectureMipsCpuArchitectureAlphaCpuArchitecturePPCCpuArchitectureSHXCpuArchitectureARMCpuArchitectureIA64CpuArchitectureAlpha64CpuArchitectureMSILCpuArchitectureAMD64CpuArchitectureWoW64" + _Arch_name_1 = "CpuArchitectureARM64" + _Arch_name_2 = "CpuArchitectureUnknown" +) + +var ( + _Arch_index_0 = [...]uint8{0, 18, 37, 57, 75, 93, 111, 130, 152, 171, 191, 211} +) + +func (i Arch) String() string { + switch { + case 0 <= i && i <= 10: + return _Arch_name_0[_Arch_index_0[i]:_Arch_index_0[i+1]] + case i == 12: + return _Arch_name_1 + case i == 65535: + return _Arch_name_2 + default: + return "Arch(" + strconv.FormatInt(int64(i), 10) + ")" + } +} + +const ( + _MemoryState_name_0 = "MemoryStateCommit" + _MemoryState_name_1 = "MemoryStateReserve" + _MemoryState_name_2 = "MemoryStateFree" +) + +func (i MemoryState) String() string { + switch { + case i == 4096: + return _MemoryState_name_0 + case i == 8192: + return _MemoryState_name_1 + case i == 65536: + return _MemoryState_name_2 + default: + return "MemoryState(" + strconv.FormatInt(int64(i), 10) + ")" + } +} + +const ( + _MemoryType_name_0 = "MemoryTypePrivate" + _MemoryType_name_1 = "MemoryTypeMapped" + _MemoryType_name_2 = "MemoryTypeImage" +) + +func (i MemoryType) String() string { + switch { + case i == 131072: + return _MemoryType_name_0 + case i == 262144: + return _MemoryType_name_1 + case i == 16777216: + return _MemoryType_name_2 + default: + return "MemoryType(" + strconv.FormatInt(int64(i), 10) + ")" + } +} + +const ( + _MemoryProtection_name_0 = "MemoryProtectNoAccessMemoryProtectReadOnly" + _MemoryProtection_name_1 = "MemoryProtectReadWrite" + _MemoryProtection_name_2 = "MemoryProtectWriteCopy" + _MemoryProtection_name_3 = "MemoryProtectExecute" + _MemoryProtection_name_4 = "MemoryProtectExecuteRead" + _MemoryProtection_name_5 = "MemoryProtectExecuteReadWrite" + _MemoryProtection_name_6 = "MemoryProtectExecuteWriteCopy" + _MemoryProtection_name_7 = "MemoryProtectPageGuard" + _MemoryProtection_name_8 = "MemoryProtectNoCache" + _MemoryProtection_name_9 = "MemoryProtectWriteCombine" +) + +var ( + _MemoryProtection_index_0 = [...]uint8{0, 21, 42} +) + +func (i MemoryProtection) String() string { + switch { + case 1 <= i && i <= 2: + i -= 1 + return _MemoryProtection_name_0[_MemoryProtection_index_0[i]:_MemoryProtection_index_0[i+1]] + case i == 4: + return _MemoryProtection_name_1 + case i == 8: + return _MemoryProtection_name_2 + case i == 16: + return _MemoryProtection_name_3 + case i == 32: + return _MemoryProtection_name_4 + case i == 64: + return _MemoryProtection_name_5 + case i == 128: + return _MemoryProtection_name_6 + case i == 256: + return _MemoryProtection_name_7 + case i == 512: + return _MemoryProtection_name_8 + case i == 1024: + return _MemoryProtection_name_9 + default: + return "MemoryProtection(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/go-delve/delve/pkg/proc/core/minidump/minidump.go b/vendor/github.com/go-delve/delve/pkg/proc/core/minidump/minidump.go new file mode 100644 index 0000000..b344674 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/core/minidump/minidump.go @@ -0,0 +1,686 @@ +package minidump + +// Package minidump provides a loader for Windows Minidump files. +// Minidump files are the Windows equivalent of unix core dumps. +// They can be created by the kernel when a program crashes (however this is +// disabled for Go programs) or programmatically using either WinDbg or the +// ProcDump utility. +// +// The file format is described on MSDN starting at: +// https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_header +// which is the structure found at offset 0 on a minidump file. +// +// Further information on the format can be found reading +// chromium-breakpad's minidump loading code, specifically: +// https://chromium.googlesource.com/breakpad/breakpad/+/master/src/google_breakpad/common/minidump_cpu_amd64.h +// and: +// https://chromium.googlesource.com/breakpad/breakpad/+/master/src/google_breakpad/common/minidump_format.h + +import ( + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "unicode/utf16" + "unsafe" + + "github.com/go-delve/delve/pkg/proc/winutil" +) + +type minidumpBuf struct { + buf []byte + kind string + off int + err error + ctx string +} + +func (buf *minidumpBuf) u16() uint16 { + const stride = 2 + if buf.err != nil { + return 0 + } + if buf.off+stride >= len(buf.buf) { + buf.err = fmt.Errorf("minidump %s truncated at offset %#x while %s", buf.kind, buf.off, buf.ctx) + } + r := binary.LittleEndian.Uint16(buf.buf[buf.off : buf.off+stride]) + buf.off += stride + return r +} + +func (buf *minidumpBuf) u32() uint32 { + const stride = 4 + if buf.err != nil { + return 0 + } + if buf.off+stride >= len(buf.buf) { + buf.err = fmt.Errorf("minidump %s truncated at offset %#x while %s", buf.kind, buf.off, buf.ctx) + } + r := binary.LittleEndian.Uint32(buf.buf[buf.off : buf.off+stride]) + buf.off += stride + return r +} + +func (buf *minidumpBuf) u64() uint64 { + const stride = 8 + if buf.err != nil { + return 0 + } + if buf.off+stride >= len(buf.buf) { + buf.err = fmt.Errorf("minidump %s truncated at offset %#x while %s", buf.kind, buf.off, buf.ctx) + } + r := binary.LittleEndian.Uint64(buf.buf[buf.off : buf.off+stride]) + buf.off += stride + return r +} + +func streamBuf(stream *Stream, buf *minidumpBuf, name string) *minidumpBuf { + return &minidumpBuf{ + buf: buf.buf, + kind: "stream", + off: stream.Offset, + err: nil, + ctx: fmt.Sprintf("reading %s stream at %#x", name, stream.Offset), + } +} + +// ErrNotAMinidump is the error returned when the file being loaded is not a +// minidump file. +type ErrNotAMinidump struct { + what string + got uint32 +} + +func (err ErrNotAMinidump) Error() string { + return fmt.Sprintf("not a minidump, invalid %s %#x", err.what, err.got) +} + +const ( + minidumpSignature = 0x504d444d // 'MDMP' + minidumpVersion = 0xa793 +) + +// Minidump represents a minidump file +type Minidump struct { + Timestamp uint32 + Flags FileFlags + + Streams []Stream + + Threads []Thread + Modules []Module + + Pid uint32 + + MemoryRanges []MemoryRange + MemoryInfo []MemoryInfo + + streamNum uint32 + streamOff uint32 +} + +// Stream represents one (uninterpreted) stream in a minidump file. +// See: https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_directory +type Stream struct { + Type StreamType + Offset int + RawData []byte +} + +// Thread represents an entry in the ThreadList stream. +// See: https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_thread +type Thread struct { + ID uint32 + SuspendCount uint32 + PriorityClass uint32 + Priority uint32 + TEB uint64 + Context winutil.CONTEXT +} + +// Module represents an entry in the ModuleList stream. +// See: https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_module +type Module struct { + BaseOfImage uint64 + SizeOfImage uint32 + Checksum uint32 + TimeDateStamp uint32 + Name string + VersionInfo VSFixedFileInfo + + // CVRecord stores a CodeView record and is populated when a module's debug information resides in a PDB file. It identifies the PDB file. + CVRecord []byte + + // MiscRecord is populated when a module's debug information resides in a DBG file. It identifies the DBG file. This field is effectively obsolete with modules built by recent toolchains. + MiscRecord []byte +} + +// VSFixedFileInfo: Visual Studio Fixed File Info. +// See: https://docs.microsoft.com/en-us/windows/desktop/api/verrsrc/ns-verrsrc-tagvs_fixedfileinfo +type VSFixedFileInfo struct { + Signature uint32 + StructVersion uint32 + FileVersionHi uint32 + FileVersionLo uint32 + ProductVersionHi uint32 + ProductVersionLo uint32 + FileFlagsMask uint32 + FileFlags uint32 + FileOS uint32 + FileType uint32 + FileSubtype uint32 + FileDateHi uint32 + FileDateLo uint32 +} + +// MemoryRange represents a region of memory saved to the core file, it's constructed after either: +// 1. parsing an entry in the Memory64List stream. +// 2. parsing the stack field of an entry in the ThreadList stream. +type MemoryRange struct { + Addr uint64 + Data []byte +} + +// ReadMemory reads len(buf) bytes of memory starting at addr into buf from this memory region. +func (m *MemoryRange) ReadMemory(buf []byte, addr uintptr) (int, error) { + if len(buf) == 0 { + return 0, nil + } + if (uint64(addr) < m.Addr) || (uint64(addr)+uint64(len(buf)) > m.Addr+uint64(len(m.Data))) { + return 0, io.EOF + } + copy(buf, m.Data[uint64(addr)-m.Addr:]) + return len(buf), nil +} + +// MemoryInfo reprents an entry in the MemoryInfoList stream. +// See: https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_memory_info +type MemoryInfo struct { + Addr uint64 + Size uint64 + State MemoryState + Protection MemoryProtection + Type MemoryType +} + +//go:generate stringer -type FileFlags,StreamType,Arch,MemoryState,MemoryType,MemoryProtection + +// MemoryState is the type of the State field of MINIDUMP_MEMORY_INFO +type MemoryState uint32 + +const ( + MemoryStateCommit MemoryState = 0x1000 + MemoryStateReserve MemoryState = 0x2000 + MemoryStateFree MemoryState = 0x10000 +) + +// MemoryType is the type of the Type field of MINIDUMP_MEMORY_INFO +type MemoryType uint32 + +const ( + MemoryTypePrivate MemoryType = 0x20000 + MemoryTypeMapped MemoryType = 0x40000 + MemoryTypeImage MemoryType = 0x1000000 +) + +// MemoryProtection is the type of the Protection field of MINIDUMP_MEMORY_INFO +type MemoryProtection uint32 + +const ( + MemoryProtectNoAccess MemoryProtection = 0x01 // PAGE_NOACCESS + MemoryProtectReadOnly MemoryProtection = 0x02 // PAGE_READONLY + MemoryProtectReadWrite MemoryProtection = 0x04 // PAGE_READWRITE + MemoryProtectWriteCopy MemoryProtection = 0x08 // PAGE_WRITECOPY + MemoryProtectExecute MemoryProtection = 0x10 // PAGE_EXECUTE + MemoryProtectExecuteRead MemoryProtection = 0x20 // PAGE_EXECUTE_READ + MemoryProtectExecuteReadWrite MemoryProtection = 0x40 // PAGE_EXECUTE_READWRITE + MemoryProtectExecuteWriteCopy MemoryProtection = 0x80 // PAGE_EXECUTE_WRITECOPY + // These options can be combined with the previous flags + MemoryProtectPageGuard MemoryProtection = 0x100 // PAGE_GUARD + MemoryProtectNoCache MemoryProtection = 0x200 // PAGE_NOCACHE + MemoryProtectWriteCombine MemoryProtection = 0x400 // PAGE_WRITECOMBINE + +) + +// FileFlags is the type of the Flags field of MINIDUMP_HEADER +type FileFlags uint64 + +const ( + FileNormal FileFlags = 0x00000000 + FileWithDataSegs FileFlags = 0x00000001 + FileWithFullMemory FileFlags = 0x00000002 + FileWithHandleData FileFlags = 0x00000004 + FileFilterMemory FileFlags = 0x00000008 + FileScanMemory FileFlags = 0x00000010 + FileWithUnloadedModules FileFlags = 0x00000020 + FileWithIncorrectlyReferencedMemory FileFlags = 0x00000040 + FileFilterModulePaths FileFlags = 0x00000080 + FileWithProcessThreadData FileFlags = 0x00000100 + FileWithPrivateReadWriteMemory FileFlags = 0x00000200 + FileWithoutOptionalData FileFlags = 0x00000400 + FileWithFullMemoryInfo FileFlags = 0x00000800 + FileWithThreadInfo FileFlags = 0x00001000 + FileWithCodeSegs FileFlags = 0x00002000 + FileWithoutAuxilliarySegs FileFlags = 0x00004000 + FileWithFullAuxilliaryState FileFlags = 0x00008000 + FileWithPrivateCopyMemory FileFlags = 0x00010000 + FileIgnoreInaccessibleMemory FileFlags = 0x00020000 + FileWithTokenInformation FileFlags = 0x00040000 +) + +// StreamType is the type of the StreamType field of MINIDUMP_DIRECTORY +type StreamType uint32 + +const ( + UnusedStream StreamType = 0 + ReservedStream0 StreamType = 1 + ReservedStream1 StreamType = 2 + ThreadListStream StreamType = 3 + ModuleListStream StreamType = 4 + MemoryListStream StreamType = 5 + ExceptionStream StreamType = 6 + SystemInfoStream StreamType = 7 + ThreadExListStream StreamType = 8 + Memory64ListStream StreamType = 9 + CommentStreamA StreamType = 10 + CommentStreamW StreamType = 11 + HandleDataStream StreamType = 12 + FunctionTableStream StreamType = 13 + UnloadedModuleStream StreamType = 14 + MiscInfoStream StreamType = 15 + MemoryInfoListStream StreamType = 16 + ThreadInfoListStream StreamType = 17 + HandleOperationListStream StreamType = 18 + TokenStream StreamType = 19 + JavascriptDataStream StreamType = 20 + SystemMemoryInfoStream StreamType = 21 + ProcessVMCounterStream StreamType = 22 +) + +// Arch is the type of the ProcessorArchitecture field of MINIDUMP_SYSTEM_INFO. +type Arch uint16 + +const ( + CpuArchitectureX86 Arch = 0 + CpuArchitectureMips Arch = 1 + CpuArchitectureAlpha Arch = 2 + CpuArchitecturePPC Arch = 3 + CpuArchitectureSHX Arch = 4 // Super-H + CpuArchitectureARM Arch = 5 + CpuArchitectureIA64 Arch = 6 + CpuArchitectureAlpha64 Arch = 7 + CpuArchitectureMSIL Arch = 8 // Microsoft Intermediate Language + CpuArchitectureAMD64 Arch = 9 + CpuArchitectureWoW64 Arch = 10 + CpuArchitectureARM64 Arch = 12 + CpuArchitectureUnknown Arch = 0xffff +) + +// Open reads the minidump file at path and returns it as a Minidump structure. +func Open(path string, logfn func(fmt string, args ...interface{})) (*Minidump, error) { + rawbuf, err := ioutil.ReadFile(path) //TODO(aarzilli): mmap? + if err != nil { + return nil, err + } + + buf := &minidumpBuf{buf: rawbuf, kind: "file"} + + var mdmp Minidump + + readMinidumpHeader(&mdmp, buf) + if buf.err != nil { + return nil, buf.err + } + + if logfn != nil { + logfn("Minidump Header\n") + logfn("Num Streams: %d\n", mdmp.streamNum) + logfn("Streams offset: %#x\n", mdmp.streamOff) + logfn("File flags: %s\n", fileFlagsToString(mdmp.Flags)) + logfn("Offset after header %#x\n", buf.off) + } + + readDirectory(&mdmp, buf) + if buf.err != nil { + return nil, buf.err + } + + for i := range mdmp.Streams { + stream := &mdmp.Streams[i] + if stream.Type != SystemInfoStream { + continue + } + + sb := streamBuf(stream, buf, "system info") + if buf.err != nil { + return nil, buf.err + } + + arch := Arch(sb.u16()) + + if logfn != nil { + logfn("Found processor architecture %s\n", arch.String()) + } + + if arch != CpuArchitectureAMD64 { + return nil, fmt.Errorf("unsupported architecture %s", arch.String()) + } + } + + for i := range mdmp.Streams { + stream := &mdmp.Streams[i] + if logfn != nil { + logfn("Stream %d: type:%s off:%#x size:%#x\n", i, stream.Type, stream.Offset, len(stream.RawData)) + } + switch stream.Type { + case ThreadListStream: + readThreadList(&mdmp, streamBuf(stream, buf, "thread list")) + if logfn != nil { + for i := range mdmp.Threads { + logfn("\tID:%#x TEB:%#x\n", mdmp.Threads[i].ID, mdmp.Threads[i].TEB) + } + } + case ModuleListStream: + readModuleList(&mdmp, streamBuf(stream, buf, "module list")) + if logfn != nil { + for i := range mdmp.Modules { + logfn("\tName:%q BaseOfImage:%#x SizeOfImage:%#x\n", mdmp.Modules[i].Name, mdmp.Modules[i].BaseOfImage, mdmp.Modules[i].SizeOfImage) + } + } + case ExceptionStream: + //TODO(aarzilli): this stream contains the exception that made the + //process stop and caused the minidump to be taken. If we ever start + //caring about this we should parse this. + case Memory64ListStream: + readMemory64List(&mdmp, streamBuf(stream, buf, "memory64 list"), logfn) + case MemoryInfoListStream: + readMemoryInfoList(&mdmp, streamBuf(stream, buf, "memory info list"), logfn) + case MiscInfoStream: + readMiscInfo(&mdmp, streamBuf(stream, buf, "misc info")) + if logfn != nil { + logfn("\tPid: %#x\n", mdmp.Pid) + } + case CommentStreamW: + if logfn != nil { + logfn("\t%q\n", decodeUTF16(stream.RawData)) + } + case CommentStreamA: + if logfn != nil { + logfn("\t%s\n", string(stream.RawData)) + } + } + if buf.err != nil { + return nil, buf.err + } + } + + return &mdmp, nil +} + +// decodeUTF16 converts a NUL-terminated UTF16LE string to (non NUL-terminated) UTF8. +func decodeUTF16(in []byte) string { + utf16encoded := []uint16{} + for i := 0; i+1 < len(in); i += 2 { + var ch uint16 + ch = uint16(in[i]) + uint16(in[i+1])<<8 + utf16encoded = append(utf16encoded, ch) + } + s := string(utf16.Decode(utf16encoded)) + if len(s) > 0 && s[len(s)-1] == 0 { + s = s[:len(s)-1] + } + return s +} + +func fileFlagsToString(flags FileFlags) string { + out := []byte{} + for i, name := range _FileFlags_map { + if i == 0 { + continue + } + if flags&i != 0 { + if len(out) > 0 { + out = append(out, '|') + } + out = append(out, name...) + } + } + if len(out) == 0 { + return flags.String() + } + return string(out) +} + +// readMinidumpHeader reads the minidump file header +func readMinidumpHeader(mdmp *Minidump, buf *minidumpBuf) { + buf.ctx = "reading minidump header" + + if sig := buf.u32(); sig != minidumpSignature { + buf.err = ErrNotAMinidump{"signature", sig} + return + } + + if ver := buf.u16(); ver != minidumpVersion { + buf.err = ErrNotAMinidump{"version", uint32(ver)} + return + } + + buf.u16() // implementation specific version + mdmp.streamNum = buf.u32() + mdmp.streamOff = buf.u32() + buf.u32() // checksum, but it's always 0 + mdmp.Timestamp = buf.u32() + mdmp.Flags = FileFlags(buf.u64()) +} + +// readDirectory reads the list of streams (i.e. the minidum "directory") +func readDirectory(mdmp *Minidump, buf *minidumpBuf) { + buf.off = int(mdmp.streamOff) + + mdmp.Streams = make([]Stream, mdmp.streamNum) + for i := range mdmp.Streams { + buf.ctx = fmt.Sprintf("reading stream directory entry %d", i) + stream := &mdmp.Streams[i] + stream.Type = StreamType(buf.u32()) + stream.Offset, stream.RawData = readLocationDescriptor(buf) + if buf.err != nil { + return + } + } +} + +// readLocationDescriptor reads a location descriptor structure (a structure +// which describes a subregion of the file), and returns the destination +// offset and a slice into the minidump file's buffer. +func readLocationDescriptor(buf *minidumpBuf) (off int, rawData []byte) { + sz := buf.u32() + off = int(buf.u32()) + if buf.err != nil { + return off, nil + } + end := off + int(sz) + if off >= len(buf.buf) || end > len(buf.buf) { + buf.err = fmt.Errorf("location starting at %#x of size %#x is past the end of file, while %s", off, sz, buf.ctx) + return 0, nil + } + rawData = buf.buf[off:end] + return +} + +func readString(buf *minidumpBuf) string { + startOff := buf.off + sz := buf.u32() + if buf.err != nil { + return "" + } + end := buf.off + int(sz) + if buf.off >= len(buf.buf) || end > len(buf.buf) { + buf.err = fmt.Errorf("string starting at %#x of size %#x is past the end of file, while %s", startOff, sz, buf.ctx) + return "" + } + return decodeUTF16(buf.buf[buf.off:end]) +} + +// readThreadList reads a thread list stream and adds the threads to the minidump. +func readThreadList(mdmp *Minidump, buf *minidumpBuf) { + threadNum := buf.u32() + if buf.err != nil { + return + } + + mdmp.Threads = make([]Thread, threadNum) + + for i := range mdmp.Threads { + buf.ctx = fmt.Sprintf("reading thread list entry %d", i) + thread := &mdmp.Threads[i] + + thread.ID = buf.u32() + thread.SuspendCount = buf.u32() + thread.PriorityClass = buf.u32() + thread.Priority = buf.u32() + thread.TEB = buf.u64() + if buf.err != nil { + return + } + + readMemoryDescriptor(mdmp, buf) // thread stack + _, rawThreadContext := readLocationDescriptor(buf) // thread context + thread.Context = *((*winutil.CONTEXT)(unsafe.Pointer(&rawThreadContext[0]))) + if buf.err != nil { + return + } + } +} + +// readModuleList reads a module list stream and adds the modules to the minidump. +func readModuleList(mdmp *Minidump, buf *minidumpBuf) { + moduleNum := buf.u32() + if buf.err != nil { + return + } + + mdmp.Modules = make([]Module, moduleNum) + + for i := range mdmp.Modules { + buf.ctx = fmt.Sprintf("reading module list entry %d", i) + module := &mdmp.Modules[i] + + module.BaseOfImage = buf.u64() + module.SizeOfImage = buf.u32() + module.Checksum = buf.u32() + module.TimeDateStamp = buf.u32() + nameOff := int(buf.u32()) + + versionInfoVec := make([]uint32, unsafe.Sizeof(VSFixedFileInfo{})/unsafe.Sizeof(uint32(0))) + for j := range versionInfoVec { + versionInfoVec[j] = buf.u32() + } + + module.VersionInfo = *(*VSFixedFileInfo)(unsafe.Pointer(&versionInfoVec[0])) + + _, module.CVRecord = readLocationDescriptor(buf) + _, module.MiscRecord = readLocationDescriptor(buf) + + if buf.err != nil { + return + } + + nameBuf := minidumpBuf{buf: buf.buf, kind: "file", off: nameOff, err: nil, ctx: buf.ctx} + module.Name = readString(&nameBuf) + if nameBuf.err != nil { + buf.err = nameBuf.err + return + } + } +} + +// readMemory64List reads a _MINIDUMP_MEMORY64_LIST structure, containing +// the description of the process memory. +// See: https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_memory64_list +// And: https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/ns-minidumpapiset-_minidump_memory_descriptor +func readMemory64List(mdmp *Minidump, buf *minidumpBuf, logfn func(fmt string, args ...interface{})) { + rangesNum := buf.u64() + baseOff := int(buf.u64()) + if buf.err != nil { + return + } + + for i := uint64(0); i < rangesNum; i++ { + addr := buf.u64() + sz := buf.u64() + + end := baseOff + int(sz) + if baseOff >= len(buf.buf) || end > len(buf.buf) { + buf.err = fmt.Errorf("memory range at %#x of size %#x is past the end of file, while %s", baseOff, sz, buf.ctx) + return + } + + mdmp.addMemory(addr, buf.buf[baseOff:end]) + + if logfn != nil { + logfn("\tMemory %d addr:%#x size:%#x FileOffset:%#x\n", i, addr, sz, baseOff) + } + + baseOff = end + } +} + +func readMemoryInfoList(mdmp *Minidump, buf *minidumpBuf, logfn func(fmt string, args ...interface{})) { + startOff := buf.off + sizeOfHeader := int(buf.u32()) + sizeOfEntry := int(buf.u32()) + numEntries := buf.u64() + + buf.off = startOff + sizeOfHeader + + mdmp.MemoryInfo = make([]MemoryInfo, numEntries) + + for i := range mdmp.MemoryInfo { + memInfo := &mdmp.MemoryInfo[i] + startOff := buf.off + + memInfo.Addr = buf.u64() + buf.u64() // allocation_base + + buf.u32() // allocation_protection + buf.u32() // alignment + + memInfo.Size = buf.u64() + + memInfo.State = MemoryState(buf.u32()) + memInfo.Protection = MemoryProtection(buf.u32()) + memInfo.Type = MemoryType(buf.u32()) + + if logfn != nil { + logfn("\tMemoryInfo %d Addr:%#x Size:%#x %s %s %s\n", i, memInfo.Addr, memInfo.Size, memInfo.State, memInfo.Protection, memInfo.Type) + } + + buf.off = startOff + sizeOfEntry + } +} + +// readMiscInfo reads the process_id from a MiscInfo stream. +func readMiscInfo(mdmp *Minidump, buf *minidumpBuf) { + buf.u32() // size of info + buf.u32() // flags1 + + mdmp.Pid = buf.u32() // process_id + // there are more fields here, but we don't care about them +} + +// readMemoryDescriptor reads a memory descriptor struct and adds it to the memory map of the minidump. +func readMemoryDescriptor(mdmp *Minidump, buf *minidumpBuf) { + addr := buf.u64() + if buf.err != nil { + return + } + _, rawData := readLocationDescriptor(buf) + if buf.err != nil { + return + } + mdmp.addMemory(addr, rawData) +} + +func (mdmp *Minidump) addMemory(addr uint64, data []byte) { + mdmp.MemoryRanges = append(mdmp.MemoryRanges, MemoryRange{addr, data}) +} diff --git a/vendor/github.com/go-delve/delve/pkg/proc/core/windows_amd64_minidump.go b/vendor/github.com/go-delve/delve/pkg/proc/core/windows_amd64_minidump.go new file mode 100644 index 0000000..08627c5 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/core/windows_amd64_minidump.go @@ -0,0 +1,59 @@ +package core + +import ( + "github.com/go-delve/delve/pkg/logflags" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/core/minidump" + "github.com/go-delve/delve/pkg/proc/winutil" +) + +func readAMD64Minidump(minidumpPath, exePath string) (*Process, error) { + var logfn func(string, ...interface{}) + if logflags.Minidump() { + logfn = logflags.MinidumpLogger().Infof + } + + mdmp, err := minidump.Open(minidumpPath, logfn) + if err != nil { + if _, isNotAMinidump := err.(minidump.ErrNotAMinidump); isNotAMinidump { + return nil, ErrUnrecognizedFormat + } + return nil, err + } + + memory := &SplicedMemory{} + + for i := range mdmp.MemoryRanges { + m := &mdmp.MemoryRanges[i] + memory.Add(m, uintptr(m.Addr), uintptr(len(m.Data))) + } + + p := &Process{ + mem: memory, + Threads: map[int]*Thread{}, + bi: proc.NewBinaryInfo("windows", "amd64"), + breakpoints: proc.NewBreakpointMap(), + pid: int(mdmp.Pid), + } + + for i := range mdmp.Threads { + th := &mdmp.Threads[i] + p.Threads[int(th.ID)] = &Thread{&windowsAMD64Thread{th}, p, proc.CommonThread{}} + if p.currentThread == nil { + p.currentThread = p.Threads[int(th.ID)] + } + } + return p, nil +} + +type windowsAMD64Thread struct { + th *minidump.Thread +} + +func (th *windowsAMD64Thread) pid() int { + return int(th.th.ID) +} + +func (th *windowsAMD64Thread) registers(floatingPoint bool) (proc.Registers, error) { + return winutil.NewAMD64Registers(&th.th.Context, th.th.TEB, floatingPoint), nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/disasm.go b/vendor/github.com/go-delve/delve/pkg/proc/disasm.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/disasm.go rename to vendor/github.com/go-delve/delve/pkg/proc/disasm.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/disasm_amd64.go similarity index 95% rename from vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go rename to vendor/github.com/go-delve/delve/pkg/proc/disasm_amd64.go index 1f33c6e..bc5ba2c 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/disasm_amd64.go @@ -65,6 +65,14 @@ func (inst *AsmInstruction) IsCall() bool { return inst.Inst.Op == x86asm.CALL || inst.Inst.Op == x86asm.LCALL } +// IsRet returns true if the instruction is a RET or LRET instruction. +func (inst *AsmInstruction) IsRet() bool { + if inst.Inst == nil { + return false + } + return inst.Inst.Op == x86asm.RET || inst.Inst.Op == x86asm.LRET +} + func resolveCallArg(inst *archInst, currentGoroutine bool, regs Registers, mem MemoryReadWriter, bininfo *BinaryInfo) *Location { if inst.Op != x86asm.CALL && inst.Op != x86asm.LCALL { return nil @@ -110,7 +118,7 @@ func resolveCallArg(inst *archInst, currentGoroutine bool, regs Registers, mem M file, line, fn := bininfo.PCToLine(pc) if fn == nil { - return nil + return &Location{PC: pc} } return &Location{PC: pc, File: file, Line: line, Fn: fn} } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/doc.go b/vendor/github.com/go-delve/delve/pkg/proc/doc.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/doc.go rename to vendor/github.com/go-delve/delve/pkg/proc/doc.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/eval.go b/vendor/github.com/go-delve/delve/pkg/proc/eval.go similarity index 96% rename from vendor/github.com/derekparker/delve/pkg/proc/eval.go rename to vendor/github.com/go-delve/delve/pkg/proc/eval.go index 8f7bfba..1020c6c 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/eval.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/eval.go @@ -14,9 +14,9 @@ import ( "strconv" "strings" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/dwarf/reader" - "github.com/derekparker/delve/pkg/goversion" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/goversion" ) var errOperationOnSpecialFloat = errors.New("operations on non-finite floats not implemented") @@ -114,15 +114,25 @@ func (scope *EvalScope) evalToplevelTypeCast(t ast.Expr, cfg LoadConfig) (*Varia case "string": switch argv.Kind { + case reflect.String: + s := constant.StringVal(argv.Value) + v.Value = constant.MakeString(s) + v.Len = int64(len(s)) + return v, nil case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr: b, _ := constant.Int64Val(argv.Value) s := string(b) v.Value = constant.MakeString(s) v.Len = int64(len(s)) return v, nil - - case reflect.Slice: - switch elemType := argv.RealType.(*godwarf.SliceType).ElemType.(type) { + case reflect.Slice, reflect.Array: + var elem godwarf.Type + if argv.Kind == reflect.Slice { + elem = argv.RealType.(*godwarf.SliceType).ElemType + } else { + elem = argv.RealType.(*godwarf.ArrayType).Type + } + switch elemType := elem.(type) { case *godwarf.UintType: if elemType.Name != "uint8" && elemType.Name != "byte" { return nil, nil @@ -1198,7 +1208,7 @@ func (err *typeConvErr) Error() string { func (v *Variable) isType(typ godwarf.Type, kind reflect.Kind) error { if v.DwarfType != nil { - if typ != nil && typ.String() != v.RealType.String() { + if typ == nil || !sameType(typ, v.RealType) { return &typeConvErr{v.DwarfType, typ} } return nil @@ -1255,6 +1265,34 @@ func (v *Variable) isType(typ godwarf.Type, kind reflect.Kind) error { return nil } +func sameType(t1, t2 godwarf.Type) bool { + // Because of a bug in the go linker a type that refers to another type + // (for example a pointer type) will usually use the typedef but rarely use + // the non-typedef entry directly. + // For types that we read directly from go this is fine because it's + // consistent, however we also synthesize some types ourselves + // (specifically pointers and slices) and we always use a reference through + // a typedef. + t1 = resolveTypedef(t1) + t2 = resolveTypedef(t2) + + if tt1, isptr1 := t1.(*godwarf.PtrType); isptr1 { + tt2, isptr2 := t2.(*godwarf.PtrType) + if !isptr2 { + return false + } + return sameType(tt1.Type, tt2.Type) + } + if tt1, isslice1 := t1.(*godwarf.SliceType); isslice1 { + tt2, isslice2 := t2.(*godwarf.SliceType) + if !isslice2 { + return false + } + return sameType(tt1.ElemType, tt2.ElemType) + } + return t1.String() == t2.String() +} + func (v *Variable) sliceAccess(idx int) (*Variable, error) { if idx < 0 || int64(idx) >= v.Len { return nil, fmt.Errorf("index out of bounds") diff --git a/vendor/github.com/derekparker/delve/pkg/proc/fncall.go b/vendor/github.com/go-delve/delve/pkg/proc/fncall.go similarity index 94% rename from vendor/github.com/derekparker/delve/pkg/proc/fncall.go rename to vendor/github.com/go-delve/delve/pkg/proc/fncall.go index b723986..286165e 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/fncall.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/fncall.go @@ -11,11 +11,10 @@ import ( "reflect" "sort" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/dwarf/op" - "github.com/derekparker/delve/pkg/dwarf/reader" - "github.com/derekparker/delve/pkg/logflags" - "github.com/sirupsen/logrus" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/logflags" "golang.org/x/arch/x86/x86asm" ) @@ -81,7 +80,7 @@ type functionCallState struct { // CallFunction starts a debugger injected function call on the current thread of p. // See runtime.debugCallV1 in $GOROOT/src/runtime/asm_amd64.s for a // description of the protocol. -func CallFunction(p Process, expr string, retLoadCfg *LoadConfig) error { +func CallFunction(p Process, expr string, retLoadCfg *LoadConfig, checkEscape bool) error { bi := p.BinInfo() if !p.Common().fncallEnabled { return errFuncCallUnsupportedBackend @@ -126,7 +125,7 @@ func CallFunction(p Process, expr string, retLoadCfg *LoadConfig) error { return err } - argmem, err := funcCallArgFrame(fn, argvars, g, bi) + argmem, err := funcCallArgFrame(fn, argvars, g, bi, checkEscape) if err != nil { return err } @@ -153,10 +152,7 @@ func CallFunction(p Process, expr string, retLoadCfg *LoadConfig) error { } func fncallLog(fmtstr string, args ...interface{}) { - if !logflags.FnCall() { - return - } - logrus.WithFields(logrus.Fields{"layer": "proc", "kind": "fncall"}).Infof(fmtstr, args...) + logflags.FnCallLogger().Infof(fmtstr, args...) } // writePointer writes val as an architecture pointer at addr in mem. @@ -218,7 +214,7 @@ func funcCallEvalExpr(p Process, expr string) (fn *Function, closureAddr uint64, if fnvar.Kind != reflect.Func { return nil, 0, nil, fmt.Errorf("expression %q is not a function", exprToString(callexpr.Fun)) } - fnvar.loadValue(LoadConfig{false, 0, 0, 0, 0}) + fnvar.loadValue(LoadConfig{false, 0, 0, 0, 0, 0}) if fnvar.Unreadable != nil { return nil, 0, nil, fnvar.Unreadable } @@ -259,7 +255,7 @@ type funcCallArg struct { // funcCallArgFrame checks type and pointer escaping for the arguments and // returns the argument frame. -func funcCallArgFrame(fn *Function, actualArgs []*Variable, g *G, bi *BinaryInfo) (argmem []byte, err error) { +func funcCallArgFrame(fn *Function, actualArgs []*Variable, g *G, bi *BinaryInfo, checkEscape bool) (argmem []byte, err error) { argFrameSize, formalArgs, err := funcCallArgs(fn, bi, false) if err != nil { return nil, err @@ -278,9 +274,11 @@ func funcCallArgFrame(fn *Function, actualArgs []*Variable, g *G, bi *BinaryInfo formalArg := &formalArgs[i] actualArg := actualArgs[i] - //TODO(aarzilli): only apply the escapeCheck to leaking parameters. - if err := escapeCheck(actualArg, formalArg.name, g); err != nil { - return nil, fmt.Errorf("can not pass %s to %s: %v", actualArg.Name, formalArg.name, err) + if checkEscape { + //TODO(aarzilli): only apply the escapeCheck to leaking parameters. + if err := escapeCheck(actualArg, formalArg.name, g); err != nil { + return nil, fmt.Errorf("cannot use %s as argument %s in function %s: %v", actualArg.Name, formalArg.name, fn.Name, err) + } } //TODO(aarzilli): autmoatic wrapping in interfaces for cases not handled @@ -343,7 +341,13 @@ func funcCallArgs(fn *Function, bi *BinaryInfo, includeRet bool) (argFrameSize i func escapeCheck(v *Variable, name string, g *G) error { switch v.Kind { case reflect.Ptr: - w := v.maybeDereference() + var w *Variable + if len(v.Children) == 1 { + // this branch is here to support pointers constructed with typecasts from ints or the '&' operator + w = &v.Children[0] + } else { + w = v.maybeDereference() + } return escapeCheckPointer(w.Addr, name, g) case reflect.Chan, reflect.String, reflect.Slice: return escapeCheckPointer(v.Base, name, g) diff --git a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver.go b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver.go similarity index 92% rename from vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver.go rename to vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver.go index 9fa7f0e..80e2172 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver.go @@ -68,23 +68,20 @@ import ( "errors" "fmt" "go/ast" - "io/ioutil" "net" "os" "os/exec" "runtime" "strconv" "strings" - "sync" "time" "golang.org/x/arch/x86/x86asm" - "github.com/derekparker/delve/pkg/logflags" - "github.com/derekparker/delve/pkg/proc" - "github.com/derekparker/delve/pkg/proc/linutil" - "github.com/mattn/go-isatty" - "github.com/sirupsen/logrus" + "github.com/go-delve/delve/pkg/logflags" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" + isatty "github.com/mattn/go-isatty" ) const ( @@ -130,7 +127,7 @@ type Process struct { common proc.CommonProcess } -// Thread is a thread. +// Thread represents an operating system thread. type Thread struct { ID int strID string @@ -142,8 +139,7 @@ type Thread struct { } // ErrBackendUnavailable is returned when the stub program can not be found. -type ErrBackendUnavailable struct { -} +type ErrBackendUnavailable struct{} func (err *ErrBackendUnavailable) Error() string { return "backend unavailable" @@ -172,11 +168,7 @@ type gdbRegister struct { // Detach. // Use Listen, Dial or Connect to complete connection. func New(process *os.Process) *Process { - logger := logrus.New().WithFields(logrus.Fields{"layer": "gdbconn"}) - logger.Logger.Level = logrus.DebugLevel - if !logflags.GdbWire() { - logger.Logger.Out = ioutil.Discard - } + logger := logflags.GdbWireLogger() p := &Process{ conn: gdbConn{ maxTransmitAttempts: maxTransmitAttempts, @@ -205,7 +197,7 @@ func New(process *os.Process) *Process { } // Listen waits for a connection from the stub. -func (p *Process) Listen(listener net.Listener, path string, pid int) error { +func (p *Process) Listen(listener net.Listener, path string, pid int, debugInfoDirs []string) error { acceptChan := make(chan net.Conn) go func() { @@ -219,7 +211,7 @@ func (p *Process) Listen(listener net.Listener, path string, pid int) error { if conn == nil { return errors.New("could not connect") } - return p.Connect(conn, path, pid) + return p.Connect(conn, path, pid, debugInfoDirs) case status := <-p.waitChan: listener.Close() return fmt.Errorf("stub exited while waiting for connection: %v", status) @@ -227,11 +219,11 @@ func (p *Process) Listen(listener net.Listener, path string, pid int) error { } // Dial attempts to connect to the stub. -func (p *Process) Dial(addr string, path string, pid int) error { +func (p *Process) Dial(addr string, path string, pid int, debugInfoDirs []string) error { for { conn, err := net.Dial("tcp", addr) if err == nil { - return p.Connect(conn, path, pid) + return p.Connect(conn, path, pid, debugInfoDirs) } select { case status := <-p.waitChan: @@ -248,9 +240,8 @@ func (p *Process) Dial(addr string, path string, pid int) error { // program and the PID of the target process, both are optional, however // some stubs do not provide ways to determine path and pid automatically // and Connect will be unable to function without knowing them. -func (p *Process) Connect(conn net.Conn, path string, pid int) error { +func (p *Process) Connect(conn net.Conn, path string, pid int, debugInfoDirs []string) error { p.conn.conn = conn - p.conn.pid = pid err := p.conn.handshake() if err != nil { @@ -270,55 +261,7 @@ func (p *Process) Connect(conn net.Conn, path string, pid int) error { } } - if path == "" { - // If we are attaching to a running process and the user didn't specify - // the executable file manually we must ask the stub for it. - // We support both qXfer:exec-file:read:: (the gdb way) and calling - // qProcessInfo (the lldb way). - // Unfortunately debugserver on macOS supports neither. - path, err = p.conn.readExecFile() - if err != nil { - if isProtocolErrorUnsupported(err) { - _, path, err = p.loadProcessInfo(pid) - if err != nil { - conn.Close() - return err - } - } else { - conn.Close() - return fmt.Errorf("could not determine executable path: %v", err) - } - } - } - - if path == "" { - // try using jGetLoadedDynamicLibrariesInfos which is the only way to do - // this supported on debugserver (but only on macOS >= 12.10) - images, _ := p.conn.getLoadedDynamicLibraries() - for _, image := range images { - if image.MachHeader.FileType == macho.TypeExec { - path = image.Pathname - break - } - } - } - - var entryPoint uint64 - if auxv, err := p.conn.readAuxv(); err == nil { - // If we can't read the auxiliary vector it just means it's not supported - // by the OS or by the stub. If we are debugging a PIE and the entry point - // is needed proc.LoadBinaryInfo will complain about it. - entryPoint = linutil.EntryPointFromAuxvAMD64(auxv) - } - - var wg sync.WaitGroup - err = p.bi.LoadBinaryInfo(path, entryPoint, &wg) - wg.Wait() - if err == nil { - err = p.bi.LoadError() - } - if err != nil { - conn.Close() + if err := p.initialize(path, debugInfoDirs); err != nil { return err } @@ -335,36 +278,6 @@ func (p *Process) Connect(conn net.Conn, path string, pid int) error { p.loadGInstrAddr = addr } } - - err = p.updateThreadList(&threadUpdater{p: p}) - if err != nil { - conn.Close() - p.bi.Close() - return err - } - - if p.conn.pid <= 0 { - p.conn.pid, _, err = p.loadProcessInfo(0) - if err != nil && !isProtocolErrorUnsupported(err) { - conn.Close() - p.bi.Close() - return err - } - } - - p.selectedGoroutine, _ = proc.GetG(p.CurrentThread()) - - proc.CreateUnrecoveredPanicBreakpoint(p, p.writeBreakpoint, &p.breakpoints) - - panicpc, err := proc.FindFunctionLocation(p, "runtime.startpanic", true, 0) - if err == nil { - bp, err := p.breakpoints.SetWithID(-1, panicpc, p.writeBreakpoint) - if err == nil { - bp.Name = proc.UnrecoveredPanic - bp.Variables = []string{"runtime.curg._panic.arg"} - } - } - return nil } @@ -405,7 +318,7 @@ func getLdEnvVars() []string { // LLDBLaunch starts an instance of lldb-server and connects to it, asking // it to launch the specified target program with the specified arguments // (cmd) on the specified directory wd. -func LLDBLaunch(cmd []string, wd string, foreground bool) (*Process, error) { +func LLDBLaunch(cmd []string, wd string, foreground bool, debugInfoDirs []string) (*Process, error) { switch runtime.GOOS { case "windows": return nil, ErrUnsupportedOS @@ -482,9 +395,9 @@ func LLDBLaunch(cmd []string, wd string, foreground bool) (*Process, error) { p.conn.isDebugserver = isDebugserver if listener != nil { - err = p.Listen(listener, cmd[0], 0) + err = p.Listen(listener, cmd[0], 0, debugInfoDirs) } else { - err = p.Dial(port, cmd[0], 0) + err = p.Dial(port, cmd[0], 0, debugInfoDirs) } if err != nil { return nil, err @@ -497,13 +410,13 @@ func LLDBLaunch(cmd []string, wd string, foreground bool) (*Process, error) { // Path is path to the target's executable, path only needs to be specified // for some stubs that do not provide an automated way of determining it // (for example debugserver). -func LLDBAttach(pid int, path string) (*Process, error) { +func LLDBAttach(pid int, path string, debugInfoDirs []string) (*Process, error) { if runtime.GOOS == "windows" { return nil, ErrUnsupportedOS } isDebugserver := false - var proc *exec.Cmd + var process *exec.Cmd var listener net.Listener var port string if _, err := os.Stat(debugserverExecutable); err == nil { @@ -512,32 +425,31 @@ func LLDBAttach(pid int, path string) (*Process, error) { if err != nil { return nil, err } - proc = exec.Command(debugserverExecutable, "-R", fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), "--attach="+strconv.Itoa(pid)) + process = exec.Command(debugserverExecutable, "-R", fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), "--attach="+strconv.Itoa(pid)) } else { if _, err := exec.LookPath("lldb-server"); err != nil { return nil, &ErrBackendUnavailable{} } port = unusedPort() - proc = exec.Command("lldb-server", "gdbserver", "--attach", strconv.Itoa(pid), port) + process = exec.Command("lldb-server", "gdbserver", "--attach", strconv.Itoa(pid), port) } - proc.Stdout = os.Stdout - proc.Stderr = os.Stderr + process.Stdout = os.Stdout + process.Stderr = os.Stderr + process.SysProcAttr = sysProcAttr(false) - proc.SysProcAttr = sysProcAttr(false) - - err := proc.Start() + err := process.Start() if err != nil { return nil, err } - p := New(proc.Process) + p := New(process.Process) p.conn.isDebugserver = isDebugserver if listener != nil { - err = p.Listen(listener, path, pid) + err = p.Listen(listener, path, pid, debugInfoDirs) } else { - err = p.Dial(port, path, pid) + err = p.Dial(port, path, pid, debugInfoDirs) } if err != nil { return nil, err @@ -545,10 +457,80 @@ func LLDBAttach(pid int, path string) (*Process, error) { return p, nil } -// loadProcessInfo uses qProcessInfo to load the inferior's PID and +// EntryPoint will return the process entry point address, useful for +// debugging PIEs. +func (p *Process) EntryPoint() (uint64, error) { + var entryPoint uint64 + if auxv, err := p.conn.readAuxv(); err == nil { + // If we can't read the auxiliary vector it just means it's not supported + // by the OS or by the stub. If we are debugging a PIE and the entry point + // is needed proc.LoadBinaryInfo will complain about it. + entryPoint = linutil.EntryPointFromAuxvAMD64(auxv) + } + return entryPoint, nil +} + +// initialize uses qProcessInfo to load the inferior's PID and // executable path. This command is not supported by all stubs and not all // stubs will report both the PID and executable path. -func (p *Process) loadProcessInfo(pid int) (int, string, error) { +func (p *Process) initialize(path string, debugInfoDirs []string) error { + var err error + if path == "" { + // If we are attaching to a running process and the user didn't specify + // the executable file manually we must ask the stub for it. + // We support both qXfer:exec-file:read:: (the gdb way) and calling + // qProcessInfo (the lldb way). + // Unfortunately debugserver on macOS supports neither. + path, err = p.conn.readExecFile() + if err != nil { + if isProtocolErrorUnsupported(err) { + _, path, err = queryProcessInfo(p, p.Pid()) + if err != nil { + p.conn.conn.Close() + return err + } + } else { + p.conn.conn.Close() + return fmt.Errorf("could not determine executable path: %v", err) + } + } + } + + if path == "" { + // try using jGetLoadedDynamicLibrariesInfos which is the only way to do + // this supported on debugserver (but only on macOS >= 12.10) + images, _ := p.conn.getLoadedDynamicLibraries() + for _, image := range images { + if image.MachHeader.FileType == macho.TypeExec { + path = image.Pathname + break + } + } + } + + err = p.updateThreadList(&threadUpdater{p: p}) + if err != nil { + p.conn.conn.Close() + p.bi.Close() + return err + } + + if p.conn.pid <= 0 { + p.conn.pid, _, err = queryProcessInfo(p, 0) + if err != nil && !isProtocolErrorUnsupported(err) { + p.conn.conn.Close() + p.bi.Close() + return err + } + } + if err = proc.PostInitializationSetup(p, path, debugInfoDirs, p.writeBreakpoint); err != nil { + p.conn.conn.Close() + return err + } + return nil +} + +func queryProcessInfo(p *Process, pid int) (int, string, error) { pi, err := p.conn.queryProcessInfo(pid) if err != nil { return 0, "", err @@ -659,7 +641,7 @@ func (p *Process) ContinueOnce() (proc.Thread, error) { // resume all threads var threadID string - var sig uint8 = 0 + var sig uint8 var tu = threadUpdater{p: p} var err error continueLoop: @@ -697,6 +679,14 @@ continueLoop: // process so we must stop here. case 0x91, 0x92, 0x93, 0x94, 0x95, 0x96: /* TARGET_EXC_BAD_ACCESS */ break continueLoop + + // Signal 0 is returned by rr when it reaches the start of the process + // in backward continue mode. + case 0: + if p.conn.direction == proc.Backward { + break continueLoop + } + default: // any other signal is always propagated to inferior } @@ -706,13 +696,19 @@ continueLoop: return nil, err } + if p.BinInfo().GOOS == "linux" { + if err := linutil.ElfUpdateSharedObjects(p); err != nil { + return nil, err + } + } + if err := p.setCurrentBreakpoints(); err != nil { return nil, err } for _, thread := range p.threads { if thread.strID == threadID { - var err error = nil + var err error switch sig { case 0x91: err = errors.New("bad access") @@ -734,6 +730,13 @@ continueLoop: return nil, fmt.Errorf("could not find thread %s", threadID) } +// SetSelectedGoroutine will set internally the goroutine that should be +// the default for any command executed, the goroutine being actively +// followed. +func (p *Process) SetSelectedGoroutine(g *proc.G) { + p.selectedGoroutine = g +} + // StepInstruction will step exactly one CPU instruction. func (p *Process) StepInstruction() error { thread := p.currentThread @@ -1025,9 +1028,6 @@ func (p *Process) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) { func (p *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) { f, l, fn := p.bi.PCToLine(uint64(addr)) - if fn == nil { - return "", 0, nil, nil, proc.InvalidAddressError{Address: addr} - } if err := p.conn.setBreakpoint(addr); err != nil { return "", 0, nil, nil, err @@ -1310,7 +1310,6 @@ func (t *Thread) Blocked() bool { default: return strings.HasPrefix(fn.Name, "syscall.Syscall") || strings.HasPrefix(fn.Name, "syscall.RawSyscall") } - return false } // loadGInstr returns the correct MOV instruction for the current @@ -1569,25 +1568,25 @@ func (t *Thread) clearBreakpointState() { } // SetCurrentBreakpoint will find and set the threads current breakpoint. -func (thread *Thread) SetCurrentBreakpoint() error { - thread.clearBreakpointState() - regs, err := thread.Registers(false) +func (t *Thread) SetCurrentBreakpoint() error { + t.clearBreakpointState() + regs, err := t.Registers(false) if err != nil { return err } pc := regs.PC() - if bp, ok := thread.p.FindBreakpoint(pc); ok { - if thread.regs.PC() != bp.Addr { - if err := thread.SetPC(bp.Addr); err != nil { + if bp, ok := t.p.FindBreakpoint(pc); ok { + if t.regs.PC() != bp.Addr { + if err := t.SetPC(bp.Addr); err != nil { return err } } - thread.CurrentBreakpoint = bp.CheckCondition(thread) - if thread.CurrentBreakpoint.Breakpoint != nil && thread.CurrentBreakpoint.Active { - if g, err := proc.GetG(thread); err == nil { - thread.CurrentBreakpoint.HitCount[g.ID]++ + t.CurrentBreakpoint = bp.CheckCondition(t) + if t.CurrentBreakpoint.Breakpoint != nil && t.CurrentBreakpoint.Active { + if g, err := proc.GetG(t); err == nil { + t.CurrentBreakpoint.HitCount[g.ID]++ } - thread.CurrentBreakpoint.TotalHitCount++ + t.CurrentBreakpoint.TotalHitCount++ } } return nil @@ -1827,9 +1826,12 @@ func (t *Thread) SetDX(dx uint64) error { return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value) } -func (regs *gdbRegisters) Slice() []proc.Register { +func (regs *gdbRegisters) Slice(floatingPoint bool) []proc.Register { r := make([]proc.Register, 0, len(regs.regsInfo)) for _, reginfo := range regs.regsInfo { + if reginfo.Group == "float" && !floatingPoint { + continue + } switch { case reginfo.Name == "eflags": r = proc.AppendEflagReg(r, reginfo.Name, uint64(binary.LittleEndian.Uint32(regs.regs[reginfo.Name].value))) @@ -1842,6 +1844,9 @@ func (regs *gdbRegisters) Slice() []proc.Register { case reginfo.Bitsize == 64: r = proc.AppendQwordReg(r, reginfo.Name, binary.LittleEndian.Uint64(regs.regs[reginfo.Name].value)) case reginfo.Bitsize == 80: + if !floatingPoint { + continue + } idx := 0 for _, stprefix := range []string{"stmm", "st"} { if strings.HasPrefix(reginfo.Name, stprefix) { @@ -1853,10 +1858,12 @@ func (regs *gdbRegisters) Slice() []proc.Register { r = proc.AppendX87Reg(r, idx, binary.LittleEndian.Uint16(value[8:]), binary.LittleEndian.Uint64(value[:8])) case reginfo.Bitsize == 128: - r = proc.AppendSSEReg(r, strings.ToUpper(reginfo.Name), regs.regs[reginfo.Name].value) + if floatingPoint { + r = proc.AppendSSEReg(r, strings.ToUpper(reginfo.Name), regs.regs[reginfo.Name].value) + } case reginfo.Bitsize == 256: - if !strings.HasPrefix(strings.ToLower(reginfo.Name), "ymm") { + if !strings.HasPrefix(strings.ToLower(reginfo.Name), "ymm") || !floatingPoint { continue } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_conn.go b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_conn.go similarity index 99% rename from vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_conn.go rename to vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_conn.go index b2dfed6..107f9d8 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_conn.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_conn.go @@ -16,8 +16,8 @@ import ( "sync" "time" - "github.com/derekparker/delve/pkg/logflags" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/logflags" + "github.com/go-delve/delve/pkg/proc" "github.com/sirupsen/logrus" ) @@ -227,7 +227,8 @@ type gdbRegisterInfo struct { Name string `xml:"name,attr"` Bitsize int `xml:"bitsize,attr"` Offset int - Regnum int `xml:"regnum,attr"` + Regnum int `xml:"regnum,attr"` + Group string `xml:"group,attr"` } // readTargetXml reads target.xml file from stub using qXfer:features:read, diff --git a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_unix.go b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_unix.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_unix.go rename to vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_unix.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_windows.go b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_windows.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_windows.go rename to vendor/github.com/go-delve/delve/pkg/proc/gdbserial/gdbserver_windows.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/rr.go b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/rr.go similarity index 94% rename from vendor/github.com/derekparker/delve/pkg/proc/gdbserial/rr.go rename to vendor/github.com/go-delve/delve/pkg/proc/gdbserial/rr.go index 5ee41dc..a2f5dec 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/gdbserial/rr.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/gdbserial/rr.go @@ -53,7 +53,7 @@ func Record(cmd []string, wd string, quiet bool) (tracedir string, err error) { // Replay starts an instance of rr in replay mode, with the specified trace // directory, and connects to it. -func Replay(tracedir string, quiet bool) (*Process, error) { +func Replay(tracedir string, quiet bool, debugInfoDirs []string) (*Process, error) { if err := checkRRAvailabe(); err != nil { return nil, err } @@ -82,7 +82,7 @@ func Replay(tracedir string, quiet bool) (*Process, error) { p := New(rrcmd.Process) p.tracedir = tracedir - err = p.Dial(init.port, init.exe, 0) + err = p.Dial(init.port, init.exe, 0, debugInfoDirs) if err != nil { rrcmd.Process.Kill() return nil, err @@ -257,11 +257,11 @@ func splitQuotedFields(in string) []string { } // RecordAndReplay acts like calling Record and then Replay. -func RecordAndReplay(cmd []string, wd string, quiet bool) (p *Process, tracedir string, err error) { +func RecordAndReplay(cmd []string, wd string, quiet bool, debugInfoDirs []string) (p *Process, tracedir string, err error) { tracedir, err = Record(cmd, wd, quiet) if tracedir == "" { return nil, "", err } - p, err = Replay(tracedir, quiet) + p, err = Replay(tracedir, quiet, debugInfoDirs) return p, tracedir, err } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/interface.go b/vendor/github.com/go-delve/delve/pkg/proc/interface.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/proc/interface.go rename to vendor/github.com/go-delve/delve/pkg/proc/interface.go index 7b7f13e..9a4245a 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/interface.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/interface.go @@ -68,6 +68,7 @@ type Info interface { // ErrProcessExited or ProcessDetachedError). Valid() (bool, error) BinInfo() *BinaryInfo + EntryPoint() (uint64, error) // Common returns a struct with fields common to all backends Common() *CommonProcess @@ -86,6 +87,7 @@ type ThreadInfo interface { // GoroutineInfo is an interface for getting information on running goroutines. type GoroutineInfo interface { SelectedGoroutine() *G + SetSelectedGoroutine(*G) } // ProcessManipulation is an interface for changing the execution state of a process. diff --git a/vendor/github.com/derekparker/delve/pkg/proc/linutil/auxv.go b/vendor/github.com/go-delve/delve/pkg/proc/linutil/auxv.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/linutil/auxv.go rename to vendor/github.com/go-delve/delve/pkg/proc/linutil/auxv.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/linutil/doc.go b/vendor/github.com/go-delve/delve/pkg/proc/linutil/doc.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/linutil/doc.go rename to vendor/github.com/go-delve/delve/pkg/proc/linutil/doc.go diff --git a/vendor/github.com/go-delve/delve/pkg/proc/linutil/dynamic.go b/vendor/github.com/go-delve/delve/pkg/proc/linutil/dynamic.go new file mode 100644 index 0000000..1f70ff0 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/linutil/dynamic.go @@ -0,0 +1,172 @@ +package linutil + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + + "github.com/go-delve/delve/pkg/proc" +) + +const ( + maxNumLibraries = 1000000 // maximum number of loaded libraries, to avoid loading forever on corrupted memory + maxLibraryPathLength = 1000000 // maximum length for the path of a library, to avoid loading forever on corrupted memory +) + +var ErrTooManyLibraries = errors.New("number of loaded libraries exceeds maximum") + +const ( + _DT_NULL = 0 // DT_NULL as defined by SysV ABI specification + _DT_DEBUG = 21 // DT_DEBUG as defined by SysV ABI specification +) + +// dynamicSearchDebug searches for the DT_DEBUG entry in the .dynamic section +func dynamicSearchDebug(p proc.Process) (uint64, error) { + bi := p.BinInfo() + mem := p.CurrentThread() + + dynbuf := make([]byte, bi.ElfDynamicSection.Size) + _, err := mem.ReadMemory(dynbuf, uintptr(bi.ElfDynamicSection.Addr)) + if err != nil { + return 0, err + } + + rd := bytes.NewReader(dynbuf) + + for { + var tag, val uint64 + if err := binary.Read(rd, binary.LittleEndian, &tag); err != nil { + return 0, err + } + if err := binary.Read(rd, binary.LittleEndian, &val); err != nil { + return 0, err + } + switch tag { + case _DT_NULL: + return 0, nil + case _DT_DEBUG: + return val, nil + } + } +} + +// hard-coded offsets of the fields of the r_debug and link_map structs, see +// /usr/include/elf/link.h for a full description of those structs. +const ( + _R_DEBUG_MAP_OFFSET = 8 + _LINK_MAP_ADDR_OFFSET = 0 // offset of link_map.l_addr field (base address shared object is loaded at) + _LINK_MAP_NAME_OFFSET = 8 // offset of link_map.l_name field (absolute file name object was found in) + _LINK_MAP_LD = 16 // offset of link_map.l_ld field (dynamic section of the shared object) + _LINK_MAP_NEXT = 24 // offset of link_map.l_next field + _LINK_MAP_PREV = 32 // offset of link_map.l_prev field +) + +func readPtr(p proc.Process, addr uint64) (uint64, error) { + ptrbuf := make([]byte, p.BinInfo().Arch.PtrSize()) + _, err := p.CurrentThread().ReadMemory(ptrbuf, uintptr(addr)) + if err != nil { + return 0, err + } + return binary.LittleEndian.Uint64(ptrbuf), nil +} + +type linkMap struct { + addr uint64 + name string + ld uint64 + next, prev uint64 +} + +func readLinkMapNode(p proc.Process, r_map uint64) (*linkMap, error) { + bi := p.BinInfo() + + var lm linkMap + var ptrs [5]uint64 + for i := range ptrs { + var err error + ptrs[i], err = readPtr(p, r_map+uint64(bi.Arch.PtrSize()*i)) + if err != nil { + return nil, err + } + } + lm.addr = ptrs[0] + var err error + lm.name, err = readCString(p, ptrs[1]) + if err != nil { + return nil, err + } + lm.ld = ptrs[2] + lm.next = ptrs[3] + lm.prev = ptrs[4] + return &lm, nil +} + +func readCString(p proc.Process, addr uint64) (string, error) { + if addr == 0 { + return "", nil + } + mem := p.CurrentThread() + buf := make([]byte, 1) + r := []byte{} + for { + if len(r) > maxLibraryPathLength { + return "", fmt.Errorf("error reading libraries: string too long (%d)", len(r)) + } + _, err := mem.ReadMemory(buf, uintptr(addr)) + if err != nil { + return "", err + } + if buf[0] == 0 { + break + } + r = append(r, buf[0]) + addr++ + } + return string(r), nil +} + +// ElfUpdateSharedObjects reads the list of dynamic libraries loaded by the +// dynamic linker from the .dynamic section and uses it to update p.BinInfo(). +// See the SysV ABI for a description of how the .dynamic section works: +// http://www.sco.com/developers/gabi/latest/contents.html +func ElfUpdateSharedObjects(p proc.Process) error { + bi := p.BinInfo() + if bi.ElfDynamicSection.Addr == 0 { + // no dynamic section, therefore nothing to do here + return nil + } + debugAddr, err := dynamicSearchDebug(p) + if err != nil { + return err + } + if debugAddr == 0 { + // no DT_DEBUG entry + return nil + } + + r_map, err := readPtr(p, debugAddr+_R_DEBUG_MAP_OFFSET) + if err != nil { + return err + } + + libs := []string{} + + for { + if r_map == 0 { + break + } + if len(libs) > maxNumLibraries { + return ErrTooManyLibraries + } + lm, err := readLinkMapNode(p, r_map) + if err != nil { + return err + } + bi.AddImage(lm.name, lm.addr) + libs = append(libs, lm.name) + r_map = lm.next + } + + return nil +} diff --git a/vendor/github.com/go-delve/delve/pkg/proc/linutil/regs.go b/vendor/github.com/go-delve/delve/pkg/proc/linutil/regs.go new file mode 100644 index 0000000..d20a010 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/linutil/regs.go @@ -0,0 +1,399 @@ +package linutil + +import ( + "bytes" + "encoding/binary" + "fmt" + + "golang.org/x/arch/x86/x86asm" + + "github.com/go-delve/delve/pkg/proc" +) + +// AMD64Registers implements the proc.Registers interface for the native/linux +// backend and core/linux backends, on AMD64. +type AMD64Registers struct { + Regs *AMD64PtraceRegs + Fpregs []proc.Register + Fpregset *AMD64Xstate +} + +// AMD64PtraceRegs is the struct used by the linux kernel to return the +// general purpose registers for AMD64 CPUs. +type AMD64PtraceRegs struct { + R15 uint64 + R14 uint64 + R13 uint64 + R12 uint64 + Rbp uint64 + Rbx uint64 + R11 uint64 + R10 uint64 + R9 uint64 + R8 uint64 + Rax uint64 + Rcx uint64 + Rdx uint64 + Rsi uint64 + Rdi uint64 + Orig_rax uint64 + Rip uint64 + Cs uint64 + Eflags uint64 + Rsp uint64 + Ss uint64 + Fs_base uint64 + Gs_base uint64 + Ds uint64 + Es uint64 + Fs uint64 + Gs uint64 +} + +// Slice returns the registers as a list of (name, value) pairs. +func (r *AMD64Registers) Slice(floatingPoint bool) []proc.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([]proc.Register, 0, len(regs)+len(r.Fpregs)) + for _, reg := range regs { + if reg.k == "Eflags" { + out = proc.AppendEflagReg(out, reg.k, reg.v) + } else { + out = proc.AppendQwordReg(out, reg.k, reg.v) + } + } + if floatingPoint { + out = append(out, r.Fpregs...) + } + return out +} + +// PC returns the value of RIP register. +func (r *AMD64Registers) PC() uint64 { + return r.Regs.Rip +} + +// SP returns the value of RSP register. +func (r *AMD64Registers) SP() uint64 { + return r.Regs.Rsp +} + +func (r *AMD64Registers) BP() uint64 { + return r.Regs.Rbp +} + +// CX returns the value of RCX register. +func (r *AMD64Registers) CX() uint64 { + return r.Regs.Rcx +} + +// TLS returns the address of the thread local storage memory segment. +func (r *AMD64Registers) TLS() uint64 { + return r.Regs.Fs_base +} + +// GAddr returns the address of the G variable if it is known, 0 and false +// otherwise. +func (r *AMD64Registers) GAddr() (uint64, bool) { + return 0, false +} + +// Get returns the value of the n-th register (in x86asm order). +func (r *AMD64Registers) Get(n int) (uint64, error) { + reg := x86asm.Reg(n) + const ( + mask8 = 0x000f + mask16 = 0x00ff + mask32 = 0xffff + ) + + switch reg { + // 8-bit + case x86asm.AL: + return r.Regs.Rax & mask8, nil + case x86asm.CL: + return r.Regs.Rcx & mask8, nil + case x86asm.DL: + return r.Regs.Rdx & mask8, nil + case x86asm.BL: + return r.Regs.Rbx & mask8, nil + case x86asm.AH: + return (r.Regs.Rax >> 8) & mask8, nil + case x86asm.CH: + return (r.Regs.Rcx >> 8) & mask8, nil + case x86asm.DH: + return (r.Regs.Rdx >> 8) & mask8, nil + case x86asm.BH: + return (r.Regs.Rbx >> 8) & mask8, nil + case x86asm.SPB: + return r.Regs.Rsp & mask8, nil + case x86asm.BPB: + return r.Regs.Rbp & mask8, nil + case x86asm.SIB: + return r.Regs.Rsi & mask8, nil + case x86asm.DIB: + return r.Regs.Rdi & mask8, nil + case x86asm.R8B: + return r.Regs.R8 & mask8, nil + case x86asm.R9B: + return r.Regs.R9 & mask8, nil + case x86asm.R10B: + return r.Regs.R10 & mask8, nil + case x86asm.R11B: + return r.Regs.R11 & mask8, nil + case x86asm.R12B: + return r.Regs.R12 & mask8, nil + case x86asm.R13B: + return r.Regs.R13 & mask8, nil + case x86asm.R14B: + return r.Regs.R14 & mask8, nil + case x86asm.R15B: + return r.Regs.R15 & mask8, nil + + // 16-bit + case x86asm.AX: + return r.Regs.Rax & mask16, nil + case x86asm.CX: + return r.Regs.Rcx & mask16, nil + case x86asm.DX: + return r.Regs.Rdx & mask16, nil + case x86asm.BX: + return r.Regs.Rbx & mask16, nil + case x86asm.SP: + return r.Regs.Rsp & mask16, nil + case x86asm.BP: + return r.Regs.Rbp & mask16, nil + case x86asm.SI: + return r.Regs.Rsi & mask16, nil + case x86asm.DI: + return r.Regs.Rdi & mask16, nil + case x86asm.R8W: + return r.Regs.R8 & mask16, nil + case x86asm.R9W: + return r.Regs.R9 & mask16, nil + case x86asm.R10W: + return r.Regs.R10 & mask16, nil + case x86asm.R11W: + return r.Regs.R11 & mask16, nil + case x86asm.R12W: + return r.Regs.R12 & mask16, nil + case x86asm.R13W: + return r.Regs.R13 & mask16, nil + case x86asm.R14W: + return r.Regs.R14 & mask16, nil + case x86asm.R15W: + return r.Regs.R15 & mask16, nil + + // 32-bit + case x86asm.EAX: + return r.Regs.Rax & mask32, nil + case x86asm.ECX: + return r.Regs.Rcx & mask32, nil + case x86asm.EDX: + return r.Regs.Rdx & mask32, nil + case x86asm.EBX: + return r.Regs.Rbx & mask32, nil + case x86asm.ESP: + return r.Regs.Rsp & mask32, nil + case x86asm.EBP: + return r.Regs.Rbp & mask32, nil + case x86asm.ESI: + return r.Regs.Rsi & mask32, nil + case x86asm.EDI: + return r.Regs.Rdi & mask32, nil + case x86asm.R8L: + return r.Regs.R8 & mask32, nil + case x86asm.R9L: + return r.Regs.R9 & mask32, nil + case x86asm.R10L: + return r.Regs.R10 & mask32, nil + case x86asm.R11L: + return r.Regs.R11 & mask32, nil + case x86asm.R12L: + return r.Regs.R12 & mask32, nil + case x86asm.R13L: + return r.Regs.R13 & mask32, nil + case x86asm.R14L: + return r.Regs.R14 & mask32, nil + case x86asm.R15L: + return r.Regs.R15 & mask32, nil + + // 64-bit + case x86asm.RAX: + return r.Regs.Rax, nil + case x86asm.RCX: + return r.Regs.Rcx, nil + case x86asm.RDX: + return r.Regs.Rdx, nil + case x86asm.RBX: + return r.Regs.Rbx, nil + case x86asm.RSP: + return r.Regs.Rsp, nil + case x86asm.RBP: + return r.Regs.Rbp, nil + case x86asm.RSI: + return r.Regs.Rsi, nil + case x86asm.RDI: + return r.Regs.Rdi, nil + case x86asm.R8: + return r.Regs.R8, nil + case x86asm.R9: + return r.Regs.R9, nil + case x86asm.R10: + return r.Regs.R10, nil + case x86asm.R11: + return r.Regs.R11, nil + case x86asm.R12: + return r.Regs.R12, nil + case x86asm.R13: + return r.Regs.R13, nil + case x86asm.R14: + return r.Regs.R14, nil + case x86asm.R15: + return r.Regs.R15, nil + } + + return 0, proc.ErrUnknownRegister +} + +// Copy returns a copy of these registers that is guarenteed not to change. +func (r *AMD64Registers) Copy() proc.Registers { + var rr AMD64Registers + rr.Regs = &AMD64PtraceRegs{} + rr.Fpregset = &AMD64Xstate{} + *(rr.Regs) = *(r.Regs) + if r.Fpregset != nil { + *(rr.Fpregset) = *(r.Fpregset) + } + if r.Fpregs != nil { + rr.Fpregs = make([]proc.Register, len(r.Fpregs)) + copy(rr.Fpregs, r.Fpregs) + } + return &rr +} + +// AMD64PtraceFpRegs tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h +type AMD64PtraceFpRegs 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 +} + +// AMD64Xstate represents amd64 XSAVE area. See Section 13.1 (and +// following) of Intel® 64 and IA-32 Architectures Software Developer’s +// Manual, Volume 1: Basic Architecture. +type AMD64Xstate struct { + AMD64PtraceFpRegs + Xsave []byte // raw xsave area + AvxState bool // contains AVX state + YmmSpace [256]byte +} + +// Decode decodes an XSAVE area to a list of name/value pairs of registers. +func (xsave *AMD64Xstate) Decode() (regs []proc.Register) { + // x87 registers + regs = proc.AppendWordReg(regs, "CW", xsave.Cwd) + regs = proc.AppendWordReg(regs, "SW", xsave.Swd) + regs = proc.AppendWordReg(regs, "TW", xsave.Ftw) + regs = proc.AppendWordReg(regs, "FOP", xsave.Fop) + regs = proc.AppendQwordReg(regs, "FIP", xsave.Rip) + regs = proc.AppendQwordReg(regs, "FDP", xsave.Rdp) + + for i := 0; i < len(xsave.StSpace); i += 4 { + regs = proc.AppendX87Reg(regs, i/4, uint16(xsave.StSpace[i+2]), uint64(xsave.StSpace[i+1])<<32|uint64(xsave.StSpace[i])) + } + + // SSE registers + regs = proc.AppendMxcsrReg(regs, "MXCSR", uint64(xsave.Mxcsr)) + regs = proc.AppendDwordReg(regs, "MXCSR_MASK", xsave.MxcrMask) + + for i := 0; i < len(xsave.XmmSpace); i += 16 { + regs = proc.AppendSSEReg(regs, fmt.Sprintf("XMM%d", i/16), xsave.XmmSpace[i:i+16]) + if xsave.AvxState { + regs = proc.AppendSSEReg(regs, fmt.Sprintf("YMM%d", i/16), xsave.YmmSpace[i:i+16]) + } + } + + return +} + +const ( + _XSAVE_HEADER_START = 512 + _XSAVE_HEADER_LEN = 64 + _XSAVE_EXTENDED_REGION_START = 576 + _XSAVE_SSE_REGION_LEN = 416 +) + +// LinuxX86XstateRead reads a byte array containing an XSAVE area into regset. +// If readLegacy is true regset.PtraceFpRegs will be filled with the +// contents of the legacy region of the XSAVE area. +// See Section 13.1 (and following) of Intel® 64 and IA-32 Architectures +// Software Developer’s Manual, Volume 1: Basic Architecture. +func AMD64XstateRead(xstateargs []byte, readLegacy bool, regset *AMD64Xstate) error { + if _XSAVE_HEADER_START+_XSAVE_HEADER_LEN >= len(xstateargs) { + return nil + } + if readLegacy { + rdr := bytes.NewReader(xstateargs[:_XSAVE_HEADER_START]) + if err := binary.Read(rdr, binary.LittleEndian, ®set.AMD64PtraceFpRegs); err != nil { + return err + } + } + 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 nil + } + + if xstate_bv&(1<<2) == 0 { + // AVX state not present + return nil + } + + avxstate := xstateargs[_XSAVE_EXTENDED_REGION_START:] + regset.AvxState = true + copy(regset.YmmSpace[:], avxstate[:len(regset.YmmSpace)]) + + return nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/mem.go b/vendor/github.com/go-delve/delve/pkg/proc/mem.go similarity index 94% rename from vendor/github.com/derekparker/delve/pkg/proc/mem.go rename to vendor/github.com/go-delve/delve/pkg/proc/mem.go index a5aa469..1ccc024 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/mem.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/mem.go @@ -2,8 +2,9 @@ package proc import ( "errors" + "fmt" - "github.com/derekparker/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/op" ) const cacheEnabled = true @@ -93,7 +94,7 @@ type compositeMemory struct { data []byte } -func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []op.Piece) *compositeMemory { +func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []op.Piece) (*compositeMemory, error) { cmem := &compositeMemory{realmem: mem, regs: regs, pieces: pieces, data: []byte{}} for _, piece := range pieces { if piece.IsRegister { @@ -102,6 +103,9 @@ func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []o if sz == 0 && len(pieces) == 1 { sz = len(reg) } + if sz > len(reg) { + return nil, fmt.Errorf("could not read %d bytes from register %d (size: %d)", sz, piece.RegNum, len(reg)) + } cmem.data = append(cmem.data, reg[:sz]...) } else { buf := make([]byte, piece.Size) @@ -109,7 +113,7 @@ func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []o cmem.data = append(cmem.data, buf...) } } - return cmem + return cmem, nil } func (mem *compositeMemory) ReadMemory(data []byte, addr uintptr) (int, error) { diff --git a/vendor/github.com/derekparker/delve/pkg/proc/moduledata.go b/vendor/github.com/go-delve/delve/pkg/proc/moduledata.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/proc/moduledata.go rename to vendor/github.com/go-delve/delve/pkg/proc/moduledata.go index 0508ac7..a24714e 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/moduledata.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/moduledata.go @@ -88,7 +88,7 @@ func resolveTypeOff(bi *BinaryInfo, typeAddr uintptr, off uintptr, mem MemoryRea if err != nil { return nil, err } - v.loadValue(LoadConfig{false, 1, 0, 0, -1}) + v.loadValue(LoadConfig{false, 1, 0, 0, -1, 0}) addr, _ := constant.Int64Val(v.Value) return v.newVariable(v.Name, uintptr(addr), rtyp, mem), nil } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/exc.h b/vendor/github.com/go-delve/delve/pkg/proc/native/exc.h similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/exc.h rename to vendor/github.com/go-delve/delve/pkg/proc/native/exc.h diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/exc_user_darwin.c b/vendor/github.com/go-delve/delve/pkg/proc/native/exc_user_darwin.c similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/exc_user_darwin.c rename to vendor/github.com/go-delve/delve/pkg/proc/native/exc_user_darwin.c diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/exec_darwin.c b/vendor/github.com/go-delve/delve/pkg/proc/native/exec_darwin.c similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/exec_darwin.c rename to vendor/github.com/go-delve/delve/pkg/proc/native/exec_darwin.c diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/exec_darwin.h b/vendor/github.com/go-delve/delve/pkg/proc/native/exec_darwin.h similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/exec_darwin.h rename to vendor/github.com/go-delve/delve/pkg/proc/native/exec_darwin.h diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.h b/vendor/github.com/go-delve/delve/pkg/proc/native/mach_exc.h similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.h rename to vendor/github.com/go-delve/delve/pkg/proc/native/mach_exc.h diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc_user_darwin.c b/vendor/github.com/go-delve/delve/pkg/proc/native/mach_exc_user_darwin.c similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc_user_darwin.c rename to vendor/github.com/go-delve/delve/pkg/proc/native/mach_exc_user_darwin.c diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/nonative_darwin.go b/vendor/github.com/go-delve/delve/pkg/proc/native/nonative_darwin.go similarity index 84% rename from vendor/github.com/derekparker/delve/pkg/proc/native/nonative_darwin.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/nonative_darwin.go index f5e5d96..690b3bc 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/nonative_darwin.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/nonative_darwin.go @@ -6,18 +6,18 @@ import ( "errors" "sync" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) var ErrNativeBackendDisabled = errors.New("native backend disabled during compilation") // Launch returns ErrNativeBackendDisabled. -func Launch(cmd []string, wd string, foreground bool) (*Process, error) { +func Launch(cmd []string, wd string, foreground bool, _ []string) (*Process, error) { return nil, ErrNativeBackendDisabled } // Attach returns ErrNativeBackendDisabled. -func Attach(pid int) (*Process, error) { +func Attach(pid int, _ []string) (*Process, error) { return nil, ErrNativeBackendDisabled } @@ -75,7 +75,9 @@ func (dbp *Process) detach(kill bool) error { panic(ErrNativeBackendDisabled) } -func (dbp *Process) entryPoint() (uint64, error) { +// EntryPoint returns the entry point for the process, +// useful for PIEs. +func (dbp *Process) EntryPoint() (uint64, error) { panic(ErrNativeBackendDisabled) } @@ -85,17 +87,17 @@ func (t *Thread) Blocked() bool { } // SetPC sets the value of the PC register. -func (thread *Thread) SetPC(pc uint64) error { +func (t *Thread) SetPC(pc uint64) error { panic(ErrNativeBackendDisabled) } // SetSP sets the value of the SP register. -func (thread *Thread) SetSP(sp uint64) error { +func (t *Thread) SetSP(sp uint64) error { panic(ErrNativeBackendDisabled) } // SetDX sets the value of the DX register. -func (thread *Thread) SetDX(dx uint64) error { +func (t *Thread) SetDX(dx uint64) error { panic(ErrNativeBackendDisabled) } @@ -126,3 +128,5 @@ func (t *Thread) restoreRegisters(sr proc.Registers) error { func (t *Thread) Stopped() bool { panic(ErrNativeBackendDisabled) } + +func initialize(dbp *Process) error { return nil } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/proc.go b/vendor/github.com/go-delve/delve/pkg/proc/native/proc.go similarity index 89% rename from vendor/github.com/derekparker/delve/pkg/proc/native/proc.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/proc.go index 1d6d3a4..bf60603 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/proc.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/proc.go @@ -6,13 +6,14 @@ import ( "runtime" "sync" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // Process represents all of the information the debugger // is holding onto regarding the process we are debugging. type Process struct { - bi *proc.BinaryInfo + bi *proc.BinaryInfo + pid int // Process Pid // Breakpoint table, holds information on breakpoints. @@ -184,32 +185,6 @@ func (dbp *Process) Breakpoints() *proc.BreakpointMap { return &dbp.breakpoints } -// LoadInformation finds the executable and then uses it -// to parse the following information: -// * Dwarf .debug_frame section -// * Dwarf .debug_line section -// * Go symbol table. -func (dbp *Process) LoadInformation(path string) error { - var wg sync.WaitGroup - - path = findExecutable(path, dbp.pid) - - entryPoint, err := dbp.entryPoint() - if err != nil { - return err - } - - wg.Add(1) - go dbp.loadProcessInformation(&wg) - err = dbp.bi.LoadBinaryInfo(path, entryPoint, &wg) - wg.Wait() - if err == nil { - err = dbp.bi.LoadError() - } - - return err -} - // RequestManualStop sets the `halt` flag and // sends SIGSTOP to all threads. func (dbp *Process) RequestManualStop() error { @@ -236,9 +211,6 @@ func (dbp *Process) CheckAndClearManualStopRequest() bool { func (dbp *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) { f, l, fn := dbp.bi.PCToLine(uint64(addr)) - if fn == nil { - return "", 0, nil, nil, proc.InvalidAddressError{Address: addr} - } originalData := make([]byte, dbp.bi.Arch.BreakpointSize()) _, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr)) @@ -379,26 +351,23 @@ func (dbp *Process) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) { return nil, false } -// Returns a new Process struct. -func initializeDebugProcess(dbp *Process, path string) (*Process, error) { - err := dbp.LoadInformation(path) - if err != nil { - return dbp, err +// initialize will ensure that all relevant information is loaded +// so the process is ready to be debugged. +func (dbp *Process) initialize(path string, debugInfoDirs []string) error { + if err := initialize(dbp); err != nil { + return err } - if err := dbp.updateThreadList(); err != nil { - return dbp, err + return err } + return proc.PostInitializationSetup(dbp, path, debugInfoDirs, dbp.writeBreakpoint) +} - // 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, _ = proc.GetG(dbp.currentThread) - - proc.CreateUnrecoveredPanicBreakpoint(dbp, dbp.writeBreakpoint, &dbp.breakpoints) - - return dbp, nil +// SetSelectedGoroutine will set internally the goroutine that should be +// the default for any command executed, the goroutine being actively +// followed. +func (dbp *Process) SetSelectedGoroutine(g *proc.G) { + dbp.selectedGoroutine = g } // ClearInternalBreakpoints will clear all non-user set breakpoints. These diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.c b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.c similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.c rename to vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.c diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.go b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.go similarity index 96% rename from vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.go index 84cf364..fda8c54 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.go @@ -13,12 +13,11 @@ import ( "os" "os/exec" "path/filepath" - "sync" "unsafe" sys "golang.org/x/sys/unix" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // OSProcessDetails holds Darwin specific information. @@ -38,7 +37,7 @@ type OSProcessDetails struct { // 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, foreground bool) (*Process, error) { +func Launch(cmd []string, wd string, foreground bool, _ []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, proc.ErrNotExecutable @@ -119,7 +118,7 @@ func Launch(cmd []string, wd string, foreground bool) (*Process, error) { } dbp.os.initialized = true - dbp, err = initializeDebugProcess(dbp, argv0Go) + err = dbp.initialize(argv0Go, []string{}) if err != nil { return nil, err } @@ -132,7 +131,7 @@ func Launch(cmd []string, wd string, foreground bool) (*Process, error) { } // Attach to an existing process with the given PID. -func Attach(pid int) (*Process, error) { +func Attach(pid int, _ []string) (*Process, error) { dbp := New(pid) kret := C.acquire_mach_task(C.int(pid), @@ -155,7 +154,7 @@ func Attach(pid int) (*Process, error) { return nil, err } - dbp, err = initializeDebugProcess(dbp, "") + err = dbp.initialize("", []string{}) if err != nil { dbp.Detach(false) return nil, err @@ -383,10 +382,6 @@ func (dbp *Process) waitForStop() ([]int, error) { } } -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) @@ -464,7 +459,9 @@ func (dbp *Process) detach(kill bool) error { return PtraceDetach(dbp.pid, 0) } -func (dbp *Process) entryPoint() (uint64, error) { +func (dbp *Process) EntryPoint() (uint64, error) { //TODO(aarzilli): implement this return 0, nil } + +func initialize(dbp *Process) error { return nil } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.h b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.h similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.h rename to vendor/github.com/go-delve/delve/pkg/proc/native/proc_darwin.h diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_linux.go b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_linux.go similarity index 90% rename from vendor/github.com/derekparker/delve/pkg/proc/native/proc_linux.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/proc_linux.go index 6527f3e..81be437 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_linux.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_linux.go @@ -12,15 +12,15 @@ import ( "regexp" "strconv" "strings" - "sync" "syscall" "time" sys "golang.org/x/sys/unix" - "github.com/derekparker/delve/pkg/proc" - "github.com/derekparker/delve/pkg/proc/linutil" - "github.com/mattn/go-isatty" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" + + isatty "github.com/mattn/go-isatty" ) // Process statuses @@ -46,7 +46,9 @@ type OSProcessDetails struct { // 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, foreground bool) (*Process, error) { +// If the DWARF information cannot be found in the binary, Delve will look +// for external debug files in the directories passed in. +func Launch(cmd []string, wd string, foreground bool, debugInfoDirs []string) (*Process, error) { var ( process *exec.Cmd err error @@ -88,11 +90,16 @@ func Launch(cmd []string, wd string, foreground bool) (*Process, error) { if err != nil { return nil, fmt.Errorf("waiting for target execve failed: %s", err) } - return initializeDebugProcess(dbp, process.Path) + if err = dbp.initialize(cmd[0], debugInfoDirs); err != nil { + return nil, err + } + return dbp, nil } -// Attach to an existing process with the given PID. -func Attach(pid int) (*Process, error) { +// Attach to an existing process with the given PID. Once attached, if +// the DWARF information cannot be found in the binary, Delve will look +// for external debug files in the directories passed in. +func Attach(pid int, debugInfoDirs []string) (*Process, error) { dbp := New(pid) dbp.common = proc.NewCommonProcess(true) @@ -106,7 +113,7 @@ func Attach(pid int) (*Process, error) { return nil, err } - dbp, err = initializeDebugProcess(dbp, "") + err = dbp.initialize(findExecutable("", dbp.pid), debugInfoDirs) if err != nil { dbp.Detach(false) return nil, err @@ -114,6 +121,33 @@ func Attach(pid int) (*Process, error) { return dbp, nil } +func initialize(dbp *Process) error { + 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 { + return fmt.Errorf("could not read proc stat: %v", err) + } + expr := fmt.Sprintf("%d\\s*\\((.*)\\)", dbp.pid) + rexp, err := regexp.Compile(expr) + if err != nil { + return fmt.Errorf("regexp compile error: %v", err) + } + match := rexp.FindSubmatch(stat) + if match == nil { + return fmt.Errorf("no match found using regexp '%s' in /proc/%d/stat", expr, dbp.pid) + } + comm = match[1] + } + dbp.os.comm = strings.Replace(string(comm), "%", "%%", -1) + return nil +} + // kill kills the target process. func (dbp *Process) kill() (err error) { if dbp.exited { @@ -199,7 +233,7 @@ func (dbp *Process) updateThreadList() error { return err } } - return nil + return linutil.ElfUpdateSharedObjects(dbp) } func findExecutable(path string, pid int) string { @@ -295,35 +329,7 @@ func (dbp *Process) trapWaitInternal(pid int, halt bool) (*Thread, error) { } } -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 (dbp *Process) loadProcessInformation() { } func status(pid int, comm string) rune { @@ -447,6 +453,10 @@ func (dbp *Process) stop(trapthread *Thread) (err error) { } } + if err := linutil.ElfUpdateSharedObjects(dbp); err != nil { + return err + } + // set breakpoints on all threads for _, th := range dbp.threads { if th.CurrentBreakpoint.Breakpoint == nil { @@ -479,7 +489,9 @@ func (dbp *Process) detach(kill bool) error { return nil } -func (dbp *Process) entryPoint() (uint64, error) { +// EntryPoint will return the process entry point address, useful for +// debugging PIEs. +func (dbp *Process) EntryPoint() (uint64, error) { auxvbuf, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/auxv", dbp.pid)) if err != nil { return 0, fmt.Errorf("could not read auxiliary vector: %v", err) diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_windows.go b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_windows.go similarity index 93% rename from vendor/github.com/derekparker/delve/pkg/proc/native/proc_windows.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/proc_windows.go index 7cf7482..c204a5c 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/proc_windows.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/proc_windows.go @@ -7,13 +7,12 @@ import ( "os" "os/exec" "path/filepath" - "sync" "syscall" "unsafe" sys "golang.org/x/sys/windows" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // OSProcessDetails holds Windows specific information. @@ -37,7 +36,7 @@ func openExecutablePathPE(path string) (*pe.File, io.Closer, error) { } // Launch creates and begins debugging a new process. -func Launch(cmd []string, wd string, foreground bool) (*Process, error) { +func Launch(cmd []string, wd string, foreground bool, _ []string) (*Process, error) { argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err @@ -77,11 +76,14 @@ func Launch(cmd []string, wd string, foreground bool) (*Process, error) { dbp.pid = p.Pid dbp.childProcess = true - return newDebugProcess(dbp, argv0Go) + if err = dbp.initialize(argv0Go, []string{}); err != nil { + dbp.Detach(true) + return nil, err + } + return dbp, nil } -// newDebugProcess prepares process pid for debugging. -func newDebugProcess(dbp *Process, exepath string) (*Process, error) { +func initialize(dbp *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 @@ -93,29 +95,25 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) { tid, exitCode, err = dbp.waitForDebugEvent(waitBlocking) }) if err != nil { - return nil, err + return err } if tid == 0 { dbp.postExit() - return nil, proc.ErrProcessExited{Pid: dbp.pid, Status: exitCode} + return proc.ErrProcessExited{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 + return 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) + return err } // findExePath searches for process pid, and returns its executable path. @@ -153,7 +151,7 @@ func findExePath(pid int) (string, error) { } // Attach to an existing process with the given PID. -func Attach(pid int) (*Process, error) { +func Attach(pid int, _ []string) (*Process, error) { // TODO: Probably should have SeDebugPrivilege before starting here. err := _DebugActiveProcess(uint32(pid)) if err != nil { @@ -163,11 +161,9 @@ func Attach(pid int) (*Process, error) { if err != nil { return nil, err } - dbp, err := newDebugProcess(New(pid), exepath) - if err != nil { - if dbp != nil { - dbp.Detach(false) - } + dbp := New(pid) + if err = dbp.initialize(exepath, []string{}); err != nil { + dbp.Detach(true) return nil, err } return dbp, nil @@ -245,6 +241,8 @@ const ( waitDontHandleExceptions ) +const _MS_VC_EXCEPTION = 0x406D1388 // part of VisualC protocol to set thread names + func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, exitCode int, err error) { var debugEvent _DEBUG_EVENT shouldExit := false @@ -346,6 +344,10 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e case _EXCEPTION_SINGLE_STEP: dbp.os.breakThread = tid return tid, 0, nil + case _MS_VC_EXCEPTION: + // This exception is sent to set the thread name in VisualC, we should + // mask it or it might crash the program. + continueStatus = _DBG_CONTINUE default: continueStatus = _DBG_EXCEPTION_NOT_HANDLED } @@ -386,10 +388,6 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { 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") } @@ -482,7 +480,7 @@ func (dbp *Process) detach(kill bool) error { return _DebugActiveProcessStop(uint32(dbp.pid)) } -func (dbp *Process) entryPoint() (uint64, error) { +func (dbp *Process) EntryPoint() (uint64, error) { return dbp.os.entryPoint, nil } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_darwin.go b/vendor/github.com/go-delve/delve/pkg/proc/native/ptrace_darwin.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_darwin.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/ptrace_darwin.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_linux.go b/vendor/github.com/go-delve/delve/pkg/proc/native/ptrace_linux.go similarity index 84% rename from vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_linux.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/ptrace_linux.go index c456987..8c33dd3 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_linux.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/ptrace_linux.go @@ -6,7 +6,7 @@ import ( sys "golang.org/x/sys/unix" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" ) // PtraceAttach executes the sys.PtraceAttach call. @@ -57,8 +57,8 @@ func PtracePeekUser(tid int, off uintptr) (uintptr, error) { // 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 proc.LinuxX86Xstate, err error) { - _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(®set.PtraceFpRegs)), 0, 0) +func PtraceGetRegset(tid int) (regset linutil.AMD64Xstate, err error) { + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(®set.AMD64PtraceFpRegs)), 0, 0) if err == syscall.Errno(0) || err == syscall.ENODEV { // ignore ENODEV, it just means this CPU doesn't have X87 registers (??) err = nil @@ -68,8 +68,9 @@ func PtraceGetRegset(tid int) (regset proc.LinuxX86Xstate, err error) { 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) { - if err == syscall.ENODEV { - // ignore ENODEV, it just means this CPU or kernel doesn't support XSTATE, see https://github.com/derekparker/delve/issues/1022 + if err == syscall.ENODEV || err == syscall.EIO { + // ignore ENODEV, it just means this CPU or kernel doesn't support XSTATE, see https://github.com/go-delve/delve/issues/1022 + // also ignore EIO, it means that we are running on an old kernel (pre 2.6.34) and PTRACE_GETREGSET is not implemented err = nil } return @@ -78,6 +79,6 @@ func PtraceGetRegset(tid int) (regset proc.LinuxX86Xstate, err error) { } regset.Xsave = xstateargs[:iov.Len] - err = proc.LinuxX86XstateRead(regset.Xsave, false, ®set) + err = linutil.AMD64XstateRead(regset.Xsave, false, ®set) return regset, err } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/registers_darwin_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/native/registers_darwin_amd64.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/proc/native/registers_darwin_amd64.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/registers_darwin_amd64.go index 16fa847..fec7066 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/registers_darwin_amd64.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/registers_darwin_amd64.go @@ -12,7 +12,7 @@ import ( "golang.org/x/arch/x86/x86asm" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // Regs represents CPU registers on an AMD64 processor. @@ -42,7 +42,7 @@ type Regs struct { fpregs []proc.Register } -func (r *Regs) Slice() []proc.Register { +func (r *Regs) Slice(floatingPoint bool) []proc.Register { var regs = []struct { k string v uint64 @@ -78,7 +78,9 @@ func (r *Regs) Slice() []proc.Register { out = proc.AppendQwordReg(out, reg.k, reg.v) } } - out = append(out, r.fpregs...) + if floatingPoint { + out = append(out, r.fpregs...) + } return out } diff --git a/vendor/github.com/go-delve/delve/pkg/proc/native/registers_linux_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/native/registers_linux_amd64.go new file mode 100644 index 0000000..276d599 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/registers_linux_amd64.go @@ -0,0 +1,87 @@ +package native + +import ( + "fmt" + + sys "golang.org/x/sys/unix" + + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" +) + +// SetPC sets RIP to the value specified by 'pc'. +func (thread *Thread) SetPC(pc uint64) error { + ir, err := registers(thread, false) + if err != nil { + return err + } + r := ir.(*linutil.AMD64Registers) + r.Regs.Rip = pc + thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, (*sys.PtraceRegs)(r.Regs)) }) + return err +} + +// SetSP sets RSP to the value specified by 'sp' +func (thread *Thread) SetSP(sp uint64) (err error) { + var ir proc.Registers + ir, err = registers(thread, false) + if err != nil { + return err + } + r := ir.(*linutil.AMD64Registers) + r.Regs.Rsp = sp + thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, (*sys.PtraceRegs)(r.Regs)) }) + return +} + +func (thread *Thread) SetDX(dx uint64) (err error) { + var ir proc.Registers + ir, err = registers(thread, false) + if err != nil { + return err + } + r := ir.(*linutil.AMD64Registers) + r.Regs.Rdx = dx + thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, (*sys.PtraceRegs)(r.Regs)) }) + return +} + +func registers(thread *Thread, floatingPoint bool) (proc.Registers, error) { + var ( + regs linutil.AMD64PtraceRegs + err error + ) + thread.dbp.execPtraceFunc(func() { err = sys.PtraceGetRegs(thread.ID, (*sys.PtraceRegs)(®s)) }) + if err != nil { + return nil, err + } + r := &linutil.AMD64Registers{®s, nil, nil} + if floatingPoint { + var fpregset linutil.AMD64Xstate + r.Fpregs, fpregset, err = thread.fpRegisters() + r.Fpregset = &fpregset + if err != nil { + return nil, err + } + } + return r, nil +} + +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 []proc.Register, fpregs linutil.AMD64Xstate, err error) { + thread.dbp.execPtraceFunc(func() { fpregs, err = PtraceGetRegset(thread.ID) }) + regs = fpregs.Decode() + if err != nil { + err = fmt.Errorf("could not get floating point registers: %v", err.Error()) + } + return +} diff --git a/vendor/github.com/go-delve/delve/pkg/proc/native/registers_windows_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/native/registers_windows_amd64.go new file mode 100644 index 0000000..32a56e8 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/registers_windows_amd64.go @@ -0,0 +1,71 @@ +package native + +import ( + "fmt" + "unsafe" + + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/winutil" +) + +// SetPC sets the RIP register to the value specified by `pc`. +func (thread *Thread) SetPC(pc uint64) error { + context := winutil.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) +} + +// SetSP sets the RSP register to the value specified by `sp`. +func (thread *Thread) SetSP(sp uint64) error { + context := winutil.NewCONTEXT() + context.ContextFlags = _CONTEXT_ALL + + err := _GetThreadContext(thread.os.hThread, context) + if err != nil { + return err + } + + context.Rsp = sp + + return _SetThreadContext(thread.os.hThread, context) +} + +func (thread *Thread) SetDX(dx uint64) error { + context := winutil.NewCONTEXT() + context.ContextFlags = _CONTEXT_ALL + + err := _GetThreadContext(thread.os.hThread, context) + if err != nil { + return err + } + + context.Rdx = dx + + return _SetThreadContext(thread.os.hThread, context) +} + +func registers(thread *Thread, floatingPoint bool) (proc.Registers, error) { + context := winutil.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) + } + + return winutil.NewAMD64Registers(context, uint64(threadInfo.TebBaseAddress), floatingPoint), nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows.go b/vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows.go similarity index 93% rename from vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows.go index 03fdc52..b066a1b 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows.go @@ -4,6 +4,8 @@ package native import ( "syscall" + + "github.com/go-delve/delve/pkg/proc/winutil" ) type _NTSTATUS int32 @@ -97,6 +99,11 @@ func _NT_SUCCESS(x _NTSTATUS) bool { return x >= 0 } +// zsyscall_windows.go, an autogenerated file, wants to refer to the context +// structure as _CONTEXT, but we need to have it in pkg/proc/winutil.CONTEXT +// because it's also used on non-windows operating systems. +type _CONTEXT = winutil.CONTEXT + //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 diff --git a/vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows_amd64.go new file mode 100644 index 0000000..5aa7da9 --- /dev/null +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/syscall_windows_amd64.go @@ -0,0 +1,24 @@ +package native + +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 _DEBUG_EVENT struct { + DebugEventCode uint32 + ProcessId uint32 + ThreadId uint32 + _ uint32 // to align Union properly + U [160]byte +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/threads.go b/vendor/github.com/go-delve/delve/pkg/proc/native/threads.go similarity index 99% rename from vendor/github.com/derekparker/delve/pkg/proc/native/threads.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/threads.go index 07c835e..6f639d6 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/threads.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/threads.go @@ -3,7 +3,7 @@ package native import ( "fmt" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // Thread represents a single thread in the traced process diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.c b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.c similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.c rename to vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.c diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.go b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.go index bf422ab..9aeea20 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.go @@ -12,7 +12,7 @@ import ( sys "golang.org/x/sys/unix" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // WaitStatus is a synonym for the platform-specific WaitStatus diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.h b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.h similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.h rename to vendor/github.com/go-delve/delve/pkg/proc/native/threads_darwin.h diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_linux.go b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_linux.go similarity index 88% rename from vendor/github.com/derekparker/delve/pkg/proc/native/threads_linux.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/threads_linux.go index 6e0da76..d33141c 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_linux.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_linux.go @@ -7,7 +7,8 @@ import ( sys "golang.org/x/sys/unix" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" ) type WaitStatus sys.WaitStatus @@ -83,21 +84,21 @@ func (t *Thread) Blocked() bool { } func (t *Thread) restoreRegisters(savedRegs proc.Registers) error { - sr := savedRegs.(*Regs) + sr := savedRegs.(*linutil.AMD64Registers) var restoreRegistersErr error t.dbp.execPtraceFunc(func() { - restoreRegistersErr = sys.PtraceSetRegs(t.ID, sr.regs) + restoreRegistersErr = sys.PtraceSetRegs(t.ID, (*sys.PtraceRegs)(sr.Regs)) if restoreRegistersErr != nil { return } - if sr.fpregset.Xsave != nil { - iov := sys.Iovec{Base: &sr.fpregset.Xsave[0], Len: uint64(len(sr.fpregset.Xsave))} + if sr.Fpregset.Xsave != nil { + iov := sys.Iovec{Base: &sr.Fpregset.Xsave[0], Len: uint64(len(sr.Fpregset.Xsave))} _, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(t.ID), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0) return } - _, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETFPREGS, uintptr(t.ID), uintptr(0), uintptr(unsafe.Pointer(&sr.fpregset.PtraceFpRegs)), 0, 0) + _, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETFPREGS, uintptr(t.ID), uintptr(0), uintptr(unsafe.Pointer(&sr.Fpregset.AMD64PtraceFpRegs)), 0, 0) return }) if restoreRegistersErr == syscall.Errno(0) { diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_windows.go b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_windows.go similarity index 94% rename from vendor/github.com/derekparker/delve/pkg/proc/native/threads_windows.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/threads_windows.go index 8a43dbc..899962b 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/threads_windows.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/native/threads_windows.go @@ -6,7 +6,8 @@ import ( sys "golang.org/x/sys/windows" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/winutil" ) // WaitStatus is a synonym for the platform-specific WaitStatus @@ -19,7 +20,7 @@ type OSSpecificDetails struct { } func (t *Thread) singleStep() error { - context := newCONTEXT() + context := winutil.NewCONTEXT() context.ContextFlags = _CONTEXT_ALL // Set the processor TRAP flag @@ -154,5 +155,5 @@ func (t *Thread) ReadMemory(buf []byte, addr uintptr) (int, error) { } func (t *Thread) restoreRegisters(savedRegs proc.Registers) error { - return _SetThreadContext(t.os.hThread, savedRegs.(*Regs).context) + return _SetThreadContext(t.os.hThread, savedRegs.(*winutil.AMD64Registers).Context) } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/zsyscall_windows.go b/vendor/github.com/go-delve/delve/pkg/proc/native/zsyscall_windows.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/proc/native/zsyscall_windows.go rename to vendor/github.com/go-delve/delve/pkg/proc/native/zsyscall_windows.go diff --git a/vendor/github.com/derekparker/delve/pkg/proc/proc.go b/vendor/github.com/go-delve/delve/pkg/proc/proc.go similarity index 74% rename from vendor/github.com/derekparker/delve/pkg/proc/proc.go rename to vendor/github.com/go-delve/delve/pkg/proc/proc.go index 4984387..19eb76c 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/proc.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/proc.go @@ -19,8 +19,16 @@ var ErrNotExecutable = errors.New("not an executable file") // only possible on recorded (traced) programs. var ErrNotRecorded = errors.New("not a recording") -// UnrecoveredPanic is the name given to the unrecovered panic breakpoint. -const UnrecoveredPanic = "unrecovered-panic" +const ( + // UnrecoveredPanic is the name given to the unrecovered panic breakpoint. + UnrecoveredPanic = "unrecovered-panic" + + // FatalThrow is the name given to the breakpoint triggered when the target process dies because of a fatal runtime error + FatalThrow = "runtime-fatal-throw" + + unrecoveredPanicID = -1 + fatalThrowID = -2 +) // ErrProcessExited indicates that the process has exited and contains both // process id and exit status. @@ -41,6 +49,31 @@ func (pe ProcessDetachedError) Error() string { return "detached from the process" } +// PostInitializationSetup handles all of the initialization procedures +// that must happen after Delve creates or attaches to a process. +func PostInitializationSetup(p Process, path string, debugInfoDirs []string, writeBreakpoint WriteBreakpointFn) error { + entryPoint, err := p.EntryPoint() + if err != nil { + return err + } + + err = p.BinInfo().LoadBinaryInfo(path, entryPoint, debugInfoDirs) + if err == nil { + err = p.BinInfo().LoadError() + } + if err != nil { + return err + } + + g, _ := GetG(p.CurrentThread()) + p.SetSelectedGoroutine(g) + + createUnrecoveredPanicBreakpoint(p, writeBreakpoint) + createFatalThrowBreakpoint(p, writeBreakpoint) + + return nil +} + // FindFileLocation returns the PC for a given file:line. // Assumes that `file` is normalized to lower case and '/' on Windows. func FindFileLocation(p Process, fileName string, lineno int) (uint64, error) { @@ -69,7 +102,7 @@ func (err *ErrFunctionNotFound) Error() string { // 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 +// https://github.com/go-delve/delve/issues/170 func FindFunctionLocation(p Process, funcName string, firstLine bool, lineOffset int) (uint64, error) { bi := p.BinInfo() origfn := bi.LookupFunc[funcName] @@ -88,6 +121,33 @@ func FindFunctionLocation(p Process, funcName string, firstLine bool, lineOffset return origfn.Entry, nil } +// FunctionReturnLocations will return a list of addresses corresponding +// to 'ret' or 'call runtime.deferreturn'. +func FunctionReturnLocations(p Process, funcName string) ([]uint64, error) { + const deferReturn = "runtime.deferreturn" + + g := p.SelectedGoroutine() + fn, ok := p.BinInfo().LookupFunc[funcName] + if !ok { + return nil, fmt.Errorf("unable to find function %s", funcName) + } + + instructions, err := Disassemble(p, g, fn.Entry, fn.End) + if err != nil { + return nil, err + } + + var addrs []uint64 + for _, instruction := range instructions { + if instruction.IsRet() { + addrs = append(addrs, instruction.Loc.PC) + } + } + addrs = append(addrs, findDeferReturnCalls(instructions)...) + + return addrs, nil +} + // Next continues execution until the next source line. func Next(dbp Process) (err error) { if _, err := dbp.Valid(); err != nil { @@ -184,7 +244,8 @@ func Continue(dbp Process) error { return conditionErrors(threads) } case curbp.Active && curbp.Internal: - if curbp.Kind == StepBreakpoint { + switch curbp.Kind { + case StepBreakpoint: // See description of proc.(*Process).next for the meaning of StepBreakpoints if err := conditionErrors(threads); err != nil { return err @@ -204,7 +265,7 @@ func Continue(dbp Process) error { if err = setStepIntoBreakpoint(dbp, text, SameGoroutineCondition(dbp.SelectedGoroutine())); err != nil { return err } - } else { + default: curthread.Common().returnValues = curbp.Breakpoint.returnInfo.Collect(curthread) if err := dbp.ClearInternalBreakpoints(); err != nil { return err @@ -281,7 +342,7 @@ func stepInstructionOut(dbp Process, curthread Thread, fnname1, fnname2 string) if g := dbp.SelectedGoroutine(); g != nil { g.CurrentLoc = *loc } - return nil + return curthread.SetCurrentBreakpoint() } } } @@ -436,14 +497,22 @@ func StepOut(dbp Process) error { return Continue(dbp) } -// GoroutinesInfo returns an array of G structures representing the information -// Delve cares about from the internal runtime G structure. -func GoroutinesInfo(dbp Process) ([]*G, error) { +// GoroutinesInfo searches for goroutines starting at index 'start', and +// returns an array of up to 'count' (or all found elements, if 'count' is 0) +// G structures representing the information Delve care about from the internal +// runtime G structure. +// GoroutinesInfo also returns the next index to be used as 'start' argument +// while scanning for all available goroutines, or -1 if there was an error +// or if the index already reached the last possible value. +func GoroutinesInfo(dbp Process, start, count int) ([]*G, int, error) { if _, err := dbp.Valid(); err != nil { - return nil, err + return nil, -1, err } if dbp.Common().allGCache != nil { - return dbp.Common().allGCache, nil + // We can't use the cached array to fulfill a subrange request + if start == 0 && (count == 0 || count >= len(dbp.Common().allGCache)) { + return dbp.Common().allGCache, -1, nil + } } var ( @@ -465,12 +534,12 @@ func GoroutinesInfo(dbp Process) ([]*G, error) { addr, err := rdr.AddrFor("runtime.allglen", dbp.BinInfo().staticBase) if err != nil { - return nil, err + return nil, -1, err } allglenBytes := make([]byte, 8) _, err = dbp.CurrentThread().ReadMemory(allglenBytes, uintptr(addr)) if err != nil { - return nil, err + return nil, -1, err } allglen := binary.LittleEndian.Uint64(allglenBytes) @@ -480,17 +549,20 @@ func GoroutinesInfo(dbp Process) ([]*G, error) { // try old name (pre Go 1.6) allgentryaddr, err = rdr.AddrFor("runtime.allg", dbp.BinInfo().staticBase) if err != nil { - return nil, err + return nil, -1, err } } faddr := make([]byte, dbp.BinInfo().Arch.PtrSize()) _, err = dbp.CurrentThread().ReadMemory(faddr, uintptr(allgentryaddr)) if err != nil { - return nil, err + return nil, -1, err } allgptr := binary.LittleEndian.Uint64(faddr) - for i := uint64(0); i < allglen; i++ { + for i := uint64(start); i < allglen; i++ { + if count != 0 && len(allg) >= count { + return allg, int(i), nil + } gvar, err := newGVariable(dbp.CurrentThread(), uintptr(allgptr+(i*uint64(dbp.BinInfo().Arch.PtrSize()))), true) if err != nil { allg = append(allg, &G{Unreadable: err}) @@ -504,7 +576,7 @@ func GoroutinesInfo(dbp Process) ([]*G, error) { if thg, allocated := threadg[g.ID]; allocated { loc, err := thg.Thread.Location() if err != nil { - return nil, err + return nil, -1, err } g.Thread = thg.Thread // Prefer actual thread location information. @@ -515,36 +587,78 @@ func GoroutinesInfo(dbp Process) ([]*G, error) { allg = append(allg, g) } } - dbp.Common().allGCache = allg + if start == 0 { + dbp.Common().allGCache = allg + } - return allg, nil + return allg, -1, nil } // FindGoroutine returns a G struct representing the goroutine // specified by `gid`. func FindGoroutine(dbp Process, gid int) (*G, error) { - if gid == -1 { - return dbp.SelectedGoroutine(), nil + if selg := dbp.SelectedGoroutine(); (gid == -1) || (selg != nil && selg.ID == gid) || (selg == nil && gid == 0) { + // Return the currently selected goroutine in the following circumstances: + // + // 1. if the caller asks for gid == -1 (because that's what a goroutine ID of -1 means in our API). + // 2. if gid == selg.ID. + // this serves two purposes: (a) it's an optimizations that allows us + // to avoid reading any other goroutine and, more importantly, (b) we + // could be reading an incorrect value for the goroutine ID of a thread. + // This condition usually happens when a goroutine calls runtime.clone + // and for a short period of time two threads will appear to be running + // the same goroutine. + // 3. if the caller asks for gid == 0 and the selected goroutine is + // either 0 or nil. + // Goroutine 0 is special, it either means we have no current goroutine + // (for example, running C code), or that we are running on a speical + // stack (system stack, signal handling stack) and we didn't properly + // detect it. + // Since there could be multiple goroutines '0' running simultaneously + // if the user requests it return the one that's already selected or + // nil if there isn't a selected goroutine. + return selg, nil } - gs, err := GoroutinesInfo(dbp) - if err != nil { - return nil, err + if gid == 0 { + return nil, fmt.Errorf("Unknown goroutine %d", gid) } - for i := range gs { - if gs[i].ID == gid { - if gs[i].Unreadable != nil { - return nil, gs[i].Unreadable - } - return gs[i], nil + + // Calling GoroutinesInfo could be slow if there are many goroutines + // running, check if a running goroutine has been requested first. + for _, thread := range dbp.ThreadList() { + g, _ := GetG(thread) + if g != nil && g.ID == gid { + return g, nil } } + + const goroutinesInfoLimit = 10 + nextg := 0 + for nextg >= 0 { + var gs []*G + var err error + gs, nextg, err = GoroutinesInfo(dbp, nextg, goroutinesInfoLimit) + if err != nil { + return nil, err + } + for i := range gs { + if gs[i].ID == gid { + if gs[i].Unreadable != nil { + return nil, gs[i].Unreadable + } + 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 ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) { +// If deferCall is > 0 the eval scope will be relative to the specified deferred call. +func ConvertEvalScope(dbp Process, gid, frame, deferCall int) (*EvalScope, error) { if _, err := dbp.Valid(); err != nil { return nil, err } @@ -564,7 +678,7 @@ func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) { thread = g.Thread } - locs, err := g.Stacktrace(frame+1, false) + locs, err := g.Stacktrace(frame+1, deferCall > 0) if err != nil { return nil, err } @@ -573,6 +687,19 @@ func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) { return nil, fmt.Errorf("Frame %d does not exist in goroutine %d", frame, gid) } + if deferCall > 0 { + if deferCall-1 >= len(locs[frame].Defers) { + return nil, fmt.Errorf("Frame %d only has %d deferred calls", frame, len(locs[frame].Defers)) + } + + d := locs[frame].Defers[deferCall-1] + if d.Unreadable != nil { + return nil, d.Unreadable + } + + return d.EvalScope(ct) + } + return FrameToScope(dbp.BinInfo(), thread, g, locs[frame:]...), nil } @@ -606,21 +733,30 @@ func FrameToScope(bi *BinaryInfo, thread MemoryReadWriter, g *G, frames ...Stack return s } -// CreateUnrecoveredPanicBreakpoint creates the unrecoverable-panic breakpoint. +// createUnrecoveredPanicBreakpoint creates the unrecoverable-panic breakpoint. // This function is meant to be called by implementations of the Process interface. -func CreateUnrecoveredPanicBreakpoint(p Process, writeBreakpoint writeBreakpointFn, breakpoints *BreakpointMap) { +func createUnrecoveredPanicBreakpoint(p Process, writeBreakpoint WriteBreakpointFn) { panicpc, err := FindFunctionLocation(p, "runtime.startpanic", true, 0) if _, isFnNotFound := err.(*ErrFunctionNotFound); isFnNotFound { panicpc, err = FindFunctionLocation(p, "runtime.fatalpanic", true, 0) } if err == nil { - bp, err := breakpoints.SetWithID(-1, panicpc, writeBreakpoint) + bp, err := p.Breakpoints().SetWithID(unrecoveredPanicID, panicpc, writeBreakpoint) if err == nil { bp.Name = UnrecoveredPanic bp.Variables = []string{"runtime.curg._panic.arg"} } } +} +func createFatalThrowBreakpoint(p Process, writeBreakpoint WriteBreakpointFn) { + fatalpc, err := FindFunctionLocation(p, "runtime.fatalthrow", true, 0) + if err == nil { + bp, err := p.Breakpoints().SetWithID(fatalThrowID, fatalpc, writeBreakpoint) + if err == nil { + bp.Name = FatalThrow + } + } } // FirstPCAfterPrologue returns the address of the first diff --git a/vendor/github.com/derekparker/delve/pkg/proc/registers.go b/vendor/github.com/go-delve/delve/pkg/proc/registers.go similarity index 70% rename from vendor/github.com/derekparker/delve/pkg/proc/registers.go rename to vendor/github.com/go-delve/delve/pkg/proc/registers.go index 1826762..7776523 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/registers.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/registers.go @@ -23,7 +23,7 @@ type Registers interface { // GAddr returns the address of the G variable if it is known, 0 and false otherwise GAddr() (uint64, bool) Get(int) (uint64, error) - Slice() []Register + Slice(floatingPoint bool) []Register // Copy returns a copy of the registers that is guaranteed not to change // when the registers of the associated thread change. Copy() Registers @@ -250,99 +250,3 @@ func (descr flagRegisterDescr) Describe(reg uint64, bitsize int) string { } return fmt.Sprintf("%#0*x\t[%s]", bitsize/4, reg, strings.Join(r, " ")) } - -// PtraceFpRegs 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 -} - -// LinuxX86Xstate represents amd64 XSAVE area. See Section 13.1 (and -// following) of Intel® 64 and IA-32 Architectures Software Developer’s -// Manual, Volume 1: Basic Architecture. -type LinuxX86Xstate struct { - PtraceFpRegs - Xsave []byte // raw xsave area - AvxState bool // contains AVX state - YmmSpace [256]byte -} - -// Decode decodes an XSAVE area to a list of name/value pairs of registers. -func (xsave *LinuxX86Xstate) Decode() (regs []Register) { - // x87 registers - regs = AppendWordReg(regs, "CW", xsave.Cwd) - regs = AppendWordReg(regs, "SW", xsave.Swd) - regs = AppendWordReg(regs, "TW", xsave.Ftw) - regs = AppendWordReg(regs, "FOP", xsave.Fop) - regs = AppendQwordReg(regs, "FIP", xsave.Rip) - regs = AppendQwordReg(regs, "FDP", xsave.Rdp) - - for i := 0; i < len(xsave.StSpace); i += 4 { - regs = AppendX87Reg(regs, i/4, uint16(xsave.StSpace[i+2]), uint64(xsave.StSpace[i+1])<<32|uint64(xsave.StSpace[i])) - } - - // SSE registers - regs = AppendMxcsrReg(regs, "MXCSR", uint64(xsave.Mxcsr)) - regs = AppendDwordReg(regs, "MXCSR_MASK", xsave.MxcrMask) - - for i := 0; i < len(xsave.XmmSpace); i += 16 { - regs = AppendSSEReg(regs, fmt.Sprintf("XMM%d", i/16), xsave.XmmSpace[i:i+16]) - if xsave.AvxState { - regs = AppendSSEReg(regs, fmt.Sprintf("YMM%d", i/16), xsave.YmmSpace[i:i+16]) - } - } - - return -} - -const ( - _XSAVE_HEADER_START = 512 - _XSAVE_HEADER_LEN = 64 - _XSAVE_EXTENDED_REGION_START = 576 - _XSAVE_SSE_REGION_LEN = 416 -) - -// LinuxX86XstateRead reads a byte array containing an XSAVE area into regset. -// If readLegacy is true regset.PtraceFpRegs will be filled with the -// contents of the legacy region of the XSAVE area. -// See Section 13.1 (and following) of Intel® 64 and IA-32 Architectures -// Software Developer’s Manual, Volume 1: Basic Architecture. -func LinuxX86XstateRead(xstateargs []byte, readLegacy bool, regset *LinuxX86Xstate) error { - if _XSAVE_HEADER_START+_XSAVE_HEADER_LEN >= len(xstateargs) { - return nil - } - if readLegacy { - rdr := bytes.NewReader(xstateargs[:_XSAVE_HEADER_START]) - if err := binary.Read(rdr, binary.LittleEndian, ®set.PtraceFpRegs); err != nil { - return err - } - } - 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 nil - } - - if xstate_bv&(1<<2) == 0 { - // AVX state not present - return nil - } - - avxstate := xstateargs[_XSAVE_EXTENDED_REGION_START:] - regset.AvxState = true - copy(regset.YmmSpace[:], avxstate[:len(regset.YmmSpace)]) - - return nil -} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/registers_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/registers_amd64.go similarity index 98% rename from vendor/github.com/derekparker/delve/pkg/proc/registers_amd64.go rename to vendor/github.com/go-delve/delve/pkg/proc/registers_amd64.go index fac817a..8ef4658 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/registers_amd64.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/registers_amd64.go @@ -79,7 +79,7 @@ func GetDwarfRegister(regs Registers, i int) []byte { return buf.Bytes() } if regname, ok := dwarfToName[i]; ok { - regslice := regs.Slice() + regslice := regs.Slice(true) for _, reg := range regslice { if reg.Name == regname { return reg.Bytes diff --git a/vendor/github.com/derekparker/delve/pkg/proc/stack.go b/vendor/github.com/go-delve/delve/pkg/proc/stack.go similarity index 89% rename from vendor/github.com/derekparker/delve/pkg/proc/stack.go rename to vendor/github.com/go-delve/delve/pkg/proc/stack.go index 07258f3..5de27fc 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/stack.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/stack.go @@ -7,9 +7,9 @@ import ( "go/constant" "strings" - "github.com/derekparker/delve/pkg/dwarf/frame" - "github.com/derekparker/delve/pkg/dwarf/op" - "github.com/derekparker/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/dwarf/frame" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/reader" ) // This code is partly adapted from runtime.gentraceback in @@ -375,36 +375,21 @@ func (it *stackIterator) newStackframe(ret, retaddr uint64) Stackframe { it.regs.FrameBase = it.frameBase(fn) } r := Stackframe{Current: Location{PC: it.pc, File: f, Line: l, Fn: fn}, Regs: it.regs, Ret: ret, addrret: retaddr, stackHi: it.stackhi, SystemStack: it.systemstack, lastpc: it.pc} - if !it.top { - fnname := "" - if r.Current.Fn != nil { - fnname = r.Current.Fn.Name - } - switch fnname { + r.Call = r.Current + if !it.top && r.Current.Fn != nil && it.pc != r.Current.Fn.Entry { + // if the return address is the entry point of the function that + // contains it then this is some kind of fake return frame (for example + // runtime.sigreturn) that didn't actually call the current frame, + // attempting to get the location of the CALL instruction would just + // obfuscate what's going on, since there is no CALL instruction. + switch r.Current.Fn.Name { case "runtime.mstart", "runtime.systemstack_switch": // these frames are inserted by runtime.systemstack and there is no CALL // instruction to look for at pc - 1 - r.Call = r.Current default: - if r.Current.Fn != nil && it.pc == r.Current.Fn.Entry { - // if the return address is the entry point of the function that - // contains it then this is some kind of fake return frame (for example - // runtime.sigreturn) that didn't actually call the current frame, - // attempting to get the location of the CALL instruction would just - // obfuscate what's going on, since there is no CALL instruction. - r.Call = r.Current - } else { - r.lastpc = it.pc - 1 - r.Call.File, r.Call.Line, r.Call.Fn = it.bi.PCToLine(it.pc - 1) - if r.Call.Fn == nil { - r.Call.File = "?" - r.Call.Line = -1 - } - r.Call.PC = r.Current.PC - } + r.lastpc = it.pc - 1 + r.Call.File, r.Call.Line = r.Current.Fn.cu.lineInfo.PCToLine(r.Current.Fn.Entry, it.pc-1) } - } else { - r.Call = r.Current } return r } @@ -594,6 +579,7 @@ type Defer struct { DeferPC uint64 // PC address of instruction that added this defer SP uint64 // Value of SP register when this function was deferred (this field gets adjusted when the stack is moved to match the new stack space) link *Defer // Next deferred function + argSz int64 variable *Variable Unreadable error @@ -644,7 +630,7 @@ func (g *G) readDefers(frames []Stackframe) { } func (d *Defer) load() { - d.variable.loadValue(LoadConfig{false, 1, 0, 0, -1}) + d.variable.loadValue(LoadConfig{false, 1, 0, 0, -1, 0}) if d.variable.Unreadable != nil { d.Unreadable = d.variable.Unreadable return @@ -660,6 +646,7 @@ func (d *Defer) load() { d.DeferPC, _ = constant.Uint64Val(d.variable.fieldVariable("pc").Value) d.SP, _ = constant.Uint64Val(d.variable.fieldVariable("sp").Value) + d.argSz, _ = constant.Int64Val(d.variable.fieldVariable("siz").Value) linkvar := d.variable.fieldVariable("link").maybeDereference() if linkvar.Addr != 0 { @@ -685,3 +672,40 @@ func (d *Defer) Next() *Defer { } return d.link } + +// EvalScope returns an EvalScope relative to the argument frame of this deferred call. +// The argument frame of a deferred call is stored in memory immediately +// after the deferred header. +func (d *Defer) EvalScope(thread Thread) (*EvalScope, error) { + scope, err := GoroutineScope(thread) + if err != nil { + return nil, fmt.Errorf("could not get scope: %v", err) + } + + bi := thread.BinInfo() + scope.PC = d.DeferredPC + scope.File, scope.Line, scope.Fn = bi.PCToLine(d.DeferredPC) + + if scope.Fn == nil { + return nil, fmt.Errorf("could not find function at %#x", d.DeferredPC) + } + + // The arguments are stored immediately after the defer header struct, i.e. + // addr+sizeof(_defer). Since CFA in go is always the address of the first + // argument, that's what we use for the value of CFA. + // For SP we use CFA minus the size of one pointer because that would be + // the space occupied by pushing the return address on the stack during the + // CALL. + scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize) + scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize())) + + bi.dwarfReader.Seek(scope.Fn.offset) + e, err := bi.dwarfReader.Next() + if err != nil { + return nil, fmt.Errorf("could not read DWARF function entry: %v", err) + } + scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs) + scope.Mem = cacheMemory(scope.Mem, uintptr(scope.Regs.CFA), int(d.argSz)) + + return scope, nil +} diff --git a/vendor/github.com/derekparker/delve/pkg/proc/threads.go b/vendor/github.com/go-delve/delve/pkg/proc/threads.go similarity index 91% rename from vendor/github.com/derekparker/delve/pkg/proc/threads.go rename to vendor/github.com/go-delve/delve/pkg/proc/threads.go index 3de30a8..b07df24 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/threads.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/threads.go @@ -10,8 +10,8 @@ import ( "reflect" "strings" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/reader" ) // Thread represents a thread. @@ -225,15 +225,7 @@ func next(dbp Process, stepInto, inlinedStepOut bool) error { } 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) - } - } + deferreturns := findDeferReturnCalls(text) // Set breakpoint on the most recently deferred function (if any) var deferpc uint64 @@ -333,6 +325,20 @@ func next(dbp Process, stepInto, inlinedStepOut bool) error { return nil } +func findDeferReturnCalls(text []AsmInstruction) []uint64 { + const deferreturn = "runtime.deferreturn" + 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 == deferreturn { + deferreturns = append(deferreturns, instr.Loc.PC) + } + } + return deferreturns +} + // Removes instructions belonging to inlined calls of topframe from pcs. // If includeCurrentFn is true it will also remove all instructions // belonging to the current function. @@ -373,21 +379,16 @@ func setStepIntoBreakpoint(dbp Process, text []AsmInstruction, cond ast.Expr) er instr := text[0] - if instr.DestLoc == nil || instr.DestLoc.Fn == nil { + if instr.DestLoc == nil { + // Call destination couldn't be resolved because this was not the + // current instruction, therefore the step-into breakpoint can not be set. 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) { + if fn != nil && strings.HasPrefix(fn.Name, "runtime.") && !isExportedRuntime(fn.Name) { return nil } @@ -395,8 +396,19 @@ func setStepIntoBreakpoint(dbp Process, text []AsmInstruction, cond ast.Expr) er // or entire packages from being stepped into with 'step' // those extra checks should be done here. + pc := instr.DestLoc.PC + + // We want to skip the function prologue but we should only do it if the + // destination address of the CALL instruction is the entry point of the + // function. + // Calls to runtime.duffzero and duffcopy inserted by the compiler can + // sometimes point inside the body of those functions, well after the + // prologue. + if fn != nil && fn.Entry == instr.DestLoc.PC { + pc, _ = FirstPCAfterPrologue(dbp, fn, false) + } + // Set a breakpoint after the function's prologue - pc, _ := FirstPCAfterPrologue(dbp, fn, false) if _, err := dbp.SetBreakpoint(pc, NextBreakpoint, cond); err != nil { if _, ok := err.(BreakpointExistsError); !ok { return err @@ -465,6 +477,10 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) { // 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 GetG(thread Thread) (*G, error) { + if loc, _ := thread.Location(); loc.Fn != nil && loc.Fn.Name == "runtime.clone" { + // When threads are executing runtime.clone the value of TLS is unreliable. + return nil, nil + } gaddr, err := getGVariable(thread) if err != nil { return nil, err diff --git a/vendor/github.com/derekparker/delve/pkg/proc/types.go b/vendor/github.com/go-delve/delve/pkg/proc/types.go similarity index 95% rename from vendor/github.com/derekparker/delve/pkg/proc/types.go rename to vendor/github.com/go-delve/delve/pkg/proc/types.go index 1a0c390..e87cb30 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/types.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/types.go @@ -8,7 +8,6 @@ import ( "fmt" "go/ast" "go/constant" - "go/parser" "go/token" "path/filepath" "reflect" @@ -18,12 +17,12 @@ import ( "sync" "unsafe" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/dwarf/line" - "github.com/derekparker/delve/pkg/dwarf/op" - "github.com/derekparker/delve/pkg/dwarf/reader" - "github.com/derekparker/delve/pkg/goversion" - "github.com/derekparker/delve/pkg/logflags" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/line" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/goversion" + "github.com/go-delve/delve/pkg/logflags" "github.com/sirupsen/logrus" ) @@ -180,7 +179,7 @@ func (v functionsDebugInfoByEntry) Swap(i, j int) { v[i], v[j] = v[j], v[i] type compileUnitsByLowpc []*compileUnit func (v compileUnitsByLowpc) Len() int { return len(v) } -func (v compileUnitsByLowpc) Less(i int, j int) bool { return v[i].LowPC < v[j].LowPC } +func (v compileUnitsByLowpc) Less(i int, j int) bool { return v[i].lowPC < v[j].lowPC } func (v compileUnitsByLowpc) Swap(i int, j int) { v[i], v[j] = v[j], v[i] } type packageVarsByAddr []packageVar @@ -230,18 +229,18 @@ outer: if lang, _ := entry.Val(dwarf.AttrLanguage).(int64); lang == dwarfGoLanguage { cu.isgo = true } - cu.Name, _ = entry.Val(dwarf.AttrName).(string) + cu.name, _ = entry.Val(dwarf.AttrName).(string) compdir, _ := entry.Val(dwarf.AttrCompDir).(string) if compdir != "" { - cu.Name = filepath.Join(compdir, cu.Name) + cu.name = filepath.Join(compdir, cu.name) } - cu.Ranges, _ = bi.dwarf.Ranges(entry) - for i := range cu.Ranges { - cu.Ranges[i][0] += bi.staticBase - cu.Ranges[i][1] += bi.staticBase + cu.ranges, _ = bi.dwarf.Ranges(entry) + for i := range cu.ranges { + cu.ranges[i][0] += bi.staticBase + cu.ranges[i][1] += bi.staticBase } - if len(cu.Ranges) >= 1 { - cu.LowPC = cu.Ranges[0][0] + if len(cu.ranges) >= 1 { + cu.lowPC = cu.ranges[0][0] } lineInfoOffset, _ := entry.Val(dwarf.AttrStmtList).(int64) if lineInfoOffset >= 0 && lineInfoOffset < int64(len(debugLineBytes)) { @@ -398,6 +397,13 @@ outer: highpc = ranges[0][1] + bi.staticBase } name, ok2 := entry.Val(dwarf.AttrName).(string) + if !ok2 { + originOffset, hasAbstractOrigin := entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset) + if hasAbstractOrigin { + name, ok2 = abstractOriginNameTable[originOffset] + } + } + var fn Function if (ok1 == !inlined) && ok2 { if inlined { @@ -559,45 +565,8 @@ func (bi *BinaryInfo) registerRuntimeTypeToDIE(entry *dwarf.Entry, ardr *reader. // * After go1.11 the runtimeTypeToDIE map is used to look up the address of // the type and map it drectly to a DIE. func runtimeTypeToDIE(_type *Variable, dataAddr uintptr) (typ godwarf.Type, kind int64, err error) { - var go17 bool - var typestring *Variable - bi := _type.bi - // Determine if we are in go1.7 or later - typestring, err = _type.structMember("_string") - if err == nil { - typestring = typestring.maybeDereference() - } else { - err = nil - go17 = true - } - - if !go17 { - // pre-go1.7 compatibility - if typestring == nil || typestring.Addr == 0 || typestring.Kind != reflect.String { - return nil, 0, fmt.Errorf("invalid interface type") - } - typestring.loadValue(LoadConfig{false, 0, 512, 0, 0}) - if typestring.Unreadable != nil { - return nil, 0, fmt.Errorf("invalid interface type: %v", typestring.Unreadable) - } - - typename := constant.StringVal(typestring.Value) - - t, err := parser.ParseExpr(typename) - if err != nil { - return nil, 0, fmt.Errorf("invalid interface type, unparsable data type: %v", err) - } - - typ, err := bi.findTypeExpr(t) - if err != nil { - return nil, 0, fmt.Errorf("interface type %q not found for %#x: %v", typename, dataAddr, err) - } - - return typ, 0, nil - } - _type = _type.maybeDereference() // go 1.11 implementation: use extended attribute in debug_info @@ -880,7 +849,7 @@ func nameOfInterfaceRuntimeType(_type *Variable, kind, tflag int64) (string, err buf.WriteString("interface {") methods, _ := _type.structMember(interfacetypeFieldMhdr) - methods.loadArrayValues(0, LoadConfig{false, 1, 0, 4096, -1}) + methods.loadArrayValues(0, LoadConfig{false, 1, 0, 4096, -1, 0}) if methods.Unreadable != nil { return "", nil } @@ -941,7 +910,7 @@ func nameOfStructRuntimeType(_type *Variable, kind, tflag int64) (string, error) buf.WriteString("struct {") fields, _ := _type.structMember("fields") - fields.loadArrayValues(0, LoadConfig{false, 2, 0, 4096, -1}) + fields.loadArrayValues(0, LoadConfig{false, 2, 0, 4096, -1, 0}) if fields.Unreadable != nil { return "", fields.Unreadable } diff --git a/vendor/github.com/derekparker/delve/pkg/proc/variables.go b/vendor/github.com/go-delve/delve/pkg/proc/variables.go similarity index 90% rename from vendor/github.com/derekparker/delve/pkg/proc/variables.go rename to vendor/github.com/go-delve/delve/pkg/proc/variables.go index a8da5f9..d044bcc 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/variables.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/variables.go @@ -15,9 +15,9 @@ import ( "strings" "unsafe" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/dwarf/op" - "github.com/derekparker/delve/pkg/dwarf/reader" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/reader" ) const ( @@ -32,6 +32,8 @@ const ( hashMinTopHash = 4 // used by map reading code, indicates minimum value of tophash that isn't empty or evacuated maxFramePrefetchSize = 1 * 1024 * 1024 // Maximum prefetch size for a stack frame + + maxMapBucketsFactor = 100 // Maximum numbers of map buckets to read for every requested map entry when loading variables through (*EvalScope).LocalVariables and (*EvalScope).FunctionArguments. ) type floatSpecial uint8 @@ -122,10 +124,39 @@ type LoadConfig struct { MaxArrayValues int // MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields. MaxStructFields int + + // MaxMapBuckets is the maximum number of map buckets to read before giving up. + // A value of 0 will read as many buckets as necessary until the entire map + // is read or MaxArrayValues is reached. + // + // Loading a map is an operation that issues O(num_buckets) operations. + // Normally the number of buckets is proportional to the number of elements + // in the map, since the runtime tries to keep the load factor of maps + // between 40% and 80%. + // + // It is possible, however, to create very sparse maps either by: + // a) adding lots of entries to a map and then deleting most of them, or + // b) using the make(mapType, N) expression with a very large N + // + // When this happens delve will have to scan many empty buckets to find the + // few entries in the map. + // MaxMapBuckets can be set to avoid annoying slowdowns␣while reading + // very sparse maps. + // + // Since there is no good way for a user of delve to specify the value of + // MaxMapBuckets, this field is not actually exposed through the API. + // Instead (*EvalScope).LocalVariables and (*EvalScope).FunctionArguments + // set this field automatically to MaxArrayValues * maxMapBucketsFactor. + // Every other invocation uses the default value of 0, obtaining the old behavior. + // In practice this means that debuggers using the ListLocalVars or + // ListFunctionArgs API will not experience a massive slowdown when a very + // sparse map is in scope, but evaluating a single variable will still work + // correctly, even if the variable in question is a very sparse map. + MaxMapBuckets int } -var loadSingleValue = LoadConfig{false, 0, 64, 0, 0} -var loadFullValue = LoadConfig{true, 1, 64, 64, -1} +var loadSingleValue = LoadConfig{false, 0, 64, 0, 0, 0} +var loadFullValue = LoadConfig{true, 1, 64, 64, -1, 0} // G status, from: src/runtime/runtime2.go const ( @@ -169,6 +200,12 @@ type G struct { Unreadable error // could not read the G struct } +type Ancestor struct { + ID int64 // Goroutine ID + Unreadable error + pcsVar *Variable +} + // EvalScope is the scope for variable evaluation. Contains the thread, // current location (PC), and canonical frame address. type EvalScope struct { @@ -405,13 +442,13 @@ func (scope *EvalScope) PtrSize() int { return scope.BinInfo.Arch.PtrSize() } -// NoGError returned when a G could not be found +// ErrNoGoroutine returned when a G could not be found // for a specific thread. -type NoGError struct { +type ErrNoGoroutine struct { tid int } -func (ng NoGError) Error() string { +func (ng ErrNoGoroutine) Error() string { return fmt.Sprintf("no G executing on thread %d", ng.tid) } @@ -433,7 +470,7 @@ func (v *Variable) parseG() (*G, error) { if thread, ok := mem.(Thread); ok { id = thread.ThreadID() } - return nil, NoGError{tid: id} + return nil, ErrNoGoroutine{tid: id} } for { if _, isptr := v.RealType.(*godwarf.PtrType); !isptr { @@ -441,7 +478,7 @@ func (v *Variable) parseG() (*G, error) { } v = v.maybeDereference() } - v.loadValue(LoadConfig{false, 2, 64, 0, -1}) + v.loadValue(LoadConfig{false, 2, 64, 0, -1, 0}) if v.Unreadable != nil { return nil, v.Unreadable } @@ -586,12 +623,102 @@ func (g *G) StartLoc() Location { return Location{PC: g.StartPC, File: f, Line: l, Fn: fn} } +var errTracebackAncestorsDisabled = errors.New("tracebackancestors is disabled") + +// Ancestors returns the list of ancestors for g. +func (g *G) Ancestors(n int) ([]Ancestor, error) { + scope := globalScope(g.Thread.BinInfo(), g.Thread) + tbav, err := scope.EvalExpression("runtime.debug.tracebackancestors", loadSingleValue) + if err == nil && tbav.Unreadable == nil && tbav.Kind == reflect.Int { + tba, _ := constant.Int64Val(tbav.Value) + if tba == 0 { + return nil, errTracebackAncestorsDisabled + } + } + + av, err := g.variable.structMember("ancestors") + if err != nil { + return nil, err + } + av = av.maybeDereference() + av.loadValue(LoadConfig{MaxArrayValues: n, MaxVariableRecurse: 1, MaxStructFields: -1}) + if av.Unreadable != nil { + return nil, err + } + if av.Addr == 0 { + // no ancestors + return nil, nil + } + + r := make([]Ancestor, len(av.Children)) + + for i := range av.Children { + if av.Children[i].Unreadable != nil { + r[i].Unreadable = av.Children[i].Unreadable + continue + } + goidv := av.Children[i].fieldVariable("goid") + if goidv.Unreadable != nil { + r[i].Unreadable = goidv.Unreadable + continue + } + r[i].ID, _ = constant.Int64Val(goidv.Value) + pcsVar := av.Children[i].fieldVariable("pcs") + if pcsVar.Unreadable != nil { + r[i].Unreadable = pcsVar.Unreadable + } + pcsVar.loaded = false + pcsVar.Children = pcsVar.Children[:0] + r[i].pcsVar = pcsVar + } + + return r, nil +} + +// Stack returns the stack trace of ancestor 'a' as saved by the runtime. +func (a *Ancestor) Stack(n int) ([]Stackframe, error) { + if a.Unreadable != nil { + return nil, a.Unreadable + } + pcsVar := a.pcsVar.clone() + pcsVar.loadValue(LoadConfig{MaxArrayValues: n}) + if pcsVar.Unreadable != nil { + return nil, pcsVar.Unreadable + } + r := make([]Stackframe, len(pcsVar.Children)) + for i := range pcsVar.Children { + if pcsVar.Children[i].Unreadable != nil { + r[i] = Stackframe{Err: pcsVar.Children[i].Unreadable} + continue + } + if pcsVar.Children[i].Kind != reflect.Uint { + return nil, fmt.Errorf("wrong type for pcs item %d: %v", i, pcsVar.Children[i].Kind) + } + pc, _ := constant.Int64Val(pcsVar.Children[i].Value) + fn := a.pcsVar.bi.PCToFunc(uint64(pc)) + if fn == nil { + loc := Location{PC: uint64(pc)} + r[i] = Stackframe{Current: loc, Call: loc} + continue + } + pc2 := uint64(pc) + if pc2-1 >= fn.Entry { + pc2-- + } + f, ln := fn.cu.lineInfo.PCToLine(fn.Entry, pc2) + loc := Location{PC: uint64(pc), File: f, Line: ln, Fn: fn} + r[i] = Stackframe{Current: loc, Call: loc} + } + r[len(r)-1].Bottom = pcsVar.Len == int64(len(pcsVar.Children)) + return r, nil +} + // Returns the list of saved return addresses used by stack barriers func (g *G) stkbar() ([]savedLR, error) { if g.stkbarVar == nil { // stack barriers were removed in Go 1.9 return nil, nil } - g.stkbarVar.loadValue(LoadConfig{false, 1, 0, int(g.stkbarVar.Len), 3}) + g.stkbarVar.loadValue(LoadConfig{false, 1, 0, int(g.stkbarVar.Len), 3, 0}) if g.stkbarVar.Unreadable != nil { return nil, fmt.Errorf("unreadable stkbar: %v", g.stkbarVar.Unreadable) } @@ -658,6 +785,7 @@ func (scope *EvalScope) LocalVariables(cfg LoadConfig) ([]*Variable, error) { vars = filterVariables(vars, func(v *Variable) bool { return (v.Flags & (VariableArgument | VariableReturnArgument)) == 0 }) + cfg.MaxMapBuckets = maxMapBucketsFactor * cfg.MaxArrayValues loadValues(vars, cfg) return vars, nil } @@ -671,6 +799,7 @@ func (scope *EvalScope) FunctionArguments(cfg LoadConfig) ([]*Variable, error) { vars = filterVariables(vars, func(v *Variable) bool { return (v.Flags & (VariableArgument | VariableReturnArgument)) != 0 }) + cfg.MaxMapBuckets = maxMapBucketsFactor * cfg.MaxArrayValues loadValues(vars, cfg) return vars, nil } @@ -875,7 +1004,11 @@ func (scope *EvalScope) extractVarInfoFromEntry(varEntry *dwarf.Entry) (*Variabl mem := scope.Mem if pieces != nil { addr = fakeAddress - mem = newCompositeMemory(scope.Mem, scope.Regs, pieces) + var cmem *compositeMemory + cmem, err = newCompositeMemory(scope.Mem, scope.Regs, pieces) + if cmem != nil { + mem = cmem + } } v := scope.newVariable(n, uintptr(addr), t, mem) @@ -895,6 +1028,10 @@ func (v *Variable) maybeDereference() *Variable { switch t := v.RealType.(type) { case *godwarf.PtrType: + if v.Addr == 0 && len(v.Children) == 1 && v.loaded { + // fake pointer variable constructed by casting an integer to a pointer type + return &v.Children[0] + } ptrval, err := readUintRaw(v.mem, uintptr(v.Addr), t.ByteSize) r := v.newVariable("", uintptr(ptrval), t.Type, DereferenceMemory(v.mem)) if err != nil { @@ -1569,6 +1706,11 @@ func (v *Variable) loadMap(recurseLevel int, cfg LoadConfig) { if it == nil { return } + it.maxNumBuckets = uint64(cfg.MaxMapBuckets) + + if v.Len == 0 || int64(v.mapSkip) >= v.Len || cfg.MaxArrayValues == 0 { + return + } for skip := 0; skip < v.mapSkip; skip++ { if ok := it.next(); !ok { @@ -1580,9 +1722,6 @@ func (v *Variable) loadMap(recurseLevel int, cfg LoadConfig) { count := 0 errcount := 0 for it.next() { - if count >= cfg.MaxArrayValues { - break - } key := it.key() var val *Variable if it.values.fieldType.Size() > 0 { @@ -1601,6 +1740,9 @@ func (v *Variable) loadMap(recurseLevel int, cfg LoadConfig) { if errcount > maxErrCount { break } + if count >= cfg.MaxArrayValues || int64(count) >= v.Len { + break + } } } @@ -1618,6 +1760,8 @@ type mapIterator struct { values *Variable overflow *Variable + maxNumBuckets uint64 // maximum number of buckets to scan + idx int64 } @@ -1683,6 +1827,10 @@ func (it *mapIterator) nextBucket() bool { } else { it.b = nil + if it.maxNumBuckets > 0 && it.bidx >= it.maxNumBuckets { + return false + } + for it.bidx < it.numbuckets { it.b = it.buckets.clone() it.b.Addr += uintptr(uint64(it.buckets.DwarfType.Size()) * it.bidx) diff --git a/vendor/github.com/derekparker/delve/pkg/proc/native/registers_windows_amd64.go b/vendor/github.com/go-delve/delve/pkg/proc/winutil/regs.go similarity index 68% rename from vendor/github.com/derekparker/delve/pkg/proc/native/registers_windows_amd64.go rename to vendor/github.com/go-delve/delve/pkg/proc/winutil/regs.go index febf758..79c4fb3 100644 --- a/vendor/github.com/derekparker/delve/pkg/proc/native/registers_windows_amd64.go +++ b/vendor/github.com/go-delve/delve/pkg/proc/winutil/regs.go @@ -1,4 +1,4 @@ -package native +package winutil import ( "fmt" @@ -6,11 +6,11 @@ import ( "golang.org/x/arch/x86/x86asm" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) -// Regs represents CPU registers on an AMD64 processor. -type Regs struct { +// AMD64Registers represents CPU registers on an AMD64 processor. +type AMD64Registers struct { rax uint64 rbx uint64 rcx uint64 @@ -33,11 +33,48 @@ type Regs struct { fs uint64 gs uint64 tls uint64 - context *_CONTEXT - fltSave *_XMM_SAVE_AREA32 + Context *CONTEXT + fltSave *XMM_SAVE_AREA32 } -func (r *Regs) Slice() []proc.Register { +// NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT +// struct and the TEB base address of the thread. +func NewAMD64Registers(context *CONTEXT, TebBaseAddress uint64, floatingPoint bool) *AMD64Registers { + regs := &AMD64Registers{ + 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: TebBaseAddress, + } + + if floatingPoint { + regs.fltSave = &context.FltSave + } + regs.Context = context + + return regs +} + +// Slice returns the registers as a list of (name, value) pairs. +func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register { var regs = []struct { k string v uint64 @@ -66,7 +103,7 @@ func (r *Regs) Slice() []proc.Register { {"TLS", r.tls}, } outlen := len(regs) - if r.fltSave != nil { + if r.fltSave != nil && floatingPoint { outlen += 6 + 8 + 2 + 16 } out := make([]proc.Register, 0, outlen) @@ -77,7 +114,7 @@ func (r *Regs) Slice() []proc.Register { out = proc.AppendQwordReg(out, reg.k, reg.v) } } - if r.fltSave != nil { + if r.fltSave != nil && floatingPoint { out = proc.AppendWordReg(out, "CW", r.fltSave.ControlWord) out = proc.AppendWordReg(out, "SW", r.fltSave.StatusWord) out = proc.AppendWordReg(out, "TW", uint16(r.fltSave.TagWord)) @@ -101,81 +138,40 @@ func (r *Regs) Slice() []proc.Register { // PC returns the current program counter // i.e. the RIP CPU register. -func (r *Regs) PC() uint64 { +func (r *AMD64Registers) PC() uint64 { return r.rip } // SP returns the stack pointer location, // i.e. the RSP register. -func (r *Regs) SP() uint64 { +func (r *AMD64Registers) SP() uint64 { return r.rsp } -func (r *Regs) BP() uint64 { +func (r *AMD64Registers) BP() uint64 { return r.rbp } // CX returns the value of the RCX register. -func (r *Regs) CX() uint64 { +func (r *AMD64Registers) 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 { +func (r *AMD64Registers) TLS() uint64 { return r.tls } -func (r *Regs) GAddr() (uint64, bool) { +// GAddr returns the address of the G variable if it is known, 0 and false +// otherwise. +func (r *AMD64Registers) GAddr() (uint64, bool) { return 0, false } -// SetPC sets the RIP register to the value specified by `pc`. -func (thread *Thread) SetPC(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) -} - -// SetSP sets the RSP register to the value specified by `sp`. -func (thread *Thread) SetSP(sp uint64) error { - context := newCONTEXT() - context.ContextFlags = _CONTEXT_ALL - - err := _GetThreadContext(thread.os.hThread, context) - if err != nil { - return err - } - - context.Rsp = sp - - return _SetThreadContext(thread.os.hThread, context) -} - -func (thread *Thread) SetDX(dx uint64) error { - context := newCONTEXT() - context.ContextFlags = _CONTEXT_ALL - - err := _GetThreadContext(thread.os.hThread, context) - if err != nil { - return err - } - - context.Rdx = dx - - return _SetThreadContext(thread.os.hThread, context) -} - -func (r *Regs) Get(n int) (uint64, error) { +// Get returns the value of the n-th register (in x86asm order). +func (r *AMD64Registers) Get(n int) (uint64, error) { reg := x86asm.Reg(n) const ( mask8 = 0x000f @@ -332,59 +328,103 @@ func (r *Regs) Get(n int) (uint64, error) { return 0, proc.ErrUnknownRegister } -func registers(thread *Thread, floatingPoint bool) (proc.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 - } - regs.context = context - - return regs, nil -} - -func (r *Regs) Copy() proc.Registers { - var rr Regs +// Copy returns a copy of these registers that is guarenteed not to change. +func (r *AMD64Registers) Copy() proc.Registers { + var rr AMD64Registers rr = *r - rr.context = newCONTEXT() - *(rr.context) = *(r.context) - rr.fltSave = &rr.context.FltSave + rr.Context = NewCONTEXT() + *(rr.Context) = *(r.Context) + rr.fltSave = &rr.Context.FltSave return &rr } + +// M128A tracks the _M128A windows struct. +type M128A struct { + Low uint64 + High int64 +} + +// XMM_SAVE_AREA32 tracks the _XMM_SAVE_AREA32 windows struct. +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 +} + +// CONTEXT tracks the _CONTEXT of windows. +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)) +} diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/command.go b/vendor/github.com/go-delve/delve/pkg/terminal/command.go similarity index 89% rename from vendor/github.com/derekparker/delve/pkg/terminal/command.go rename to vendor/github.com/go-delve/delve/pkg/terminal/command.go index 4dab523..11b4829 100644 --- a/vendor/github.com/derekparker/delve/pkg/terminal/command.go +++ b/vendor/github.com/go-delve/delve/pkg/terminal/command.go @@ -20,9 +20,9 @@ import ( "text/tabwriter" "github.com/cosiner/argv" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" - "github.com/derekparker/delve/service/debugger" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/api" + "github.com/go-delve/delve/service/debugger" ) const optimizedFunctionWarning = "Warning: debugging optimized function" @@ -32,6 +32,7 @@ type cmdPrefix int const ( noPrefix = cmdPrefix(0) onPrefix = cmdPrefix(1 << iota) + deferredPrefix ) type callContext struct { @@ -113,24 +114,24 @@ Type "help" followed by the name of a command for more information about it.`}, break [name] -See $GOPATH/src/github.com/derekparker/delve/Documentation/cli/locspec.md for the syntax of linespec. +See $GOPATH/src/github.com/go-delve/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. +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/go-delve/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. - restart [checkpoint] - restart [-noargs] newargv... + restart [checkpoint] + restart [-noargs] newargv... - For recorded processes restarts from the start or from the specified - checkpoint. For normal processes restarts the process, optionally changing - the arguments. With -noargs, the process starts with an empty commandline. +For recorded processes restarts from the start or from the specified +checkpoint. For normal processes restarts the process, optionally changing +the arguments. With -noargs, the process starts with an empty commandline. `}, {aliases: []string{"continue", "c"}, cmdFn: c.cont, helpMsg: "Run until breakpoint or program termination."}, {aliases: []string{"step", "s"}, cmdFn: c.step, helpMsg: "Single step through program."}, @@ -139,6 +140,8 @@ See also: "help on", "help cond" and "help clear"`}, {aliases: []string{"stepout"}, cmdFn: c.stepout, helpMsg: "Step out of the current function."}, {aliases: []string{"call"}, cmdFn: c.call, helpMsg: `Resumes process, injecting a function call (EXPERIMENTAL!!!) + call [-unsafe] + Current limitations: - only pointers to stack-allocated objects can be passed as argument. - only some automatic type conversions are supported. @@ -186,11 +189,11 @@ 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, cmdFn: printVar, helpMsg: `Evaluate an expression. + {aliases: []string{"print", "p"}, allowedPrefixes: onPrefix | deferredPrefix, 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.`}, +See $GOPATH/src/github.com/go-delve/delve/Documentation/cli/expr.md for a description of supported expressions.`}, {aliases: []string{"whatis"}, cmdFn: whatisCommand, helpMsg: `Prints type of an expression. whatis `}, @@ -198,7 +201,7 @@ See $GOPATH/src/github.com/derekparker/delve/Documentation/cli/expr.md for a des [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.`}, +See $GOPATH/src/github.com/go-delve/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 [] @@ -214,12 +217,12 @@ If regex is specified only the functions matching it will be returned.`}, types [] If regex is specified only the types matching it will be returned.`}, - {aliases: []string{"args"}, allowedPrefixes: onPrefix, cmdFn: args, helpMsg: `Print function arguments. + {aliases: []string{"args"}, allowedPrefixes: onPrefix | deferredPrefix, 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: onPrefix, cmdFn: locals, helpMsg: `Print local variables. + {aliases: []string{"locals"}, allowedPrefixes: onPrefix | deferredPrefix, cmdFn: locals, helpMsg: `Print local variables. [goroutine ] [frame ] locals [-v] [] @@ -248,10 +251,13 @@ When connected to a headless instance started with the --accept-multiclient, pas Show source around current point or provided linespec.`}, {aliases: []string{"stack", "bt"}, allowedPrefixes: onPrefix, cmdFn: stackCommand, helpMsg: `Print stack trace. - [goroutine ] [frame ] stack [] [-full] [-g] [-s] [-offsets] + [goroutine ] [frame ] stack [] [-full] [-offsets] [-defer] [-a ] [-adepth ] -full every stackframe is decorated with the value of its local variables and arguments. - -offsets prints frame offset of each frame + -offsets prints frame offset of each frame. + -defer prints deferred function call stack for each frame. + -a prints stacktrace of n ancestors of the selected goroutine (target process must have tracebackancestors enabled) + -adepth configures depth of ancestor stacktrace `}, {aliases: []string{"frame"}, cmdFn: func(t *Term, ctx callContext, arg string) error { @@ -259,8 +265,8 @@ Show source around current point or provided linespec.`}, }, helpMsg: `Set the current frame, or execute command on a different frame. - frame - frame + frame + frame The first form sets frame used by subsequent commands such as "print" or "set". The second form runs the command on the given frame.`}, @@ -270,8 +276,8 @@ The second form runs the command on the given frame.`}, }, helpMsg: `Move the current frame up. - up [] - up [] + up [] + up [] Move the current frame up by . The second form runs the command on the given frame.`}, {aliases: []string{"down"}, @@ -280,10 +286,15 @@ Move the current frame up by . The second form runs the command on the given }, helpMsg: `Move the current frame down. - down [] - down [] + down [] + down [] Move the current frame down by . The second form runs the command on the given frame.`}, + {aliases: []string{"deferred"}, cmdFn: c.deferredCommand, helpMsg: `Executes command in the context of a deferred call. + + deferred + +Executes the specified command (print, args, locals) in the context of the n-th deferred call in the current frame.`}, {aliases: []string{"source"}, cmdFn: c.sourceCommand, helpMsg: `Executes a file containing a list of delve commands source `}, @@ -334,6 +345,7 @@ Defines as an alias to or removes an alias.`}, edit [locspec] If locspec is omitted edit will open the current source file in the editor, otherwise it will open the specified location.`}, + {aliases: []string{"libraries"}, cmdFn: libraries, helpMsg: `List loaded dynamic libraries`}, } if client == nil || client.Recorded() { @@ -347,7 +359,9 @@ If locspec is omitted edit will open the current source file in the editor, othe cmdFn: checkpoint, helpMsg: `Creates a checkpoint at the current position. - checkpoint [where]`, + checkpoint [note] + +The "note" is arbitrary text that can be used to identify the checkpoint, if it is not specified it defaults to the current filename:line position.`, }) c.cmds = append(c.cmds, command{ aliases: []string{"checkpoints"}, @@ -426,7 +440,7 @@ func (c *Commands) CallWithContext(cmdstr string, t *Term, ctx callContext) erro // Call takes a command to execute. func (c *Commands) Call(cmdstr string, t *Term) error { - ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: c.frame}} + ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: c.frame, DeferredCall: 0}} return c.CallWithContext(cmdstr, t, ctx) } @@ -559,6 +573,27 @@ 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 } +// The number of goroutines we're going to request on each RPC call +const goroutineBatchSize = 10000 + +func printGoroutines(t *Term, gs []*api.Goroutine, fgl formatGoroutineLoc, bPrintStack bool, state *api.DebuggerState) error { + for _, g := range gs { + prefix := " " + if state.SelectedGoroutine != nil && g.ID == state.SelectedGoroutine.ID { + prefix = "* " + } + fmt.Printf("%sGoroutine %s\n", prefix, formatGoroutine(g, fgl)) + if bPrintStack { + stack, err := t.client.Stacktrace(g.ID, 10, false, nil) + if err != nil { + return err + } + printStack(stack, "\t", false) + } + } + return nil +} + func goroutines(t *Term, ctx callContext, argstr string) error { args := strings.Split(argstr, " ") var fgl = fglUserCurrent @@ -593,26 +628,24 @@ func goroutines(t *Term, ctx callContext, argstr string) error { 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 = "* " + var ( + start = 0 + gslen = 0 + gs []*api.Goroutine + ) + for start >= 0 { + gs, start, err = t.client.ListGoroutines(start, goroutineBatchSize) + if err != nil { + return err } - fmt.Printf("%sGoroutine %s\n", prefix, formatGoroutine(g, fgl)) - if bPrintStack { - stack, err := t.client.Stacktrace(g.ID, 10, false, nil) - if err != nil { - return err - } - printStack(stack, "\t", false) + sort.Sort(byGoroutineID(gs)) + err = printGoroutines(t, gs, fgl, bPrintStack, state) + if err != nil { + return err } + gslen += len(gs) } + fmt.Printf("[%d goroutines]\n", gslen) return nil } @@ -714,6 +747,22 @@ func (c *Commands) frameCommand(t *Term, ctx callContext, argstr string, directi return nil } +func (c *Commands) deferredCommand(t *Term, ctx callContext, argstr string) error { + ctx.Prefix = deferredPrefix + + space := strings.Index(argstr, " ") + + var err error + ctx.Scope.DeferredCall, err = strconv.Atoi(argstr[:space]) + if err != nil { + return err + } + if ctx.Scope.DeferredCall <= 0 { + return errors.New("argument of deferred must be a number greater than 0 (use 'stack -defer' to see the list of deferred calls)") + } + return c.CallWithContext(argstr[space:], t, ctx) +} + func printscope(t *Term) error { state, err := t.client.GetState() if err != nil { @@ -980,7 +1029,13 @@ func (c *Commands) call(t *Term, ctx callContext, args string) error { if err := scopePrefixSwitch(t, ctx); err != nil { return err } - state, err := exitedToError(t.client.Call(args)) + const unsafePrefix = "-unsafe " + unsafe := false + if strings.HasPrefix(args, unsafePrefix) { + unsafe = true + args = args[len(unsafePrefix):] + } + state, err := exitedToError(t.client.Call(args, unsafe)) c.frame = 0 if err != nil { printcontextNoState(t) @@ -1164,6 +1219,9 @@ func edit(t *Term, ctx callContext, args string) error { } cmd := exec.Command(editor, fmt.Sprintf("+%d", lineno), file) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr return cmd.Run() } @@ -1356,6 +1414,20 @@ func stackCommand(t *Term, ctx callContext, args string) error { return err } printStack(stack, "", sa.offsets) + if sa.ancestors > 0 { + ancestors, err := t.client.Ancestors(ctx.Scope.GoroutineID, sa.ancestors, sa.ancestorDepth) + if err != nil { + return err + } + for _, ancestor := range ancestors { + fmt.Printf("Created by Goroutine %d:\n", ancestor.ID) + if ancestor.Unreadable != "" { + fmt.Printf("\t%s\n", ancestor.Unreadable) + continue + } + printStack(ancestor.Stack, "\t", false) + } + } return nil } @@ -1364,6 +1436,9 @@ type stackArgs struct { full bool offsets bool readDefers bool + + ancestors int + ancestorDepth int } func parseStackArgs(argstr string) (stackArgs, error) { @@ -1373,7 +1448,18 @@ func parseStackArgs(argstr string) (stackArgs, error) { } if argstr != "" { args := strings.Split(argstr, " ") - for i := range args { + for i := 0; i < len(args); i++ { + numarg := func(name string) (int, error) { + if i >= len(args) { + return 0, fmt.Errorf("expected number after %s", name) + } + n, err := strconv.Atoi(args[i]) + if err != nil { + return 0, fmt.Errorf("expected number after %s: %v", name, err) + } + return n, nil + + } switch args[i] { case "-full": r.full = true @@ -1381,6 +1467,20 @@ func parseStackArgs(argstr string) (stackArgs, error) { r.offsets = true case "-defer": r.readDefers = true + case "-a": + i++ + n, err := numarg("-a") + if err != nil { + return stackArgs{}, err + } + r.ancestors = n + case "-adepth": + i++ + n, err := numarg("-adepth") + if err != nil { + return stackArgs{}, err + } + r.ancestorDepth = n default: n, err := strconv.Atoi(args[i]) if err != nil { @@ -1390,6 +1490,9 @@ func parseStackArgs(argstr string) (stackArgs, error) { } } } + if r.ancestors > 0 && r.ancestorDepth == 0 { + r.ancestorDepth = r.depth + } return r, nil } @@ -1526,6 +1629,18 @@ func disassCommand(t *Term, ctx callContext, args string) error { return nil } +func libraries(t *Term, ctx callContext, args string) error { + libs, err := t.client.ListDynamicLibraries() + if err != nil { + return err + } + d := digits(len(libs)) + for i := range libs { + fmt.Printf("%"+strconv.Itoa(d)+"d. %s\n", i, libs[i].Path) + } + return nil +} + func digits(n int) int { if n <= 0 { return 1 @@ -1565,7 +1680,7 @@ func printStack(stack []api.Stackframe, ind string, offsets bool) { } for j, d := range stack[i].Defers { - deferHeader := fmt.Sprintf("%s defer %d: ", s, j) + deferHeader := fmt.Sprintf("%s defer %d: ", s, j+1) s2 := strings.Repeat(" ", len(deferHeader)) if d.Unreadable != "" { fmt.Printf("%s(unreadable defer: %s)\n", deferHeader, d.Unreadable) @@ -1669,7 +1784,14 @@ func printcontextThread(t *Term, th *api.Thread) { 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()) + // For AI compatibility return values are included in the + // argument list. This is a relic of the dark ages when the + // Go debug information did not distinguish between the two. + // Filter them out here instead, so during trace operations + // they are not printed as an argument. + if (ar.Flags & api.VariableArgument) != 0 { + arg = append(arg, ar.SinglelineString()) + } } args = strings.Join(arg, ", ") } @@ -1874,6 +1996,9 @@ func (c *Commands) executeFile(t *Term, name string) error { } if err := c.Call(line, t); err != nil { + if _, isExitRequest := err.(ExitRequestError); isExitRequest { + return err + } fmt.Printf("%s:%d: %v\n", name, lineno, err) } } @@ -1923,7 +2048,7 @@ func checkpoints(t *Term, ctx callContext, args string) error { } w := new(tabwriter.Writer) w.Init(os.Stdout, 4, 4, 2, ' ', 0) - fmt.Fprintln(w, "ID\tWhen\tWhere") + fmt.Fprintln(w, "ID\tWhen\tNote") for _, cp := range cps { fmt.Fprintf(w, "c%d\t%s\t%s\n", cp.ID, cp.When, cp.Where) } diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/config.go b/vendor/github.com/go-delve/delve/pkg/terminal/config.go similarity index 99% rename from vendor/github.com/derekparker/delve/pkg/terminal/config.go rename to vendor/github.com/go-delve/delve/pkg/terminal/config.go index ee0ed93..80bc4ae 100644 --- a/vendor/github.com/derekparker/delve/pkg/terminal/config.go +++ b/vendor/github.com/go-delve/delve/pkg/terminal/config.go @@ -8,7 +8,7 @@ import ( "strings" "text/tabwriter" - "github.com/derekparker/delve/pkg/config" + "github.com/go-delve/delve/pkg/config" ) func configureCmd(t *Term, ctx callContext, args string) error { diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go b/vendor/github.com/go-delve/delve/pkg/terminal/disasmprint.go similarity index 93% rename from vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go rename to vendor/github.com/go-delve/delve/pkg/terminal/disasmprint.go index 313fde8..d6015ff 100644 --- a/vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go +++ b/vendor/github.com/go-delve/delve/pkg/terminal/disasmprint.go @@ -7,7 +7,7 @@ import ( "path/filepath" "text/tabwriter" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/service/api" ) func DisasmPrint(dv api.AsmInstructions, out io.Writer) { diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/docgen.go b/vendor/github.com/go-delve/delve/pkg/terminal/docgen.go similarity index 85% rename from vendor/github.com/derekparker/delve/pkg/terminal/docgen.go rename to vendor/github.com/go-delve/delve/pkg/terminal/docgen.go index ad99e0b..eb30dde 100644 --- a/vendor/github.com/derekparker/delve/pkg/terminal/docgen.go +++ b/vendor/github.com/go-delve/delve/pkg/terminal/docgen.go @@ -7,7 +7,7 @@ import ( ) func replaceDocPath(s string) string { - const docpath = "$GOPATH/src/github.com/derekparker/delve/" + const docpath = "$GOPATH/src/github.com/go-delve/delve/" for { start := strings.Index(s, docpath) @@ -22,7 +22,7 @@ func replaceDocPath(s string) string { } text := s[start+len(docpath) : end] - s = s[:start] + fmt.Sprintf("[%s](//github.com/derekparker/delve/tree/master/%s)", text, text) + s[end:] + s = s[:start] + fmt.Sprintf("[%s](//github.com/go-delve/delve/tree/master/%s)", text, text) + s[end:] } } diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/terminal.go b/vendor/github.com/go-delve/delve/pkg/terminal/terminal.go similarity index 92% rename from vendor/github.com/derekparker/delve/pkg/terminal/terminal.go rename to vendor/github.com/go-delve/delve/pkg/terminal/terminal.go index a980837..5e6ecbc 100644 --- a/vendor/github.com/derekparker/delve/pkg/terminal/terminal.go +++ b/vendor/github.com/go-delve/delve/pkg/terminal/terminal.go @@ -13,9 +13,9 @@ import ( "github.com/peterh/liner" - "github.com/derekparker/delve/pkg/config" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/pkg/config" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/api" ) const ( @@ -64,20 +64,6 @@ type Term struct { // New returns a new Term. func New(client service.Client, conf *config.Config) *Term { - if client != nil && client.IsMulticlient() { - state, _ := client.GetStateNonBlocking() - // The error return of GetState will usually be the ErrProcessExited, - // which we don't care about. If there are other errors they will show up - // later, here we are only concerned about stopping a running target so - // that we can initialize our connection. - if state != nil && state.Running { - _, err := client.Halt() - if err != nil { - fmt.Fprintf(os.Stderr, "could not halt: %v", err) - return nil - } - } - } cmds := DebugCommands(client) if conf != nil && conf.Aliases != nil { cmds.Merge(conf.Aliases) @@ -204,6 +190,9 @@ func (t *Term) Run() (int, error) { if t.InitFile != "" { err := t.cmds.executeFile(t, t.InitFile) if err != nil { + if _, ok := err.(ExitRequestError); ok { + return t.handleExit() + } fmt.Fprintf(os.Stderr, "Error executing init file: %s\n", err) } } @@ -264,7 +253,14 @@ func (t *Term) substitutePath(path string) string { if t.conf == nil { return path } - separator := string(os.PathSeparator) + + // On windows paths returned from headless server are as c:/dir/dir + // though os.PathSeparator is '\\' + + separator := "/" //make it default + if strings.Index(path, "\\") != -1 { //dependent on the path + separator = "\\" + } for _, r := range t.conf.SubstitutePath { from := crossPlatformPath(r.From) to := r.To diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/terminal_other.go b/vendor/github.com/go-delve/delve/pkg/terminal/terminal_other.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/terminal/terminal_other.go rename to vendor/github.com/go-delve/delve/pkg/terminal/terminal_other.go diff --git a/vendor/github.com/derekparker/delve/pkg/terminal/terminal_windows.go b/vendor/github.com/go-delve/delve/pkg/terminal/terminal_windows.go similarity index 100% rename from vendor/github.com/derekparker/delve/pkg/terminal/terminal_windows.go rename to vendor/github.com/go-delve/delve/pkg/terminal/terminal_windows.go diff --git a/vendor/github.com/derekparker/delve/pkg/version/version.go b/vendor/github.com/go-delve/delve/pkg/version/version.go similarity index 81% rename from vendor/github.com/derekparker/delve/pkg/version/version.go rename to vendor/github.com/go-delve/delve/pkg/version/version.go index 2eaea3e..b1cb50b 100644 --- a/vendor/github.com/derekparker/delve/pkg/version/version.go +++ b/vendor/github.com/go-delve/delve/pkg/version/version.go @@ -14,8 +14,8 @@ type Version struct { var ( // DelveVersion is the current version of Delve. DelveVersion = Version{ - Major: "1", Minor: "1", Patch: "0", Metadata: "", - Build: "$Id: 1990ba12450cab9425a2ae62e6ab988725023d5c $", + Major: "1", Minor: "2", Patch: "0", Metadata: "", + Build: "$Id: 068e2451004e95d0b042e5257e34f0f08ce01466 $", } ) diff --git a/vendor/github.com/derekparker/delve/service/api/conversions.go b/vendor/github.com/go-delve/delve/service/api/conversions.go similarity index 94% rename from vendor/github.com/derekparker/delve/service/api/conversions.go rename to vendor/github.com/go-delve/delve/service/api/conversions.go index 5810111..8c24586 100644 --- a/vendor/github.com/derekparker/delve/service/api/conversions.go +++ b/vendor/github.com/go-delve/delve/service/api/conversions.go @@ -2,14 +2,15 @@ package api import ( "bytes" + "fmt" "go/constant" "go/printer" "go/token" "reflect" "strconv" - "github.com/derekparker/delve/pkg/dwarf/godwarf" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/proc" ) // ConvertBreakpoint converts from a proc.Breakpoint to @@ -23,6 +24,7 @@ func ConvertBreakpoint(bp *proc.Breakpoint) *Breakpoint { Line: bp.Line, Addr: bp.Addr, Tracepoint: bp.Tracepoint, + TraceReturn: bp.TraceReturn, Stacktrace: bp.Stacktrace, Goroutine: bp.Goroutine, Variables: bp.Variables, @@ -142,8 +144,9 @@ func ConvertVar(v *proc.Variable) *Variable { case reflect.String, reflect.Func: r.Value = constant.StringVal(v.Value) default: - r.Value = v.ConstDescr() - if r.Value == "" { + if cd := v.ConstDescr(); cd != "" { + r.Value = fmt.Sprintf("%s (%s)", cd, v.Value.String()) + } else { r.Value = v.Value.String() } } @@ -282,6 +285,7 @@ func LoadConfigToProc(cfg *LoadConfig) *proc.LoadConfig { cfg.MaxStringLen, cfg.MaxArrayValues, cfg.MaxStructFields, + 0, // MaxMapBuckets is set internally by pkg/proc, read its documentation for an explanation. } } @@ -312,3 +316,7 @@ func ConvertRegisters(in []proc.Register) (out []Register) { func ConvertCheckpoint(in proc.Checkpoint) (out Checkpoint) { return Checkpoint(in) } + +func ConvertImage(image *proc.Image) Image { + return Image{Path: image.Path} +} diff --git a/vendor/github.com/derekparker/delve/service/api/prettyprint.go b/vendor/github.com/go-delve/delve/service/api/prettyprint.go similarity index 93% rename from vendor/github.com/derekparker/delve/service/api/prettyprint.go rename to vendor/github.com/go-delve/delve/service/api/prettyprint.go index 4534b32..5100bf8 100644 --- a/vendor/github.com/derekparker/delve/service/api/prettyprint.go +++ b/vendor/github.com/go-delve/delve/service/api/prettyprint.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "reflect" + "strings" ) const ( @@ -52,7 +53,11 @@ func (v *Variable) writeTo(buf io.Writer, top, newlines, includeType bool, inden if v.Type == "" || len(v.Children) == 0 { fmt.Fprint(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) + if strings.Contains(v.Type, "/") { + fmt.Fprintf(buf, "(%q)(%#x)", v.Type, v.Children[0].Addr) + } else { + fmt.Fprintf(buf, "(%s)(%#x)", v.Type, v.Children[0].Addr) + } } else { fmt.Fprint(buf, "*") v.Children[0].writeTo(buf, false, newlines, includeType, indent) @@ -61,7 +66,7 @@ func (v *Variable) writeTo(buf io.Writer, top, newlines, includeType bool, inden if len(v.Children) == 0 { fmt.Fprintf(buf, "unsafe.Pointer(nil)") } else { - fmt.Fprintf(buf, "unsafe.Pointer(0x%x)", v.Children[0].Addr) + fmt.Fprintf(buf, "unsafe.Pointer(%#x)", v.Children[0].Addr) } case reflect.String: v.writeStringTo(buf) @@ -107,7 +112,11 @@ func (v *Variable) writeTo(buf io.Writer, top, newlines, includeType bool, inden v.Children[0].writeTo(buf, false, newlines, !includeType, indent) } } else if data.OnlyAddr { - fmt.Fprintf(buf, "*(*%q)(0x%x)", v.Type, v.Addr) + if strings.Contains(v.Type, "/") { + fmt.Fprintf(buf, "*(*%q)(%#x)", v.Type, v.Addr) + } else { + fmt.Fprintf(buf, "*(*%s)(%#x)", v.Type, v.Addr) + } } else { v.Children[0].writeTo(buf, false, newlines, !includeType, indent) } @@ -158,7 +167,11 @@ func (v *Variable) writeArrayTo(buf io.Writer, newlines, includeType bool, inden 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) + if strings.Contains(v.Type, "/") { + fmt.Fprintf(buf, "(*%q)(%#x)", v.Type, v.Addr) + } else { + fmt.Fprintf(buf, "(*%s)(%#x)", v.Type, v.Addr) + } return } diff --git a/vendor/github.com/derekparker/delve/service/api/types.go b/vendor/github.com/go-delve/delve/service/api/types.go similarity index 94% rename from vendor/github.com/derekparker/delve/service/api/types.go rename to vendor/github.com/go-delve/delve/service/api/types.go index 373cea9..960d2df 100644 --- a/vendor/github.com/derekparker/delve/service/api/types.go +++ b/vendor/github.com/go-delve/delve/service/api/types.go @@ -8,7 +8,7 @@ import ( "strconv" "unicode" - "github.com/derekparker/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc" ) // ErrNotExecutable is an error returned when trying @@ -59,8 +59,11 @@ type Breakpoint struct { // Breakpoint condition Cond string - // tracepoint flag + // Tracepoint flag, signifying this is a tracepoint. Tracepoint bool `json:"continue"` + // TraceReturn flag signifying this is a breakpoint set at a return + // statement in a traced function. + TraceReturn bool `json:"traceReturn"` // retrieve goroutine information Goroutine bool `json:"goroutine"` // number of stack frames to retrieve @@ -197,11 +200,11 @@ const ( // that may outlive the stack frame are allocated on the heap instead and // only the address is recorded on the stack. These variables will be // marked with this flag. - VariableEscaped = VariableFlags(proc.VariableEscaped) + VariableEscaped = (1 << iota) // VariableShadowed is set for local variables that are shadowed by a // variable with the same name in another scope - VariableShadowed = VariableFlags(proc.VariableShadowed) + VariableShadowed // VariableConstant means this variable is a constant value VariableConstant @@ -308,6 +311,8 @@ type DebuggerCommand struct { ReturnInfoLoadConfig *LoadConfig // Expr is the expression argument for a Call command Expr string `json:"expr,omitempty"` + // UnsafeCall disabled parameter escape checking for function calls + UnsafeCall bool `json:"unsafeCall,omitempty"` } // BreakpointInfo contains informations about the current breakpoint @@ -322,8 +327,9 @@ type BreakpointInfo struct { // EvalScope is the scope a command should // be evaluated in. Describes the goroutine and frame number. type EvalScope struct { - GoroutineID int - Frame int + GoroutineID int + Frame int + DeferredCall int // when DeferredCall is n > 0 this eval scope is relative to the n-th deferred call in the current frame } const ( @@ -436,3 +442,16 @@ type Checkpoint struct { When string Where string } + +// Image represents a loaded shared object (go plugin or shared library) +type Image struct { + Path string +} + +// Ancestor represents a goroutine ancestor +type Ancestor struct { + ID int64 + Stack []Stackframe + + Unreadable string +} diff --git a/vendor/github.com/derekparker/delve/service/client.go b/vendor/github.com/go-delve/delve/service/client.go similarity index 94% rename from vendor/github.com/derekparker/delve/service/client.go rename to vendor/github.com/go-delve/delve/service/client.go index b2ff046..a15c0e2 100644 --- a/vendor/github.com/derekparker/delve/service/client.go +++ b/vendor/github.com/go-delve/delve/service/client.go @@ -3,7 +3,7 @@ package service import ( "time" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/service/api" ) // Client represents a debugger service client. All client methods are @@ -39,7 +39,7 @@ type Client interface { // StepOut continues to the return address of the current function StepOut() (*api.DebuggerState, error) // Call resumes process execution while making a function call. - Call(expr string) (*api.DebuggerState, error) + Call(expr string, unsafe bool) (*api.DebuggerState, error) // SingleStep will step a single cpu instruction. StepInstruction() (*api.DebuggerState, error) @@ -95,11 +95,14 @@ type Client interface { ListRegisters(threadID int, includeFp bool) (api.Registers, error) // ListGoroutines lists all goroutines. - ListGoroutines() ([]*api.Goroutine, error) + ListGoroutines(start, count int) ([]*api.Goroutine, int, error) // Returns stacktrace Stacktrace(goroutineID int, depth int, readDefers bool, cfg *api.LoadConfig) ([]api.Stackframe, error) + // Returns ancestor stacktraces + Ancestors(goroutineID int, numAncestors int, depth int) ([]api.Ancestor, error) + // Returns whether we attached to a running process or not AttachedToExistingProcess() bool @@ -138,6 +141,9 @@ type Client interface { // IsMulticlien returns true if the headless instance is multiclient. IsMulticlient() bool + // ListDynamicLibraries returns a list of loaded dynamic libraries. + ListDynamicLibraries() ([]api.Image, error) + // Disconnect closes the connection to the server without sending a Detach request first. // If cont is true a continue command will be sent instead. Disconnect(cont bool) error diff --git a/vendor/github.com/derekparker/delve/service/config.go b/vendor/github.com/go-delve/delve/service/config.go similarity index 90% rename from vendor/github.com/derekparker/delve/service/config.go rename to vendor/github.com/go-delve/delve/service/config.go index dcd128b..837abca 100644 --- a/vendor/github.com/derekparker/delve/service/config.go +++ b/vendor/github.com/go-delve/delve/service/config.go @@ -29,6 +29,10 @@ type Config struct { // CoreFile specifies the path to the core dump to open. CoreFile string + // DebugInfoDirectories is the list of directories to look for + // when resolving external debug info files. + DebugInfoDirectories []string + // Selects server backend. Backend string diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger.go b/vendor/github.com/go-delve/delve/service/debugger/debugger.go similarity index 88% rename from vendor/github.com/derekparker/delve/service/debugger/debugger.go rename to vendor/github.com/go-delve/delve/service/debugger/debugger.go index 746684f..a318ab4 100644 --- a/vendor/github.com/derekparker/delve/service/debugger/debugger.go +++ b/vendor/github.com/go-delve/delve/service/debugger/debugger.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "go/parser" - "io/ioutil" "path/filepath" "regexp" "runtime" @@ -13,13 +12,13 @@ import ( "sync" "time" - "github.com/derekparker/delve/pkg/goversion" - "github.com/derekparker/delve/pkg/logflags" - "github.com/derekparker/delve/pkg/proc" - "github.com/derekparker/delve/pkg/proc/core" - "github.com/derekparker/delve/pkg/proc/gdbserial" - "github.com/derekparker/delve/pkg/proc/native" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/pkg/goversion" + "github.com/go-delve/delve/pkg/logflags" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/core" + "github.com/go-delve/delve/pkg/proc/gdbserial" + "github.com/go-delve/delve/pkg/proc/native" + "github.com/go-delve/delve/service/api" "github.com/sirupsen/logrus" ) @@ -65,16 +64,16 @@ type Config struct { // Foreground lets target process access stdin. Foreground bool + + // DebugInfoDirectories is the list of directories to look for + // when resolving external debug info files. + DebugInfoDirectories []string } // New creates a new Debugger. ProcessArgs specify the commandline arguments for the // new process. func New(config *Config, processArgs []string) (*Debugger, error) { - logger := logrus.New().WithFields(logrus.Fields{"layer": "debugger"}) - logger.Logger.Level = logrus.DebugLevel - if !logflags.Debugger() { - logger.Logger.Out = ioutil.Discard - } + logger := logflags.DebuggerLogger() d := &Debugger{ config: config, processArgs: processArgs, @@ -102,10 +101,10 @@ func New(config *Config, processArgs []string) (*Debugger, error) { switch d.config.Backend { case "rr": d.log.Infof("opening trace %s", d.config.CoreFile) - p, err = gdbserial.Replay(d.config.CoreFile, false) + p, err = gdbserial.Replay(d.config.CoreFile, false, d.config.DebugInfoDirectories) default: d.log.Infof("opening core file %s (executable %s)", d.config.CoreFile, d.processArgs[0]) - p, err = core.OpenCore(d.config.CoreFile, d.processArgs[0]) + p, err = core.OpenCore(d.config.CoreFile, d.processArgs[0], d.config.DebugInfoDirectories) } if err != nil { err = go11DecodeErrorCheck(err) @@ -132,17 +131,17 @@ func New(config *Config, processArgs []string) (*Debugger, error) { func (d *Debugger) Launch(processArgs []string, wd string) (proc.Process, error) { switch d.config.Backend { case "native": - return native.Launch(processArgs, wd, d.config.Foreground) + return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories) case "lldb": - return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground)) + return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories)) case "rr": - p, _, err := gdbserial.RecordAndReplay(processArgs, wd, false) + p, _, err := gdbserial.RecordAndReplay(processArgs, wd, false, d.config.DebugInfoDirectories) return p, err case "default": if runtime.GOOS == "darwin" { - return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground)) + return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories)) } - return native.Launch(processArgs, wd, d.config.Foreground) + return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories) default: return nil, fmt.Errorf("unknown backend %q", d.config.Backend) } @@ -157,14 +156,14 @@ var ErrNoAttachPath = errors.New("must specify executable path on macOS") func (d *Debugger) Attach(pid int, path string) (proc.Process, error) { switch d.config.Backend { case "native": - return native.Attach(pid) + return native.Attach(pid, d.config.DebugInfoDirectories) case "lldb": - return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path)) + return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path, d.config.DebugInfoDirectories)) case "default": if runtime.GOOS == "darwin" { - return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path)) + return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path, d.config.DebugInfoDirectories)) } - return native.Attach(pid) + return native.Attach(pid, d.config.DebugInfoDirectories) default: return nil, fmt.Errorf("unknown backend %q", d.config.Backend) } @@ -195,6 +194,14 @@ func (d *Debugger) LastModified() time.Time { return d.target.BinInfo().LastModified() } +// FunctionReturnLocations returns all return locations +// for the given function. See the documentation for the +// function of the same name within the `proc` package for +// more information. +func (d *Debugger) FunctionReturnLocations(fnName string) ([]uint64, error) { + return proc.FunctionReturnLocations(d.target, fnName) +} + // Detach detaches from the target process. // If `kill` is true we will kill the process after // detaching. @@ -348,6 +355,8 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin } switch { + case requestedBp.TraceReturn: + addr = requestedBp.Addr case len(requestedBp.File) > 0: fileName := requestedBp.File if runtime.GOOS == "windows" { @@ -414,6 +423,7 @@ func (d *Debugger) CancelNext() error { func copyBreakpointInfo(bp *proc.Breakpoint, requested *api.Breakpoint) (err error) { bp.Name = requested.Name bp.Tracepoint = requested.Tracepoint + bp.TraceReturn = requested.TraceReturn bp.Goroutine = requested.Goroutine bp.Stacktrace = requested.Stacktrace bp.Variables = requested.Variables @@ -565,7 +575,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er err = proc.Continue(d.target) case api.Call: d.log.Debugf("function call %s", command.Expr) - err = proc.CallFunction(d.target, command.Expr, api.LoadConfigToProc(command.ReturnInfoLoadConfig)) + err = proc.CallFunction(d.target, command.Expr, api.LoadConfigToProc(command.ReturnInfoLoadConfig), !command.UnsafeCall) case api.Rewind: d.log.Debug("rewinding") if err := d.target.Direction(proc.Backward); err != nil { @@ -617,6 +627,15 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er if withBreakpointInfo { err = d.collectBreakpointInformation(state) } + for _, th := range state.Threads { + if th.Breakpoint != nil && th.Breakpoint.TraceReturn { + for _, v := range th.BreakpointInfo.Arguments { + if (v.Flags & api.VariableReturnArgument) != 0 { + th.ReturnValues = append(th.ReturnValues, v) + } + } + } + } return state, err } @@ -806,7 +825,7 @@ func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, e if err != nil { return nil, err } - return api.ConvertRegisters(regs.Slice()), err + return api.ConvertRegisters(regs.Slice(floatingPoint)), err } func convertVars(pv []*proc.Variable) []api.Variable { @@ -825,7 +844,7 @@ func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]a d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame) + s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall) if err != nil { return nil, err } @@ -841,7 +860,7 @@ func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) ( d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame) + s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall) if err != nil { return nil, err } @@ -858,7 +877,7 @@ func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg p d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame) + s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall) if err != nil { return nil, err } @@ -875,7 +894,7 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string) d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame) + s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall) if err != nil { return err } @@ -883,19 +902,19 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string) } // Goroutines will return a list of goroutines in the target process. -func (d *Debugger) Goroutines() ([]*api.Goroutine, error) { +func (d *Debugger) Goroutines(start, count int) ([]*api.Goroutine, int, error) { d.processMutex.Lock() defer d.processMutex.Unlock() goroutines := []*api.Goroutine{} - gs, err := proc.GoroutinesInfo(d.target) + gs, nextg, err := proc.GoroutinesInfo(d.target, start, count) if err != nil { - return nil, err + return nil, 0, err } for _, g := range gs { goroutines = append(goroutines, api.ConvertGoroutine(g)) } - return goroutines, err + return goroutines, nextg, err } // Stacktrace returns a list of Stackframes for the given goroutine. The @@ -928,6 +947,48 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, readDefers bool, cfg *proc return d.convertStacktrace(rawlocs, cfg) } +// Ancestors returns the stacktraces for the ancestors of a goroutine. +func (d *Debugger) Ancestors(goroutineID, numAncestors, depth int) ([]api.Ancestor, error) { + d.processMutex.Lock() + defer d.processMutex.Unlock() + + if _, err := d.target.Valid(); err != nil { + return nil, err + } + + g, err := proc.FindGoroutine(d.target, goroutineID) + if err != nil { + return nil, err + } + if g == nil { + return nil, errors.New("no selected goroutine") + } + + ancestors, err := g.Ancestors(numAncestors) + if err != nil { + return nil, err + } + + r := make([]api.Ancestor, len(ancestors)) + for i := range ancestors { + r[i].ID = ancestors[i].ID + if ancestors[i].Unreadable != nil { + r[i].Unreadable = ancestors[i].Unreadable.Error() + continue + } + frames, err := ancestors[i].Stack(depth) + if err != nil { + r[i].Unreadable = fmt.Sprintf("could not read ancestor stacktrace: %v", err) + continue + } + r[i].Stack, err = d.convertStacktrace(frames, nil) + if err != nil { + r[i].Unreadable = fmt.Sprintf("could not read ancestor stacktrace: %v", err) + } + } + return r, nil +} + func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) { locations := make([]api.Stackframe, 0, len(rawlocs)) for i := range rawlocs { @@ -1009,7 +1070,7 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat return nil, err } - s, _ := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame) + s, _ := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall) locs, err := loc.Find(d, s, locStr) for i := range locs { @@ -1094,6 +1155,18 @@ func (d *Debugger) ClearCheckpoint(id int) error { return d.target.ClearCheckpoint(id) } +// ListDynamicLibraries returns a list of loaded dynamic libraries. +func (d *Debugger) ListDynamicLibraries() []api.Image { + d.processMutex.Lock() + defer d.processMutex.Unlock() + bi := d.target.BinInfo() + r := make([]api.Image, len(bi.Images)) + for i := range bi.Images { + r[i] = api.ConvertImage(bi.Images[i]) + } + return r +} + func go11DecodeErrorCheck(err error) error { if _, isdecodeerr := err.(dwarf.DecodeError); !isdecodeerr { return err diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go b/vendor/github.com/go-delve/delve/service/debugger/debugger_darwin.go similarity index 100% rename from vendor/github.com/derekparker/delve/service/debugger/debugger_darwin.go rename to vendor/github.com/go-delve/delve/service/debugger/debugger_darwin.go diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go b/vendor/github.com/go-delve/delve/service/debugger/debugger_linux.go similarity index 100% rename from vendor/github.com/derekparker/delve/service/debugger/debugger_linux.go rename to vendor/github.com/go-delve/delve/service/debugger/debugger_linux.go diff --git a/vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go b/vendor/github.com/go-delve/delve/service/debugger/debugger_windows.go similarity index 100% rename from vendor/github.com/derekparker/delve/service/debugger/debugger_windows.go rename to vendor/github.com/go-delve/delve/service/debugger/debugger_windows.go diff --git a/vendor/github.com/derekparker/delve/service/debugger/locations.go b/vendor/github.com/go-delve/delve/service/debugger/locations.go similarity index 96% rename from vendor/github.com/derekparker/delve/service/debugger/locations.go rename to vendor/github.com/go-delve/delve/service/debugger/locations.go index 32289d4..29419f3 100644 --- a/vendor/github.com/derekparker/delve/service/debugger/locations.go +++ b/vendor/github.com/go-delve/delve/service/debugger/locations.go @@ -3,14 +3,15 @@ package debugger import ( "fmt" "go/constant" + "path" "path/filepath" "reflect" "runtime" "strconv" "strings" - "github.com/derekparker/delve/pkg/proc" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/service/api" ) const maxFindLocationCandidates = 5 @@ -265,7 +266,7 @@ func (loc *AddrLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str } return []api.Location{{PC: uint64(addr)}}, nil } else { - v, err := scope.EvalExpression(loc.AddrExpr, proc.LoadConfig{true, 0, 0, 0, 0}) + v, err := scope.EvalExpression(loc.AddrExpr, proc.LoadConfig{true, 0, 0, 0, 0, 0}) if err != nil { return nil, err } @@ -293,6 +294,10 @@ func (loc *NormalLocationSpec) FileMatch(path string) bool { return partialPathMatch(loc.Base, path) } +func tryMatchRelativePathByProc(expr, debugname, file string) bool { + return len(expr) > 0 && expr[0] == '.' && file == path.Join(path.Dir(debugname), expr) +} + func partialPathMatch(expr, path string) bool { if runtime.GOOS == "windows" { // Accept `expr` which is case-insensitive and slash-insensitive match to `path` @@ -329,7 +334,7 @@ func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s limit := maxFindLocationCandidates var candidateFiles []string for _, file := range d.target.BinInfo().Sources { - if loc.FileMatch(file) { + if loc.FileMatch(file) || (len(d.processArgs) >= 1 && tryMatchRelativePathByProc(loc.Base, d.processArgs[0], file)) { candidateFiles = append(candidateFiles, file) if len(candidateFiles) >= limit { break diff --git a/vendor/github.com/derekparker/delve/service/listenerpipe.go b/vendor/github.com/go-delve/delve/service/listenerpipe.go similarity index 100% rename from vendor/github.com/derekparker/delve/service/listenerpipe.go rename to vendor/github.com/go-delve/delve/service/listenerpipe.go diff --git a/vendor/github.com/derekparker/delve/service/rpc1/client.go b/vendor/github.com/go-delve/delve/service/rpc1/client.go similarity index 99% rename from vendor/github.com/derekparker/delve/service/rpc1/client.go rename to vendor/github.com/go-delve/delve/service/rpc1/client.go index c0f2535..945ac18 100644 --- a/vendor/github.com/derekparker/delve/service/rpc1/client.go +++ b/vendor/github.com/go-delve/delve/service/rpc1/client.go @@ -9,7 +9,7 @@ import ( "sync" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/service/api" ) // Client is a RPC service.Client. diff --git a/vendor/github.com/derekparker/delve/service/rpc1/readme.txtr b/vendor/github.com/go-delve/delve/service/rpc1/readme.txtr similarity index 100% rename from vendor/github.com/derekparker/delve/service/rpc1/readme.txtr rename to vendor/github.com/go-delve/delve/service/rpc1/readme.txtr diff --git a/vendor/github.com/derekparker/delve/service/rpc1/server.go b/vendor/github.com/go-delve/delve/service/rpc1/server.go similarity index 96% rename from vendor/github.com/derekparker/delve/service/rpc1/server.go rename to vendor/github.com/go-delve/delve/service/rpc1/server.go index 10a6345..af11ec6 100644 --- a/vendor/github.com/derekparker/delve/service/rpc1/server.go +++ b/vendor/github.com/go-delve/delve/service/rpc1/server.go @@ -4,13 +4,13 @@ import ( "errors" "fmt" - "github.com/derekparker/delve/pkg/proc" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" - "github.com/derekparker/delve/service/debugger" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/api" + "github.com/go-delve/delve/service/debugger" ) -var defaultLoadConfig = proc.LoadConfig{true, 1, 64, 64, -1} +var defaultLoadConfig = proc.LoadConfig{true, 1, 64, 64, -1, 0} type RPCServer struct { // config is all the information necessary to start the debugger and server. @@ -283,7 +283,7 @@ func (s *RPCServer) ListTypes(filter string, types *[]string) error { } func (s *RPCServer) ListGoroutines(arg interface{}, goroutines *[]*api.Goroutine) error { - gs, err := s.debugger.Goroutines() + gs, _, err := s.debugger.Goroutines(0, 0) if err != nil { return err } diff --git a/vendor/github.com/derekparker/delve/service/rpc2/client.go b/vendor/github.com/go-delve/delve/service/rpc2/client.go similarity index 88% rename from vendor/github.com/derekparker/delve/service/rpc2/client.go rename to vendor/github.com/go-delve/delve/service/rpc2/client.go index bb22cd2..1242434 100644 --- a/vendor/github.com/derekparker/delve/service/rpc2/client.go +++ b/vendor/github.com/go-delve/delve/service/rpc2/client.go @@ -8,8 +8,8 @@ import ( "net/rpc/jsonrpc" "time" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/api" ) // Client is a RPC service.Client. @@ -74,7 +74,7 @@ func (c *RPCClient) RestartFrom(pos string, resetArgs bool, newArgs []string) ([ func (c *RPCClient) GetState() (*api.DebuggerState, error) { var out StateOut - err := c.call("State", StateIn{}, &out) + err := c.call("State", StateIn{NonBlocking: false}, &out) return out.State, err } @@ -117,7 +117,7 @@ func (c *RPCClient) continueDir(cmd string) <-chan *api.DebuggerState { for i := range state.Threads { if state.Threads[i].Breakpoint != nil { isbreakpoint = true - istracepoint = istracepoint && state.Threads[i].Breakpoint.Tracepoint + istracepoint = istracepoint && (state.Threads[i].Breakpoint.Tracepoint || state.Threads[i].Breakpoint.TraceReturn) } } @@ -144,13 +144,13 @@ func (c *RPCClient) Step() (*api.DebuggerState, error) { func (c *RPCClient) StepOut() (*api.DebuggerState, error) { var out CommandOut - err := c.call("Command", &api.DebuggerCommand{Name: api.StepOut, ReturnInfoLoadConfig: c.retValLoadCfg}, &out) + err := c.call("Command", api.DebuggerCommand{Name: api.StepOut, ReturnInfoLoadConfig: c.retValLoadCfg}, &out) return &out.State, err } -func (c *RPCClient) Call(expr string) (*api.DebuggerState, error) { +func (c *RPCClient) Call(expr string, unsafe bool) (*api.DebuggerState, error) { var out CommandOut - err := c.call("Command", &api.DebuggerCommand{Name: api.Call, ReturnInfoLoadConfig: c.retValLoadCfg, Expr: expr}, &out) + err := c.call("Command", api.DebuggerCommand{Name: api.Call, ReturnInfoLoadConfig: c.retValLoadCfg, Expr: expr, UnsafeCall: unsafe}, &out) return &out.State, err } @@ -298,10 +298,10 @@ func (c *RPCClient) ListFunctionArgs(scope api.EvalScope, cfg api.LoadConfig) ([ return out.Args, err } -func (c *RPCClient) ListGoroutines() ([]*api.Goroutine, error) { +func (c *RPCClient) ListGoroutines(start, count int) ([]*api.Goroutine, int, error) { var out ListGoroutinesOut - err := c.call("ListGoroutines", ListGoroutinesIn{}, &out) - return out.Goroutines, err + err := c.call("ListGoroutines", ListGoroutinesIn{start, count}, &out) + return out.Goroutines, out.Nextg, err } func (c *RPCClient) Stacktrace(goroutineId, depth int, readDefers bool, cfg *api.LoadConfig) ([]api.Stackframe, error) { @@ -310,6 +310,12 @@ func (c *RPCClient) Stacktrace(goroutineId, depth int, readDefers bool, cfg *api return out.Locations, err } +func (c *RPCClient) Ancestors(goroutineID int, numAncestors int, depth int) ([]api.Ancestor, error) { + var out AncestorsOut + err := c.call("Ancestors", AncestorsIn{goroutineID, numAncestors, depth}, &out) + return out.Ancestors, err +} + func (c *RPCClient) AttachedToExistingProcess() bool { out := new(AttachedToExistingProcessOut) c.call("AttachedToExistingProcess", AttachedToExistingProcessIn{}, out) @@ -375,6 +381,12 @@ func (c *RPCClient) SetReturnValuesLoadConfig(cfg *api.LoadConfig) { c.retValLoadCfg = cfg } +func (c *RPCClient) FunctionReturnLocations(fnName string) ([]uint64, error) { + var out FunctionReturnLocationsOut + err := c.call("FunctionReturnLocations", FunctionReturnLocationsIn{fnName}, &out) + return out.Addrs, err +} + func (c *RPCClient) IsMulticlient() bool { var out IsMulticlientOut c.call("IsMulticlient", IsMulticlientIn{}, &out) @@ -389,6 +401,12 @@ func (c *RPCClient) Disconnect(cont bool) error { return c.client.Close() } +func (c *RPCClient) ListDynamicLibraries() ([]api.Image, error) { + var out ListDynamicLibrariesOut + c.call("ListDynamicLibraries", ListDynamicLibrariesIn{}, &out) + return out.List, nil +} + 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/go-delve/delve/service/rpc2/server.go similarity index 86% rename from vendor/github.com/derekparker/delve/service/rpc2/server.go rename to vendor/github.com/go-delve/delve/service/rpc2/server.go index cde9dbe..542cbee 100644 --- a/vendor/github.com/derekparker/delve/service/rpc2/server.go +++ b/vendor/github.com/go-delve/delve/service/rpc2/server.go @@ -5,9 +5,9 @@ import ( "fmt" "time" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" - "github.com/derekparker/delve/service/debugger" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/api" + "github.com/go-delve/delve/service/debugger" ) type RPCServer struct { @@ -174,10 +174,24 @@ func (s *RPCServer) Stacktrace(arg StacktraceIn, out *StacktraceOut) error { } var err error out.Locations, err = s.debugger.Stacktrace(arg.Id, arg.Depth, arg.Defers, api.LoadConfigToProc(cfg)) - if err != nil { - return err - } - return nil + return err +} + +type AncestorsIn struct { + GoroutineID int + NumAncestors int + Depth int +} + +type AncestorsOut struct { + Ancestors []api.Ancestor +} + +// Ancestors returns the stacktraces for the ancestors of a goroutine. +func (s *RPCServer) Ancestors(arg AncestorsIn, out *AncestorsOut) error { + var err error + out.Ancestors, err = s.debugger.Ancestors(arg.GoroutineID, arg.NumAncestors, arg.Depth) + return err } type ListBreakpointsIn struct { @@ -423,7 +437,7 @@ type EvalOut struct { // EvalVariable returns a variable in the specified context. // -// See https://github.com/derekparker/delve/wiki/Expressions for +// See https://github.com/go-delve/delve/wiki/Expressions for // a description of acceptable values of arg.Expr. func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error { cfg := arg.Cfg @@ -508,19 +522,28 @@ func (s *RPCServer) ListTypes(arg ListTypesIn, out *ListTypesOut) error { } type ListGoroutinesIn struct { + Start int + Count int } type ListGoroutinesOut struct { Goroutines []*api.Goroutine + Nextg int } // ListGoroutines lists all goroutines. +// If Count is specified ListGoroutines will return at the first Count +// goroutines and an index in Nextg, that can be passed as the Start +// parameter, to get more goroutines from ListGoroutines. +// Passing a value of Start that wasn't returned by ListGoroutines will skip +// an undefined number of goroutines. func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error { - gs, err := s.debugger.Goroutines() + gs, nextg, err := s.debugger.Goroutines(arg.Start, arg.Count) if err != nil { return err } out.Goroutines = gs + out.Nextg = nextg return nil } @@ -655,3 +678,47 @@ func (s *RPCServer) IsMulticlient(arg IsMulticlientIn, out *IsMulticlientOut) er } return nil } + +// FunctionReturnLocationsIn holds arguments for the +// FunctionReturnLocationsRPC call. It holds the name of +// the function for which all return locations should be +// given. +type FunctionReturnLocationsIn struct { + // FnName is the name of the function for which all + // return locations should be given. + FnName string +} + +// FunctionReturnLocationsOut holds the result of the FunctionReturnLocations +// RPC call. It provides the list of addresses that the given function returns, +// for example with a `RET` instruction or `CALL runtime.deferreturn`. +type FunctionReturnLocationsOut struct { + // Addrs is the list of all locations where the given function returns. + Addrs []uint64 +} + +// FunctionReturnLocations is the implements the client call of the same name. Look at client documentation for more information. +func (s *RPCServer) FunctionReturnLocations(in FunctionReturnLocationsIn, out *FunctionReturnLocationsOut) error { + addrs, err := s.debugger.FunctionReturnLocations(in.FnName) + if err != nil { + return err + } + *out = FunctionReturnLocationsOut{ + Addrs: addrs, + } + return nil +} + +// ListDynamicLibrariesIn holds the arguments of ListDynamicLibraries +type ListDynamicLibrariesIn struct { +} + +// ListDynamicLibrariesOut holds the return values of ListDynamicLibraries +type ListDynamicLibrariesOut struct { + List []api.Image +} + +func (s *RPCServer) ListDynamicLibraries(in ListDynamicLibrariesIn, out *ListDynamicLibrariesOut) error { + out.List = s.debugger.ListDynamicLibraries() + return nil +} diff --git a/vendor/github.com/derekparker/delve/service/rpccallback.go b/vendor/github.com/go-delve/delve/service/rpccallback.go similarity index 100% rename from vendor/github.com/derekparker/delve/service/rpccallback.go rename to vendor/github.com/go-delve/delve/service/rpccallback.go diff --git a/vendor/github.com/derekparker/delve/service/rpccommon/server.go b/vendor/github.com/go-delve/delve/service/rpccommon/server.go similarity index 93% rename from vendor/github.com/derekparker/delve/service/rpccommon/server.go rename to vendor/github.com/go-delve/delve/service/rpccommon/server.go index a0cc4c3..df09e13 100644 --- a/vendor/github.com/derekparker/delve/service/rpccommon/server.go +++ b/vendor/github.com/go-delve/delve/service/rpccommon/server.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "net/rpc" "net/rpc/jsonrpc" @@ -16,13 +15,13 @@ import ( "unicode" "unicode/utf8" - "github.com/derekparker/delve/pkg/logflags" - "github.com/derekparker/delve/pkg/version" - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" - "github.com/derekparker/delve/service/debugger" - "github.com/derekparker/delve/service/rpc1" - "github.com/derekparker/delve/service/rpc2" + "github.com/go-delve/delve/pkg/logflags" + "github.com/go-delve/delve/pkg/version" + "github.com/go-delve/delve/service" + "github.com/go-delve/delve/service/api" + "github.com/go-delve/delve/service/debugger" + "github.com/go-delve/delve/service/rpc1" + "github.com/go-delve/delve/service/rpc2" "github.com/sirupsen/logrus" ) @@ -68,17 +67,13 @@ type methodType struct { // NewServer creates a new RPCServer. func NewServer(config *service.Config) *ServerImpl { - logger := logrus.New().WithFields(logrus.Fields{"layer": "rpc"}) - logger.Logger.Level = logrus.DebugLevel - if !logflags.RPC() { - logger.Logger.Out = ioutil.Discard - } + logger := logflags.RPCLogger() if config.APIVersion < 2 { logger.Info("Using API v1") } if config.Foreground { // Print listener address - fmt.Printf("API server listening at: %s\n", config.Listener.Addr()) + logflags.WriteAPIListeningMessage(config.Listener.Addr().String()) } return &ServerImpl{ config: config, @@ -121,11 +116,12 @@ func (s *ServerImpl) Run() error { // Create and start the debugger if s.debugger, err = debugger.New(&debugger.Config{ - AttachPid: s.config.AttachPid, - WorkingDir: s.config.WorkingDir, - CoreFile: s.config.CoreFile, - Backend: s.config.Backend, - Foreground: s.config.Foreground, + AttachPid: s.config.AttachPid, + WorkingDir: s.config.WorkingDir, + CoreFile: s.config.CoreFile, + Backend: s.config.Backend, + Foreground: s.config.Foreground, + DebugInfoDirectories: s.config.DebugInfoDirectories, }, s.config.ProcessArgs); err != nil { return err diff --git a/vendor/github.com/derekparker/delve/service/server.go b/vendor/github.com/go-delve/delve/service/server.go similarity index 100% rename from vendor/github.com/derekparker/delve/service/server.go rename to vendor/github.com/go-delve/delve/service/server.go diff --git a/vendor/github.com/lib/pq/oid/gen.go b/vendor/github.com/lib/pq/oid/gen.go deleted file mode 100644 index cd4aea8..0000000 --- a/vendor/github.com/lib/pq/oid/gen.go +++ /dev/null @@ -1,74 +0,0 @@ -// +build ignore - -// Generate the table of OID values -// Run with 'go run gen.go'. -package main - -import ( - "database/sql" - "fmt" - "log" - "os" - "os/exec" - - _ "github.com/lib/pq" -) - -func main() { - datname := os.Getenv("PGDATABASE") - sslmode := os.Getenv("PGSSLMODE") - - if datname == "" { - os.Setenv("PGDATABASE", "pqgotest") - } - - if sslmode == "" { - os.Setenv("PGSSLMODE", "disable") - } - - db, err := sql.Open("postgres", "") - if err != nil { - log.Fatal(err) - } - cmd := exec.Command("gofmt") - cmd.Stderr = os.Stderr - w, err := cmd.StdinPipe() - if err != nil { - log.Fatal(err) - } - f, err := os.Create("types.go") - if err != nil { - log.Fatal(err) - } - cmd.Stdout = f - err = cmd.Start() - if err != nil { - log.Fatal(err) - } - fmt.Fprintln(w, "// generated by 'go run gen.go'; do not edit") - fmt.Fprintln(w, "\npackage oid") - fmt.Fprintln(w, "const (") - rows, err := db.Query(` - SELECT typname, oid - FROM pg_type WHERE oid < 10000 - ORDER BY oid; - `) - if err != nil { - log.Fatal(err) - } - var name string - var oid int - for rows.Next() { - err = rows.Scan(&name, &oid) - if err != nil { - log.Fatal(err) - } - fmt.Fprintf(w, "T_%s Oid = %d\n", name, oid) - } - if err = rows.Err(); err != nil { - log.Fatal(err) - } - fmt.Fprintln(w, ")") - w.Close() - cmd.Wait() -} diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md new file mode 100644 index 0000000..56729a9 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -0,0 +1,48 @@ +# go-colorable + +[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) +[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) +[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master) +[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) + +Colorable writer for windows. + +For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) +This package is possible to handle escape sequence for ansi color on windows. + +## Too Bad! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) + + +## So Good! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) + +## Usage + +```go +logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) +logrus.SetOutput(colorable.NewColorableStdout()) + +logrus.Info("succeeded") +logrus.Warn("not correct") +logrus.Error("something error") +logrus.Fatal("panic") +``` + +You can compile above code on non-windows OSs. + +## Installation + +``` +$ go get github.com/mattn/go-colorable +``` + +# License + +MIT + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md new file mode 100644 index 0000000..1e69004 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -0,0 +1,50 @@ +# go-isatty + +[![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty) +[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) +[![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) +[![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty) + +isatty for golang + +## Usage + +```go +package main + +import ( + "fmt" + "github.com/mattn/go-isatty" + "os" +) + +func main() { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Println("Is Terminal") + } else if isatty.IsCygwinTerminal(os.Stdout.Fd()) { + fmt.Println("Is Cygwin/MSYS2 Terminal") + } else { + fmt.Println("Is Not Terminal") + } +} +``` + +## Installation + +``` +$ go get github.com/mattn/go-isatty +``` + +## License + +MIT + +## Author + +Yasuhiro Matsumoto (a.k.a mattn) + +## Thanks + +* k-takata: base idea for IsCygwinTerminal + + https://github.com/k-takata/go-iscygpty diff --git a/vendor/github.com/peterh/liner/README.md b/vendor/github.com/peterh/liner/README.md new file mode 100644 index 0000000..9148b24 --- /dev/null +++ b/vendor/github.com/peterh/liner/README.md @@ -0,0 +1,100 @@ +Liner +===== + +Liner is a command line editor with history. It was inspired by linenoise; +everything Unix-like is a VT100 (or is trying very hard to be). If your +terminal is not pretending to be a VT100, change it. Liner also support +Windows. + +Liner is released under the X11 license (which is similar to the new BSD +license). + +Line Editing +------------ + +The following line editing commands are supported on platforms and terminals +that Liner supports: + +Keystroke | Action +--------- | ------ +Ctrl-A, Home | Move cursor to beginning of line +Ctrl-E, End | Move cursor to end of line +Ctrl-B, Left | Move cursor one character left +Ctrl-F, Right| Move cursor one character right +Ctrl-Left, Alt-B | Move cursor to previous word +Ctrl-Right, Alt-F | Move cursor to next word +Ctrl-D, Del | (if line is *not* empty) Delete character under cursor +Ctrl-D | (if line *is* empty) End of File - usually quits application +Ctrl-C | Reset input (create new empty prompt) +Ctrl-L | Clear screen (line is unmodified) +Ctrl-T | Transpose previous character with current character +Ctrl-H, BackSpace | Delete character before cursor +Ctrl-W | Delete word leading up to cursor +Ctrl-K | Delete from cursor to end of line +Ctrl-U | Delete from start of line to cursor +Ctrl-P, Up | Previous match from history +Ctrl-N, Down | Next match from history +Ctrl-R | Reverse Search history (Ctrl-S forward, Ctrl-G cancel) +Ctrl-Y | Paste from Yank buffer (Alt-Y to paste next yank instead) +Tab | Next completion +Shift-Tab | (after Tab) Previous completion + +Getting started +----------------- + +```go +package main + +import ( + "log" + "os" + "path/filepath" + "strings" + + "github.com/peterh/liner" +) + +var ( + history_fn = filepath.Join(os.TempDir(), ".liner_example_history") + names = []string{"john", "james", "mary", "nancy"} +) + +func main() { + line := liner.NewLiner() + defer line.Close() + + line.SetCtrlCAborts(true) + + line.SetCompleter(func(line string) (c []string) { + for _, n := range names { + if strings.HasPrefix(n, strings.ToLower(line)) { + c = append(c, n) + } + } + return + }) + + if f, err := os.Open(history_fn); err == nil { + line.ReadHistory(f) + f.Close() + } + + if name, err := line.Prompt("What is your name? "); err == nil { + log.Print("Got: ", name) + line.AppendHistory(name) + } else if err == liner.ErrPromptAborted { + log.Print("Aborted") + } else { + log.Print("Error reading line: ", err) + } + + if f, err := os.Create(history_fn); err != nil { + log.Print("Error writing history file: ", err) + } else { + line.WriteHistory(f) + f.Close() + } +} +``` + +For documentation, see http://godoc.org/github.com/peterh/liner diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md new file mode 100644 index 0000000..1bd1deb --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -0,0 +1,123 @@ +# 1.0.5 + +* Fix hooks race (#707) +* Fix panic deadlock (#695) + +# 1.0.4 + +* Fix race when adding hooks (#612) +* Fix terminal check in AppEngine (#635) + +# 1.0.3 + +* Replace example files with testable examples + +# 1.0.2 + +* bug: quote non-string values in text formatter (#583) +* Make (*Logger) SetLevel a public method + +# 1.0.1 + +* bug: fix escaping in text formatter (#575) + +# 1.0.0 + +* Officially changed name to lower-case +* bug: colors on Windows 10 (#541) +* bug: fix race in accessing level (#512) + +# 0.11.5 + +* feature: add writer and writerlevel to entry (#372) + +# 0.11.4 + +* bug: fix undefined variable on solaris (#493) + +# 0.11.3 + +* formatter: configure quoting of empty values (#484) +* formatter: configure quoting character (default is `"`) (#484) +* bug: fix not importing io correctly in non-linux environments (#481) + +# 0.11.2 + +* bug: fix windows terminal detection (#476) + +# 0.11.1 + +* bug: fix tty detection with custom out (#471) + +# 0.11.0 + +* performance: Use bufferpool to allocate (#370) +* terminal: terminal detection for app-engine (#343) +* feature: exit handler (#375) + +# 0.10.0 + +* feature: Add a test hook (#180) +* feature: `ParseLevel` is now case-insensitive (#326) +* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) +* performance: avoid re-allocations on `WithFields` (#335) + +# 0.9.0 + +* logrus/text_formatter: don't emit empty msg +* logrus/hooks/airbrake: move out of main repository +* logrus/hooks/sentry: move out of main repository +* logrus/hooks/papertrail: move out of main repository +* logrus/hooks/bugsnag: move out of main repository +* logrus/core: run tests with `-race` +* logrus/core: detect TTY based on `stderr` +* logrus/core: support `WithError` on logger +* logrus/core: Solaris support + +# 0.8.7 + +* logrus/core: fix possible race (#216) +* logrus/doc: small typo fixes and doc improvements + + +# 0.8.6 + +* hooks/raven: allow passing an initialized client + +# 0.8.5 + +* logrus/core: revert #208 + +# 0.8.4 + +* formatter/text: fix data race (#218) + +# 0.8.3 + +* logrus/core: fix entry log level (#208) +* logrus/core: improve performance of text formatter by 40% +* logrus/core: expose `LevelHooks` type +* logrus/core: add support for DragonflyBSD and NetBSD +* formatter/text: print structs more verbosely + +# 0.8.2 + +* logrus: fix more Fatal family functions + +# 0.8.1 + +* logrus: fix not exiting on `Fatalf` and `Fatalln` + +# 0.8.0 + +* logrus: defaults to stderr instead of stdout +* hooks/sentry: add special field for `*http.Request` +* formatter/text: ignore Windows for colors + +# 0.7.3 + +* formatter/\*: allow configuration of timestamp layout + +# 0.7.2 + +* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md new file mode 100644 index 0000000..072e99b --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -0,0 +1,461 @@ +# Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) + +Logrus is a structured logger for Go (golang), completely API compatible with +the standard library logger. + +**Seeing weird case-sensitive problems?** It's in the past been possible to +import Logrus as both upper- and lower-case. Due to the Go package environment, +this caused issues in the community and we needed a standard. Some environments +experienced problems with the upper-case variant, so the lower-case was decided. +Everything using `logrus` will need to use the lower-case: +`github.com/sirupsen/logrus`. Any package that isn't, should be changed. + +To fix Glide, see [these +comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437). +For an in-depth explanation of the casing issue, see [this +comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). + +**Are you interested in assisting in maintaining Logrus?** Currently I have a +lot of obligations, and I am unable to provide Logrus with the maintainership it +needs. If you'd like to help, please reach out to me at `simon at author's +username dot com`. + +Nicely color-coded in development (when a TTY is attached, otherwise just +plain text): + +![Colored](http://i.imgur.com/PY7qMwd.png) + +With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash +or Splunk: + +```json +{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the +ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} + +{"level":"warning","msg":"The group's number increased tremendously!", +"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"A giant walrus appears!", +"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", +"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} + +{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, +"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} +``` + +With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not +attached, the output is compatible with the +[logfmt](http://godoc.org/github.com/kr/logfmt) format: + +```text +time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 +time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 +time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true +time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 +time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 +time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true +exit status 1 +``` + +#### Case-sensitivity + +The organization's name was changed to lower-case--and this will not be changed +back. If you are getting import conflicts due to case sensitivity, please use +the lower-case import: `github.com/sirupsen/logrus`. + +#### Example + +The simplest way to use Logrus is simply the package-level exported logger: + +```go +package main + +import ( + log "github.com/sirupsen/logrus" +) + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + }).Info("A walrus appears") +} +``` + +Note that it's completely api-compatible with the stdlib logger, so you can +replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"` +and you'll now have the flexibility of Logrus. You can customize it all you +want: + +```go +package main + +import ( + "os" + log "github.com/sirupsen/logrus" +) + +func init() { + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.JSONFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + + // Only log the warning severity or above. + log.SetLevel(log.WarnLevel) +} + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(log.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(log.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") + + // A common pattern is to re-use fields between logging statements by re-using + // the logrus.Entry returned from WithFields() + contextLogger := log.WithFields(log.Fields{ + "common": "this is a common field", + "other": "I also should be logged always", + }) + + contextLogger.Info("I'll be logged with common and other field") + contextLogger.Info("Me too") +} +``` + +For more advanced usage such as logging to multiple locations from the same +application, you can also create an instance of the `logrus` Logger: + +```go +package main + +import ( + "os" + "github.com/sirupsen/logrus" +) + +// Create a new instance of the logger. You can have any number of instances. +var log = logrus.New() + +func main() { + // The API for setting attributes is a little different than the package level + // exported logger. See Godoc. + log.Out = os.Stdout + + // You could set this to any `io.Writer` such as a file + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") +} +``` + +#### Fields + +Logrus encourages careful, structured logging through logging fields instead of +long, unparseable error messages. For example, instead of: `log.Fatalf("Failed +to send event %s to topic %s with key %d")`, you should log the much more +discoverable: + +```go +log.WithFields(log.Fields{ + "event": event, + "topic": topic, + "key": key, +}).Fatal("Failed to send event") +``` + +We've found this API forces you to think about logging in a way that produces +much more useful logging messages. We've been in countless situations where just +a single added field to a log statement that was already there would've saved us +hours. The `WithFields` call is optional. + +In general, with Logrus using any of the `printf`-family functions should be +seen as a hint you should add a field, however, you can still use the +`printf`-family functions with Logrus. + +#### Default Fields + +Often it's helpful to have fields _always_ attached to log statements in an +application or parts of one. For example, you may want to always log the +`request_id` and `user_ip` in the context of a request. Instead of writing +`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on +every line, you can create a `logrus.Entry` to pass around instead: + +```go +requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) +requestLogger.Info("something happened on that request") # will log request_id and user_ip +requestLogger.Warn("something not great happened") +``` + +#### Hooks + +You can add hooks for logging levels. For example to send errors to an exception +tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to +multiple places simultaneously, e.g. syslog. + +Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in +`init`: + +```go +import ( + log "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + "log/syslog" +) + +func init() { + + // Use the Airbrake hook to report errors that have Error severity or above to + // an exception tracker. You can create custom hooks, see the Hooks section. + log.AddHook(airbrake.NewHook(123, "xyz", "production")) + + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + if err != nil { + log.Error("Unable to connect to local syslog daemon") + } else { + log.AddHook(hook) + } +} +``` +Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). + +A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks) + + +#### Level logging + +Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. + +```go +log.Debug("Useful debugging information.") +log.Info("Something noteworthy happened!") +log.Warn("You should probably take a look at this.") +log.Error("Something failed but I'm not quitting.") +// Calls os.Exit(1) after logging +log.Fatal("Bye.") +// Calls panic() after logging +log.Panic("I'm bailing.") +``` + +You can set the logging level on a `Logger`, then it will only log entries with +that severity or anything above it: + +```go +// Will log anything that is info or above (warn, error, fatal, panic). Default. +log.SetLevel(log.InfoLevel) +``` + +It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose +environment if your application has that. + +#### Entries + +Besides the fields added with `WithField` or `WithFields` some fields are +automatically added to all logging events: + +1. `time`. The timestamp when the entry was created. +2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after + the `AddFields` call. E.g. `Failed to send event.` +3. `level`. The logging level. E.g. `info`. + +#### Environments + +Logrus has no notion of environment. + +If you wish for hooks and formatters to only be used in specific environments, +you should handle that yourself. For example, if your application has a global +variable `Environment`, which is a string representation of the environment you +could do: + +```go +import ( + log "github.com/sirupsen/logrus" +) + +init() { + // do something here to set environment depending on an environment variable + // or command-line flag + if Environment == "production" { + log.SetFormatter(&log.JSONFormatter{}) + } else { + // The TextFormatter is default, you don't actually have to do this. + log.SetFormatter(&log.TextFormatter{}) + } +} +``` + +This configuration is how `logrus` was intended to be used, but JSON in +production is mostly only useful if you do log aggregation with tools like +Splunk or Logstash. + +#### Formatters + +The built-in logging formatters are: + +* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise + without colors. + * *Note:* to force colored output when there is no TTY, set the `ForceColors` + field to `true`. To force no colored output even if there is a TTY set the + `DisableColors` field to `true`. For Windows, see + [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * When colors are enabled, levels are truncated to 4 characters by default. To disable + truncation set the `DisableLevelTruncation` field to `true`. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). +* `logrus.JSONFormatter`. Logs fields as JSON. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). + +Third party logging formatters: + +* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine. +* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. +* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. +* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. + +You can define your formatter by implementing the `Formatter` interface, +requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a +`Fields` type (`map[string]interface{}`) with all your fields as well as the +default ones (see Entries section above): + +```go +type MyJSONFormatter struct { +} + +log.SetFormatter(new(MyJSONFormatter)) + +func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { + // Note this doesn't include Time, Level and Message which are available on + // the Entry. Consult `godoc` on information about those fields or read the + // source of the official loggers. + serialized, err := json.Marshal(entry.Data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return append(serialized, '\n'), nil +} +``` + +#### Logger as an `io.Writer` + +Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. + +```go +w := logger.Writer() +defer w.Close() + +srv := http.Server{ + // create a stdlib log.Logger that writes to + // logrus.Logger. + ErrorLog: log.New(w, "", 0), +} +``` + +Each line written to that writer will be printed the usual way, using formatters +and hooks. The level for those entries is `info`. + +This means that we can override the standard library logger easily: + +```go +logger := logrus.New() +logger.Formatter = &logrus.JSONFormatter{} + +// Use logrus for standard log output +// Note that `log` here references stdlib's log +// Not logrus imported under the name `log`. +log.SetOutput(logger.Writer()) +``` + +#### Rotation + +Log rotation is not provided with Logrus. Log rotation should be done by an +external program (like `logrotate(8)`) that can compress and delete old log +entries. It should not be a feature of the application-level logger. + +#### Tools + +| Tool | Description | +| ---- | ----------- | +|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.| +|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | + +#### Testing + +Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: + +* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook +* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): + +```go +import( + "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSomething(t*testing.T){ + logger, hook := test.NewNullLogger() + logger.Error("Helloerror") + + assert.Equal(t, 1, len(hook.Entries)) + assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal(t, "Helloerror", hook.LastEntry().Message) + + hook.Reset() + assert.Nil(t, hook.LastEntry()) +} +``` + +#### Fatal handlers + +Logrus can register one or more functions that will be called when any `fatal` +level message is logged. The registered handlers will be executed before +logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need +to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. + +``` +... +handler := func() { + // gracefully shutdown something... +} +logrus.RegisterExitHandler(handler) +... +``` + +#### Thread safety + +By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs. +If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. + +Situation when locking is not needed includes: + +* You have no hooks registered, or hooks calling is already thread-safe. + +* Writing to logger.Out is already thread-safe, for example: + + 1) logger.Out is protected by locks. + + 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing) + + (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) diff --git a/vendor/github.com/sirupsen/logrus/appveyor.yml b/vendor/github.com/sirupsen/logrus/appveyor.yml new file mode 100644 index 0000000..b4ffca2 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/appveyor.yml @@ -0,0 +1,14 @@ +version: "{build}" +platform: x64 +clone_folder: c:\gopath\src\github.com\sirupsen\logrus +environment: + GOPATH: c:\gopath +branches: + only: + - master +install: + - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% + - go version +build_script: + - go get -t + - go test diff --git a/vendor/golang.org/x/arch/x86/x86asm/Makefile b/vendor/golang.org/x/arch/x86/x86asm/Makefile new file mode 100644 index 0000000..9eb4557 --- /dev/null +++ b/vendor/golang.org/x/arch/x86/x86asm/Makefile @@ -0,0 +1,3 @@ +tables.go: ../x86map/map.go ../x86.csv + go run ../x86map/map.go -fmt=decoder ../x86.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go + diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go deleted file mode 100644 index af3af60..0000000 --- a/vendor/golang.org/x/sys/windows/aliases.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows -// +build go1.9 - -package windows - -import "syscall" - -type Errno = syscall.Errno -type SysProcAttr = syscall.SysProcAttr diff --git a/vendor/golang.org/x/sys/windows/asm_windows_arm.s b/vendor/golang.org/x/sys/windows/asm_windows_arm.s deleted file mode 100644 index 55d8b91..0000000 --- a/vendor/golang.org/x/sys/windows/asm_windows_arm.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -TEXT ·getprocaddress(SB),NOSPLIT,$0 - B syscall·getprocaddress(SB) - -TEXT ·loadlibrary(SB),NOSPLIT,$0 - B syscall·loadlibrary(SB) diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index 62fc31b..24aa90b 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -43,11 +43,6 @@ const ( SC_STATUS_PROCESS_INFO = 0 - SC_ACTION_NONE = 0 - SC_ACTION_RESTART = 1 - SC_ACTION_REBOOT = 2 - SC_ACTION_RUN_COMMAND = 3 - SERVICE_STOPPED = 1 SERVICE_START_PENDING = 2 SERVICE_STOP_PENDING = 3 @@ -153,19 +148,6 @@ type ENUM_SERVICE_STATUS_PROCESS struct { ServiceStatusProcess SERVICE_STATUS_PROCESS } -type SERVICE_FAILURE_ACTIONS struct { - ResetPeriod uint32 - RebootMsg *uint16 - Command *uint16 - ActionsCount uint32 - Actions *SC_ACTION -} - -type SC_ACTION struct { - Type uint32 - Delay uint32 -} - //sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle //sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW //sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 8a00b71..1e9f4bb 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -112,14 +112,12 @@ func Getpagesize() int { return 4096 } // NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. // This is useful when interoperating with Windows code requiring callbacks. -// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. func NewCallback(fn interface{}) uintptr { return syscall.NewCallback(fn) } // NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention. // This is useful when interoperating with Windows code requiring callbacks. -// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. func NewCallbackCDecl(fn interface{}) uintptr { return syscall.NewCallbackCDecl(fn) } @@ -655,7 +653,7 @@ type RawSockaddr struct { type RawSockaddrAny struct { Addr RawSockaddr - Pad [100]int8 + Pad [96]int8 } type Sockaddr interface { @@ -704,69 +702,19 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } -type RawSockaddrUnix struct { - Family uint16 - Path [UNIX_PATH_MAX]int8 -} - type SockaddrUnix struct { Name string - raw RawSockaddrUnix } func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { - name := sa.Name - n := len(name) - if n > len(sa.raw.Path) { - return nil, 0, syscall.EINVAL - } - if n == len(sa.raw.Path) && name[0] != '@' { - return nil, 0, syscall.EINVAL - } - sa.raw.Family = AF_UNIX - for i := 0; i < n; i++ { - sa.raw.Path[i] = int8(name[i]) - } - // length is family (uint16), name, NUL. - sl := int32(2) - if n > 0 { - sl += int32(n) + 1 - } - if sa.raw.Path[0] == '@' { - sa.raw.Path[0] = 0 - // Don't count trailing NUL for abstract address. - sl-- - } - - return unsafe.Pointer(&sa.raw), sl, nil + // TODO(brainman): implement SockaddrUnix.sockaddr() + return nil, 0, syscall.EWINDOWS } func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { switch rsa.Addr.Family { case AF_UNIX: - pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) - sa := new(SockaddrUnix) - if pp.Path[0] == 0 { - // "Abstract" Unix domain socket. - // Rewrite leading NUL as @ for textual display. - // (This is the standard convention.) - // Not friendly to overwrite in place, - // but the callers below don't care. - pp.Path[0] = '@' - } - - // Assume path ends at NUL. - // This is not technically the Linux semantics for - // abstract Unix domain sockets--they are supposed - // to be uninterpreted fixed-size binary blobs--but - // everyone uses this convention. - n := 0 - for n < len(pp.Path) && pp.Path[n] != 0 { - n++ - } - bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] - sa.Name = string(bytes) - return sa, nil + return nil, syscall.EWINDOWS case AF_INET: pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 141ca81..52c2037 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -94,29 +94,16 @@ const ( FILE_APPEND_DATA = 0x00000004 FILE_WRITE_ATTRIBUTES = 0x00000100 - FILE_SHARE_READ = 0x00000001 - FILE_SHARE_WRITE = 0x00000002 - FILE_SHARE_DELETE = 0x00000004 - - FILE_ATTRIBUTE_READONLY = 0x00000001 - FILE_ATTRIBUTE_HIDDEN = 0x00000002 - FILE_ATTRIBUTE_SYSTEM = 0x00000004 - FILE_ATTRIBUTE_DIRECTORY = 0x00000010 - FILE_ATTRIBUTE_ARCHIVE = 0x00000020 - FILE_ATTRIBUTE_DEVICE = 0x00000040 - FILE_ATTRIBUTE_NORMAL = 0x00000080 - FILE_ATTRIBUTE_TEMPORARY = 0x00000100 - FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200 - FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400 - FILE_ATTRIBUTE_COMPRESSED = 0x00000800 - FILE_ATTRIBUTE_OFFLINE = 0x00001000 - FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000 - FILE_ATTRIBUTE_ENCRYPTED = 0x00004000 - FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000 - FILE_ATTRIBUTE_VIRTUAL = 0x00010000 - FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000 - FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x00040000 - FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x00400000 + FILE_SHARE_READ = 0x00000001 + FILE_SHARE_WRITE = 0x00000002 + FILE_SHARE_DELETE = 0x00000004 + FILE_ATTRIBUTE_READONLY = 0x00000001 + FILE_ATTRIBUTE_HIDDEN = 0x00000002 + FILE_ATTRIBUTE_SYSTEM = 0x00000004 + FILE_ATTRIBUTE_DIRECTORY = 0x00000010 + FILE_ATTRIBUTE_ARCHIVE = 0x00000020 + FILE_ATTRIBUTE_NORMAL = 0x00000080 + FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400 INVALID_FILE_ATTRIBUTES = 0xffffffff @@ -270,87 +257,15 @@ const ( USAGE_MATCH_TYPE_AND = 0 USAGE_MATCH_TYPE_OR = 1 - /* msgAndCertEncodingType values for CertOpenStore function */ X509_ASN_ENCODING = 0x00000001 PKCS_7_ASN_ENCODING = 0x00010000 - /* storeProvider values for CertOpenStore function */ - CERT_STORE_PROV_MSG = 1 - CERT_STORE_PROV_MEMORY = 2 - CERT_STORE_PROV_FILE = 3 - CERT_STORE_PROV_REG = 4 - CERT_STORE_PROV_PKCS7 = 5 - CERT_STORE_PROV_SERIALIZED = 6 - CERT_STORE_PROV_FILENAME_A = 7 - CERT_STORE_PROV_FILENAME_W = 8 - CERT_STORE_PROV_FILENAME = CERT_STORE_PROV_FILENAME_W - CERT_STORE_PROV_SYSTEM_A = 9 - CERT_STORE_PROV_SYSTEM_W = 10 - CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W - CERT_STORE_PROV_COLLECTION = 11 - CERT_STORE_PROV_SYSTEM_REGISTRY_A = 12 - CERT_STORE_PROV_SYSTEM_REGISTRY_W = 13 - CERT_STORE_PROV_SYSTEM_REGISTRY = CERT_STORE_PROV_SYSTEM_REGISTRY_W - CERT_STORE_PROV_PHYSICAL_W = 14 - CERT_STORE_PROV_PHYSICAL = CERT_STORE_PROV_PHYSICAL_W - CERT_STORE_PROV_SMART_CARD_W = 15 - CERT_STORE_PROV_SMART_CARD = CERT_STORE_PROV_SMART_CARD_W - CERT_STORE_PROV_LDAP_W = 16 - CERT_STORE_PROV_LDAP = CERT_STORE_PROV_LDAP_W - CERT_STORE_PROV_PKCS12 = 17 + CERT_STORE_PROV_MEMORY = 2 + + CERT_STORE_ADD_ALWAYS = 4 - /* store characteristics (low WORD of flag) for CertOpenStore function */ - CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001 - CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004 - CERT_STORE_DELETE_FLAG = 0x00000010 - CERT_STORE_UNSAFE_PHYSICAL_FLAG = 0x00000020 - CERT_STORE_SHARE_STORE_FLAG = 0x00000040 - CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080 - CERT_STORE_MANIFOLD_FLAG = 0x00000100 - CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200 - CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400 - CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800 - CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000 - CERT_STORE_CREATE_NEW_FLAG = 0x00002000 - CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000 - CERT_STORE_READONLY_FLAG = 0x00008000 - /* store locations (high WORD of flag) for CertOpenStore function */ - CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000 - CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000 - CERT_SYSTEM_STORE_CURRENT_SERVICE = 0x00040000 - CERT_SYSTEM_STORE_SERVICES = 0x00050000 - CERT_SYSTEM_STORE_USERS = 0x00060000 - CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY = 0x00070000 - CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY = 0x00080000 - CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE = 0x00090000 - CERT_SYSTEM_STORE_UNPROTECTED_FLAG = 0x40000000 - CERT_SYSTEM_STORE_RELOCATE_FLAG = 0x80000000 - - /* Miscellaneous high-WORD flags for CertOpenStore function */ - CERT_REGISTRY_STORE_REMOTE_FLAG = 0x00010000 - CERT_REGISTRY_STORE_SERIALIZED_FLAG = 0x00020000 - CERT_REGISTRY_STORE_ROAMING_FLAG = 0x00040000 - CERT_REGISTRY_STORE_MY_IE_DIRTY_FLAG = 0x00080000 - CERT_REGISTRY_STORE_LM_GPT_FLAG = 0x01000000 - CERT_REGISTRY_STORE_CLIENT_GPT_FLAG = 0x80000000 - CERT_FILE_STORE_COMMIT_ENABLE_FLAG = 0x00010000 - CERT_LDAP_STORE_SIGN_FLAG = 0x00010000 - CERT_LDAP_STORE_AREC_EXCLUSIVE_FLAG = 0x00020000 - CERT_LDAP_STORE_OPENED_FLAG = 0x00040000 - CERT_LDAP_STORE_UNBIND_FLAG = 0x00080000 - - /* addDisposition values for CertAddCertificateContextToStore function */ - CERT_STORE_ADD_NEW = 1 - CERT_STORE_ADD_USE_EXISTING = 2 - CERT_STORE_ADD_REPLACE_EXISTING = 3 - CERT_STORE_ADD_ALWAYS = 4 - CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5 - CERT_STORE_ADD_NEWER = 6 - CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7 - - /* ErrorStatus values for CertTrustStatus struct */ CERT_TRUST_NO_ERROR = 0x00000000 CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001 CERT_TRUST_IS_REVOKED = 0x00000004 @@ -367,31 +282,11 @@ const ( CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000 CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000 CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000 - CERT_TRUST_IS_PARTIAL_CHAIN = 0x00010000 - CERT_TRUST_CTL_IS_NOT_TIME_VALID = 0x00020000 - CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID = 0x00040000 - CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE = 0x00080000 - CERT_TRUST_HAS_WEAK_SIGNATURE = 0x00100000 CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000 CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000 CERT_TRUST_IS_EXPLICIT_DISTRUST = 0x04000000 CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT = 0x08000000 - /* InfoStatus values for CertTrustStatus struct */ - CERT_TRUST_HAS_EXACT_MATCH_ISSUER = 0x00000001 - CERT_TRUST_HAS_KEY_MATCH_ISSUER = 0x00000002 - CERT_TRUST_HAS_NAME_MATCH_ISSUER = 0x00000004 - CERT_TRUST_IS_SELF_SIGNED = 0x00000008 - CERT_TRUST_HAS_PREFERRED_ISSUER = 0x00000100 - CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY = 0x00000400 - CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS = 0x00000400 - CERT_TRUST_IS_PEER_TRUSTED = 0x00000800 - CERT_TRUST_HAS_CRL_VALIDITY_EXTENDED = 0x00001000 - CERT_TRUST_IS_FROM_EXCLUSIVE_TRUST_STORE = 0x00002000 - CERT_TRUST_IS_CA_TRUSTED = 0x00004000 - CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000 - - /* policyOID values for CertVerifyCertificateChainPolicy function */ CERT_CHAIN_POLICY_BASE = 1 CERT_CHAIN_POLICY_AUTHENTICODE = 2 CERT_CHAIN_POLICY_AUTHENTICODE_TS = 3 @@ -400,7 +295,6 @@ const ( CERT_CHAIN_POLICY_NT_AUTH = 6 CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7 CERT_CHAIN_POLICY_EV = 8 - CERT_CHAIN_POLICY_SSL_F12 = 9 CERT_E_EXPIRED = 0x800B0101 CERT_E_ROLE = 0x800B0103 @@ -408,16 +302,8 @@ const ( CERT_E_UNTRUSTEDROOT = 0x800B0109 CERT_E_CN_NO_MATCH = 0x800B010F - /* AuthType values for SSLExtraCertChainPolicyPara struct */ AUTHTYPE_CLIENT = 1 AUTHTYPE_SERVER = 2 - - /* Checks values for SSLExtraCertChainPolicyPara struct */ - SECURITY_FLAG_IGNORE_REVOCATION = 0x00000080 - SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100 - SECURITY_FLAG_IGNORE_WRONG_USAGE = 0x00000200 - SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000 - SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000 ) var ( @@ -426,14 +312,6 @@ var ( OID_SGC_NETSCAPE = []byte("2.16.840.1.113730.4.1\x00") ) -// Pointer represents a pointer to an arbitrary Windows type. -// -// Pointer-typed fields may point to one of many different types. It's -// up to the caller to provide a pointer to the appropriate type, cast -// to Pointer. The caller must obey the unsafe.Pointer rules while -// doing so. -type Pointer *struct{} - // Invented values to support what package os expects. type Timeval struct { Sec int32 @@ -1002,15 +880,11 @@ type MibIfRow struct { Descr [MAXLEN_IFDESCR]byte } -type CertInfo struct { - // Not implemented -} - type CertContext struct { EncodingType uint32 EncodedCert *byte Length uint32 - CertInfo *CertInfo + CertInfo uintptr Store Handle } @@ -1025,16 +899,12 @@ type CertChainContext struct { RevocationFreshnessTime uint32 } -type CertTrustListInfo struct { - // Not implemented -} - type CertSimpleChain struct { Size uint32 TrustStatus CertTrustStatus NumElements uint32 Elements **CertChainElement - TrustListInfo *CertTrustListInfo + TrustListInfo uintptr HasRevocationFreshnessTime uint32 RevocationFreshnessTime uint32 } @@ -1049,18 +919,14 @@ type CertChainElement struct { ExtendedErrorInfo *uint16 } -type CertRevocationCrlInfo struct { - // Not implemented -} - type CertRevocationInfo struct { Size uint32 RevocationResult uint32 RevocationOid *byte - OidSpecificInfo Pointer + OidSpecificInfo uintptr HasFreshnessTime uint32 FreshnessTime uint32 - CrlInfo *CertRevocationCrlInfo + CrlInfo uintptr // *CertRevocationCrlInfo } type CertTrustStatus struct { @@ -1091,7 +957,7 @@ type CertChainPara struct { type CertChainPolicyPara struct { Size uint32 Flags uint32 - ExtraPolicyPara Pointer + ExtraPolicyPara uintptr } type SSLExtraCertChainPolicyPara struct { @@ -1106,7 +972,7 @@ type CertChainPolicyStatus struct { Error uint32 ChainIndex uint32 ElementIndex uint32 - ExtraPolicyStatus Pointer + ExtraPolicyStatus uintptr } const ( @@ -1453,7 +1319,7 @@ type SmallRect struct { Bottom int16 } -// Used with GetConsoleScreenBuffer to retrieve information about a console +// Used with GetConsoleScreenBuffer to retreive information about a console // screen buffer. See // https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str // for details. @@ -1465,5 +1331,3 @@ type ConsoleScreenBufferInfo struct { Window SmallRect MaximumWindowSize Coord } - -const UNIX_PATH_MAX = 108 // defined in afunix.h diff --git a/vendor/golang.org/x/sys/windows/types_windows_arm.go b/vendor/golang.org/x/sys/windows/types_windows_arm.go deleted file mode 100644 index 74571e3..0000000 --- a/vendor/golang.org/x/sys/windows/types_windows_arm.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package windows - -type WSAData struct { - Version uint16 - HighVersion uint16 - Description [WSADESCRIPTION_LEN + 1]byte - SystemStatus [WSASYS_STATUS_LEN + 1]byte - MaxSockets uint16 - MaxUdpDg uint16 - VendorInfo *byte -} - -type Servent struct { - Name *byte - Aliases **byte - Port uint16 - Proto *byte -} diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index fc56aec..318c616 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -1,4 +1,4 @@ -// Code generated by 'go generate'; DO NOT EDIT. +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT package windows diff --git a/vendor/vendor.json b/vendor/vendor.json index 8542120..385dfec 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -15,143 +15,11 @@ "revisionTime": "2017-03-06T13:59:04Z" }, { - "checksumSHA1": "71Ih+BWcUNqZZcKKWcCmDRTZBFw=", - "origin": "github.com/derekparker/delve/vendor/github.com/cosiner/argv", + "checksumSHA1": "RT7G1na3Buq45tRUN+39hTRQfB8=", + "origin": "github.com/go-delve/delve/vendor/github.com/cosiner/argv", "path": "github.com/cosiner/argv", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "v+Q3iYeRP3r9ajsW0J2PxGWdlwA=", - "path": "github.com/derekparker/delve/pkg/config", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "GhNaVSsHXTmTHd7julSi5xtZD2w=", - "path": "github.com/derekparker/delve/pkg/dwarf/frame", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "VCDMk/5/pkVOQCBcATdCixGpk3s=", - "path": "github.com/derekparker/delve/pkg/dwarf/godwarf", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "cJJirrDqATjg6/XbPrG7KCIsP9E=", - "path": "github.com/derekparker/delve/pkg/dwarf/line", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "7GMg+SBj0vNTzYFm5rTQkbQGhTQ=", - "path": "github.com/derekparker/delve/pkg/dwarf/op", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "RVPaMaM17/ijwKLWT1BXnF7/VQQ=", - "path": "github.com/derekparker/delve/pkg/dwarf/reader", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "j+wqqyt6QT2RI+Ini8exsY+pIFY=", - "path": "github.com/derekparker/delve/pkg/dwarf/util", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "Zx84VNxBFf9BnN9CnrQ/StvY16I=", - "path": "github.com/derekparker/delve/pkg/goversion", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "OYBYJW2zF7M6xisSTsn6buWAgpY=", - "path": "github.com/derekparker/delve/pkg/logflags", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "d0BcJ+psIqmd7f6A+V6GGjNMKU8=", - "path": "github.com/derekparker/delve/pkg/proc", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "7kXN1G9KbRIs3lAH9OazJ9ZKfoY=", - "path": "github.com/derekparker/delve/pkg/proc/core", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "Oyb/UKf3dHNT6InxkYpqMRN8mAI=", - "path": "github.com/derekparker/delve/pkg/proc/gdbserial", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "mHDcnJ0Rons7meAq9DWuBCZbW7E=", - "path": "github.com/derekparker/delve/pkg/proc/linutil", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "HzvEoJxB+b7b+gl2iwWn2QTSx2k=", - "path": "github.com/derekparker/delve/pkg/proc/native", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "eUso2+RCuyy5y8w7xomMZa+PLLs=", - "path": "github.com/derekparker/delve/pkg/terminal", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "njXG5km7KDV7IVuZReheCSRfXSQ=", - "path": "github.com/derekparker/delve/pkg/version", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "U39K0wH1Vnkw4LVOoinqIwX8yPY=", - "path": "github.com/derekparker/delve/service", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "9UZsK1xmwZ3AKrY4zzuYaIgVQgQ=", - "path": "github.com/derekparker/delve/service/api", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "VlivUa2TLlBe6p1/YVRi3u/Lzv8=", - "path": "github.com/derekparker/delve/service/debugger", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "EgqZMArkM5kmJ+QuLj/N/jqSRWU=", - "path": "github.com/derekparker/delve/service/rpc1", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "+2fLw0nSU41hfy6ISGZ47B3+N1s=", - "path": "github.com/derekparker/delve/service/rpc2", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" - }, - { - "checksumSHA1": "0Sw6L7LHcIE6VG7IpAZG8MhnICY=", - "path": "github.com/derekparker/delve/service/rpccommon", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { "checksumSHA1": "hveFTNQ9YEyYRs6SWuXM+XU9qRI=", @@ -159,6 +27,150 @@ "revision": "fd9ec7deca8bf46ecd2a795baaacf2b3a9be1197", "revisionTime": "2016-10-26T20:31:22Z" }, + { + "checksumSHA1": "fp8iJjvryUGswhpYc32d/0BqCaU=", + "path": "github.com/go-delve/delve/pkg/config", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "UxU+rBogEV80d8zKVpdFRO/6q9E=", + "path": "github.com/go-delve/delve/pkg/dwarf/frame", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "sENH0C+S3jEa80BTfUhZKLILyCk=", + "path": "github.com/go-delve/delve/pkg/dwarf/godwarf", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "ZO1Xiq5WpdnJsKtuTuHbXj89gM8=", + "path": "github.com/go-delve/delve/pkg/dwarf/line", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "RpupChLlqEw3mTF4Vd24dGHp1is=", + "path": "github.com/go-delve/delve/pkg/dwarf/op", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "rt20EAj6YKLQTq8I04MAJSVBlL0=", + "path": "github.com/go-delve/delve/pkg/dwarf/reader", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "7t8NqlzPV23du/GdZtTPRhF8V9s=", + "path": "github.com/go-delve/delve/pkg/dwarf/util", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "MUXMNLwltzOHg1tS9NW0i23iaIw=", + "path": "github.com/go-delve/delve/pkg/goversion", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "eaY/BDlqkwjU9icE+kWclfxPcJM=", + "path": "github.com/go-delve/delve/pkg/logflags", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "jUYhbQVuBUMhTAatmrGNSiWMYkc=", + "path": "github.com/go-delve/delve/pkg/proc", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "2MZJHAtoC33D4aY+TGbgXY3zrEI=", + "path": "github.com/go-delve/delve/pkg/proc/core", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "3go6qO59K/8qBwWMrh+uejMC/ks=", + "path": "github.com/go-delve/delve/pkg/proc/core/minidump", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "HiKHMgML6t6kgu/xIaQkNcbi4jU=", + "path": "github.com/go-delve/delve/pkg/proc/gdbserial", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "KE39qmqFbVr62FotevrmiSYpcvc=", + "path": "github.com/go-delve/delve/pkg/proc/linutil", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "ry65N9mANSiyzaLzoV54FIIyc3k=", + "path": "github.com/go-delve/delve/pkg/proc/native", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "SurwM9wvUtFDTCi0MU0a2QpTQB4=", + "path": "github.com/go-delve/delve/pkg/proc/winutil", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "selgT31LR/kxkYi8rEfugt1xByk=", + "path": "github.com/go-delve/delve/pkg/terminal", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "A3QVD3uNjiKzN82F0lhk2b5RWrY=", + "path": "github.com/go-delve/delve/pkg/version", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "k0Zt5Vjg9J6PTC2rv4zH9Uu8R98=", + "path": "github.com/go-delve/delve/service", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "Ck8PPrW6UWtzceQFSbVRnA5jyN0=", + "path": "github.com/go-delve/delve/service/api", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "IPPSKVkBXS1+N6GHQLI1O++impc=", + "path": "github.com/go-delve/delve/service/debugger", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "FwZylP9YWkeDhcBUrQU3imwggFg=", + "path": "github.com/go-delve/delve/service/rpc1", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "jweed9UomrG6/+5eGv5ug+qisho=", + "path": "github.com/go-delve/delve/service/rpc2", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, + { + "checksumSHA1": "LDLdEfcp8Y0GBw3GF1z+w9KVrIQ=", + "path": "github.com/go-delve/delve/service/rpccommon", + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" + }, { "checksumSHA1": "59kg2xC3rBxV0/5SIv+LA4qva08=", "path": "github.com/go-sql-driver/mysql", @@ -178,52 +190,52 @@ "revisionTime": "2016-08-06T14:40:29Z" }, { - "checksumSHA1": "xppHi82MLqVx1eyQmbhTesAEjx8=", + "checksumSHA1": "KzsJ/GkPEyvxG8eBcKrHRFoPhzU=", "path": "github.com/lib/pq/oid", "revision": "80f8150043c80fb52dee6bc863a709cdac7ec8f8", "revisionTime": "2016-08-06T14:40:29Z" }, { - "checksumSHA1": "+FYEqyNlPCPeFXxg7VUFp8LG108=", - "origin": "github.com/derekparker/delve/vendor/github.com/mattn/go-colorable", + "checksumSHA1": "uAVg4Tj5Fxi62z7/ScDEkHr6Ue8=", + "origin": "github.com/go-delve/delve/vendor/github.com/mattn/go-colorable", "path": "github.com/mattn/go-colorable", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { - "checksumSHA1": "lfn20o8UQyaq8aWKQU98qRMJlVA=", - "origin": "github.com/derekparker/delve/vendor/github.com/mattn/go-isatty", + "checksumSHA1": "y/A5iuvwjytQE2CqVuphQRXR2nI=", + "origin": "github.com/go-delve/delve/vendor/github.com/mattn/go-isatty", "path": "github.com/mattn/go-isatty", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { - "checksumSHA1": "ph3cNYbXMV3WTwgJz6IrmgyCFkM=", - "origin": "github.com/derekparker/delve/vendor/github.com/peterh/liner", + "checksumSHA1": "BcKVRsLhMzSj4ksVqslEThK6tjA=", + "origin": "github.com/go-delve/delve/vendor/github.com/peterh/liner", "path": "github.com/peterh/liner", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { - "checksumSHA1": "HSvSst2y+SkMz+BoQCxBwlWTi/w=", - "origin": "github.com/derekparker/delve/vendor/github.com/sirupsen/logrus", + "checksumSHA1": "PNnR2QlZlBudLfws/cQRbzhuMRg=", + "origin": "github.com/go-delve/delve/vendor/github.com/sirupsen/logrus", "path": "github.com/sirupsen/logrus", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { - "checksumSHA1": "T3ucRoHVYE7IKEjd0AvA59wUUg4=", - "origin": "github.com/derekparker/delve/vendor/golang.org/x/arch/x86/x86asm", + "checksumSHA1": "Tfz3fwv4nEPRjPefO3GY/UY4TFs=", + "origin": "github.com/go-delve/delve/vendor/golang.org/x/arch/x86/x86asm", "path": "golang.org/x/arch/x86/x86asm", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { "checksumSHA1": "BGm8lKZmvJbf/YOJLeL1rw2WVjA=", - "origin": "github.com/derekparker/delve/vendor/golang.org/x/crypto/ssh/terminal", + "origin": "github.com/go-delve/delve/vendor/golang.org/x/crypto/ssh/terminal", "path": "golang.org/x/crypto/ssh/terminal", - "revision": "74c98bc9616ad4ee324eb4d31717b61f4a6ab8ce", - "revisionTime": "2018-05-29T15:01:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { "checksumSHA1": "SiJNkx+YGtq3Gtr6Ldu6OW83O+U=", @@ -232,11 +244,11 @@ "revisionTime": "2018-10-11T14:35:51Z" }, { - "checksumSHA1": "Y7nctMxT58lRM78VtElPerhcnEs=", - "origin": "github.com/beego/bee/vendor/golang.org/x/sys/windows", + "checksumSHA1": "cFNQekaQ8KckfywxwWwZauiz9BY=", + "origin": "github.com/go-delve/delve/vendor/golang.org/x/sys/windows", "path": "golang.org/x/sys/windows", - "revision": "fa43e7bc11baaae89f3f902b2b4d832b68234844", - "revisionTime": "2018-10-11T14:35:51Z" + "revision": "cba328f83404a02bc7a71842590a5c9a434f6015", + "revisionTime": "2019-03-29T16:14:16Z" }, { "checksumSHA1": "+OgOXBoiQ+X+C2dsAeiOHwBIEH0=",