Browse Source

Merge pull request #552 from MZIchenjl/fix-mojave-dlv

Fix delve build error on mojave
master
astaxie GitHub 1 year ago
parent
commit
10bb0454f6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 19737 additions and 3764 deletions
  1. +4
    -3
      cmd/commands/dlv/dlv_amd64.go
  2. +24
    -0
      vendor/github.com/cosiner/argv/LICENSE
  3. +34
    -0
      vendor/github.com/cosiner/argv/argv.go
  4. +79
    -0
      vendor/github.com/cosiner/argv/cmd.go
  5. +222
    -0
      vendor/github.com/cosiner/argv/parser.go
  6. +282
    -0
      vendor/github.com/cosiner/argv/scanner.go
  7. +0
    -122
      vendor/github.com/derekparker/delve/dwarf/line/line_parser.go
  8. +0
    -252
      vendor/github.com/derekparker/delve/dwarf/line/state_machine.go
  9. +0
    -84
      vendor/github.com/derekparker/delve/dwarf/op/op.go
  10. +62
    -15
      vendor/github.com/derekparker/delve/pkg/config/config.go
  11. +63
    -0
      vendor/github.com/derekparker/delve/pkg/config/split.go
  12. +9
    -27
      vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go
  13. +0
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go
  14. +18
    -9
      vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go
  15. +52
    -57
      vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go
  16. +107
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/sections.go
  17. +124
    -108
      vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/type.go
  18. +152
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/line/line_parser.go
  19. +450
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/line/state_machine.go
  20. +197
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/op/op.go
  21. +515
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/op/opcodes.go
  22. +175
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/op/opcodes.table
  23. +102
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/op/regs.go
  24. +133
    -32
      vendor/github.com/derekparker/delve/pkg/dwarf/reader/reader.go
  25. +114
    -0
      vendor/github.com/derekparker/delve/pkg/dwarf/reader/variables.go
  26. +24
    -76
      vendor/github.com/derekparker/delve/pkg/dwarf/util/buf.go
  27. +46
    -1
      vendor/github.com/derekparker/delve/pkg/dwarf/util/util.go
  28. +178
    -0
      vendor/github.com/derekparker/delve/pkg/goversion/go_version.go
  29. +83
    -0
      vendor/github.com/derekparker/delve/pkg/logflags/logflags.go
  30. +306
    -0
      vendor/github.com/derekparker/delve/pkg/proc/arch.go
  31. +878
    -0
      vendor/github.com/derekparker/delve/pkg/proc/bininfo.go
  32. +437
    -0
      vendor/github.com/derekparker/delve/pkg/proc/breakpoints.go
  33. +526
    -0
      vendor/github.com/derekparker/delve/pkg/proc/core/core.go
  34. +556
    -0
      vendor/github.com/derekparker/delve/pkg/proc/core/linux_amd64_core.go
  35. +121
    -0
      vendor/github.com/derekparker/delve/pkg/proc/disasm.go
  36. +31
    -25
      vendor/github.com/derekparker/delve/pkg/proc/disasm_amd64.go
  37. +0
    -0
      vendor/github.com/derekparker/delve/pkg/proc/doc.go
  38. +454
    -98
      vendor/github.com/derekparker/delve/pkg/proc/eval.go
  39. +561
    -0
      vendor/github.com/derekparker/delve/pkg/proc/fncall.go
  40. +1877
    -0
      vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver.go
  41. +1233
    -0
      vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_conn.go
  42. +16
    -0
      vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_unix.go
  43. +10
    -0
      vendor/github.com/derekparker/delve/pkg/proc/gdbserial/gdbserver_windows.go
  44. +267
    -0
      vendor/github.com/derekparker/delve/pkg/proc/gdbserial/rr.go
  45. +129
    -0
      vendor/github.com/derekparker/delve/pkg/proc/interface.go
  46. +39
    -0
      vendor/github.com/derekparker/delve/pkg/proc/linutil/auxv.go
  47. +4
    -0
      vendor/github.com/derekparker/delve/pkg/proc/linutil/doc.go
  48. +156
    -0
      vendor/github.com/derekparker/delve/pkg/proc/mem.go
  49. +48
    -34
      vendor/github.com/derekparker/delve/pkg/proc/moduledata.go
  50. +0
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/exc.h
  51. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/exc_user_darwin.c
  52. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/exec_darwin.c
  53. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/exec_darwin.h
  54. +0
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.defs
  55. +0
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc.h
  56. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/mach_exc_user_darwin.c
  57. +128
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/nonative_darwin.go
  58. +453
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/proc.go
  59. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.c
  60. +118
    -159
      vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.go
  61. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/proc_darwin.h
  62. +176
    -165
      vendor/github.com/derekparker/delve/pkg/proc/native/proc_linux.go
  63. +497
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/proc_windows.go
  64. +3
    -1
      vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_darwin.go
  65. +13
    -26
      vendor/github.com/derekparker/delve/pkg/proc/native/ptrace_linux.go
  66. +46
    -34
      vendor/github.com/derekparker/delve/pkg/proc/native/registers_darwin_amd64.go
  67. +77
    -60
      vendor/github.com/derekparker/delve/pkg/proc/native/registers_linux_amd64.go
  68. +69
    -26
      vendor/github.com/derekparker/delve/pkg/proc/native/registers_windows_amd64.go
  69. +1
    -1
      vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows.go
  70. +1
    -1
      vendor/github.com/derekparker/delve/pkg/proc/native/syscall_windows_amd64.go
  71. +174
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/threads.go
  72. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.c
  73. +37
    -20
      vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.go
  74. +2
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/threads_darwin.h
  75. +132
    -0
      vendor/github.com/derekparker/delve/pkg/proc/native/threads_linux.go
  76. +38
    -31
      vendor/github.com/derekparker/delve/pkg/proc/native/threads_windows.go
  77. +1
    -1
      vendor/github.com/derekparker/delve/pkg/proc/native/zsyscall_windows.go
  78. +658
    -0
      vendor/github.com/derekparker/delve/pkg/proc/proc.go
  79. +348
    -0
      vendor/github.com/derekparker/delve/pkg/proc/registers.go
  80. +90
    -0
      vendor/github.com/derekparker/delve/pkg/proc/registers_amd64.go
  81. +687
    -0
      vendor/github.com/derekparker/delve/pkg/proc/stack.go
  82. +568
    -0
      vendor/github.com/derekparker/delve/pkg/proc/threads.go
  83. +1288
    -0
      vendor/github.com/derekparker/delve/pkg/proc/types.go
  84. +2119
    -0
      vendor/github.com/derekparker/delve/pkg/proc/variables.go
  85. +721
    -178
      vendor/github.com/derekparker/delve/pkg/terminal/command.go
  86. +191
    -0
      vendor/github.com/derekparker/delve/pkg/terminal/config.go
  87. +3
    -2
      vendor/github.com/derekparker/delve/pkg/terminal/disasmprint.go
  88. +7
    -7
      vendor/github.com/derekparker/delve/pkg/terminal/docgen.go
  89. +175
    -31
      vendor/github.com/derekparker/delve/pkg/terminal/terminal.go
  90. +0
    -0
      vendor/github.com/derekparker/delve/pkg/terminal/terminal_other.go
  91. +0
    -0
      vendor/github.com/derekparker/delve/pkg/terminal/terminal_windows.go
  92. +4
    -1
      vendor/github.com/derekparker/delve/pkg/version/version.go
  93. +0
    -79
      vendor/github.com/derekparker/delve/proc/arch.go
  94. +0
    -163
      vendor/github.com/derekparker/delve/proc/breakpoints.go
  95. +0
    -67
      vendor/github.com/derekparker/delve/proc/disasm.go
  96. +0
    -113
      vendor/github.com/derekparker/delve/proc/go_version.go
  97. +0
    -57
      vendor/github.com/derekparker/delve/proc/mem.go
  98. +0
    -942
      vendor/github.com/derekparker/delve/proc/proc.go
  99. +0
    -643
      vendor/github.com/derekparker/delve/proc/proc_windows.go
  100. +0
    -13
      vendor/github.com/derekparker/delve/proc/ptrace_windows.go

