mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 17:56:45 +08:00
proc: Back to using vendored golang.org/x/debug/ (#585)
Patch https://go-review.googlesource.com/23085 has been merged so we can go back to using golang.org/x/debug/.
This commit is contained in:
committed by
Derek Parker
parent
da910cc3bd
commit
372869c9e1
15
Godeps/Godeps.json
generated
15
Godeps/Godeps.json
generated
@ -1,6 +1,7 @@
|
||||
{
|
||||
"ImportPath": "github.com/derekparker/delve",
|
||||
"GoVersion": "go1.5",
|
||||
"GodepVersion": "v74",
|
||||
"Packages": [
|
||||
"github.com/derekparker/delve/cmd/dlv",
|
||||
"github.com/derekparker/delve/cmd/dlv/cmds",
|
||||
@ -16,7 +17,7 @@
|
||||
"github.com/derekparker/delve/service",
|
||||
"github.com/derekparker/delve/service/api",
|
||||
"github.com/derekparker/delve/service/debugger",
|
||||
"github.com/derekparker/delve/service/rpc",
|
||||
"github.com/derekparker/delve/service/rpccommon",
|
||||
"github.com/derekparker/delve/service/test",
|
||||
"github.com/derekparker/delve/terminal",
|
||||
"github.com/derekparker/delve/version"
|
||||
@ -69,6 +70,18 @@
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "b084184666e02084b8ccb9b704bf0d79c466eb1d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/debug/dwarf",
|
||||
"Rev": "fb508927b491eca48a708e9d000fdb7afa53c32b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/debug/elf",
|
||||
"Rev": "fb508927b491eca48a708e9d000fdb7afa53c32b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/debug/macho",
|
||||
"Rev": "fb508927b491eca48a708e9d000fdb7afa53c32b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/sys/unix",
|
||||
"Rev": "eb2c74142fd19a79b3f237334c7384d5167b1b46"
|
||||
|
||||
@ -1,155 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dwarf
|
||||
|
||||
// This file provides simple methods to access the symbol table by name and address.
|
||||
|
||||
import "fmt"
|
||||
|
||||
// lookupEntry returns the Entry for the name. If tag is non-zero, only entries
|
||||
// with that tag are considered.
|
||||
func (d *Data) lookupEntry(name string, tag Tag) (*Entry, error) {
|
||||
r := d.Reader()
|
||||
for {
|
||||
entry, err := r.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry == nil {
|
||||
// TODO: why don't we get an error here?
|
||||
break
|
||||
}
|
||||
if tag != 0 && tag != entry.Tag {
|
||||
continue
|
||||
}
|
||||
nameAttr := entry.Val(AttrName)
|
||||
if nameAttr == nil {
|
||||
continue
|
||||
}
|
||||
if nameAttr.(string) == name {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("DWARF entry for %q not found", name)
|
||||
}
|
||||
|
||||
// LookupEntry returns the Entry for the named symbol.
|
||||
func (d *Data) LookupEntry(name string) (*Entry, error) {
|
||||
return d.lookupEntry(name, 0)
|
||||
}
|
||||
|
||||
// LookupFunction returns the address of the named symbol, a function.
|
||||
func (d *Data) LookupFunction(name string) (uint64, error) {
|
||||
entry, err := d.lookupEntry(name, TagSubprogram)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
addrAttr := entry.Val(AttrLowpc)
|
||||
if addrAttr == nil {
|
||||
return 0, fmt.Errorf("symbol %q has no LowPC attribute", name)
|
||||
}
|
||||
addr, ok := addrAttr.(uint64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("symbol %q has non-uint64 LowPC attribute", name)
|
||||
}
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// TODO: should LookupVariable handle both globals and locals? Locals don't
|
||||
// necessarily have a fixed address. They may be in a register, or otherwise
|
||||
// move around.
|
||||
|
||||
// LookupVariable returns the location of a named symbol, a variable.
|
||||
func (d *Data) LookupVariable(name string) (uint64, error) {
|
||||
entry, err := d.lookupEntry(name, TagVariable)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("variable %s: %s", name, err)
|
||||
}
|
||||
loc, err := d.EntryLocation(entry)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("variable %s: %s", name, err)
|
||||
}
|
||||
return loc, nil
|
||||
}
|
||||
|
||||
// EntryLocation returns the address of the object referred to by the given Entry.
|
||||
func (d *Data) EntryLocation(e *Entry) (uint64, error) {
|
||||
loc, _ := e.Val(AttrLocation).([]byte)
|
||||
if len(loc) == 0 {
|
||||
return 0, fmt.Errorf("DWARF entry has no Location attribute")
|
||||
}
|
||||
// TODO: implement the DWARF Location bytecode. What we have here only
|
||||
// recognizes a program with a single literal opAddr bytecode.
|
||||
if asize := d.unit[0].asize; loc[0] == opAddr && len(loc) == 1+asize {
|
||||
switch asize {
|
||||
case 1:
|
||||
return uint64(loc[1]), nil
|
||||
case 2:
|
||||
return uint64(d.order.Uint16(loc[1:])), nil
|
||||
case 4:
|
||||
return uint64(d.order.Uint32(loc[1:])), nil
|
||||
case 8:
|
||||
return d.order.Uint64(loc[1:]), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("DWARF entry has an unimplemented Location op")
|
||||
}
|
||||
|
||||
// EntryTypeOffset returns the offset in the given Entry's type attribute.
|
||||
func (d *Data) EntryTypeOffset(e *Entry) (Offset, error) {
|
||||
v := e.Val(AttrType)
|
||||
if v == nil {
|
||||
return 0, fmt.Errorf("DWARF entry has no Type attribute")
|
||||
}
|
||||
off, ok := v.(Offset)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("DWARF entry has an invalid Type attribute")
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
// LookupPC returns the name of a symbol at the specified PC.
|
||||
func (d *Data) LookupPC(pc uint64) (string, error) {
|
||||
entry, _, err := d.EntryForPC(pc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
nameAttr := entry.Val(AttrName)
|
||||
if nameAttr == nil {
|
||||
// TODO: this shouldn't be possible.
|
||||
return "", fmt.Errorf("LookupPC: TODO")
|
||||
}
|
||||
name, ok := nameAttr.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("name for PC %#x is not a string", pc)
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// EntryForPC returns the entry and address for a symbol at the specified PC.
|
||||
func (d *Data) EntryForPC(pc uint64) (entry *Entry, lowpc uint64, err error) {
|
||||
// TODO: do something better than a linear scan?
|
||||
r := d.Reader()
|
||||
for {
|
||||
entry, err := r.Next()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if entry == nil {
|
||||
// TODO: why don't we get an error here.
|
||||
break
|
||||
}
|
||||
if entry.Tag != TagSubprogram {
|
||||
continue
|
||||
}
|
||||
lowpc, lok := entry.Val(AttrLowpc).(uint64)
|
||||
highpc, hok := entry.Val(AttrHighpc).(uint64)
|
||||
if !lok || !hok || pc < lowpc || highpc <= pc {
|
||||
continue
|
||||
}
|
||||
return entry, lowpc, nil
|
||||
}
|
||||
return nil, 0, fmt.Errorf("PC %#x not found", pc)
|
||||
}
|
||||
@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/dwarf/op"
|
||||
)
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"go/token"
|
||||
"reflect"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/dwarf/reader"
|
||||
)
|
||||
|
||||
@ -494,7 +494,7 @@ func (scope *EvalScope) evalTypeAssert(node *ast.TypeAssertExpr) (*Variable, err
|
||||
return nil, err
|
||||
}
|
||||
if xv.Children[0].DwarfType.String() != typ.String() {
|
||||
return nil, fmt.Errorf("interface conversion: %s is %s, not %s", xv.DwarfType.String(), xv.Children[0].TypeString(), typ)
|
||||
return nil, fmt.Errorf("interface conversion: %s is %s, not %s", xv.DwarfType.Common().Name, xv.Children[0].TypeString(), typ.Common().Name)
|
||||
}
|
||||
return &xv.Children[0], nil
|
||||
}
|
||||
@ -633,7 +633,7 @@ func (scope *EvalScope) evalAddrOf(node *ast.UnaryExpr) (*Variable, error) {
|
||||
|
||||
xev.OnlyAddr = true
|
||||
|
||||
typename := "*" + xev.DwarfType.String()
|
||||
typename := "*" + xev.DwarfType.Common().Name
|
||||
rv := scope.newVariable("", 0, &dwarf.PtrType{CommonType: dwarf.CommonType{ByteSize: int64(scope.Thread.dbp.arch.PtrSize()), Name: typename}, Type: xev.DwarfType})
|
||||
rv.Children = []Variable{*xev}
|
||||
rv.loaded = true
|
||||
@ -1102,7 +1102,7 @@ func (v *Variable) reslice(low int64, high int64) (*Variable, error) {
|
||||
ByteSize: 24,
|
||||
Name: "",
|
||||
},
|
||||
StructName: fmt.Sprintf("[]%s", v.fieldType),
|
||||
StructName: fmt.Sprintf("[]%s", v.fieldType.Common().Name),
|
||||
Kind: "struct",
|
||||
Field: nil,
|
||||
},
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
"github.com/derekparker/delve/dwarf/line"
|
||||
"github.com/derekparker/delve/dwarf/reader"
|
||||
|
||||
@ -15,7 +15,7 @@ import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/macho"
|
||||
"golang.org/x/debug/macho"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
"github.com/derekparker/delve/dwarf/line"
|
||||
|
||||
@ -16,7 +16,7 @@ import (
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/elf"
|
||||
"golang.org/x/debug/elf"
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
"github.com/derekparker/delve/dwarf/line"
|
||||
)
|
||||
|
||||
@ -15,7 +15,7 @@ import (
|
||||
|
||||
sys "golang.org/x/sys/windows"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
"github.com/derekparker/delve/dwarf/line"
|
||||
)
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
)
|
||||
|
||||
// Thread represents a single thread in the traced process
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
)
|
||||
|
||||
// Do not call this function directly it isn't able to deal correctly with package paths
|
||||
@ -22,7 +22,7 @@ func (dbp *Process) findType(name string) (dwarf.Type, error) {
|
||||
}
|
||||
|
||||
func (dbp *Process) pointerTo(typ dwarf.Type) dwarf.Type {
|
||||
return &dwarf.PtrType{dwarf.CommonType{int64(dbp.arch.PtrSize()), "", reflect.Ptr, 0}, typ}
|
||||
return &dwarf.PtrType{dwarf.CommonType{int64(dbp.arch.PtrSize()), "*" + typ.Common().Name, reflect.Ptr, 0}, typ}
|
||||
}
|
||||
|
||||
func (dbp *Process) findTypeExpr(expr ast.Expr) (dwarf.Type, error) {
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/dwarf/op"
|
||||
"github.com/derekparker/delve/dwarf/reader"
|
||||
)
|
||||
@ -282,7 +282,7 @@ func (v *Variable) TypeString() string {
|
||||
return "nil"
|
||||
}
|
||||
if v.DwarfType != nil {
|
||||
return v.DwarfType.String()
|
||||
return v.DwarfType.Common().Name
|
||||
}
|
||||
return v.Kind.String()
|
||||
}
|
||||
@ -626,10 +626,10 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
|
||||
// not a regular struct member
|
||||
for _, field := range t.Field {
|
||||
isEmbeddedStructMember :=
|
||||
(field.Type.String() == field.Name) ||
|
||||
(field.Type.Common().Name == field.Name) ||
|
||||
(len(field.Name) > 1 &&
|
||||
field.Name[0] == '*' &&
|
||||
field.Type.String()[1:] == field.Name[1:])
|
||||
field.Type.Common().Name[1:] == field.Name[1:])
|
||||
if !isEmbeddedStructMember {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/proc"
|
||||
)
|
||||
|
||||
@ -88,6 +88,9 @@ func prettyTypeName(typ dwarf.Type) string {
|
||||
if typ == nil {
|
||||
return ""
|
||||
}
|
||||
if typ.Common().Name != "" {
|
||||
return typ.Common().Name
|
||||
}
|
||||
r := typ.String()
|
||||
if r == "*void" {
|
||||
return "unsafe.Pointer"
|
||||
|
||||
0
dwarf/debug/LICENSE → vendor/golang.org/x/debug/LICENSE
generated
vendored
0
dwarf/debug/LICENSE → vendor/golang.org/x/debug/LICENSE
generated
vendored
12
dwarf/debug/dwarf/buf.go → vendor/golang.org/x/debug/dwarf/buf.go
generated
vendored
12
dwarf/debug/dwarf/buf.go → vendor/golang.org/x/debug/dwarf/buf.go
generated
vendored
@ -8,6 +8,7 @@ package dwarf
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@ -173,6 +174,17 @@ func (b *buf) addr() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// assertEmpty checks that everything has been read from b.
|
||||
func (b *buf) assertEmpty() {
|
||||
if len(b.data) == 0 {
|
||||
return
|
||||
}
|
||||
if len(b.data) > 5 {
|
||||
b.error(fmt.Sprintf("unexpected extra data: %x...", b.data[0:5]))
|
||||
}
|
||||
b.error(fmt.Sprintf("unexpected extra data: %x", b.data))
|
||||
}
|
||||
|
||||
func (b *buf) error(s string) {
|
||||
if b.err == nil {
|
||||
b.data = nil
|
||||
249
vendor/golang.org/x/debug/dwarf/cache.go
generated
vendored
Normal file
249
vendor/golang.org/x/debug/dwarf/cache.go
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dwarf
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// pcToFuncEntries maps PC ranges to function entries.
|
||||
//
|
||||
// Each element contains a *Entry for a function and its corresponding start PC.
|
||||
// If we know the address one past the last instruction of a function, and it is
|
||||
// not equal to the start address of the next function, we mark that with
|
||||
// another element containing that address and a nil entry. The elements are
|
||||
// sorted by PC. Among elements with the same PC, those with non-nil *Entry
|
||||
// are put earlier.
|
||||
type pcToFuncEntries []pcToFuncEntry
|
||||
type pcToFuncEntry struct {
|
||||
pc uint64
|
||||
entry *Entry
|
||||
}
|
||||
|
||||
func (p pcToFuncEntries) Len() int { return len(p) }
|
||||
func (p pcToFuncEntries) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
func (p pcToFuncEntries) Less(i, j int) bool {
|
||||
if p[i].pc != p[j].pc {
|
||||
return p[i].pc < p[j].pc
|
||||
}
|
||||
return p[i].entry != nil && p[j].entry == nil
|
||||
}
|
||||
|
||||
// nameCache maps each symbol name to a linked list of the entries with that name.
|
||||
type nameCache map[string]*nameCacheEntry
|
||||
type nameCacheEntry struct {
|
||||
entry *Entry
|
||||
link *nameCacheEntry
|
||||
}
|
||||
|
||||
// pcToLineEntries maps PCs to line numbers.
|
||||
//
|
||||
// It is a slice of (PC, line, file number) triples, sorted by PC. The file
|
||||
// number is an index into the source files slice.
|
||||
// If (PC1, line1, file1) and (PC2, line2, file2) are two consecutive elements,
|
||||
// then the span of addresses [PC1, PC2) belongs to (line1, file1). If an
|
||||
// element's file number is zero, it only marks the end of a span.
|
||||
//
|
||||
// TODO: could save memory by changing pcToLineEntries and lineToPCEntries to use
|
||||
// interval trees containing references into .debug_line.
|
||||
type pcToLineEntries []pcToLineEntry
|
||||
type pcToLineEntry struct {
|
||||
pc uint64
|
||||
line uint64
|
||||
file uint64
|
||||
}
|
||||
|
||||
func (p pcToLineEntries) Len() int { return len(p) }
|
||||
func (p pcToLineEntries) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
func (p pcToLineEntries) Less(i, j int) bool {
|
||||
if p[i].pc != p[j].pc {
|
||||
return p[i].pc < p[j].pc
|
||||
}
|
||||
return p[i].file > p[j].file
|
||||
}
|
||||
|
||||
// byFileLine is used temporarily while building lineToPCEntries.
|
||||
type byFileLine []pcToLineEntry
|
||||
|
||||
func (b byFileLine) Len() int { return len(b) }
|
||||
func (b byFileLine) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
func (b byFileLine) Less(i, j int) bool {
|
||||
if b[i].file != b[j].file {
|
||||
return b[i].file < b[j].file
|
||||
}
|
||||
return b[i].line < b[j].line
|
||||
}
|
||||
|
||||
// lineToPCEntries maps line numbers to breakpoint addresses.
|
||||
//
|
||||
// The slice contains, for each source file in Data, a slice of (line, PC)
|
||||
// pairs, sorted by line. Note that there may be more than one PC for a line.
|
||||
type lineToPCEntries [][]lineToPCEntry
|
||||
type lineToPCEntry struct {
|
||||
line uint64
|
||||
pc uint64
|
||||
}
|
||||
|
||||
func (d *Data) buildLineToPCCache(pclfs pcToLineEntries) {
|
||||
// TODO: only include lines where is_stmt is true
|
||||
sort.Sort(byFileLine(pclfs))
|
||||
// Make a slice of (line, PC) pairs for each (non-zero) file.
|
||||
var (
|
||||
c = make(lineToPCEntries, len(d.sourceFiles))
|
||||
curSlice []lineToPCEntry
|
||||
)
|
||||
for i, pclf := range pclfs {
|
||||
if pclf.file == 0 {
|
||||
// This entry indicated the end of an instruction sequence, not a breakpoint.
|
||||
continue
|
||||
}
|
||||
curSlice = append(curSlice, lineToPCEntry{line: pclf.line, pc: pclf.pc})
|
||||
if i+1 == len(pclfs) || pclf.file != pclfs[i+1].file {
|
||||
// curSlice now contains all of the entries for pclf.file.
|
||||
if pclf.file > 0 && pclf.file < uint64(len(c)) {
|
||||
c[pclf.file] = curSlice
|
||||
}
|
||||
curSlice = nil
|
||||
}
|
||||
}
|
||||
d.lineToPCEntries = c
|
||||
}
|
||||
|
||||
func (d *Data) buildPCToLineCache(cache pcToLineEntries) {
|
||||
// Sort cache by PC (in increasing order), then by file number (in decreasing order).
|
||||
sort.Sort(cache)
|
||||
|
||||
// Build a copy without redundant entries.
|
||||
var out pcToLineEntries
|
||||
for i, pclf := range cache {
|
||||
if i > 0 && pclf.pc == cache[i-1].pc {
|
||||
// This entry is for the same PC as the previous entry.
|
||||
continue
|
||||
}
|
||||
if i > 0 && pclf.file == cache[i-1].file && pclf.line == cache[i-1].line {
|
||||
// This entry is for the same file and line as the previous entry.
|
||||
continue
|
||||
}
|
||||
out = append(out, pclf)
|
||||
}
|
||||
d.pcToLineEntries = out
|
||||
}
|
||||
|
||||
// buildLineCaches constructs d.sourceFiles, d.lineToPCEntries, d.pcToLineEntries.
|
||||
func (d *Data) buildLineCaches() {
|
||||
if len(d.line) == 0 {
|
||||
return
|
||||
}
|
||||
var m lineMachine
|
||||
// Assume the address_size in the first unit applies to the whole program.
|
||||
// TODO: we could handle executables containing code for multiple address
|
||||
// sizes using DW_AT_stmt_list attributes.
|
||||
if len(d.unit) == 0 {
|
||||
return
|
||||
}
|
||||
buf := makeBuf(d, &d.unit[0], "line", 0, d.line)
|
||||
if err := m.parseHeader(&buf); err != nil {
|
||||
return
|
||||
}
|
||||
for _, f := range m.header.file {
|
||||
d.sourceFiles = append(d.sourceFiles, f.name)
|
||||
}
|
||||
var cache pcToLineEntries
|
||||
fn := func(m *lineMachine) bool {
|
||||
if m.endSequence {
|
||||
cache = append(cache, pcToLineEntry{
|
||||
pc: m.address,
|
||||
line: 0,
|
||||
file: 0,
|
||||
})
|
||||
} else {
|
||||
cache = append(cache, pcToLineEntry{
|
||||
pc: m.address,
|
||||
line: m.line,
|
||||
file: m.file,
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
m.evalCompilationUnit(&buf, fn)
|
||||
d.buildLineToPCCache(cache)
|
||||
d.buildPCToLineCache(cache)
|
||||
}
|
||||
|
||||
// buildInfoCaches initializes nameCache and pcToFuncEntries by walking the
|
||||
// top-level entries under each compile unit. It swallows any errors in parsing.
|
||||
func (d *Data) buildInfoCaches() {
|
||||
// TODO: record errors somewhere?
|
||||
d.nameCache = make(map[string]*nameCacheEntry)
|
||||
|
||||
var pcToFuncEntries pcToFuncEntries
|
||||
|
||||
r := d.Reader()
|
||||
loop:
|
||||
for {
|
||||
entry, err := r.Next()
|
||||
if entry == nil || err != nil {
|
||||
break loop
|
||||
}
|
||||
if entry.Tag != TagCompileUnit /* DW_TAG_compile_unit */ {
|
||||
r.SkipChildren()
|
||||
continue
|
||||
}
|
||||
for {
|
||||
entry, err := r.Next()
|
||||
if entry == nil || err != nil {
|
||||
break loop
|
||||
}
|
||||
if entry.Tag == 0 {
|
||||
// End of children of current compile unit.
|
||||
break
|
||||
}
|
||||
r.SkipChildren()
|
||||
// Update name-to-entry cache.
|
||||
if name, ok := entry.Val(AttrName).(string); ok {
|
||||
d.nameCache[name] = &nameCacheEntry{entry: entry, link: d.nameCache[name]}
|
||||
}
|
||||
|
||||
// If this entry is a function, update PC-to-containing-function cache.
|
||||
if entry.Tag != TagSubprogram /* DW_TAG_subprogram */ {
|
||||
continue
|
||||
}
|
||||
|
||||
// DW_AT_low_pc, if present, is the address of the first instruction of
|
||||
// the function.
|
||||
lowpc, ok := entry.Val(AttrLowpc).(uint64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
pcToFuncEntries = append(pcToFuncEntries, pcToFuncEntry{lowpc, entry})
|
||||
|
||||
// DW_AT_high_pc, if present (TODO: and of class address) is the address
|
||||
// one past the last instruction of the function.
|
||||
highpc, ok := entry.Val(AttrHighpc).(uint64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
pcToFuncEntries = append(pcToFuncEntries, pcToFuncEntry{highpc, nil})
|
||||
}
|
||||
}
|
||||
// Sort elements by PC. If there are multiple elements with the same PC,
|
||||
// those with non-nil *Entry are placed earlier.
|
||||
sort.Sort(pcToFuncEntries)
|
||||
|
||||
// Copy only the first element for each PC to out.
|
||||
n := 0
|
||||
for i, ce := range pcToFuncEntries {
|
||||
if i == 0 || ce.pc != pcToFuncEntries[i-1].pc {
|
||||
n++
|
||||
}
|
||||
}
|
||||
out := make([]pcToFuncEntry, 0, n)
|
||||
for i, ce := range pcToFuncEntries {
|
||||
if i == 0 || ce.pc != pcToFuncEntries[i-1].pc {
|
||||
out = append(out, ce)
|
||||
}
|
||||
}
|
||||
d.pcToFuncEntries = out
|
||||
}
|
||||
0
dwarf/debug/dwarf/const.go → vendor/golang.org/x/debug/dwarf/const.go
generated
vendored
0
dwarf/debug/dwarf/const.go → vendor/golang.org/x/debug/dwarf/const.go
generated
vendored
0
dwarf/debug/dwarf/entry.go → vendor/golang.org/x/debug/dwarf/entry.go
generated
vendored
0
dwarf/debug/dwarf/entry.go → vendor/golang.org/x/debug/dwarf/entry.go
generated
vendored
0
dwarf/debug/dwarf/frame.go → vendor/golang.org/x/debug/dwarf/frame.go
generated
vendored
0
dwarf/debug/dwarf/frame.go → vendor/golang.org/x/debug/dwarf/frame.go
generated
vendored
124
dwarf/debug/dwarf/line.go → vendor/golang.org/x/debug/dwarf/line.go
generated
vendored
124
dwarf/debug/dwarf/line.go → vendor/golang.org/x/debug/dwarf/line.go
generated
vendored
@ -11,91 +11,40 @@ package dwarf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PCToLine returns the file and line number corresponding to the PC value.
|
||||
// It returns an error if a correspondence cannot be found.
|
||||
func (d *Data) PCToLine(pc uint64) (file string, line uint64, err error) {
|
||||
if len(d.line) == 0 {
|
||||
c := d.pcToLineEntries
|
||||
if len(c) == 0 {
|
||||
return "", 0, fmt.Errorf("PCToLine: no line table")
|
||||
}
|
||||
var m lineMachine
|
||||
// Assume the first info unit is the same as us. Extremely likely. TODO?
|
||||
if len(d.unit) == 0 {
|
||||
return "", 0, fmt.Errorf("no info section")
|
||||
}
|
||||
buf := makeBuf(d, &d.unit[0], "line", 0, d.line)
|
||||
if err = m.parseHeader(&buf); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
state := pcSearchState{pc: pc, newSequence: true}
|
||||
if err = m.evalCompilationUnit(&buf, state.findPC); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
if !state.found {
|
||||
i := sort.Search(len(c), func(i int) bool { return c[i].pc > pc }) - 1
|
||||
// c[i] is now the entry in pcToLineEntries with the largest pc that is not
|
||||
// larger than the query pc.
|
||||
// The search has failed if:
|
||||
// - All pcs in c were larger than the query pc (i == -1).
|
||||
// - c[i] marked the end of a sequence of instructions (c[i].file == 0).
|
||||
// - c[i] is the last element of c, and isn't the end of a sequence of
|
||||
// instructions, and the search pc is much larger than c[i].pc. In this
|
||||
// case, we don't know the range of the last instruction, but the search
|
||||
// pc is probably past it.
|
||||
if i == -1 || c[i].file == 0 || (i+1 == len(c) && pc-c[i].pc > 1024) {
|
||||
return "", 0, fmt.Errorf("no source line defined for PC %#x", pc)
|
||||
}
|
||||
if state.lastFile >= uint64(len(m.header.file)) {
|
||||
if c[i].file >= uint64(len(d.sourceFiles)) {
|
||||
return "", 0, fmt.Errorf("invalid file number in DWARF data")
|
||||
}
|
||||
return m.header.file[state.lastFile].name, state.lastLine, nil
|
||||
return d.sourceFiles[c[i].file], c[i].line, nil
|
||||
}
|
||||
|
||||
// pcSearchState holds the state for the search PCToLine does.
|
||||
type pcSearchState struct {
|
||||
pc uint64 // pc we are searching for.
|
||||
// lastPC, lastFile, and lastLine are the PC, file number and line that were
|
||||
// output most recently by the line machine.
|
||||
lastPC uint64
|
||||
lastFile uint64
|
||||
lastLine uint64
|
||||
// found indicates that the above values correspond to the PC we're looking for.
|
||||
found bool
|
||||
// newSequence indicates that we are starting a new sequence of instructions,
|
||||
// and so last{PC,File,Line} are not valid.
|
||||
newSequence bool
|
||||
}
|
||||
|
||||
// findPC will execute for every line in the state machine, until we find state.pc.
|
||||
// It returns a bool indicating whether to continue searching.
|
||||
func (state *pcSearchState) findPC(m *lineMachine) bool {
|
||||
if !state.newSequence && state.lastPC < state.pc && state.pc < m.address {
|
||||
// The PC we are looking for is between the previous PC and the current PC,
|
||||
// so lastFile and lastLine are its source location.
|
||||
state.found = true
|
||||
return false
|
||||
}
|
||||
if m.endSequence {
|
||||
state.newSequence = true
|
||||
return true
|
||||
}
|
||||
state.newSequence = false
|
||||
state.lastPC, state.lastFile, state.lastLine = m.address, m.file, m.line
|
||||
if m.address == state.pc {
|
||||
// lastFile and lastLine are the source location of pc.
|
||||
state.found = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// LineToPCs returns the PCs corresponding to the file and line number.
|
||||
// LineToBreakpointPCs returns the PCs that should be used as breakpoints
|
||||
// corresponding to the given file and line number.
|
||||
// It returns an empty slice if no PCs were found.
|
||||
func (d *Data) LineToPCs(file string, line uint64) ([]uint64, error) {
|
||||
if len(d.line) == 0 {
|
||||
return nil, fmt.Errorf("LineToPCs: no line table")
|
||||
}
|
||||
if len(d.unit) == 0 {
|
||||
return nil, fmt.Errorf("LineToPCs: no info section")
|
||||
}
|
||||
|
||||
buf := makeBuf(d, &d.unit[0], "line", 0, d.line)
|
||||
var m lineMachine
|
||||
if err := m.parseHeader(&buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (d *Data) LineToBreakpointPCs(file string, line uint64) ([]uint64, error) {
|
||||
compDir := d.compilationDirectory()
|
||||
|
||||
// Find the closest match in the executable for the specified file.
|
||||
@ -103,46 +52,43 @@ func (d *Data) LineToPCs(file string, line uint64) ([]uint64, error) {
|
||||
// at the end of the name. If there is a tie, we prefer files that are
|
||||
// under the compilation directory. If there is still a tie, we choose
|
||||
// the file with the shortest name.
|
||||
// TODO: handle duplicate file names in the DWARF?
|
||||
var bestFile struct {
|
||||
fileNum uint64 // Index of the file in the DWARF data.
|
||||
components int // Number of matching path components.
|
||||
length int // Length of the filename.
|
||||
underComp bool // File is under the compilation directory.
|
||||
}
|
||||
for num, f := range m.header.file {
|
||||
c := matchingPathComponentSuffixSize(f.name, file)
|
||||
underComp := strings.HasPrefix(f.name, compDir)
|
||||
for filenum, filename := range d.sourceFiles {
|
||||
c := matchingPathComponentSuffixSize(filename, file)
|
||||
underComp := strings.HasPrefix(filename, compDir)
|
||||
better := false
|
||||
if c != bestFile.components {
|
||||
better = c > bestFile.components
|
||||
} else if underComp != bestFile.underComp {
|
||||
better = underComp
|
||||
} else {
|
||||
better = len(f.name) < bestFile.length
|
||||
better = len(filename) < bestFile.length
|
||||
}
|
||||
if better {
|
||||
bestFile.fileNum = uint64(num)
|
||||
bestFile.fileNum = uint64(filenum)
|
||||
bestFile.components = c
|
||||
bestFile.length = len(f.name)
|
||||
bestFile.length = len(filename)
|
||||
bestFile.underComp = underComp
|
||||
}
|
||||
}
|
||||
if bestFile.components == 0 {
|
||||
return nil, fmt.Errorf("couldn't find file %s", file)
|
||||
return nil, fmt.Errorf("couldn't find file %q", file)
|
||||
}
|
||||
|
||||
// pcs will contain the PCs for every line machine output with the correct line
|
||||
// and file number.
|
||||
var pcs []uint64
|
||||
// accumulatePCs will execute for every line machine output.
|
||||
accumulatePCs := func(m *lineMachine) (cont bool) {
|
||||
if m.line == line && m.file == bestFile.fileNum {
|
||||
pcs = append(pcs, m.address)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if err := m.evalCompilationUnit(&buf, accumulatePCs); err != nil {
|
||||
return nil, err
|
||||
c := d.lineToPCEntries[bestFile.fileNum]
|
||||
// c contains all (pc, line) pairs for the appropriate file.
|
||||
start := sort.Search(len(c), func(i int) bool { return c[i].line >= line })
|
||||
end := sort.Search(len(c), func(i int) bool { return c[i].line > line })
|
||||
// c[i].line == line for all i in the range [start, end).
|
||||
pcs := make([]uint64, 0, end-start)
|
||||
for i := start; i < end; i++ {
|
||||
pcs = append(pcs, c[i].pc)
|
||||
}
|
||||
return pcs, nil
|
||||
}
|
||||
17
dwarf/debug/dwarf/open.go → vendor/golang.org/x/debug/dwarf/open.go
generated
vendored
17
dwarf/debug/dwarf/open.go → vendor/golang.org/x/debug/dwarf/open.go
generated
vendored
@ -23,11 +23,16 @@ type Data struct {
|
||||
str []byte
|
||||
|
||||
// parsed data
|
||||
abbrevCache map[uint32]abbrevTable
|
||||
order binary.ByteOrder
|
||||
typeCache map[Offset]Type
|
||||
typeSigs map[uint64]*typeUnit
|
||||
unit []unit
|
||||
abbrevCache map[uint32]abbrevTable
|
||||
order binary.ByteOrder
|
||||
typeCache map[Offset]Type
|
||||
typeSigs map[uint64]*typeUnit
|
||||
unit []unit
|
||||
sourceFiles []string // source files listed in .debug_line.
|
||||
nameCache // map from name to top-level entries in .debug_info.
|
||||
pcToFuncEntries // cache of .debug_info data for function bounds.
|
||||
pcToLineEntries // cache of .debug_line data, used for efficient PC-to-line mapping.
|
||||
lineToPCEntries // cache of .debug_line data, used for efficient line-to-[]PC mapping.
|
||||
}
|
||||
|
||||
// New returns a new Data object initialized from the given parameters.
|
||||
@ -75,6 +80,8 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat
|
||||
return nil, err
|
||||
}
|
||||
d.unit = u
|
||||
d.buildInfoCaches()
|
||||
d.buildLineCaches()
|
||||
return d, nil
|
||||
}
|
||||
|
||||
119
vendor/golang.org/x/debug/dwarf/symbol.go
generated
vendored
Normal file
119
vendor/golang.org/x/debug/dwarf/symbol.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dwarf
|
||||
|
||||
// This file provides simple methods to access the symbol table by name and address.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// lookupEntry returns the first Entry for the name.
|
||||
// If tag is non-zero, only entries with that tag are considered.
|
||||
func (d *Data) lookupEntry(name string, tag Tag) (*Entry, error) {
|
||||
x, ok := d.nameCache[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("DWARF entry for %q not found", name)
|
||||
}
|
||||
for ; x != nil; x = x.link {
|
||||
if tag == 0 || x.entry.Tag == tag {
|
||||
return x.entry, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no DWARF entry for %q with tag %s", name, tag)
|
||||
}
|
||||
|
||||
// LookupMatchingSymbols returns the names of all top-level entries matching
|
||||
// the given regular expression.
|
||||
func (d *Data) LookupMatchingSymbols(nameRE *regexp.Regexp) (result []string, err error) {
|
||||
for name := range d.nameCache {
|
||||
if nameRE.MatchString(name) {
|
||||
result = append(result, name)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// LookupEntry returns the Entry for the named symbol.
|
||||
func (d *Data) LookupEntry(name string) (*Entry, error) {
|
||||
return d.lookupEntry(name, 0)
|
||||
}
|
||||
|
||||
// LookupFunction returns the entry for a function.
|
||||
func (d *Data) LookupFunction(name string) (*Entry, error) {
|
||||
return d.lookupEntry(name, TagSubprogram)
|
||||
}
|
||||
|
||||
// LookupVariable returns the entry for a (global) variable.
|
||||
func (d *Data) LookupVariable(name string) (*Entry, error) {
|
||||
return d.lookupEntry(name, TagVariable)
|
||||
}
|
||||
|
||||
// EntryLocation returns the address of the object referred to by the given Entry.
|
||||
func (d *Data) EntryLocation(e *Entry) (uint64, error) {
|
||||
loc, _ := e.Val(AttrLocation).([]byte)
|
||||
if len(loc) == 0 {
|
||||
return 0, fmt.Errorf("DWARF entry has no Location attribute")
|
||||
}
|
||||
// TODO: implement the DWARF Location bytecode. What we have here only
|
||||
// recognizes a program with a single literal opAddr bytecode.
|
||||
if asize := d.unit[0].asize; loc[0] == opAddr && len(loc) == 1+asize {
|
||||
switch asize {
|
||||
case 1:
|
||||
return uint64(loc[1]), nil
|
||||
case 2:
|
||||
return uint64(d.order.Uint16(loc[1:])), nil
|
||||
case 4:
|
||||
return uint64(d.order.Uint32(loc[1:])), nil
|
||||
case 8:
|
||||
return d.order.Uint64(loc[1:]), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("DWARF entry has an unimplemented Location op")
|
||||
}
|
||||
|
||||
// EntryType returns the Type for an Entry.
|
||||
func (d *Data) EntryType(e *Entry) (Type, error) {
|
||||
off, err := d.EntryTypeOffset(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.Type(off)
|
||||
}
|
||||
|
||||
// EntryTypeOffset returns the offset in the given Entry's type attribute.
|
||||
func (d *Data) EntryTypeOffset(e *Entry) (Offset, error) {
|
||||
v := e.Val(AttrType)
|
||||
if v == nil {
|
||||
return 0, fmt.Errorf("DWARF entry has no Type attribute")
|
||||
}
|
||||
off, ok := v.(Offset)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("DWARF entry has an invalid Type attribute")
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
// PCToFunction returns the entry and address for the function containing the
|
||||
// specified PC.
|
||||
func (d *Data) PCToFunction(pc uint64) (entry *Entry, lowpc uint64, err error) {
|
||||
p := d.pcToFuncEntries
|
||||
if len(p) == 0 {
|
||||
return nil, 0, fmt.Errorf("no function addresses loaded")
|
||||
}
|
||||
i := sort.Search(len(p), func(i int) bool { return p[i].pc > pc }) - 1
|
||||
// The search failed if:
|
||||
// - pc was before the start of any function.
|
||||
// - The largest function bound not larger than pc was the end of a function,
|
||||
// not the start of one.
|
||||
// - The largest function bound not larger than pc was the start of a function
|
||||
// that we don't know the end of, and the PC is much larger than the start.
|
||||
if i == -1 || p[i].entry == nil || (i+1 == len(p) && pc-p[i].pc >= 1<<20) {
|
||||
return nil, 0, fmt.Errorf("no function at %x", pc)
|
||||
}
|
||||
return p[i].entry, p[i].pc, nil
|
||||
}
|
||||
39
dwarf/debug/dwarf/type.go → vendor/golang.org/x/debug/dwarf/type.go
generated
vendored
39
dwarf/debug/dwarf/type.go → vendor/golang.org/x/debug/dwarf/type.go
generated
vendored
@ -9,6 +9,7 @@
|
||||
package dwarf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
@ -138,12 +139,7 @@ type PtrType struct {
|
||||
Type Type
|
||||
}
|
||||
|
||||
func (t *PtrType) String() string {
|
||||
if t.Name != "" {
|
||||
return t.Name
|
||||
}
|
||||
return "*" + t.Type.String()
|
||||
}
|
||||
func (t *PtrType) String() string { return "*" + t.Type.String() }
|
||||
|
||||
// A StructType represents a struct, union, or C++ class type.
|
||||
type StructType struct {
|
||||
@ -165,9 +161,6 @@ type StructField struct {
|
||||
}
|
||||
|
||||
func (t *StructType) String() string {
|
||||
if t.Name != "" {
|
||||
return t.Name
|
||||
}
|
||||
if t.StructName != "" {
|
||||
return t.Kind + " " + t.StructName
|
||||
}
|
||||
@ -451,6 +444,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
|
||||
// TagSubrangeType or TagEnumerationType giving one dimension.
|
||||
// dimensions are in left to right order.
|
||||
t := new(ArrayType)
|
||||
t.Name, _ = e.Val(AttrName).(string)
|
||||
t.ReflectKind = getKind(e)
|
||||
typ = t
|
||||
typeCache[off] = t
|
||||
@ -615,12 +609,30 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
|
||||
case []byte:
|
||||
// TODO: Should have original compilation
|
||||
// unit here, not unknownFormat.
|
||||
if len(loc) == 0 {
|
||||
// Empty exprloc. f.ByteOffset=0.
|
||||
break
|
||||
}
|
||||
b := makeBuf(d, unknownFormat{}, "location", 0, loc)
|
||||
if x := b.uint8(); x != opPlusUconst {
|
||||
err = DecodeError{name, kid.Offset, "unexpected opcode 0x" + strconv.FormatUint(uint64(x), 16)}
|
||||
op := b.uint8()
|
||||
switch op {
|
||||
case opPlusUconst:
|
||||
// Handle opcode sequence [DW_OP_plus_uconst <uleb128>]
|
||||
f.ByteOffset = int64(b.uint())
|
||||
b.assertEmpty()
|
||||
case opConsts:
|
||||
// Handle opcode sequence [DW_OP_consts <sleb128> DW_OP_plus]
|
||||
f.ByteOffset = b.int()
|
||||
op = b.uint8()
|
||||
if op != opPlus {
|
||||
err = DecodeError{name, kid.Offset, fmt.Sprintf("unexpected opcode 0x%x", op)}
|
||||
goto Error
|
||||
}
|
||||
b.assertEmpty()
|
||||
default:
|
||||
err = DecodeError{name, kid.Offset, fmt.Sprintf("unexpected opcode 0x%x", op)}
|
||||
goto Error
|
||||
}
|
||||
f.ByteOffset = int64(b.uint())
|
||||
if b.err != nil {
|
||||
err = b.err
|
||||
goto Error
|
||||
@ -662,6 +674,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
|
||||
// Attributes:
|
||||
// AttrType: subtype
|
||||
t := new(QualType)
|
||||
t.Name, _ = e.Val(AttrName).(string)
|
||||
t.ReflectKind = getKind(e)
|
||||
typ = t
|
||||
typeCache[off] = t
|
||||
@ -690,6 +703,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
|
||||
t.ReflectKind = getKind(e)
|
||||
typ = t
|
||||
typeCache[off] = t
|
||||
t.Name, _ = e.Val(AttrName).(string)
|
||||
t.EnumName, _ = e.Val(AttrName).(string)
|
||||
t.Val = make([]*EnumValue, 0, 8)
|
||||
for kid := next(); kid != nil; kid = next() {
|
||||
@ -735,6 +749,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
|
||||
// AttrType: type of parameter
|
||||
// TagUnspecifiedParameter: final ...
|
||||
t := new(FuncType)
|
||||
t.Name, _ = e.Val(AttrName).(string)
|
||||
t.ReflectKind = getKind(e)
|
||||
typ = t
|
||||
typeCache[off] = t
|
||||
0
dwarf/debug/dwarf/typeunit.go → vendor/golang.org/x/debug/dwarf/typeunit.go
generated
vendored
0
dwarf/debug/dwarf/typeunit.go → vendor/golang.org/x/debug/dwarf/typeunit.go
generated
vendored
0
dwarf/debug/dwarf/unit.go → vendor/golang.org/x/debug/dwarf/unit.go
generated
vendored
0
dwarf/debug/dwarf/unit.go → vendor/golang.org/x/debug/dwarf/unit.go
generated
vendored
0
dwarf/debug/elf/elf.go → vendor/golang.org/x/debug/elf/elf.go
generated
vendored
0
dwarf/debug/elf/elf.go → vendor/golang.org/x/debug/elf/elf.go
generated
vendored
2
dwarf/debug/elf/file.go → vendor/golang.org/x/debug/elf/file.go
generated
vendored
2
dwarf/debug/elf/file.go → vendor/golang.org/x/debug/elf/file.go
generated
vendored
@ -13,7 +13,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
)
|
||||
|
||||
// TODO: error reporting detail
|
||||
0
dwarf/debug/macho/fat.go → vendor/golang.org/x/debug/macho/fat.go
generated
vendored
0
dwarf/debug/macho/fat.go → vendor/golang.org/x/debug/macho/fat.go
generated
vendored
2
dwarf/debug/macho/file.go → vendor/golang.org/x/debug/macho/file.go
generated
vendored
2
dwarf/debug/macho/file.go → vendor/golang.org/x/debug/macho/file.go
generated
vendored
@ -14,7 +14,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/debug/dwarf"
|
||||
"golang.org/x/debug/dwarf"
|
||||
)
|
||||
|
||||
// A File represents an open Mach-O file.
|
||||
0
dwarf/debug/macho/macho.go → vendor/golang.org/x/debug/macho/macho.go
generated
vendored
0
dwarf/debug/macho/macho.go → vendor/golang.org/x/debug/macho/macho.go
generated
vendored
Reference in New Issue
Block a user