如何使用 VSCode 调试 Linux 核心转储?

Posted

技术标签:

【中文标题】如何使用 VSCode 调试 Linux 核心转储?【英文标题】:How do you debug a Linux core dump using VSCode? 【发布时间】:2019-04-17 21:29:06 【问题描述】:

我特意从使用 VSCode 编写的 C++ 应用程序生成核心转储。我无法弄清楚如何调试核心转储。有没有人愿意分享这方面的经验?

***** 更新 ***** 我相信我现在可以正常工作了。我为核心文件创建了第二个调试配置。我需要添加指向生成的转储文件的“coreDumpPath”选项。我还需要删除 preLaunchTask 选项,它总是会构建一个新的可执行文件。


【问题讨论】:

【参考方案1】:

来自VScode docs

内存转储调试

VS Code 的 C/C++ 扩展还具有调试内存转储的能力。要调试内存转储,请打开您的 launch.json 文件并将coreDumpPath(用于 GDB 或 LLDB)或dumpPath(用于 Visual Studio Windows 调试器)属性添加到 C++ 启动配置,将其值设置为字符串包含内存转储的路径。这甚至适用于在 x64 机器上调试的 x86 程序。

附: 提问者已经用解决方案更新了问题。但是添加这个答案是为了帮助那些直接跳到答案部分的人;)


更新: 示例 launch.json 用于 C/C++ 扩展,没有硬编码核心文件名


    "version": "0.2.0",
    "configurations": [
        
            "type": "cppdbg",
            "request": "launch",
            "name": "Open a core dump(c/c++)",
            "program": "<Path to the program here>",
            "coreDumpPath": "$input:coreFileName",
            "cwd": "$workspaceFolder",
            "MIMode": "lldb" // or gdb, if you are using gdb
        
    ],
    "inputs": [
      
        "id": "coreFileName",
        "type": "promptString",
        "description": "Enter core file path"
      
    ]

示例 launch.json 用于 CodeLLDB 扩展,没有硬编码核心文件名


    "version": "0.2.0",
    "configurations": [
        
            "type": "lldb",
            "request": "custom",
            "name": "Open a core dump",
            "initCommands": [
                "target create -c $input:coreFileName"
            ]
        
    ],
    "inputs": [
      
        "id": "coreFileName",
        "type": "promptString",
        "description": "Enter core file path"
      
    ]    

【讨论】:

我的vscode 不接受initCommands;相反,它允许我直接给coreDumpPath 我的错... 示例 launch.json 将与 CodeLLDB 扩展一起使用,我现在也添加了 C/C++ 扩展示例。【参考方案2】:

举一个@insaf回答的具体例子。这可以用作launch.json 的模板(单击调试侧栏顶部的设置按钮进行编辑):


    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "<PATH-TO-BINARY>",
            "args": [],
            "stopAtEntry": false,
            "cwd": "$workspaceFolder",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                
            ],
            "coreDumpPath": "<PATH-TO-CORE-DUMP>"
        
    ]

相应地编辑二进制文件和核心转储的路径。

然后按下绿色播放按钮(开始调试)——它并没有真正启动任何东西,只是加载核心转储。

【讨论】:

【参考方案3】:

我写了一个little helper script,它以机器可读的方式复制了coredumpctl 的功能。

在 systemd 日志中搜索记录的核心转储 使用fzf 允许用户以交互方式选择其中之一 将选定的 coredump 解压到 /tmp/coredump 将关联的可执行文件链接到 /tmp/coredump_program

然后我创建了以下tasks.json


    "version": "2.0.0",
    "tasks": [
        
            "label": "select coredump",
            "type": "shell",
            "command": "coredumpselect.py",
            "args": [],
            "presentation": 
                "reveal": "always",
                "panel": "new"
            
        
    ]

并将以下调试配置添加到launch.json

        
            "name": "View coredump",
            "type": "cppdbg",
            "request": "launch",
            "program": "/tmp/coredump-program",
            "args": [],
            "cwd": "$workspaceRoot",
            "coreDumpPath": "/tmp/coredump",
            "preLaunchTask": "select coredump",
            "MIMode": "gdb",
        

