Skip to content
Wireshark Wiki 中文翻译整理专题首页原始页面

开发技巧

打印到控制台

有时你只是想查看一些变量,看看代码中发生了什么,而不需要进行一次重量级的调试器会话。在这些情况下,printf 可能是你最好的朋友。要让它工作,你需要:

  • 打开控制台(仅 Windows 需要):

启动 Wireshark,并进入 Edit->Preferences...->Advanced。在 Search: 框中输入 "console",然后在搜索结果中选择 gui.console_open。将 Value 改为 'ALWAYS',然后点击 Ok 按钮。

  • Wireshark 日志大体采用 GLib Messages and Logging API 中 domain 和 level 的概念。你可以使用命令行选项 --log-level=<level> 或环境变量 WIRESHARK_LOG_LEVEL=<level> 过滤日志级别。你可以使用 --log-domains=<domain> 或 WIRESHARK_LOG_DOMAINS=<domain> 过滤域。域过滤器接受以逗号分隔的域列表。按详细程度递增,可用的日志级别为 "critical"、"warning"、"message"(默认)、"info"、"debug" 和 "noisy"。如果你知道自己在查找什么,并且可以将日志输出过滤到特定域,"noisy" 级别通常更有用。
$ tshark --log-level=noisy --log-domain=main,capture --log-file=/tmp/wsdebug -r some.pcap
  • 在你的代码中放置 ws_log 语句(ws_debug、ws_info、ws_message 等,参见 wsutil/wslog.h)或 g_print。还可以使用 proto_tree_add_debug_text(tree, format),它会在当前位置直接显示调试消息。详情请查看 proto.c。

如果你关注某个条件,可以将以下内容添加到代码中:

if (condition) { g_print("Kilroy was here\n");}

请注意,printf/g_print 不适用于 dumpcap(例如 capture_loop.c),因为 stdio 被用于与 Wireshark 的捕获引擎通信。请改用 g_log 或 g_printerr

在找到 bug 之后,不要忘记稍后移除这些语句。这些类似 printf 的语句不应在生产代码中保持启用,因为它们经常会打扰不关心这些信息的用户。

在特定数据包编号处设置断点

通常你知道自己的 dissector 中有一个 bug/问题,而且只能在某个特定数据包中找到。

假设你知道编号为 1234 的数据包有 bug,那么可以将以下内容添加到代码中:

if (pinfo-&gt;fd-&gt;num == 1234) { g_print("Here is my bug\n");}

然后只需在 g_print 调用处设置断点。

当然,你需要能够访问 pinfo,但在任何 dissector 中通常都应如此。

在找到 bug 之后,不要忘记稍后移除它 😃

某些调试器(例如 gdb 和 MSVC)也允许你设置条件断点;你可以在某个例程中的某个位置设置断点,并将断点条件设为 pinfo->fd->num == 1234。

使用 GDB 调试

摘自 http://www.gnu.org/software/libtool/manual/libtool.html#Debugging-executables

如果你想在安装应用程序之前,在 UNIX 上调试自己构建的 Wireshark,就必须通过 libtool 运行 GDB,如下所示:

user@host:~/src/wireshark$ libtool --mode=execute gdb wireshark

使用 DDD 调试

DDD 是 GNU 为 GDB 命令行调试器(以及其他调试器)提供的图形化前端。http://www.gnu.org/software/ddd/

为了帮助 DDD 在调试时定位源文件,可以先 "cd" 到这些源文件所在的目录,然后通过 libtool 启动 DDD(和 GDB 一样),或者在 DDD 菜单中查看 "Edit" -> "GDB Settings..." -> "Search path for source files",并在那里显式添加路径。

不使用优化进行调试

如果你正在调试,而优化造成了问题(例如,单步执行代码时显示的行号似乎与实际执行内容不一致),请将 CMAKE_BUILD_TYPE 设置为 Debug,以便在构建时禁用优化,步骤类似如下:

mkdir buildcd buildcmake -DCMAKE_BUILD_TYPE=Debug ..makegdb run/tshark

降低 libtool 的详细输出程度

反复输入 libtool --mode=execute 很快会让人厌烦。在大多数 shell 中,你可以创建一个快捷方式来减少输入量。

Bourne 风格的 shell:

function lx{ glibtool --mode=execute $*}

C 风格的 shell:

alias lx 'glibtool --mode=execute'

使用此快捷方式,上面的 GDB 示例可以缩短为:

user@host:~/src/wireshark$ lx gdb wireshark

使用 Valgrind 调试

Valgrind 会动态分析程序,并且非常擅长捕捉与内存相关的错误。不过,在使用默认块内存分配器时,它无法捕捉 Wireshark 内存管理框架(wmem,在 wsutil/wmem/ 中实现)中的 bug。幸运的是,你可以在运行时告诉 Wireshark 改用 wmem 的 "simple" 分配器,该分配器使用 malloc 和哈希表,对 Valgrind 友好:

export WIRESHARK_DEBUG_WMEM_OVERRIDE=simple

类似地,GLib 的 GSlice 内存分配器(某些未使用 wmem 的 Wireshark 代码会用到它)也可以通过另一个环境变量改为使用 malloc:

export G_SLICE=always-malloc

假设你已经定义了 lx 快捷方式(见上文),你可以像这样检查内存问题:

lx valgrind --tool=memcheck tshark -nVxr /path/to/capture.pcap &gt; /dev/null

使用 AddressSanitizer 调试

AddressSanitizer(ASAN)可以在运行时捕捉内存安全问题,包括 use-after-free、double-free、buffer overflow 和 memory leaks。它需要 GCC 或 Clang,并可在 Linux 和 macOS 上运行。不支持 Windows 上的 MSVC。