+ 4
- 3
cmd/commands/dlv/dlv_amd64.go View File

@@ -28,10 +28,10 @@ import (
"github.com/beego/bee/cmd/commands/version"
beeLogger "github.com/beego/bee/logger"
"github.com/beego/bee/utils"
"github.com/derekparker/delve/pkg/terminal"
"github.com/derekparker/delve/service"
"github.com/derekparker/delve/service/rpc2"
"github.com/derekparker/delve/service/rpccommon"
"github.com/derekparker/delve/terminal"
"github.com/fsnotify/fsnotify"
)

@@ -152,7 +152,8 @@ func startDelveDebugger(addr string, ch chan int) int {
APIVersion: 2,
WorkingDir: ".",
ProcessArgs: []string{abs},
}, false)
Backend: "default",
})
if err := server.Run(); err != nil {
beeLogger.Log.Fatalf("Could not start debugger server: %v", err)
}
@@ -182,7 +183,7 @@ func startDelveDebugger(addr string, ch chan int) int {
}

// Stop and kill the debugger server once user quits the REPL
if err := server.Stop(true); err != nil {
if err := server.Stop(); err != nil {
beeLogger.Log.Fatalf("Could not stop Delve server: %v", err)
}
return status


+ 24
- 0
vendor/github.com/cosiner/argv/LICENSE View File

@@ -0,0 +1,24 @@
The MIT License (MIT)

Copyright (c) 2017 aihui zhu

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

+ 34
- 0
vendor/github.com/cosiner/argv/argv.go View File

@@ -0,0 +1,34 @@
// Package argv parse command line string into arguments array using the bash syntax.
package argv

import "strings"

// ParseEnv parsing environment variables as key/value pair.
//
// Item will be ignored if one of the key and value is empty.
func ParseEnv(env []string) map[string]string {
var m map[string]string
for _, e := range env {
secs := strings.SplitN(e, "=", 2)
if len(secs) == 2 {
key := strings.TrimSpace(secs[0])
val := strings.TrimSpace(secs[1])
if key == "" || val == "" {
continue
}
if m == nil {
m = make(map[string]string)
}
m[key] = val
}
}
return m
}

// Argv split cmdline string as array of argument array by the '|' character.
//
// The parsing rules is same as bash. The environment variable will be replaced
// and string surround by '`' will be passed to reverse quote parser.
func Argv(cmdline []rune, env map[string]string, reverseQuoteParser ReverseQuoteParser) ([][]string, error) {
return NewParser(NewScanner(cmdline, env), reverseQuoteParser).Parse()
}

+ 79
- 0
vendor/github.com/cosiner/argv/cmd.go View File

@@ -0,0 +1,79 @@
package argv

import (
"bytes"
"errors"
"io"
"os/exec"
"strings"
)

// Run execute cmdline string and return the output
func Run(cmdline []rune, env map[string]string) ([]rune, error) {
args, err := Argv(cmdline, env, Run)
if err != nil {
return nil, err
}
cmds, err := Cmds(args)
if err != nil {
return nil, err
}

output := bytes.NewBuffer(make([]byte, 0, 1024))
err = Pipe(nil, output, cmds...)
str := output.String()
str = strings.TrimSpace(str)
return []rune(str), err
}

// Cmds generate exec.Cmd for each command.
func Cmds(args [][]string) ([]*exec.Cmd, error) {
var cmds []*exec.Cmd
for _, argv := range args {
if len(argv) == 0 {
return nil, errors.New("invalid cmd")
}

cmds = append(cmds, exec.Command(argv[0], argv[1:]...))
}
return cmds, nil
}

// Pipe pipe previous command's stdout to next command's stdin, if in or
// out is nil, it will be ignored.
func Pipe(in io.Reader, out io.Writer, cmds ...*exec.Cmd) error {
l := len(cmds)
if l == 0 {
return nil
}

var err error
for i := 1; i < l; i++ {
cmds[i].Stdin, err = cmds[i-1].StdoutPipe()
if err != nil {
break
}
}
if err != nil {
return err
}
if in != nil {
cmds[0].Stdin = in
}
if out != nil {
cmds[l-1].Stdout = out
}
for i := range cmds {
err = cmds[i].Start()
if err != nil {
return err
}
}
for i := range cmds {
err = cmds[i].Wait()
if err != nil {
return err
}
}
return nil
}

+ 222
- 0
vendor/github.com/cosiner/argv/parser.go View File

@@ -0,0 +1,222 @@
package argv

import "errors"

type (
// ReverseQuoteParser parse strings quoted by '`' and return it's result. Commonly,
// it should run it os command.
ReverseQuoteParser func([]rune, map[string]string) ([]rune, error)

// Parser take tokens from Scanner, and do syntax checking, and generate the splitted arguments array.
Parser struct {
s *Scanner
tokbuf []Token
r ReverseQuoteParser

sections [][]string
currSection []string

currStrValid bool
currStr []rune
}
)

// NewParser create a cmdline string parser.
func NewParser(s *Scanner, r ReverseQuoteParser) *Parser {
if r == nil {
r = func(r []rune, env map[string]string) ([]rune, error) {
return r, nil
}
}

return &Parser{
s: s,
r: r,
}
}

func (p *Parser) nextToken() (Token, error) {
if l := len(p.tokbuf); l > 0 {
tok := p.tokbuf[l-1]
p.tokbuf = p.tokbuf[:l-1]
return tok, nil
}

return p.s.Next()
}

var (
// ErrInvalidSyntax was reported if there is a syntax error in command line string.
ErrInvalidSyntax = errors.New("invalid syntax")
)

func (p *Parser) unreadToken(tok Token) {
p.tokbuf = append(p.tokbuf, tok)
}

// Parse split command line string into arguments array.
//
// EBNF:
// Cmdline = Section [ Pipe Cmdline ]
// Section = [Space] SpacedSection { SpacedSection }
// SpacedSection = MultipleUnit [Space]
// MultipleUnit = Unit {Unit}
// Unit = String | ReverseQuote
func (p *Parser) Parse() ([][]string, error) {
err := p.cmdline()
if err != nil {
return nil, err
}
return p.sections, nil
}

func (p *Parser) cmdline() error {
err := p.section()
if err != nil {
return err
}
p.endSection()

tok, err := p.nextToken()
if err != nil {
return err
}
if tok.Type == TokEOF {
return nil
}
if !p.accept(tok.Type, TokPipe) {
return ErrInvalidSyntax
}
return p.cmdline()
}

func (p *Parser) section() error {
leftSpace, err := p.optional(TokSpace)
if err != nil {
return err
}

var isFirst = true
for {
unit, err := p.spacedSection()
if isFirst {
isFirst = false
} else {
if err == ErrInvalidSyntax {
break
}
}
if err != nil {
return err
}

p.appendUnit(leftSpace, unit)
leftSpace = unit.rightSpace
}
return nil
}

type unit struct {
rightSpace bool
toks []Token
}

func (p *Parser) spacedSection() (u unit, err error) {
u.toks, err = p.multipleUnit()
if err != nil {
return
}
u.rightSpace, err = p.optional(TokSpace)
return
}

func (p *Parser) multipleUnit() ([]Token, error) {
var (
toks []Token
isFirst = true
)
for {
tok, err := p.unit()
if isFirst {
isFirst = false
} else {
if err == ErrInvalidSyntax {
break
}
}
if err != nil {
return nil, err
}
toks = append(toks, tok)
}
return toks, nil
}

func (p *Parser) unit() (Token, error) {
tok, err := p.nextToken()
if err != nil {
return tok, err
}
if p.accept(tok.Type, TokString, TokReversequote) {
return tok, nil
}
p.unreadToken(tok)
return tok, ErrInvalidSyntax
}

func (p *Parser) optional(typ TokenType) (bool, error) {
tok, err := p.nextToken()
if err != nil {
return false, err
}
var ok bool
if ok = p.accept(tok.Type, typ); !ok {
p.unreadToken(tok)
}
return ok, nil
}

func (p *Parser) accept(t TokenType, types ...TokenType) bool {
for _, typ := range types {
if t == typ {
return true
}
}
return false
}

func (p *Parser) appendUnit(leftSpace bool, u unit) error {
if leftSpace {
p.currStr = p.currStr[:0]
}
for _, tok := range u.toks {
if tok.Type == TokReversequote {
val, err := p.r(tok.Value, p.s.envs())
if err != nil {
return err
}
p.currStr = append(p.currStr, val...)
} else {
p.currStr = append(p.currStr, tok.Value...)
}
}
p.currStrValid = true
if u.rightSpace {
p.currSection = append(p.currSection, string(p.currStr))
p.currStr = p.currStr[:0]
p.currStrValid = false
}
return nil
}

func (p *Parser) endSection() {
if p.currStrValid {
p.currSection = append(p.currSection, string(p.currStr))
}
p.currStr = p.currStr[:0]
p.currStrValid = false
if len(p.currSection) > 0 {
p.sections = append(p.sections, p.currSection)
p.currSection = nil
}
}

+ 282
- 0
vendor/github.com/cosiner/argv/scanner.go View File

@@ -0,0 +1,282 @@
package argv

import "unicode"

// Scanner is a cmdline string scanner.
//
// It split cmdline string to tokens: space, string, pipe, reverse quote string.
type Scanner struct {
env map[string]string

text []rune
rpos int
dollarBuf []rune
}

// NewScanner create a scanner and init it's internal states.
func NewScanner(text []rune, env map[string]string) *Scanner {
return &Scanner{
text: text,
env: env,
}
}

func (s *Scanner) envs() map[string]string {
return s.env
}

const _RuneEOF = 0

func (s *Scanner) nextRune() rune {
if s.rpos >= len(s.text) {
return _RuneEOF
}

r := s.text[s.rpos]
s.rpos++
return r
}

func (s *Scanner) unreadRune(r rune) {
if r != _RuneEOF {
s.rpos--
}
}

func (s *Scanner) isEscapeChars(r rune) (rune, bool) {
switch r {
case 'a':
return '\a', true
case 'b':
return '\b', true
case 'f':
return '\f', true
case 'n':
return '\n', true
case 'r':
return '\r', true
case 't':
return '\t', true
case 'v':
return '\v', true
case '\\':
return '\\', true
case '$':
return '$', true
}
return r, false
}

func (s *Scanner) endEnv(r rune) bool {
if r == '_' || (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') {
return false
}
return true
}

// TokenType is the type of tokens recognized by the scanner.
type TokenType uint32

// Token is generated by the scanner with a type and value.
type Token struct {
Type TokenType
Value []rune
}

const (
// TokString for string, single quoted string and double quoted string
TokString TokenType = iota + 1
// TokPipe is the '|' character
TokPipe
// TokReversequote is reverse quoted string
TokReversequote
// TokSpace represent space character sequence
TokSpace
// TokEOF means the input end.
TokEOF
)

func (s *Scanner) getEnv(name string) string {
return s.env[name]
}

func (s *Scanner) specialVar(r rune) (string, bool) {
switch r {
case '0', '*', '#', '@', '?', '$':
v, has := s.env[string(r)]
return v, has
default:
return "", false
}
}

func (s *Scanner) checkDollarStart(tok *Token, r rune, from, switchTo uint8) uint8 {
state := from
nr := s.nextRune()
if val, has := s.specialVar(nr); has {
if val != "" {
tok.Value = append(tok.Value, []rune(val)...)
}
} else if s.endEnv(nr) {
tok.Value = append(tok.Value, r)
s.unreadRune(nr)
} else {
state = switchTo
s.dollarBuf = append(s.dollarBuf[:0], nr)
}
return state
}

func (s *Scanner) checkDollarEnd(tok *Token, r rune, from, switchTo uint8) uint8 {
var state = from
if s.endEnv(r) {
tok.Value = append(tok.Value, []rune(s.getEnv(string(s.dollarBuf)))...)
state = switchTo
s.unreadRune(r)
} else {
s.dollarBuf = append(s.dollarBuf, r)
}
return state
}

// Next return next token, if it reach the end, TOK_EOF will be returned.
//
// Error is returned for invalid syntax such as unpaired quotes.
func (s *Scanner) Next() (Token, error) {
const (
Initial = iota + 1
Space
ReverseQuote
String
StringDollar
StringQuoteSingle
StringQuoteDouble
StringQuoteDoubleDollar
)

var (
tok Token

state uint8 = Initial
)
s.dollarBuf = s.dollarBuf[:0]
for {
r := s.nextRune()
switch state {
case Initial:
switch {
case r == _RuneEOF:
tok.Type = TokEOF
return tok, nil
case r == '|':
tok.Type = TokPipe
return tok, nil
case r == '`':
state = ReverseQuote
case unicode.IsSpace(r):
state = Space
s.unreadRune(r)
default:
state = String
s.unreadRune(r)
}
case Space:
if r == _RuneEOF || !unicode.IsSpace(r) {
s.unreadRune(r)
tok.Type = TokSpace
return tok, nil
}
case ReverseQuote:
switch r {
case _RuneEOF:
return tok, ErrInvalidSyntax
case '`':
tok.Type = TokReversequote
return tok, nil
default:
tok.Value = append(tok.Value, r)
}
case String:
switch {
case r == _RuneEOF || r == '|' || r == '`' || unicode.IsSpace(r):
tok.Type = TokString
s.unreadRune(r)
return tok, nil
case r == '\'':
state = StringQuoteSingle
case r == '"':
state = StringQuoteDouble
case r == '\\':
nr := s.nextRune()
if nr == _RuneEOF {
return tok, ErrInvalidSyntax
}
tok.Value = append(tok.Value, nr)
case r == '$':
state = s.checkDollarStart(&tok, r, state, StringDollar)
default:
tok.Value = append(tok.Value, r)
}
case StringDollar:
state = s.checkDollarEnd(&tok, r, state, String)
case StringQuoteSingle:
switch r {
case _RuneEOF:
return tok, ErrInvalidSyntax
case '\'':
state = String
case '\\':
nr := s.nextRune()
if escape, ok := s.isEscapeChars(nr); ok {
tok.Value = append(tok.Value, escape)
} else {
tok.Value = append(tok.Value, r)
s.unreadRune(nr)
}
default:
tok.Value = append(tok.Value, r)
}
case StringQuoteDouble:
switch r {
case _RuneEOF:
return tok, ErrInvalidSyntax
case '"':
state = String
case '\\':
nr := s.nextRune()
if nr == _RuneEOF {
return tok, ErrInvalidSyntax
}
if escape, ok := s.isEscapeChars(nr); ok {
tok.Value = append(tok.Value, escape)
} else {
tok.Value = append(tok.Value, r)
s.unreadRune(nr)
}
case '$':
state = s.checkDollarStart(&tok, r, state, StringQuoteDoubleDollar)
default:
tok.Value = append(tok.Value, r)
}
case StringQuoteDoubleDollar:
state = s.checkDollarEnd(&tok, r, state, StringQuoteDouble)
}
}
}

// Scan is a utility function help split input text as tokens.
func Scan(text []rune, env map[string]string) ([]Token, error) {
s := NewScanner(text, env)
var tokens []Token
for {
tok, err := s.Next()
if err != nil {
return nil, err
}
tokens = append(tokens, tok)
if tok.Type == TokEOF {
break
}
}
return tokens, nil
}

+ 0
- 122
vendor/github.com/derekparker/delve/dwarf/line/line_parser.go View File

@@ -1,122 +0,0 @@
package line

import (
"bytes"
"encoding/binary"

"github.com/derekparker/delve/dwarf/util"
)

type DebugLinePrologue struct {
UnitLength uint32
Version uint16
Length uint32
MinInstrLength uint8
InitialIsStmt uint8
LineBase int8
LineRange uint8
OpcodeBase uint8
StdOpLengths []uint8
}

type DebugLineInfo struct {
Prologue *DebugLinePrologue
IncludeDirs []string
FileNames []*FileEntry
Instructions []byte
Lookup map[string]*FileEntry
}

type FileEntry struct {
Name string
DirIdx uint64
LastModTime uint64
Length uint64
}

type DebugLines []*DebugLineInfo

func (d *DebugLines) GetLineInfo(name string) *DebugLineInfo {
// Find in which table file exists and return it.
for _, l := range *d {
if _, ok := l.Lookup[name]; ok {
return l
}
}
return nil
}

func Parse(data []byte) DebugLines {
var (
lines = make(DebugLines, 0)
buf = bytes.NewBuffer(data)
)

// We have to parse multiple file name tables here.
for buf.Len() > 0 {
dbl := new(DebugLineInfo)
dbl.Lookup = make(map[string]*FileEntry)

parseDebugLinePrologue(dbl, buf)
parseIncludeDirs(dbl, buf)
parseFileEntries(dbl, buf)

// Instructions size calculation breakdown:
// - dbl.Prologue.UnitLength is the length of the entire unit, not including the 4 bytes to represent that length.
// - dbl.Prologue.Length is the length of the prologue not including unit length, version or prologue length itself.
// - So you have UnitLength - PrologueLength - (version_length_bytes(2) + prologue_length_bytes(4)).
dbl.Instructions = buf.Next(int(dbl.Prologue.UnitLength - dbl.Prologue.Length - 6))

lines = append(lines, dbl)
}

return lines
}

func parseDebugLinePrologue(dbl *DebugLineInfo, buf *bytes.Buffer) {
p := new(DebugLinePrologue)

p.UnitLength = binary.LittleEndian.Uint32(buf.Next(4))
p.Version = binary.LittleEndian.Uint16(buf.Next(2))
p.Length = binary.LittleEndian.Uint32(buf.Next(4))
p.MinInstrLength = uint8(buf.Next(1)[0])
p.InitialIsStmt = uint8(buf.Next(1)[0])
p.LineBase = int8(buf.Next(1)[0])
p.LineRange = uint8(buf.Next(1)[0])
p.OpcodeBase = uint8(buf.Next(1)[0])

p.StdOpLengths = make([]uint8, p.OpcodeBase-1)
binary.Read(buf, binary.LittleEndian, &p.StdOpLengths)

dbl.Prologue = p
}

func parseIncludeDirs(info *DebugLineInfo, buf *bytes.Buffer) {
for {
str, _ := util.ParseString(buf)
if str == "" {
break
}

info.IncludeDirs = append(info.IncludeDirs, str)
}
}

func parseFileEntries(info *DebugLineInfo, buf *bytes.Buffer) {
for {
entry := new(FileEntry)

name, _ := util.ParseString(buf)
if name == "" {
break
}

entry.Name = name
entry.DirIdx, _ = util.DecodeULEB128(buf)
entry.LastModTime, _ = util.DecodeULEB128(buf)
entry.Length, _ = util.DecodeULEB128(buf)

info.FileNames = append(info.FileNames, entry)
info.Lookup[name] = entry
}
}

+ 0
- 252
vendor/github.com/derekparker/delve/dwarf/line/state_machine.go View File

@@ -1,252 +0,0 @@
package line

import (
"bytes"
"encoding/binary"
"errors"
"fmt"

"github.com/derekparker/delve/dwarf/util"
)

type Location struct {
File string
Line int
Address uint64
Delta int
}

type StateMachine struct {
dbl *DebugLineInfo
file string
line int
address uint64
column uint
isStmt bool
basicBlock bool
endSeq bool
lastWasStandard bool
lastDelta int
}

type opcodefn func(*StateMachine, *bytes.Buffer)

// Special opcodes
const (
DW_LNS_copy = 1
DW_LNS_advance_pc = 2
DW_LNS_advance_line = 3
DW_LNS_set_file = 4
DW_LNS_set_column = 5
DW_LNS_negate_stmt = 6
DW_LNS_set_basic_block = 7
DW_LNS_const_add_pc = 8
DW_LNS_fixed_advance_pc = 9
)

// Extended opcodes
const (
DW_LINE_end_sequence = 1
DW_LINE_set_address = 2
DW_LINE_define_file = 3
)

var standardopcodes = map[byte]opcodefn{
DW_LNS_copy: copyfn,
DW_LNS_advance_pc: advancepc,
DW_LNS_advance_line: advanceline,
DW_LNS_set_file: setfile,
DW_LNS_set_column: setcolumn,
DW_LNS_negate_stmt: negatestmt,
DW_LNS_set_basic_block: setbasicblock,
DW_LNS_const_add_pc: constaddpc,
DW_LNS_fixed_advance_pc: fixedadvancepc,
}

var extendedopcodes = map[byte]opcodefn{
DW_LINE_end_sequence: endsequence,
DW_LINE_set_address: setaddress,
DW_LINE_define_file: definefile,
}

func newStateMachine(dbl *DebugLineInfo) *StateMachine {
return &StateMachine{dbl: dbl, file: dbl.FileNames[0].Name, line: 1}
}

// Returns all PCs for a given file/line. Useful for loops where the 'for' line
// could be split amongst 2 PCs.
func (dbl *DebugLines) AllPCsForFileLine(f string, l int) (pcs []uint64) {
var (
foundFile bool
lastAddr uint64
lineInfo = dbl.GetLineInfo(f)
sm = newStateMachine(lineInfo)
buf = bytes.NewBuffer(lineInfo.Instructions)
)

for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
findAndExecOpcode(sm, buf, b)
if foundFile && sm.file != f {
return
}
if sm.line == l && sm.file == f && sm.address != lastAddr {
foundFile = true
pcs = append(pcs, sm.address)
line := sm.line
// Keep going until we're on a different line. We only care about
// when a line comes back around (i.e. for loop) so get to next line,
// and try to find the line we care about again.
for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
findAndExecOpcode(sm, buf, b)
if line < sm.line {
break
}
}
}
}
return
}