现在,当您启动“查看 coredump”调试操作时,您将在终端中以交互方式选择 coredump。选择其中之一后,vscode 调试器将打开它。

【讨论】:

【参考方案4】:

你不使用source code editor(甚至是VSCode)调试core转储(因为core文件没有文本格式) .您使用gdb(或者可能是其他一些debugger,例如lldb)。 GDB 有一个非常好的user manual,我强烈推荐阅读。您也不使用 VSCode 来编译您的 C++ 代码,而是使用 compiler,例如 GCC 或 Clang(可能 VSCode 可以配置为为您启动 g++)。

在 Linux 上,如果您的 C 或 C++ 程序是使用 -g passed to g++gcc 作为可执行文件 $HOME/bin/foo 构建的,您可以尝试

 gdb $HOME/bin/foo core

然后使用gdb 调试器的事后检查命令。阅读documentation of gdb 了解详情。核心转储文件的存在和名称是可配置的(在最低级别使用setrlimit(2) 和直通proc(5),所以bash builtin ulimitzsh builtin limit)。另见core(5)。请注意,您的登录 shell 可以更改为 chsh(1)。在 Linux 上,bash 通常(不总是)是默认 shell,但您可能会切换到 zsh 甚至是 fish shell。当然阅读Unix shells。

您也不需要故意生成核心转储。在gdb 下设置breakpoint 通常更简单。您可以使用gcore(1) 生成正在运行的进程的核心。您可以使用gdb(1) 的-p 选项将gdb 附加到正在运行的进程。我很少看到故意生成核心转储有用的情况。当然abort(3)(也被assert(3)使用)会生成一个core转储。

最好使用DWARF 调试信息编译您的应用程序(使用-g 选项to GCC 或Clang)。假设您的应用程序可执行文件是某个 yourapp 可执行文件。然后使用gdb yourapp core

一些源代码编辑器能够运行gdb(我的编辑器是emacs,它能够运行gdbM-x gdb)。您应该深入了解源代码编辑器的文档以了解如何执行此操作。

但我建议在终端的命令行上使用gdb。这是一个非常方便的工具。请参阅this 对相关问题的回答。

gdb 正在使用非常低级别的ptrace(2) 系统调用来设置断点等。您几乎不需要ptrace(除非您编写自己的调试器,这可能需要多年的工作),但是您使用gdb,它使用ptrace

PS。如何从 VSCode 运行 gdb 是一个不同的问题。由于我不使用VSCode,我无法回答。它甚至可能不值得做。即使有 30 年的 emacs 经验,我也经常在终端中运行 gdb。因为它比从 emacs(或 VSCode)运行它更简单。

注意。如今,在 2019 年,“源代码编辑器”几乎是“IDE”的同义词。在实践中,这两种语言都指的是相同的产品,但它们呈现它们的方式不同。您可以将 emacs 称为 IDE,我(和 GNU 社区)更喜欢将其称为源代码编辑器,但我们都将它用于相同的事情:很好地编写和浏览和工作 source code 以及构建和调试它。

【讨论】:

我试图避免在命令行模式下使用 gdb,并且不太喜欢 tui 功能。现在我有了这个工作,它真的很好,我可以看到我所有的本地\全局变量,每个线程的调用堆栈,它似乎工作得很好。只有时间会证明它在应用程序不是玩具应用程序的实际生产转储中有多好。感谢您抽出宝贵时间回答我的问题! VSCode 不是文本编辑器,它是 IDE。它具有紧密的 gdb 集成。在 VSCode 中,您可以使用 GDB 单步执行代码并在编辑器中设置断点。您可以附加到正在运行的进程并查看堆栈和回溯的样子。这是一个无用的尖刻无知的答案 大多数高级编辑器和 IDE 都能够提供集成 dbg 等功能。

以上是关于如何使用 VSCode 调试 Linux 核心转储?的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 上调试 linux 故障转储

如何从 linux 内核核心转储中找到“HZ”值?

调试Go语言的核心转储(Core Dumps)

如何调试阿帕奇?我在哪里可以找到核心转储

如何调试从执行发布文件生成的核心转储文件?

Linux 中的核心转储