Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
avocado
提交
49598f5b
A
avocado
项目概览
openeuler
/
avocado
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
avocado
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
49598f5b
编写于
2月 27, 2015
作者:
C
Cleber Rosa
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'ldoktor/documentation2'
上级
f5faa761
52e13125
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
285 addition
and
3 deletion
+285
-3
docs/source/DebuggingWithGDB.rst
docs/source/DebuggingWithGDB.rst
+60
-3
examples/tests/doublefree_nasty.py
examples/tests/doublefree_nasty.py
+41
-0
examples/tests/doublefree_nasty.py.data/doublefree.c
examples/tests/doublefree_nasty.py.data/doublefree.c
+20
-0
examples/tests/doublefree_nasty.py.data/gdb_pre
examples/tests/doublefree_nasty.py.data/gdb_pre
+1
-0
examples/tests/doublefree_nasty.py.data/iterations.yaml
examples/tests/doublefree_nasty.py.data/iterations.yaml
+101
-0
examples/tests/modify_variable.py
examples/tests/modify_variable.py
+54
-0
examples/tests/modify_variable.py.data/print_variable.c
examples/tests/modify_variable.py.data/print_variable.c
+8
-0
未找到文件。
docs/source/DebuggingWithGDB.rst
浏览文件 @
49598f5b
...
...
@@ -16,13 +16,70 @@ remote protocol for interaction with a remote target.
Please refer to :mod:`avocado.gdb` for more information.
Example
~~~~~~~
Take a look at ``examples/tests/modify_variable.py`` test::
def action(self):
"""
Execute 'print_variable'.
"""
path = os.path.join(self.srcdir, 'print_variable')
app = gdb.GDB()
app.set_file(path)
app.set_break(6)
app.run()
self.log.info("\n".join(app.read_until_break()))
app.cmd("set variable a = 0xff")
app.cmd("c")
out = "\n".join(app.read_until_break())
self.log.info(out)
app.exit()
self.assertIn("MY VARIABLE 'A' IS: ff", out)
You can see that instead of running the binary using ``process.run`` we invoke
``gdb.GDB``. This allows us to automate the interaction with the GDB in means
of setting breakpoints, executing commands and querying for output.
When you check the output (``--show-job-log``) you can see that despite
declaring the variable as 0, ff is injected and printed instead.
Transparent Debugging Usage
---------------------------
This feature is implemented as a plugin, that adds the `--gdb-run-bin` option
to the avocado `run` command. For a detailed explanation please consult the
avocado man page.
This feature is implemented as a plugin, that adds the ``--gdb-run-bin``
option to the avocado ``run`` command.
Example
~~~~~~~
The simplest way is to just run
``avocado run --gdb-run-bin=doublefree examples/tests/doublefree.py``, which
wraps each executed binary with name ``doublefree`` inside GDB server and
stops at the binary entry point.
Optionally you can specify single breakpoint using
``--gdb-run-bin=doublefree:$breakpoint`` (eg: ``doublefree:1``) or just
``doublefree:`` to stop only when an interruption happens (eg: SIGABRT).
It's worth mentioning that when breakpoint is not reached, the test finishes
without any interruption. This is helpful when you identify regions where you
should never get in your code, or places which interests you and you can run
your code in production and gdb variants. If after a long time you get to this
place, the test notifies you and you can investigate the problem. This is
demonstrated in ``examples/tests/doublefree_nasty.py`` test. To unveil the
power of Avocadu, run this test using
``avocado run --gdb-run-bin=doublefree: examples/tests/doublefree_nasty.py --gdb-prerun-commands examples/tests/doublefree_nasty.py.data/gdb_pre --multiplex examples/tests/doublefree_nasty.py.data/iterations.yaml``,
which executes 100 iterations of this test while setting all breakpoints from
the ``examples/tests/doublefree_nasty.py.data/gdb_pre`` file (you can specify
whatever GDB supports, not only breakpoints).
As you can see this test usually passes, but once in a while it gets into
the problematic area. Imagine this is very hard to spot (dependent on HW
registers, ...) and this is one way to combine regular testing and the
possibility of debugging hard-to-get parts of your code.
Caveats
~~~~~~~
...
...
examples/tests/doublefree_nasty.py
0 → 100755
浏览文件 @
49598f5b
#!/usr/bin/python
import
os
import
shutil
from
avocado
import
job
from
avocado
import
test
from
avocado.utils
import
build
from
avocado.utils
import
process
class
DoubleFreeTest
(
test
.
Test
):
"""
10% chance to execute double free exception.
"""
default_params
=
{
'source'
:
'doublefree.c'
}
__binary
=
None
# filename of the compiled program
def
setup
(
self
):
"""
Build 'doublefree'.
"""
c_file
=
self
.
get_data_path
(
self
.
params
.
source
)
shutil
.
copy
(
c_file
,
self
.
srcdir
)
self
.
__binary
=
self
.
params
[
'source'
].
rsplit
(
'.'
,
1
)[
0
]
build
.
make
(
self
.
srcdir
,
env
=
{
'CFLAGS'
:
'-g -O0'
},
extra_args
=
self
.
__binary
)
def
action
(
self
):
"""
Execute 'doublefree'.
"""
cmd
=
os
.
path
.
join
(
self
.
srcdir
,
self
.
__binary
)
cmd_result
=
process
.
run
(
cmd
)
self
.
log
.
info
(
cmd_result
)
if
__name__
==
"__main__"
:
job
.
main
()
examples/tests/doublefree_nasty.py.data/doublefree.c
0 → 100644
浏览文件 @
49598f5b
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void
handle_exception
()
{
void
*
p
=
malloc
(
1024
);
free
(
p
);
free
(
p
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
num
;
srand
(
time
(
NULL
));
num
=
rand
();
if
(
num
<
(
RAND_MAX
/
10
))
{
handle_exception
();
}
return
0
;
}
examples/tests/doublefree_nasty.py.data/gdb_pre
0 → 100644
浏览文件 @
49598f5b
break handle_exception
examples/tests/doublefree_nasty.py.data/iterations.yaml
0 → 100644
浏览文件 @
49598f5b
iterations
:
1
:
2
:
3
:
4
:
5
:
6
:
7
:
8
:
9
:
10
:
11
:
12
:
13
:
14
:
15
:
16
:
17
:
18
:
19
:
20
:
21
:
22
:
23
:
24
:
25
:
26
:
27
:
28
:
29
:
30
:
31
:
32
:
33
:
34
:
35
:
36
:
37
:
38
:
39
:
40
:
41
:
42
:
43
:
44
:
45
:
46
:
47
:
48
:
49
:
50
:
51
:
52
:
53
:
54
:
55
:
56
:
57
:
58
:
59
:
60
:
61
:
62
:
63
:
64
:
65
:
66
:
67
:
68
:
69
:
70
:
71
:
72
:
73
:
74
:
75
:
76
:
77
:
78
:
79
:
80
:
81
:
82
:
83
:
84
:
85
:
86
:
87
:
88
:
89
:
90
:
91
:
92
:
93
:
94
:
95
:
96
:
97
:
98
:
99
:
100
:
examples/tests/modify_variable.py
0 → 100755
浏览文件 @
49598f5b
#!/usr/bin/python
import
os
import
shutil
from
avocado
import
gdb
from
avocado
import
job
from
avocado
import
test
from
avocado.utils
import
build
class
PrintVariableTest
(
test
.
Test
):
"""
This demonstrates the GDB API
1) it executes C program which prints MY VARIABLE 'A' IS: 0
2) using GDB it modifies the variable to ff
3) checks the output
"""
default_params
=
{
'source'
:
'print_variable.c'
}
__binary
=
None
# filename of the compiled program
def
setup
(
self
):
"""
Build 'print_variable'.
"""
c_file
=
self
.
get_data_path
(
self
.
params
.
source
)
shutil
.
copy
(
c_file
,
self
.
srcdir
)
self
.
__binary
=
self
.
params
[
'source'
].
rsplit
(
'.'
,
1
)[
0
]
build
.
make
(
self
.
srcdir
,
env
=
{
'CFLAGS'
:
'-g -O0'
},
extra_args
=
self
.
__binary
)
def
action
(
self
):
"""
Execute 'print_variable'.
"""
path
=
os
.
path
.
join
(
self
.
srcdir
,
self
.
__binary
)
app
=
gdb
.
GDB
()
app
.
set_file
(
path
)
app
.
set_break
(
6
)
app
.
run
()
self
.
log
.
info
(
"
\n
"
.
join
(
app
.
read_until_break
()))
app
.
cmd
(
"set variable a = 0xff"
)
app
.
cmd
(
"c"
)
out
=
"
\n
"
.
join
(
app
.
read_until_break
())
self
.
log
.
info
(
out
)
app
.
exit
()
self
.
assertIn
(
"MY VARIABLE 'A' IS: ff"
,
out
)
if
__name__
==
"__main__"
:
job
.
main
()
examples/tests/modify_variable.py.data/print_variable.c
0 → 100644
浏览文件 @
49598f5b
#include <stdio.h>
int
main
(
int
argc
,
char
*
argv
[])
{
int
a
=
0
;
printf
(
"MY VARIABLE 'A' IS: %x
\n
"
,
a
);
return
0
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录