var NoSourceError = errors.New("no source available")

func (dbl *DebugLines) AllPCsBetween(begin, end uint64, filename string) ([]uint64, error) {
lineInfo := dbl.GetLineInfo(filename)
if lineInfo == nil {
return nil, NoSourceError
}
var (
pcs []uint64
lastaddr uint64
sm = newStateMachine(lineInfo)
buf = bytes.NewBuffer(lineInfo.Instructions)
)

for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
findAndExecOpcode(sm, buf, b)
if sm.address > end {
break
}
if sm.address >= begin && sm.address > lastaddr {
lastaddr = sm.address
pcs = append(pcs, sm.address)
}
}
return pcs, nil
}

func findAndExecOpcode(sm *StateMachine, buf *bytes.Buffer, b byte) {
switch {
case b == 0:
execExtendedOpcode(sm, b, buf)
case b < sm.dbl.Prologue.OpcodeBase:
execStandardOpcode(sm, b, buf)
default:
execSpecialOpcode(sm, b)
}
}

func execSpecialOpcode(sm *StateMachine, instr byte) {
var (
opcode = uint8(instr)
decoded = opcode - sm.dbl.Prologue.OpcodeBase
)

if sm.dbl.Prologue.InitialIsStmt == uint8(1) {
sm.isStmt = true
}

sm.lastDelta = int(sm.dbl.Prologue.LineBase + int8(decoded%sm.dbl.Prologue.LineRange))
sm.line += sm.lastDelta
sm.address += uint64(decoded / sm.dbl.Prologue.LineRange)
sm.basicBlock = false
sm.lastWasStandard = false
}

func execExtendedOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
_, _ = util.DecodeULEB128(buf)
b, _ := buf.ReadByte()
fn, ok := extendedopcodes[b]
if !ok {
panic(fmt.Sprintf("Encountered unknown extended opcode %#v\n", b))
}
sm.lastWasStandard = false

fn(sm, buf)
}

func execStandardOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
fn, ok := standardopcodes[instr]
if !ok {
panic(fmt.Sprintf("Encountered unknown standard opcode %#v\n", instr))
}
sm.lastWasStandard = true

fn(sm, buf)
}

func copyfn(sm *StateMachine, buf *bytes.Buffer) {
sm.basicBlock = false
}

func advancepc(sm *StateMachine, buf *bytes.Buffer) {
addr, _ := util.DecodeULEB128(buf)
sm.address += addr * uint64(sm.dbl.Prologue.MinInstrLength)
}

func advanceline(sm *StateMachine, buf *bytes.Buffer) {
line, _ := util.DecodeSLEB128(buf)
sm.line += int(line)
sm.lastDelta = int(line)
}

func setfile(sm *StateMachine, buf *bytes.Buffer) {
i, _ := util.DecodeULEB128(buf)
sm.file = sm.dbl.FileNames[i-1].Name
}

func setcolumn(sm *StateMachine, buf *bytes.Buffer) {
c, _ := util.DecodeULEB128(buf)
sm.column = uint(c)
}

