Linux on Power 上的调试工具和技术(6)
- UID
- 1066743
|
Linux on Power 上的调试工具和技术(6)
Java 调试器Java? 调试器 JDB 是一个用来调试 Java 类的命令行调试器。它提供了对本地或远程 Java 虚拟机(JVM)的检查和调试功能。其二进制文件是 jdb。
JDB 是与 java 编译器 javac 一起打包的,在 java2 rpm 包中。
有很多方法都可以开始一个 jdb 会话。最常见的方法是让 jdb 启动一个新的 Java 虚拟机,其中运行要调试的应用程序的主类。这可以通过在命令行中使用命令 jdb 替换 java 来实现。例如,如果您的应用程序的主类是 appClass,那么就使用下面的命令在 JDB 中调试这个程序:
另外一种使用 jdb 的方法是将其附加到一个早已在运行的 JVM 上。要使用 jdb 进行调试的 VM 必须是使用下面的选项启动的:
1
2
| # java -Xdebug -Xnoagent - <br>Xrunjdwp:transport=dt_socket,server=y,suspend=n,
<br>address=8888 -Djava.compiler=NONEappClass
|
然后您就可以使用下面的命令将 jdb 附加到这个 VM 上:
jdb 最常用的命令与 gdb 的类似。详细信息请参考 表 1。
图形化调试器使用图形模式的调试器相对于命令行调试器的一个优点是,在调试器中单步执行程序的同时可以看到对应的每行源代码。
GNU DDD(Data Display Debugger)就是一个调试器(例如 GDB 和 JDB)的图形化前端。除了常见的前端特性(例如查看源代码)之外,DDD 还通过将要显示的数据结构以交互式的图形化方式进行显示而闻名。
对于 SLES 9 来说,用于 PowerPC 的 DDD 二进制文件是在 SUSE Linux SDK CD 中单独提供的,也可以从 Novell 公司的网站上进行下载(参阅 参考资料)。RedHat 在 RHEL AS 4 CD 中提供了 DDD 的 rpm 包。
图 2 是在使用 DDD 来调试 清单 19 (gdbtest3.cpp)中的例子时的截图。
图 2. DDD 截屏默认情况下,DDD 使用 gdb 作为后端调试器;要切换到 jdb,请使用 ddd -jdb 来启动 DDD。
有关 DDD 的更多信息,请参考 GNU 项目 Web 站点上的 DDD 部分(参阅 参考资料)。
stracestrace 命令是可以在 Linux on POWER 架构上使用的一个功能非常强大的工具。它可以显示用户空间的应用程序所执行的全部系统调用。strace 可以以符号表的形式显示这些调用的参数和返回值。strace 从内核接收信息,并不需要采用任何特殊的方式来构建内核。要跟踪的应用程序也不需要为 strace 重新进行编译,当我们无法访问应用程序的源代码时,这是非常方便的一种方法。
下面的例子使用 strace 来跟踪一个普通用户执行 cat /etc/shadow 的过程,然后将跟踪到的结果打印到 strace.cat.out 中。这个程序依然正常运行,但是在使用 strace 运行时速度稍微有些慢;最后,我们得到一个跟踪文件。
1
2
3
| $ strace -o strace.cat.out cat /etc/shadow
cat: /etc/shadow: Permission denied
$
|
跟踪文件通常都很大。即使对这个简单的例子来说,strace.cat.out 也有 111 行长。这个文件的最后包含下面的行:
清单 26. strace.cat.out 文件中的部分行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
| 88 open("/usr/lib/locale/en_US.UTF-8/LC_NUMERIC",
O_RDONLY) = -1 ENOENT (No such file or directory)
89 open("/usr/lib/locale/en_US.utf8/LC_NUMERIC", O_RDONLY) = 3
90 fstat64(3, {st_mode=S_IFREG|0644, st_size=54, ...}) = 0
91 mmap(NULL, 54, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4010f000
92 close(3) = 0
93 open("/usr/lib/locale/en_US.UTF-8/LC_CTYPE",
O_RDONLY) = -1 ENOENT (No such file or directory)
94 open("/usr/lib/locale/en_US.utf8/LC_CTYPE", O_RDONLY) = 3
95 fstat64(3, {st_mode=S_IFREG|0644, st_size=208464, ...}) = 0
96 mmap(NULL, 208464, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40110000
97 close(3) = 0
98 fstat64(1, {st_mode=S_IFCHR|0620,
st_rdev=makedev(136, 4), ...}) = 0
99 open("/etc/shadow", O_RDONLY|O_LARGEFILE) = -1 EACCES
(Permission denied)
100 write(2, "cat: ", 5) = 5
101 write(2, "/etc/shadow", 11) = 11
102 open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo",
O_RDONLY) = -1 ENOENT (No such file or directory)
103 open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo",
O_RDONLY) = -1 ENOENT (No such file or directory)
104 open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo",
O_RDONLY) = -1 ENOENT (No such file or directory)
105 open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo",
O_RDONLY) = -1 ENOENT (No such file or directory)
106 open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo",
O_RDONLY) = -1 ENOENT (No such file or directory)
107 open("/usr/share/locale/en/LC_MESSAGES/libc.mo",
O_RDONLY) = -1 ENOENT (No such file or directory)
108 write(2, ": Permission denied", 19) = 19
109 write(2, "\n", 1) = 1
110 close(1) = 0
111 exit_group(1)
|
注意在第 99 行处,命令会失效,因为系统调用 open("/etc/shadow", O_RDONLY|O_LARGEFILE) 失效了,返回了一个 EACCESS 错误代码,这说明权限不符合。
在有些情况中,应用程序可能会挂起,并且不能响应诸如 ctrl+c(SIGINT)之类的信号。这说明应用程序正在调用的系统调用在其内核模式下挂起了,一直不会返回用户模式。strace 可以非常有用地用来判断是哪一个系统调用,以及传给这个系统调用的参数是什么。可能性最大的情况是参数的位置不对而导致了问题。
与 gdb64 是用于 64 位应用程序的 gdb 类似,strace64 也用来跟踪 64 位应用程序所请求的系统调用。
结束语在 Linux on POWER 平台上可以使用很多工具来帮助调试应用程序。本文中介绍的工具可以帮助您解决很多编码的问题。诸如 Valgrind 之类的工具可以显示内存泄漏的位置、非法读/写以及类似的内容,这可以解决内存管理的问题。
使用 gdb 和 jdb 有助于解决那些导致应用程序异常结束的问题,以及导致非预期或不想要的结果的 bug。DDD 工具可以帮助简化调试任务,方法是通过将代码的执行与源代码行联系在一起,并在数据显示窗口中可视化地显示数据结构。另外,strace 是一个功能非常强大的工具,它可以用来跟踪应用程序的所有系统调用。因此,下一次当您要在 Linux 上修复 bug 时,可以试用一下这些工具。 |
|
|
|
|
|