Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
pubx
delve
提交
7c42fc51
D
delve
项目概览
pubx
/
delve
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
delve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7c42fc51
编写于
7月 31, 2018
作者:
A
aarzilli
提交者:
Derek Parker
8月 16, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
proc: support calls to methods directly and through interface
上级
51994aaf
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
94 addition
and
10 deletion
+94
-10
_fixtures/fncall.go
_fixtures/fncall.go
+28
-1
pkg/proc/fncall.go
pkg/proc/fncall.go
+8
-4
pkg/proc/types.go
pkg/proc/types.go
+33
-3
pkg/proc/variables.go
pkg/proc/variables.go
+3
-2
service/test/variables_test.go
service/test/variables_test.go
+22
-0
未找到文件。
_fixtures/fncall.go
浏览文件 @
7c42fc51
...
@@ -35,6 +35,26 @@ func stringsJoin(v []string, sep string) string {
...
@@ -35,6 +35,26 @@ func stringsJoin(v []string, sep string) string {
return
strings
.
Join
(
v
,
sep
)
return
strings
.
Join
(
v
,
sep
)
}
}
type
astruct
struct
{
X
int
}
func
(
a
astruct
)
VRcvr
(
x
int
)
string
{
return
fmt
.
Sprintf
(
"%d + %d = %d"
,
x
,
a
.
X
,
x
+
a
.
X
)
}
func
(
pa
*
astruct
)
PRcvr
(
x
int
)
string
{
return
fmt
.
Sprintf
(
"%d - %d = %d"
,
x
,
pa
.
X
,
x
-
pa
.
X
)
}
type
PRcvrable
interface
{
PRcvr
(
int
)
string
}
type
VRcvrable
interface
{
VRcvr
(
int
)
string
}
var
zero
=
0
var
zero
=
0
func
main
()
{
func
main
()
{
...
@@ -42,7 +62,14 @@ func main() {
...
@@ -42,7 +62,14 @@ func main() {
intslice
:=
[]
int
{
1
,
2
,
3
}
intslice
:=
[]
int
{
1
,
2
,
3
}
stringslice
:=
[]
string
{
"one"
,
"two"
,
"three"
}
stringslice
:=
[]
string
{
"one"
,
"two"
,
"three"
}
comma
:=
","
comma
:=
","
a
:=
astruct
{
X
:
3
}
pa
:=
&
astruct
{
X
:
6
}
var
vable_a
VRcvrable
=
a
var
vable_pa
VRcvrable
=
pa
var
pable_pa
PRcvrable
=
pa
runtime
.
Breakpoint
()
runtime
.
Breakpoint
()
call1
(
one
,
two
)
call1
(
one
,
two
)
fmt
.
Println
(
one
,
two
,
zero
,
callpanic
,
callstacktrace
,
stringsJoin
,
intslice
,
stringslice
,
comma
)
fmt
.
Println
(
one
,
two
,
zero
,
callpanic
,
callstacktrace
,
stringsJoin
,
intslice
,
stringslice
,
comma
,
a
.
VRcvr
,
a
.
PRcvr
,
pa
,
vable_a
,
vable_pa
,
pable_pa
)
}
}
pkg/proc/fncall.go
浏览文件 @
7c42fc51
...
@@ -207,7 +207,6 @@ func funcCallEvalExpr(p Process, expr string) (fn *Function, argvars []*Variable
...
@@ -207,7 +207,6 @@ func funcCallEvalExpr(p Process, expr string) (fn *Function, argvars []*Variable
return
nil
,
nil
,
ErrNotACallExpr
return
nil
,
nil
,
ErrNotACallExpr
}
}
//TODO(aarzilli): must evaluate <var>.<method> and treat them appropriately
fnvar
,
err
:=
scope
.
evalAST
(
callexpr
.
Fun
)
fnvar
,
err
:=
scope
.
evalAST
(
callexpr
.
Fun
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
...
@@ -223,13 +222,18 @@ func funcCallEvalExpr(p Process, expr string) (fn *Function, argvars []*Variable
...
@@ -223,13 +222,18 @@ func funcCallEvalExpr(p Process, expr string) (fn *Function, argvars []*Variable
return
nil
,
nil
,
ErrNotAGoFunction
return
nil
,
nil
,
ErrNotAGoFunction
}
}
argvars
=
make
([]
*
Variable
,
len
(
callexpr
.
Args
))
argvars
=
make
([]
*
Variable
,
0
,
len
(
callexpr
.
Args
)
+
1
)
if
len
(
fnvar
.
Children
)
>
0
{
// receiver argument
argvars
=
append
(
argvars
,
&
fnvar
.
Children
[
0
])
}
for
i
:=
range
callexpr
.
Args
{
for
i
:=
range
callexpr
.
Args
{
argvar
s
[
i
],
err
=
scope
.
evalAST
(
callexpr
.
Args
[
i
])
argvar
,
err
:
=
scope
.
evalAST
(
callexpr
.
Args
[
i
])
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
argvars
[
i
]
.
Name
=
exprToString
(
callexpr
.
Args
[
i
])
argvar
.
Name
=
exprToString
(
callexpr
.
Args
[
i
])
argvars
=
append
(
argvars
,
argvar
)
}
}
return
fn
,
argvars
,
nil
return
fn
,
argvars
,
nil
...
...
pkg/proc/types.go
浏览文件 @
7c42fc51
...
@@ -192,6 +192,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGrou
...
@@ -192,6 +192,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGrou
bi
.
consts
=
make
(
map
[
dwarf
.
Offset
]
*
constantType
)
bi
.
consts
=
make
(
map
[
dwarf
.
Offset
]
*
constantType
)
bi
.
runtimeTypeToDIE
=
make
(
map
[
uint64
]
runtimeTypeDIE
)
bi
.
runtimeTypeToDIE
=
make
(
map
[
uint64
]
runtimeTypeDIE
)
reader
:=
bi
.
DwarfReader
()
reader
:=
bi
.
DwarfReader
()
ardr
:=
bi
.
DwarfReader
()
var
cu
*
compileUnit
=
nil
var
cu
*
compileUnit
=
nil
var
pu
*
partialUnit
=
nil
var
pu
*
partialUnit
=
nil
var
partialUnits
=
make
(
map
[
dwarf
.
Offset
]
*
partialUnit
)
var
partialUnits
=
make
(
map
[
dwarf
.
Offset
]
*
partialUnit
)
...
@@ -322,9 +323,7 @@ outer:
...
@@ -322,9 +323,7 @@ outer:
}
}
}
}
}
}
if
off
,
ok
:=
entry
.
Val
(
godwarf
.
AttrGoRuntimeType
)
.
(
uint64
);
ok
{
bi
.
registerRuntimeTypeToDIE
(
entry
,
ardr
)
bi
.
runtimeTypeToDIE
[
off
]
=
runtimeTypeDIE
{
entry
.
Offset
,
-
1
}
}
reader
.
SkipChildren
()
reader
.
SkipChildren
()
case
dwarf
.
TagVariable
:
case
dwarf
.
TagVariable
:
...
@@ -516,6 +515,37 @@ func (bi *BinaryInfo) expandPackagesInType(expr ast.Expr) {
...
@@ -516,6 +515,37 @@ func (bi *BinaryInfo) expandPackagesInType(expr ast.Expr) {
}
}
}
}
func
(
bi
*
BinaryInfo
)
registerRuntimeTypeToDIE
(
entry
*
dwarf
.
Entry
,
ardr
*
reader
.
Reader
)
{
if
off
,
ok
:=
entry
.
Val
(
godwarf
.
AttrGoRuntimeType
)
.
(
uint64
);
ok
{
if
_
,
ok
:=
bi
.
runtimeTypeToDIE
[
off
];
!
ok
{
bi
.
runtimeTypeToDIE
[
off
]
=
runtimeTypeDIE
{
entry
.
Offset
,
-
1
}
}
return
}
if
entry
.
Tag
!=
dwarf
.
TagTypedef
{
return
}
// For named structs the compiler will emit a TagStructType entry and a
// TagTypedef entry. The AttrGoRuntimeType is set on the TagStructType
// entry but we prefer to use the typedef instead, to make interface
// values consistent with other variables.
rtypOff
,
ok
:=
entry
.
Val
(
dwarf
.
AttrType
)
.
(
dwarf
.
Offset
)
if
!
ok
{
return
}
ardr
.
Seek
(
rtypOff
)
rentry
,
_
:=
ardr
.
Next
()
if
rentry
==
nil
{
return
}
if
off
,
ok
:=
rentry
.
Val
(
godwarf
.
AttrGoRuntimeType
)
.
(
uint64
);
ok
{
bi
.
runtimeTypeToDIE
[
off
]
=
runtimeTypeDIE
{
entry
.
Offset
,
-
1
}
}
}
// runtimeTypeToDIE returns the DIE corresponding to the runtime._type.
// runtimeTypeToDIE returns the DIE corresponding to the runtime._type.
// This is done in three different ways depending on the version of go.
// This is done in three different ways depending on the version of go.
// * Before go1.7 the type name is retrieved directly from the runtime._type
// * Before go1.7 the type name is retrieved directly from the runtime._type
...
...
pkg/proc/variables.go
浏览文件 @
7c42fc51
...
@@ -733,6 +733,7 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
...
@@ -733,6 +733,7 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
if
v
.
Unreadable
!=
nil
{
if
v
.
Unreadable
!=
nil
{
return
v
.
clone
(),
nil
return
v
.
clone
(),
nil
}
}
vname
:=
v
.
Name
switch
v
.
Kind
{
switch
v
.
Kind
{
case
reflect
.
Chan
:
case
reflect
.
Chan
:
v
=
v
.
clone
()
v
=
v
.
clone
()
...
@@ -789,12 +790,12 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
...
@@ -789,12 +790,12 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
return
embeddedField
,
nil
return
embeddedField
,
nil
}
}
}
}
return
nil
,
fmt
.
Errorf
(
"%s has no member %s"
,
v
.
N
ame
,
memberName
)
return
nil
,
fmt
.
Errorf
(
"%s has no member %s"
,
v
n
ame
,
memberName
)
default
:
default
:
if
v
.
Name
==
""
{
if
v
.
Name
==
""
{
return
nil
,
fmt
.
Errorf
(
"type %s is not a struct"
,
structVar
.
TypeString
())
return
nil
,
fmt
.
Errorf
(
"type %s is not a struct"
,
structVar
.
TypeString
())
}
}
return
nil
,
fmt
.
Errorf
(
"%s (type %s) is not a struct"
,
v
.
N
ame
,
structVar
.
TypeString
())
return
nil
,
fmt
.
Errorf
(
"%s (type %s) is not a struct"
,
v
n
ame
,
structVar
.
TypeString
())
}
}
}
}
...
...
service/test/variables_test.go
浏览文件 @
7c42fc51
...
@@ -1087,6 +1087,28 @@ func TestCallFunction(t *testing.T) {
...
@@ -1087,6 +1087,28 @@ func TestCallFunction(t *testing.T) {
{
`stringsJoin(stringslice, comma)`
,
[]
string
{
`:string:"one,two,three"`
},
nil
},
{
`stringsJoin(stringslice, comma)`
,
[]
string
{
`:string:"one,two,three"`
},
nil
},
{
`stringsJoin(s1, comma)`
,
nil
,
errors
.
New
(
"could not find symbol value for s1"
)},
{
`stringsJoin(s1, comma)`
,
nil
,
errors
.
New
(
"could not find symbol value for s1"
)},
{
`stringsJoin(intslice, comma)`
,
nil
,
errors
.
New
(
"can not convert value of type []int to []string"
)},
{
`stringsJoin(intslice, comma)`
,
nil
,
errors
.
New
(
"can not convert value of type []int to []string"
)},
// The following set of calls was constructed using https://docs.google.com/document/d/1bMwCey-gmqZVTpRax-ESeVuZGmjwbocYs1iHplK-cjo/pub as a reference
{
`a.VRcvr(1)`
,
[]
string
{
`:string:"1 + 3 = 4"`
},
nil
},
// direct call of a method with value receiver / on a value
{
`a.PRcvr(2)`
,
[]
string
{
`:string:"2 - 3 = -1"`
},
nil
},
// direct call of a method with pointer receiver / on a value
{
`pa.VRcvr(3)`
,
[]
string
{
`:string:"3 + 6 = 9"`
},
nil
},
// direct call of a method with value receiver / on a pointer
{
`pa.PRcvr(4)`
,
[]
string
{
`:string:"4 - 6 = -2"`
},
nil
},
// direct call of a method with pointer receiver / on a pointer
{
`vable_pa.VRcvr(6)`
,
[]
string
{
`:string:"6 + 6 = 12"`
},
nil
},
// indirect call of method on interface / containing value with value method
{
`pable_pa.PRcvr(7)`
,
[]
string
{
`:string:"7 - 6 = 1"`
},
nil
},
// indirect call of method on interface / containing pointer with value method
{
`vable_a.VRcvr(5)`
,
[]
string
{
`:string:"5 + 3 = 8"`
},
nil
},
// indirect call of method on interface / containing pointer with pointer method
{
`pa.nonexistent()`
,
nil
,
errors
.
New
(
"pa has no member nonexistent"
)},
{
`a.nonexistent()`
,
nil
,
errors
.
New
(
"a has no member nonexistent"
)},
{
`vable_pa.nonexistent()`
,
nil
,
errors
.
New
(
"vable_pa has no member nonexistent"
)},
{
`vable_a.nonexistent()`
,
nil
,
errors
.
New
(
"vable_a has no member nonexistent"
)},
{
`pable_pa.nonexistent()`
,
nil
,
errors
.
New
(
"pable_pa has no member nonexistent"
)},
//TODO(aarzilli): indirect call of func value / set to top-level func
//TODO(aarzilli): indirect call of func value / set to func literal
//TODO(aarzilli): indirect call of func value / set to value method
//TODO(aarzilli): indirect call of func value / set to pointer method
}
}
withTestProcess
(
"fncall"
,
t
,
func
(
p
proc
.
Process
,
fixture
protest
.
Fixture
)
{
withTestProcess
(
"fncall"
,
t
,
func
(
p
proc
.
Process
,
fixture
protest
.
Fixture
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录