func negatestmt(sm *StateMachine, buf *bytes.Buffer) {
sm.isStmt = !sm.isStmt
}

func setbasicblock(sm *StateMachine, buf *bytes.Buffer) {
sm.basicBlock = true
}

func constaddpc(sm *StateMachine, buf *bytes.Buffer) {
sm.address += (255 / uint64(sm.dbl.Prologue.LineRange))
}

func fixedadvancepc(sm *StateMachine, buf *bytes.Buffer) {
var operand uint16
binary.Read(buf, binary.LittleEndian, &operand)

sm.address += uint64(operand)
}

func endsequence(sm *StateMachine, buf *bytes.Buffer) {
sm.endSeq = true
}

func setaddress(sm *StateMachine, buf *bytes.Buffer) {
var addr uint64

binary.Read(buf, binary.LittleEndian, &addr)

sm.address = addr
}

func definefile(sm *StateMachine, buf *bytes.Buffer) {
var (
_, _ = util.ParseString(buf)
_, _ = util.DecodeULEB128(buf)
_, _ = util.DecodeULEB128(buf)
_, _ = util.DecodeULEB128(buf)
)

// Don't do anything here yet.
}

+ 0
- 84
vendor/github.com/derekparker/delve/dwarf/op/op.go View File

@@ -1,84 +0,0 @@
package op

import (
"bytes"
"encoding/binary"
"errors"
"fmt"

"github.com/derekparker/delve/dwarf/util"
)

const (
DW_OP_addr = 0x3
DW_OP_call_frame_cfa = 0x9c
DW_OP_plus = 0x22
DW_OP_consts = 0x11
DW_OP_plus_uconsts = 0x23
)

type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error)

var oplut = map[byte]stackfn{
DW_OP_call_frame_cfa: callframecfa,
DW_OP_plus: plus,
DW_OP_consts: consts,
DW_OP_addr: addr,
DW_OP_plus_uconsts: plusuconsts,
}

func ExecuteStackProgram(cfa int64, instructions []byte) (int64, error) {
stack := make([]int64, 0, 3)
buf := bytes.NewBuffer(instructions)

for opcode, err := buf.ReadByte(); err == nil; opcode, err = buf.ReadByte() {
fn, ok := oplut[opcode]
if !ok {
return 0, fmt.Errorf("invalid instruction %#v", opcode)
}

stack, err = fn(buf, stack, cfa)
if err != nil {
return 0, err
}
}

if len(stack) == 0 {
return 0, errors.New("empty OP stack")
}

return stack[len(stack)-1], nil
}

func callframecfa(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
if cfa == 0 {
return stack, fmt.Errorf("Could not retrieve CFA for current PC")
}
return append(stack, int64(cfa)), nil
}

func addr(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
return append(stack, int64(binary.LittleEndian.Uint64(buf.Next(8)))), nil
}

func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
var (
slen = len(stack)
digits = stack[slen-2 : slen]
st = stack[:slen-2]
)

return append(st, digits[0]+digits[1]), nil
}

func plusuconsts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
slen := len(stack)
num, _ := util.DecodeULEB128(buf)
stack[slen-1] = stack[slen-1] + int64(num)
return stack, nil
}

func consts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
num, _ := util.DecodeSLEB128(buf)
return append(stack, num), nil
}

vendor/github.com/derekparker/delve/config/config.go → vendor/github.com/derekparker/delve/pkg/config/config.go View File

@@ -7,7 +7,7 @@ import (
"os/user"
"path"

yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
)

