conversions.go 4.2 KB
Newer Older
1 2
package api

A
aarzilli 已提交
3 4
import (
	"debug/gosym"
5
	"go/constant"
6
	"golang.org/x/debug/dwarf"
7
	"reflect"
8
	"strconv"
D
Derek Parker 已提交
9

A
aarzilli 已提交
10 11
	"github.com/derekparker/delve/proc"
)
12

D
Derek Parker 已提交
13 14
// ConvertBreakpoint converts from a proc.Breakpoint to
// an api.Breakpoint.
15
func ConvertBreakpoint(bp *proc.Breakpoint) *Breakpoint {
16 17 18 19 20 21 22 23 24 25 26
	b := &Breakpoint{
		ID:            bp.ID,
		FunctionName:  bp.FunctionName,
		File:          bp.File,
		Line:          bp.Line,
		Addr:          bp.Addr,
		Tracepoint:    bp.Tracepoint,
		Stacktrace:    bp.Stacktrace,
		Goroutine:     bp.Goroutine,
		Variables:     bp.Variables,
		TotalHitCount: bp.TotalHitCount,
27
	}
28 29 30 31 32 33 34

	b.HitCount = map[string]uint64{}
	for idx := range bp.HitCount {
		b.HitCount[strconv.Itoa(idx)] = bp.HitCount[idx]
	}

	return b
35 36
}

D
Derek Parker 已提交
37 38
// ConvertThread converts a proc.Thread into an
// api thread.
39 40 41 42 43 44
func ConvertThread(th *proc.Thread) *Thread {
	var (
		function *Function
		file     string
		line     int
		pc       uint64
45
		gid      int
46 47 48 49 50 51 52
	)

	loc, err := th.Location()
	if err == nil {
		pc = loc.PC
		file = loc.File
		line = loc.Line
A
aarzilli 已提交
53
		function = ConvertFunction(loc.Fn)
54 55
	}

56 57
	var bp *Breakpoint

58
	if th.CurrentBreakpoint != nil && th.BreakpointConditionMet {
59 60 61 62
		bp = ConvertBreakpoint(th.CurrentBreakpoint)
	}

	if g, _ := th.GetG(); g != nil {
D
Derek Parker 已提交
63
		gid = g.ID
64 65
	}

66
	return &Thread{
D
Derek Parker 已提交
67
		ID:          th.ID,
68 69 70 71 72 73
		PC:          pc,
		File:        file,
		Line:        line,
		Function:    function,
		GoroutineID: gid,
		Breakpoint:  bp,
74 75 76
	}
}

77 78 79 80 81 82 83 84 85 86 87
func prettyTypeName(typ dwarf.Type) string {
	if typ == nil {
		return ""
	}
	r := typ.String()
	if r == "*void" {
		return "unsafe.Pointer"
	}
	return r
}

D
Derek Parker 已提交
88
// ConvertVar converts from proc.Variable to api.Variable.
89 90
func ConvertVar(v *proc.Variable) *Variable {
	r := Variable{
A
aarzilli 已提交
91 92 93 94 95 96
		Addr:     v.Addr,
		OnlyAddr: v.OnlyAddr,
		Name:     v.Name,
		Kind:     v.Kind,
		Len:      v.Len,
		Cap:      v.Cap,
97
	}
98

99 100
	r.Type = prettyTypeName(v.DwarfType)
	r.RealType = prettyTypeName(v.RealType)
101 102 103 104 105

	if v.Unreadable != nil {
		r.Unreadable = v.Unreadable.Error()
	}

106 107 108 109 110 111 112 113 114 115 116 117
	if v.Value != nil {
		switch v.Kind {
		case reflect.Float32:
			f, _ := constant.Float64Val(v.Value)
			r.Value = strconv.FormatFloat(f, 'f', -1, 32)
		case reflect.Float64:
			f, _ := constant.Float64Val(v.Value)
			r.Value = strconv.FormatFloat(f, 'f', -1, 64)
		case reflect.String, reflect.Func:
			r.Value = constant.StringVal(v.Value)
		default:
			r.Value = v.Value.String()
118 119 120
		}
	}

A
aarzilli 已提交
121 122 123 124
	switch v.Kind {
	case reflect.Complex64:
		r.Children = make([]Variable, 2)
		r.Len = 2
125

A
aarzilli 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
		real, _ := constant.Float64Val(constant.Real(v.Value))
		imag, _ := constant.Float64Val(constant.Imag(v.Value))

		r.Children[0].Name = "real"
		r.Children[0].Kind = reflect.Float32
		r.Children[0].Value = strconv.FormatFloat(real, 'f', -1, 32)

		r.Children[1].Name = "imaginary"
		r.Children[1].Kind = reflect.Float32
		r.Children[1].Value = strconv.FormatFloat(imag, 'f', -1, 32)
	case reflect.Complex128:
		r.Children = make([]Variable, 2)
		r.Len = 2

		real, _ := constant.Float64Val(constant.Real(v.Value))
		imag, _ := constant.Float64Val(constant.Imag(v.Value))

		r.Children[0].Name = "real"
		r.Children[0].Kind = reflect.Float64
		r.Children[0].Value = strconv.FormatFloat(real, 'f', -1, 64)

		r.Children[1].Name = "imaginary"
		r.Children[1].Kind = reflect.Float64
		r.Children[1].Value = strconv.FormatFloat(imag, 'f', -1, 64)

	default:
		r.Children = make([]Variable, len(v.Children))

		for i := range v.Children {
			r.Children[i] = *ConvertVar(&v.Children[i])
		}
157 158 159
	}

	return &r
160 161
}

D
Derek Parker 已提交
162 163
// ConvertFunction converts from gosym.Func to
// api.Function.
A
aarzilli 已提交
164 165 166 167 168 169 170 171 172 173
func ConvertFunction(fn *gosym.Func) *Function {
	if fn == nil {
		return nil
	}

	return &Function{
		Name:   fn.Name,
		Type:   fn.Type,
		Value:  fn.Value,
		GoType: fn.GoType,
174
	}
A
aarzilli 已提交
175
}
176

D
Derek Parker 已提交
177
// ConvertGoroutine converts from proc.G to api.Goroutine.
A
aarzilli 已提交
178
func ConvertGoroutine(g *proc.G) *Goroutine {
179
	return &Goroutine{
D
Derek Parker 已提交
180
		ID:             g.ID,
181 182 183
		CurrentLoc:     ConvertLocation(g.CurrentLoc),
		UserCurrentLoc: ConvertLocation(g.UserCurrent()),
		GoStatementLoc: ConvertLocation(g.Go()),
A
aarzilli 已提交
184 185 186
	}
}

D
Derek Parker 已提交
187
// ConvertLocation converts from proc.Location to api.Location.
A
aarzilli 已提交
188 189 190
func ConvertLocation(loc proc.Location) Location {
	return Location{
		PC:       loc.PC,
191
		File:     loc.File,
A
aarzilli 已提交
192 193
		Line:     loc.Line,
		Function: ConvertFunction(loc.Fn),
194 195
	}
}