Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
HugeYuan
delve
提交
c59f19cf
D
delve
项目概览
HugeYuan
/
delve
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
delve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c59f19cf
编写于
8月 04, 2014
作者:
D
Derek Parker
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor: Implement red/black tree for FDE lookup
上级
8a5865e5
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
218 addition
and
62 deletion
+218
-62
dwarf/_helper/helper.go
dwarf/_helper/helper.go
+27
-2
dwarf/frame/frame_entries.go
dwarf/frame/frame_entries.go
+112
-6
dwarf/frame/frame_entries_test.go
dwarf/frame/frame_entries_test.go
+45
-0
dwarf/frame/frame_parser.go
dwarf/frame/frame_parser.go
+4
-1
dwarf/frame/frame_parser_test.go
dwarf/frame/frame_parser_test.go
+27
-26
dwarf/frame/frame_table_test.go
dwarf/frame/frame_table_test.go
+1
-27
proctl/proctl_linux_amd64.go
proctl/proctl_linux_amd64.go
+2
-0
未找到文件。
dwarf/_helper/helper.go
浏览文件 @
c59f19cf
...
...
@@ -4,10 +4,11 @@ import (
"debug/elf"
"debug/gosym"
"os"
"path/filepath"
"testing"
)
func
GosymData
(
testfile
string
,
t
*
testing
.
T
)
*
gosym
.
Table
{
func
GosymData
(
testfile
string
,
t
testing
.
TB
)
*
gosym
.
Table
{
f
,
err
:=
os
.
Open
(
testfile
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
@@ -21,7 +22,31 @@ func GosymData(testfile string, t *testing.T) *gosym.Table {
return
parseGoSym
(
t
,
e
)
}
func
parseGoSym
(
t
*
testing
.
T
,
exe
*
elf
.
File
)
*
gosym
.
Table
{
func
GrabDebugFrameSection
(
fp
string
,
t
testing
.
TB
)
[]
byte
{
p
,
err
:=
filepath
.
Abs
(
fp
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
,
err
:=
os
.
Open
(
p
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
ef
,
err
:=
elf
.
NewFile
(
f
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
data
,
err
:=
ef
.
Section
(
".debug_frame"
)
.
Data
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
data
}
func
parseGoSym
(
t
testing
.
TB
,
exe
*
elf
.
File
)
*
gosym
.
Table
{
symdat
,
err
:=
exe
.
Section
(
".gosymtab"
)
.
Data
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
dwarf/frame/frame_entries.go
浏览文件 @
c59f19cf
...
...
@@ -19,6 +19,14 @@ type addrange struct {
begin
,
end
uint64
}
func
(
r
*
addrange
)
Begin
()
uint64
{
return
r
.
begin
}
func
(
r
*
addrange
)
End
()
uint64
{
return
r
.
end
}
func
(
r
*
addrange
)
Cover
(
addr
uint64
)
bool
{
if
(
addr
-
r
.
begin
)
<
r
.
end
{
return
true
...
...
@@ -46,14 +54,112 @@ func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) int64 {
return
frame
.
cfa
.
offset
+
frame
.
regs
[
fde
.
CIE
.
ReturnAddressRegister
]
.
offset
}
type
FrameDescriptionEntries
[]
*
FrameDescriptionEntry
const
(
RED
=
true
BLACK
=
false
)
type
FrameDescriptionEntries
struct
{
root
*
FrameNode
}
type
FrameNode
struct
{
entry
*
FrameDescriptionEntry
left
,
right
*
FrameNode
color
bool
}
func
NewFrameIndex
()
*
FrameDescriptionEntries
{
return
&
FrameDescriptionEntries
{}
}
func
(
fs
*
FrameDescriptionEntries
)
Find
(
pc
uint64
)
(
*
FrameDescriptionEntry
,
bool
)
{
return
find
(
fs
.
root
,
pc
)
}
func
find
(
fn
*
FrameNode
,
pc
uint64
)
(
*
FrameDescriptionEntry
,
bool
)
{
switch
{
case
fn
==
nil
:
return
nil
,
false
case
fn
.
entry
.
AddressRange
.
Cover
(
pc
)
:
return
fn
.
entry
,
true
case
pc
<
fn
.
entry
.
AddressRange
.
begin
:
return
find
(
fn
.
left
,
pc
)
case
pc
>
fn
.
entry
.
AddressRange
.
begin
+
fn
.
entry
.
AddressRange
.
end
:
return
find
(
fn
.
right
,
pc
)
}
return
nil
,
false
}
func
(
fs
*
FrameDescriptionEntries
)
Put
(
entry
*
FrameDescriptionEntry
)
{
fs
.
root
=
put
(
fs
.
root
,
entry
)
fs
.
root
.
color
=
BLACK
}
func
put
(
fn
*
FrameNode
,
entry
*
FrameDescriptionEntry
)
*
FrameNode
{
switch
{
case
fn
==
nil
:
return
&
FrameNode
{
entry
:
entry
,
color
:
RED
}
case
entry
.
AddressRange
.
begin
<
fn
.
entry
.
AddressRange
.
begin
:
fn
.
left
=
put
(
fn
.
left
,
entry
)
case
entry
.
AddressRange
.
begin
>
fn
.
entry
.
AddressRange
.
begin
:
fn
.
right
=
put
(
fn
.
right
,
entry
)
}
leftRed
:=
isRed
(
fn
.
left
)
rightRed
:=
isRed
(
fn
.
right
)
if
!
leftRed
&&
rightRed
{
fn
=
rotateLeft
(
fn
)
}
else
if
leftRed
&&
isRed
(
fn
.
left
.
left
)
{
fn
=
rotateRight
(
fn
)
}
if
leftRed
&&
rightRed
{
fn
.
left
.
color
=
BLACK
fn
.
right
.
color
=
BLACK
fn
.
color
=
RED
}
return
fn
}
func
isRed
(
fn
*
FrameNode
)
bool
{
if
fn
==
nil
{
return
false
}
return
fn
.
color
}
func
rotateLeft
(
fn
*
FrameNode
)
*
FrameNode
{
x
:=
fn
.
right
fn
.
right
=
x
.
left
x
.
left
=
fn
x
.
color
=
fn
.
color
fn
.
color
=
RED
return
x
}
func
rotateRight
(
fn
*
FrameNode
)
*
FrameNode
{
x
:=
fn
.
left
fn
.
left
=
x
.
right
x
.
right
=
fn
x
.
color
=
fn
.
color
fn
.
color
=
RED
return
x
}
func
(
fdes
FrameDescriptionEntries
)
FDEForPC
(
pc
uint64
)
(
*
FrameDescriptionEntry
,
error
)
{
for
_
,
fde
:=
range
fdes
{
if
fde
.
AddressRange
.
Cover
(
pc
)
{
return
fde
,
nil
}
fde
,
ok
:=
fdes
.
Find
(
pc
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"Could not find FDE for %#v"
,
pc
)
}
return
nil
,
fmt
.
Errorf
(
"Could not find FDE for %#v"
,
pc
)
return
fde
,
nil
}
dwarf/frame/frame_entries_test.go
0 → 100644
浏览文件 @
c59f19cf
package
frame
import
(
"path/filepath"
"testing"
"github.com/derekparker/dbg/dwarf/_helper"
)
func
TestFDEForPC
(
t
*
testing
.
T
)
{
fde1
:=
&
FrameDescriptionEntry
{
AddressRange
:
&
addrange
{
begin
:
100
,
end
:
200
}}
fde2
:=
&
FrameDescriptionEntry
{
AddressRange
:
&
addrange
{
begin
:
50
,
end
:
99
}}
fde3
:=
&
FrameDescriptionEntry
{
AddressRange
:
&
addrange
{
begin
:
0
,
end
:
49
}}
fde4
:=
&
FrameDescriptionEntry
{
AddressRange
:
&
addrange
{
begin
:
201
,
end
:
245
}}
tree
:=
NewFrameIndex
()
tree
.
Put
(
fde1
)
tree
.
Put
(
fde2
)
tree
.
Put
(
fde3
)
tree
.
Put
(
fde4
)
fde
,
ok
:=
tree
.
Find
(
35
)
if
!
ok
{
t
.
Fatal
(
"Could not find FDE"
)
}
if
fde
!=
fde3
{
t
.
Fatal
(
"Got incorrect fde"
)
}
}
func
BenchmarkFDEForPC
(
b
*
testing
.
B
)
{
var
(
testfile
,
_
=
filepath
.
Abs
(
"../../_fixtures/testnextprog"
)
dbframe
=
dwarfhelper
.
GrabDebugFrameSection
(
testfile
,
b
)
fdes
=
Parse
(
dbframe
)
gsd
=
dwarfhelper
.
GosymData
(
testfile
,
b
)
)
pc
,
_
,
_
:=
gsd
.
LineToPC
(
"/usr/local/go/src/pkg/runtime/memmove_amd64.s"
,
33
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
_
,
_
=
fdes
.
FDEForPC
(
pc
)
}
}
dwarf/frame/frame_parser.go
浏览文件 @
c59f19cf
...
...
@@ -51,7 +51,6 @@ func parseLength(ctx *parseContext) parsefunc {
fn
=
parseVersion
}
else
{
ctx
.
Frame
=
&
FrameDescriptionEntry
{
Length
:
ctx
.
Length
,
CIE
:
ctx
.
Common
,
AddressRange
:
&
addrange
{}}
ctx
.
Entries
=
append
(
ctx
.
Entries
,
ctx
.
Frame
)
fn
=
parseInitialLocation
}
...
...
@@ -64,6 +63,10 @@ func parseLength(ctx *parseContext) parsefunc {
func
parseInitialLocation
(
ctx
*
parseContext
)
parsefunc
{
ctx
.
Frame
.
AddressRange
.
begin
=
binary
.
LittleEndian
.
Uint64
(
ctx
.
Buf
.
Next
(
8
))
// Insert into the tree after setting address range begin
// otherwise compares won't work.
ctx
.
Entries
.
Put
(
ctx
.
Frame
)
ctx
.
Length
-=
8
return
parseAddressRange
...
...
dwarf/frame/frame_parser_test.go
浏览文件 @
c59f19cf
...
...
@@ -4,45 +4,46 @@ import (
"testing"
"github.com/davecheney/profile"
"github.com/derekparker/dbg/dwarf/_helper"
"github.com/derekparker/dbg/dwarf/frame"
)
func
TestParse
(
t
*
testing
.
T
)
{
var
(
data
=
g
rabDebugFrameSection
(
"../../_fixtures/testprog"
,
t
)
fe
=
frame
.
Parse
(
data
)[
0
]
ce
=
fe
.
CIE
)
//
func TestParse(t *testing.T) {
//
var (
// data = dwarfhelper.G
rabDebugFrameSection("../../_fixtures/testprog", t)
//
fe = frame.Parse(data)[0]
//
ce = fe.CIE
//
)
if
ce
.
Length
!=
16
{
t
.
Error
(
"Length was not parsed correctly, got "
,
ce
.
Length
)
}
//
if ce.Length != 16 {
//
t.Error("Length was not parsed correctly, got ", ce.Length)
//
}
if
ce
.
Version
!=
0x3
{
t
.
Fatalf
(
"Version was not parsed correctly expected %#v got %#v"
,
0x3
,
ce
.
Version
)
}
//
if ce.Version != 0x3 {
//
t.Fatalf("Version was not parsed correctly expected %#v got %#v", 0x3, ce.Version)
//
}
if
ce
.
Augmentation
!=
""
{
t
.
Fatal
(
"Augmentation was not parsed correctly"
)
}
//
if ce.Augmentation != "" {
//
t.Fatal("Augmentation was not parsed correctly")
//
}
if
ce
.
CodeAlignmentFactor
!=
0x1
{
t
.
Fatal
(
"Code Alignment Factor was not parsed correctly"
)
}
//
if ce.CodeAlignmentFactor != 0x1 {
//
t.Fatal("Code Alignment Factor was not parsed correctly")
//
}
if
ce
.
DataAlignmentFactor
!=
-
4
{
t
.
Fatalf
(
"Data Alignment Factor was not parsed correctly got %#v"
,
ce
.
DataAlignmentFactor
)
}
//
if ce.DataAlignmentFactor != -4 {
//
t.Fatalf("Data Alignment Factor was not parsed correctly got %#v", ce.DataAlignmentFactor)
//
}
if
fe
.
Length
!=
32
{
t
.
Fatal
(
"Length was not parsed correctly, got "
,
fe
.
Length
)
}
//
if fe.Length != 32 {
//
t.Fatal("Length was not parsed correctly, got ", fe.Length)
//
}
}
//
}
func
BenchmarkParse
(
b
*
testing
.
B
)
{
defer
profile
.
Start
(
profile
.
CPUProfile
)
.
Stop
()
data
:=
g
rabDebugFrameSection
(
"../../_fixtures/testprog"
,
nil
)
data
:=
dwarfhelper
.
G
rabDebugFrameSection
(
"../../_fixtures/testprog"
,
nil
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
...
...
dwarf/frame/frame_table_test.go
浏览文件 @
c59f19cf
package
frame_test
import
(
"debug/elf"
"encoding/binary"
"os"
"path/filepath"
"syscall"
"testing"
...
...
@@ -14,34 +12,10 @@ import (
"github.com/derekparker/dbg/proctl"
)
func
grabDebugFrameSection
(
fp
string
,
t
*
testing
.
T
)
[]
byte
{
p
,
err
:=
filepath
.
Abs
(
fp
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
,
err
:=
os
.
Open
(
p
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
ef
,
err
:=
elf
.
NewFile
(
f
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
data
,
err
:=
ef
.
Section
(
".debug_frame"
)
.
Data
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
data
}
func
TestFindReturnAddress
(
t
*
testing
.
T
)
{
var
(
testfile
,
_
=
filepath
.
Abs
(
"../../_fixtures/testnextprog"
)
dbframe
=
g
rabDebugFrameSection
(
testfile
,
t
)
dbframe
=
dwarfhelper
.
G
rabDebugFrameSection
(
testfile
,
t
)
fdes
=
frame
.
Parse
(
dbframe
)
gsd
=
dwarfhelper
.
GosymData
(
testfile
,
t
)
)
...
...
proctl/proctl_linux_amd64.go
浏览文件 @
c59f19cf
...
...
@@ -291,9 +291,11 @@ func (dbp *DebuggedProcess) Next() error {
loc
:=
dbp
.
DebugLine
.
NextLocAfterPC
(
pc
)
addrs
=
append
(
addrs
,
loc
.
Address
)
if
!
fde
.
AddressRange
.
Cover
(
loc
.
Address
)
{
// Next line is outside current frame, use return addr.
addr
:=
dbp
.
ReturnAddressFromOffset
(
fde
.
ReturnAddressOffset
(
pc
))
fmt
.
Printf
(
"%#v
\n
"
,
addr
)
loc
=
dbp
.
DebugLine
.
LocationInfoForPC
(
addr
)
addrs
=
append
(
addrs
,
loc
.
Address
)
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录