要开始使用,请用 cmake -DENABLE_ASAN=1 构建 Wireshark。

注意:ASAN 会使速度降低 2 倍(或更多),因此为 ASAN 构建单独准备一个构建目录会很有用。

使用 ASAN 调试时,多种环境变量会很有帮助。

wmem 使用的块分配器可能会阻止 ASAN 捕捉某些错误。要检测错误,可以像使用 Valgrind 时那样使用基于 malloc 的分配器,或者将 wmem 和 GSlice 的内存分配器设置为会通过 canaries 跟踪内存使用并检查已释放内存的分配器(ASAN 比 Valgrind 更擅长处理这些情况):

export WIRESHARK_DEBUG_WMEM_OVERRIDE=strictexport G_SLICE=debug-blocks

在调查内存泄漏时,以下选项可能很有用:

# This slows down a lot more but results in more precise backtraces,# especially when calling C++ standard library functions.export ASAN_OPTIONS=fast_unwind_on_malloc=0# This causes LeakSanitizer to print the addresses of leaked objects# for inspection in a debugger.export LSAN_OPTIONS=report_objects=1

如果你只关注内存安全检查,而不进行内存泄漏调试,只需使用以下方式禁用后者:

export ASAN_OPTIONS=detect_leaks=0

这些 ASAN 选项及其他选项记录在 https://github.com/google/sanitizers/wiki/AddressSanitizerFlags

在 Linux 上以非特权用户运行 dumpcap

dumpcap 需要权限才能捕获数据包。要从构建目录测试它,相对安全的选项是:

  • 添加文件系统 capabilities:sudo setcap cap_net_raw,cap_net_admin+eip run/dumpcap(缺点:如果构建目录位于以 nosuid 挂载的 tmpfs(/tmp)中,则无法工作;重新构建后更改会丢失)。

  • 使用 ambient capabilities,参见 [Wireshark-dev] Capturing packets on Linux during development。

在任何情况下都不应以(setuid)root 身份运行它,除非你不在意该环境(例如虚拟机)。

无论哪种情况,添加 capabilities 都会阻止 gdb/strace 附加。要解决此问题,请在启动 GDB 之前使用带有 cap_sys_ptrace 的 ambient capabilities。请注意,这将允许调试任何进程,包括 root 拥有的进程。

调试 GLib 警告

Wireshark 等应用程序对 GLib 的调用可能会导致警告。要调试这些警告,可以设置环境变量来影响 GLib 对这些警告的反应。结合调试器,你可以查看导致该警告的调用栈。参见 Running GLib Applications

使用 MSVC++ 调试

摘自 http://www.ethereal.com/lists/ethereal-dev/200503/msg00778.html[Ethereal-dev] How to trace Ethereal on WinXP using MSVC++?

如果你只是想调试 Wireshark,那么 Win32 二进制文件默认应已包含调试符号。你可以查看 config.nmake 文件,并确保调试开关已启用……

# Linker flags# /DEBUG generate debug infoLOCAL_LDFLAGS=/DEBUG

一旦你有了带调试符号的有效二进制文件,就可以通过在 MSVC 中打开该二进制文件来轻松调试 Wireshark。

因此,在 Visual Studio 中只需点击 File ! Open ! Project/Solution 菜单,然后浏览到 Wireshark .exe 的安装位置。通常为:c:\program files\wireshark\wireshark-gtk2。打开之后,你应该会在 Visual Studio 最左侧窗口中看到 wireshark.exe。要执行 Wireshark,只需按 F5 键。如果你想在 Wireshark 中的某个位置中断,只需打开源文件并设置断点。Wireshark.exe 的执行会在指定位置暂停。然后你可以单步执行源代码,以定位/调试你的问题。

注意:对于 Visual Studio 6,请使用 File ! Open,将文件扩展名类型改为所有文件,然后按上述步骤继续。

已过时 使用 MSVC6 的“source browser”功能

有时,能够使用 MSVC6 的 "Tools/Source Browser" 功能查找 Wireshark 函数和变量的定义与引用会非常有用。

要构建并使用所需的 "Browse Information File"(.bsc)文件:

  • 修改 config.nmake,在编译器标志中添加 /Fr 开关(此外还要进行上文所述将链接器标志改为 /DEBUG 的更改)。
# Compiler flags# /W3 warning level 3 (0 less - 4 most, 1 default)# /Zi create .pdb file for debugging# /Fr create .sbr files used by BSCMAKE to create a "Browse Information File"LOCAL_CFLAGS=/Zi /W3 /Fr
  • 像往常一样使用 nmake 构建 wireshark
  • 按如下方式创建 .bsc 文件:
 user@host:~/src/wireshark$ nmake -f Makefile.nmake wireshark.bsc
  • 按上文所述在 Visual Studio 中打开 Wireshark 二进制文件;从工具栏选择 Tools/Source_Browser;(如果出现错误消息,可能需要在 Project/Settings 下指定 .bsc 文件的位置)。输入有效标识符并选择 OK,以获取该标识符的定义和引用所在源位置(文件名和行号)的列表。

通过使用与 source browser 关联的键盘快捷键,可以相当轻松地在源文件之间导航。(参见 MSVC Help 中的 "Browse Information Files")。

例如:如果光标位于某个标识符的开头,按 F12 会立即跳转到该标识符定义所在的源文件位置。按 <Ctrl Num *> 则会将光标移回上一个位置。

于 2020-08-11 23:13:12 UTC 从 https://wiki.wireshark.org/Development/Tips 导入

相关 Wireshark Wiki 页面

网络分析技术档案