const (
@@ -20,7 +20,7 @@ type SubstitutePathRule struct {
// Directory path will be substituted if it matches `From`.
From string
// Path to which substitution is performed.
To string
To string
}

// Slice of source code path substitution rules.
@@ -29,9 +29,24 @@ type SubstitutePathRules []SubstitutePathRule
// Config defines all configuration options available to be set through the config file.
type Config struct {
// Commands aliases.
Aliases map[string][]string
Aliases map[string][]string `yaml:"aliases"`
// Source code path substitution rules.
SubstitutePath SubstitutePathRules `yaml:"substitute-path"`

// MaxStringLen is the maximum string length that the commands print,
// locals, args and vars should read (in verbose mode).
MaxStringLen *int `yaml:"max-string-len,omitempty"`
// MaxArrayValues is the maximum number of array items that the commands
// print, locals, args and vars should read (in verbose mode).
MaxArrayValues *int `yaml:"max-array-values,omitempty"`

// 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"`
}

// LoadConfig attempts to populate a Config object from the config.yml file.
@@ -49,8 +64,11 @@ func LoadConfig() *Config {

f, err := os.Open(fullConfigFile)
if err != nil {
createDefaultConfig(fullConfigFile)
return nil
f, err = createDefaultConfig(fullConfigFile)
if err != nil {
fmt.Printf("Error creating default config file: %v", err)
return nil
}
}
defer func() {
err := f.Close()
@@ -75,22 +93,37 @@ func LoadConfig() *Config {
return &c
}

func createDefaultConfig(path string) {
func SaveConfig(conf *Config) error {
fullConfigFile, err := GetConfigFilePath(configFile)
if err != nil {
return err
}

out, err := yaml.Marshal(*conf)
if err != nil {
return err
}

f, err := os.Create(fullConfigFile)
if err != nil {
return err
}
defer f.Close()

_, err = f.Write(out)
return err
}

func createDefaultConfig(path string) (*os.File, error) {
f, err := os.Create(path)
if err != nil {
fmt.Printf("Unable to create config file: %v.", err)
return
return nil, fmt.Errorf("Unable to create config file: %v.", err)
}
defer func() {
err := f.Close()
if err != nil {
fmt.Printf("Closing config file failed: %v.", err)
}
}()
err = writeDefaultConfig(f)
if err != nil {
fmt.Printf("Unable to write default configuration: %v.", err)
return nil, fmt.Errorf("Unable to write default configuration: %v.", err)
}
return f, nil
}

func writeDefaultConfig(f *os.File) error {
@@ -100,6 +133,11 @@ func writeDefaultConfig(f *os.File) error {
# This is the default configuration file. Available options are provided, but disabled.
# Delete the leading hash mark to enable an item.

# Uncomment the following line and set your preferred ANSI foreground color
# for source line numbers in the (list) command (if unset, default is 34,
# dark blue) See https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit
# source-list-line-color: 34

# Provided aliases will be added to the default aliases for a given command.
aliases:
# command: ["alias1", "alias2"]
@@ -111,6 +149,15 @@ aliases:
# commands.
substitute-path:
# - {from: path, to: path}
# Maximum number of elements loaded from an array.
# max-array-values: 64

# Maximum loaded string length.
# max-string-len: 64

# Uncomment the following line to make the whatis command also print the DWARF location expression of its argument.
# show-location-expr: true
`)
return err
}

+ 63
- 0
vendor/github.com/derekparker/delve/pkg/config/split.go View File

@@ -0,0 +1,63 @@
package config

import (
"bytes"
"unicode"
)

// 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 {
type stateEnum int
const (
inSpace stateEnum = iota
inField
inQuote
inQuoteEscaped
)
state := inSpace
r := []string{}
var buf bytes.Buffer

for _, ch := range in {
switch state {
case inSpace:
if ch == quote {
state = inQuote
} else if !unicode.IsSpace(ch) {
buf.WriteRune(ch)
state = inField
}

case inField:
if ch == quote {
state = inQuote
} else if unicode.IsSpace(ch) {
r = append(r, buf.String())
buf.Reset()
} else {
buf.WriteRune(ch)
}

case inQuote:
if ch == quote {
state = inField
} else if ch == '\\' {
state = inQuoteEscaped
} else {
buf.WriteRune(ch)
}

case inQuoteEscaped:
buf.WriteRune(ch)
state = inQuote
}
}

if buf.Len() != 0 {
r = append(r, buf.String())
}

return r
}

vendor/github.com/derekparker/delve/dwarf/frame/entries.go → vendor/github.com/derekparker/delve/pkg/dwarf/frame/entries.go View File

@@ -17,6 +17,7 @@ type CommonInformationEntry struct {
DataAlignmentFactor int64
ReturnAddressRegister uint64
InitialInstructions []byte
staticBase uint64
}

// Represents a Frame Descriptor Entry in the
@@ -25,17 +26,14 @@ type FrameDescriptionEntry struct {
Length uint32
CIE *CommonInformationEntry
Instructions []byte
begin, end uint64
begin, size uint64
order binary.ByteOrder
}

// Returns whether or not the given address is within the
// bounds of this frame.
func (fde *FrameDescriptionEntry) Cover(addr uint64) bool {
if (addr - fde.begin) < fde.end {
return true
}
return false
return (addr - fde.begin) < fde.size
}

// Address of first location for this frame.
@@ -45,7 +43,7 @@ func (fde *FrameDescriptionEntry) Begin() uint64 {

// Address of last location for this frame.
func (fde *FrameDescriptionEntry) End() uint64 {
return fde.begin + fde.end
return fde.begin + fde.size
}

// Set up frame for the given PC.
@@ -53,43 +51,27 @@ func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
return executeDwarfProgramUntilPC(fde, pc)
}

// Return the offset from the current SP that the return address is stored at.
func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) (frameOffset, returnAddressOffset int64) {
frame := fde.EstablishFrame(pc)
return frame.cfa.offset, frame.regs[fde.CIE.ReturnAddressRegister].offset
}

type FrameDescriptionEntries []*FrameDescriptionEntry

func NewFrameIndex() FrameDescriptionEntries {
return make(FrameDescriptionEntries, 0, 1000)
}

type NoFDEForPCError struct {
type ErrNoFDEForPC struct {
PC uint64
}

func (err *NoFDEForPCError) Error() string {
func (err *ErrNoFDEForPC) Error() string {
return fmt.Sprintf("could not find FDE for PC %#v", err.PC)
}

// Returns the Frame Description Entry for the given PC.
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
idx := sort.Search(len(fdes), func(i int) bool {
if fdes[i].Cover(pc) {
return true
}
if fdes[i].LessThan(pc) {
return false
}
return true
return fdes[i].Cover(pc) || fdes[i].Begin() >= pc
})
if idx == len(fdes) {
return nil, &NoFDEForPCError{pc}
if idx == len(fdes) || !fdes[idx].Cover(pc) {
return nil, &ErrNoFDEForPC{pc}
}
return fdes[idx], nil
}

func (frame *FrameDescriptionEntry) LessThan(pc uint64) bool {
return frame.End() <= pc
}

vendor/github.com/derekparker/delve/dwarf/frame/expression_constants.go → vendor/github.com/derekparker/delve/pkg/dwarf/frame/expression_constants.go View File


vendor/github.com/derekparker/delve/dwarf/frame/parser.go → vendor/github.com/derekparker/delve/pkg/dwarf/frame/parser.go View File

@@ -7,12 +7,14 @@ import (
"bytes"
"encoding/binary"

"github.com/derekparker/delve/dwarf/util"
"github.com/derekparker/delve/pkg/dwarf/util"
)

type parsefunc func(*parseContext) parsefunc

type parseContext struct {
staticBase uint64

buf *bytes.Buffer
entries FrameDescriptionEntries
common *CommonInformationEntry
@@ -23,10 +25,10 @@ type parseContext struct {
// Parse takes in data (a byte slice) and returns a slice of
// commonInformationEntry structures. Each commonInformationEntry
// has a slice of frameDescriptionEntry structures.
func Parse(data []byte, order binary.ByteOrder) FrameDescriptionEntries {
func Parse(data []byte, order binary.ByteOrder, staticBase uint64) FrameDescriptionEntries {
var (
buf = bytes.NewBuffer(data)
pctx = &parseContext{buf: buf, entries: NewFrameIndex()}
pctx = &parseContext{buf: buf, entries: NewFrameIndex(), staticBase: staticBase}
)

for fn := parselength; buf.Len() != 0; {
@@ -45,12 +47,19 @@ func cieEntry(data []byte) bool {
}

func parselength(ctx *parseContext) parsefunc {
var data = ctx.buf.Next(8)
binary.Read(ctx.buf, binary.LittleEndian, &ctx.length)

if ctx.length == 0 {
// ZERO terminator
return parselength
}

var data = ctx.buf.Next(4)

ctx.length = binary.LittleEndian.Uint32(data[:4]) - 4 // take off the length of the CIE id / CIE pointer.
ctx.length -= 4 // take off the length of the CIE id / CIE pointer.

if cieEntry(data[4:]) {
ctx.common = &CommonInformationEntry{Length: ctx.length}
if cieEntry(data) {
ctx.common = &CommonInformationEntry{Length: ctx.length, staticBase: ctx.staticBase}
return parseCIE
}

@@ -61,8 +70,8 @@ func parselength(ctx *parseContext) parsefunc {
func parseFDE(ctx *parseContext) parsefunc {
r := ctx.buf.Next(int(ctx.length))

ctx.frame.begin = binary.LittleEndian.Uint64(r[:8])
ctx.frame.end = binary.LittleEndian.Uint64(r[8:16])
ctx.frame.begin = binary.LittleEndian.Uint64(r[:8]) + ctx.staticBase
ctx.frame.size = binary.LittleEndian.Uint64(r[8:16])

// Insert into the tree after setting address range begin
// otherwise compares won't work.

vendor/github.com/derekparker/delve/dwarf/frame/table.go → vendor/github.com/derekparker/delve/pkg/dwarf/frame/table.go View File

@@ -5,41 +5,31 @@ import (
"encoding/binary"
"fmt"

"github.com/derekparker/delve/dwarf/util"
"github.com/derekparker/delve/pkg/dwarf/util"
)

type CurrentFrameAddress struct {
register uint64
offset int64
expression []byte
rule byte
}

type DWRule struct {
rule byte
offset int64
newreg uint64
expression []byte
Rule Rule
Offset int64
Reg uint64
Expression []byte
}

type FrameContext struct {
loc uint64
order binary.ByteOrder
address uint64
cfa CurrentFrameAddress
regs map[uint64]DWRule
CFA DWRule
Regs map[uint64]DWRule
initialRegs map[uint64]DWRule
prevRegs map[uint64]DWRule
buf *bytes.Buffer
cie *CommonInformationEntry
RetAddrReg uint64
codeAlignment uint64
dataAlignment int64
}

func (fctx *FrameContext) CFAOffset() int64 {
return fctx.cfa.offset
}

// Instructions used to recreate the table from the .debug_frame data.
const (
DW_CFA_nop = 0x0 // No ops
@@ -73,15 +63,19 @@ const (
)

// Rules defined for register values.
type Rule byte

const (
rule_undefined = iota
rule_sameval
rule_offset
rule_valoffset
rule_register
rule_expression
rule_valexpression
rule_architectural
RuleUndefined Rule = iota
RuleSameVal
RuleOffset
RuleValOffset
RuleRegister
RuleExpression
RuleValExpression
RuleArchitectural
RuleCFA // Value is rule.Reg + rule.Offset
RuleFramePointer // Value is stored at address rule.Reg + rule.Offset, but only if it's less than the current CFA, otherwise same value
)

const low_6_offset = 0x3f
@@ -124,7 +118,8 @@ func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext {
copy(initialInstructions, cie.InitialInstructions)
frame := &FrameContext{
cie: cie,
regs: make(map[uint64]DWRule),
Regs: make(map[uint64]DWRule),
RetAddrReg: cie.ReturnAddressRegister,
initialRegs: make(map[uint64]DWRule),
prevRegs: make(map[uint64]DWRule),
codeAlignment: cie.CodeAlignmentFactor,
@@ -142,9 +137,7 @@ func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameCon
frame.order = fde.order
frame.loc = fde.Begin()
frame.address = pc
fdeInstructions := make([]byte, len(fde.Instructions))
copy(fdeInstructions, fde.Instructions)
frame.ExecuteUntilPC(fdeInstructions)
frame.ExecuteUntilPC(fde.Instructions)

return frame
}
@@ -161,7 +154,7 @@ func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
frame.buf.Write(instructions)

// We only need to execute the instructions until
// ctx.loc > ctx.addess (which is the address we
// ctx.loc > ctx.address (which is the address we
// are currently at in the traced process).
for frame.address >= frame.loc && frame.buf.Len() > 0 {
executeDwarfInstruction(frame)
@@ -262,7 +255,7 @@ func offset(frame *FrameContext) {
offset, _ = util.DecodeULEB128(frame.buf)
)

frame.regs[uint64(reg)] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset}
frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
}

func restore(frame *FrameContext) {
@@ -274,9 +267,9 @@ func restore(frame *FrameContext) {
reg := uint64(b & low_6_offset)
oldrule, ok := frame.initialRegs[reg]
if ok {
frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset}
frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset}
} else {
frame.regs[reg] = DWRule{rule: rule_undefined}
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}
}

@@ -284,7 +277,7 @@ func setloc(frame *FrameContext) {
var loc uint64
binary.Read(frame.buf, frame.order, &loc)

frame.loc = loc
frame.loc = loc + frame.cie.staticBase
}

func offsetextended(frame *FrameContext) {
@@ -293,31 +286,31 @@ func offsetextended(frame *FrameContext) {
offset, _ = util.DecodeULEB128(frame.buf)
)

frame.regs[reg] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset}
frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
}

func undefined(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.regs[reg] = DWRule{rule: rule_undefined}
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}

func samevalue(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.regs[reg] = DWRule{rule: rule_sameval}
frame.Regs[reg] = DWRule{Rule: RuleSameVal}
}

func register(frame *FrameContext) {
reg1, _ := util.DecodeULEB128(frame.buf)
reg2, _ := util.DecodeULEB128(frame.buf)
frame.regs[reg1] = DWRule{newreg: reg2, rule: rule_register}
frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister}
}

func rememberstate(frame *FrameContext) {
frame.prevRegs = frame.regs
frame.prevRegs = frame.Regs
}

func restorestate(frame *FrameContext) {
frame.regs = frame.prevRegs
frame.Regs = frame.prevRegs
}

func restoreextended(frame *FrameContext) {
@@ -325,9 +318,9 @@ func restoreextended(frame *FrameContext) {

oldrule, ok := frame.initialRegs[reg]
if ok {
frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset}
frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset}
} else {
frame.regs[reg] = DWRule{rule: rule_undefined}
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}
}

@@ -335,32 +328,34 @@ func defcfa(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeULEB128(frame.buf)

frame.cfa.register = reg
frame.cfa.offset = int64(offset)
frame.CFA.Rule = RuleCFA
frame.CFA.Reg = reg
frame.CFA.Offset = int64(offset)
}

func defcfaregister(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.cfa.register = reg
frame.CFA.Reg = reg
}

func defcfaoffset(frame *FrameContext) {
offset, _ := util.DecodeULEB128(frame.buf)
frame.cfa.offset = int64(offset)
frame.CFA.Offset = int64(offset)
}

func defcfasf(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeSLEB128(frame.buf)

frame.cfa.register = reg
frame.cfa.offset = offset * frame.dataAlignment
frame.CFA.Rule = RuleCFA
frame.CFA.Reg = reg
frame.CFA.Offset = offset * frame.dataAlignment
}

func defcfaoffsetsf(frame *FrameContext) {
offset, _ := util.DecodeSLEB128(frame.buf)
offset *= frame.dataAlignment
frame.cfa.offset = offset
frame.CFA.Offset = offset
}

func defcfaexpression(frame *FrameContext) {
@@ -369,8 +364,8 @@ func defcfaexpression(frame *FrameContext) {
expr = frame.buf.Next(int(l))
)

frame.cfa.expression = expr
frame.cfa.rule = rule_expression
frame.CFA.Expression = expr
frame.CFA.Rule = RuleExpression
}

func expression(frame *FrameContext) {
@@ -380,7 +375,7 @@ func expression(frame *FrameContext) {
expr = frame.buf.Next(int(l))
)

frame.regs[reg] = DWRule{rule: rule_expression, expression: expr}
frame.Regs[reg] = DWRule{Rule: RuleExpression, Expression: expr}
}

func offsetextendedsf(frame *FrameContext) {
@@ -389,7 +384,7 @@ func offsetextendedsf(frame *FrameContext) {
offset, _ = util.DecodeSLEB128(frame.buf)
)

frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_offset}
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset}
}

func valoffset(frame *FrameContext) {
@@ -398,7 +393,7 @@ func valoffset(frame *FrameContext) {
offset, _ = util.DecodeULEB128(frame.buf)
)

frame.regs[reg] = DWRule{offset: int64(offset), rule: rule_valoffset}
frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset}
}

func valoffsetsf(frame *FrameContext) {
@@ -407,7 +402,7 @@ func valoffsetsf(frame *FrameContext) {
offset, _ = util.DecodeSLEB128(frame.buf)
)

frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_valoffset}
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset}
}

func valexpression(frame *FrameContext) {
@@ -417,7 +412,7 @@ func valexpression(frame *FrameContext) {
expr = frame.buf.Next(int(l))
)

frame.regs[reg] = DWRule{rule: rule_valexpression, expression: expr}
frame.Regs[reg] = DWRule{Rule: RuleValExpression, Expression: expr}
}

func louser(frame *FrameContext) {

+ 107
- 0
vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/sections.go View File

@@ -0,0 +1,107 @@
package godwarf

import (
"bytes"
"compress/zlib"
"debug/elf"
"debug/macho"
"debug/pe"
"encoding/binary"
"fmt"
"io"
)

// GetDebugSectionElf returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionElf("line") will return the contents of
// .debug_line, if .debug_line doesn't exist it will try to return the
// decompressed contents of .zdebug_line.
func GetDebugSectionElf(f *elf.File, name string) ([]byte, error) {
sec := f.Section(".debug_" + name)
if sec != nil {
return sec.Data()
}
sec = f.Section(".zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := sec.Data()
if err != nil {
return nil, err
}
return decompressMaybe(b)
}

// GetDebugSectionPE returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionPE("line") will return the contents of
// .debug_line, if .debug_line doesn't exist it will try to return the
// decompressed contents of .zdebug_line.
func GetDebugSectionPE(f *pe.File, name string) ([]byte, error) {
sec := f.Section(".debug_" + name)
if sec != nil {
return peSectionData(sec)
}
sec = f.Section(".zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := peSectionData(sec)
if err != nil {
return nil, err
}
return decompressMaybe(b)
}

func peSectionData(sec *pe.Section) ([]byte, error) {
b, err := sec.Data()
if err != nil {
return nil, err
}
if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
b = b[:sec.VirtualSize]
}
return b, nil
}

// GetDebugSectionMacho returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionMacho("line") will return the contents of
// __debug_line, if __debug_line doesn't exist it will try to return the
// decompressed contents of __zdebug_line.
func GetDebugSectionMacho(f *macho.File, name string) ([]byte, error) {
sec := f.Section("__debug_" + name)
if sec != nil {
return sec.Data()
}
sec = f.Section("__zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := sec.Data()
if err != nil {
return nil, err
}
return decompressMaybe(b)
}

func decompressMaybe(b []byte) ([]byte, error) {
if len(b) < 12 || string(b[:4]) != "ZLIB" {
// not compressed
return b, nil
}

dlen := binary.BigEndian.Uint64(b[4:12])
dbuf := make([]byte, dlen)
r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
if err != nil {
return nil, err
}
if _, err := io.ReadFull(r, dbuf); err != nil {
return nil, err
}
if err := r.Close(); err != nil {
return nil, err
}
return dbuf, nil
}

vendor/golang.org/x/debug/dwarf/type.go → vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/type.go View File

@@ -6,16 +6,44 @@
// The format is heavily biased toward C, but for simplicity
// the String methods use a pseudo-Go syntax.

package dwarf
// Borrowed from golang.org/x/debug/dwarf/type.go

package godwarf

import (
"debug/dwarf"
"fmt"
"reflect"
"strconv"

"github.com/derekparker/delve/pkg/dwarf/op"
"github.com/derekparker/delve/pkg/dwarf/util"
)

const (
AttrGoKind dwarf.Attr = 0x2900
AttrGoKey dwarf.Attr = 0x2901
AttrGoElem dwarf.Attr = 0x2902
AttrGoEmbeddedField dwarf.Attr = 0x2903
AttrGoRuntimeType dwarf.Attr = 0x2904
)

// Basic type encodings -- the value for AttrEncoding in a TagBaseType Entry.
const (
encAddress = 0x01
encBoolean = 0x02
encComplexFloat = 0x03
encFloat = 0x04
encSigned = 0x05
encSignedChar = 0x06
encUnsigned = 0x07
encUnsignedChar = 0x08
encImaginaryFloat = 0x09
)

// A Type conventionally represents a pointer to any of the
// specific Type structures (CharType, StructType, etc.).
//TODO: remove this use dwarf.Type
type Type interface {
Common() *CommonType
String() string
@@ -29,7 +57,7 @@ type CommonType struct {
ByteSize int64 // size of value of this type, in bytes
Name string // name that can be used to refer to type
ReflectKind reflect.Kind // the reflect kind of the type.
Offset Offset // the offset at which this type was read
Offset dwarf.Offset // the offset at which this type was read
}

func (c *CommonType) Common() *CommonType { return c }
@@ -158,6 +186,7 @@ type StructField struct {
ByteSize int64
BitOffset int64 // within the ByteSize bytes at ByteOffset
BitSize int64 // zero if not a bit field
Embedded bool
}

func (t *StructType) String() string {
@@ -329,31 +358,19 @@ func (t *ChanType) String() string {
return "chan " + t.ElemType.String()
}

// typeReader is used to read from either the info section or the
// types section.
type typeReader interface {
Seek(Offset)
Next() (*Entry, error)
clone() typeReader
offset() Offset
// AddressSize returns the size in bytes of addresses in the current
// compilation unit.
AddressSize() int
}

// Type reads the type at off in the DWARF ``info'' section.
func (d *Data) Type(off Offset) (Type, error) {
return d.readType("info", d.Reader(), off, d.typeCache)
func ReadType(d *dwarf.Data, off dwarf.Offset, typeCache map[dwarf.Offset]Type) (Type, error) {
return readType(d, "info", d.Reader(), off, typeCache)
}

func getKind(e *Entry) reflect.Kind {
func getKind(e *dwarf.Entry) reflect.Kind {
integer, _ := e.Val(AttrGoKind).(int64)
return reflect.Kind(integer)
}

// readType reads a type from r at off of name using and updating a
// type cache.
func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) {
func readType(d *dwarf.Data, name string, r *dwarf.Reader, off dwarf.Offset, typeCache map[dwarf.Offset]Type) (Type, error) {
if t, ok := typeCache[off]; ok {
return t, nil
}
@@ -364,10 +381,10 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
}
addressSize := r.AddressSize()
if e == nil || e.Offset != off {
return nil, DecodeError{name, off, "no type at offset"}
return nil, dwarf.DecodeError{name, off, "no type at offset"}
}