microsoft/vscode-cpptools

no hardware breakpoint support in the target

wangzhankun opened this issue · 5 comments

Environment

I develop my code on my linux server, VScode client is running on windows 11, my linux server is ubuntu 22.04. I'm developing linux hypervisor driver. So, on the server, I'm trying to use gdb to debug my driver with qemu.

  • OS and version: windows 11
  • VS Code: 1.82.0
  • C/C++ extension: 1.17.5
  • OS and version of remote machine (if applicable): ubuntu 22.04 6.2.0-33-generic
  • GDB / LLDB version: 12.1
  • qemu-system-x86_64: 7.2.6 --enable-kvm

Bug Summary and Steps to Reproduce

Bug Summary:
I can use gdb to debug driver when enabling kvm or disable kvm, I also can use vscode to debug linux kernel when disable kvm. But when I enable kvm, vscode runs into error:
image

GDB debug success

image

gdb debug error

I can use gdb to repeat the same error as vscode when I don't say "target remote :4921" but try to set hbreak.
image

But if I try to hbreak start_kernel, I cannot repeat the same error, I only have
image

Debugger Configurations

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Linux Kernel",
            "type": "cppdbg",
            "request": "launch",
            "program": "/home/wang/Documents/vmm/build/linux.build/vmlinux",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "/usr/bin/gdb",
            "miDebuggerServerAddress": "localhost:4921",
            "targetArchitecture": "x64",
            "hardwareBreakpoints": {
                "supported": true,
                "max": 4
            },
            "logging": { "engineLogging": true, "trace": true, "traceResponse": true },
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": false
                },
                {
                    "description": "set architecture i386:x86-64:intel",
                    "text": "-gdb-set architecture i386:x86-64:intel",
                    "ignoreFailures": false
                },
                {
                    "description": "将反汇编风格设置为 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": false
                },
                {
                    "description": "source .gdbinit",
                    "text": "source ${workspaceFolder}/.gdbinit",
                    "ignoreFailures": false
                },
                {
                    "text": "hbreak start_kernel",
                },
                {
                    "text": "hb kernel/src/open_close.c:113"
                }
            ],
            "preLaunchTask": "Build Kernel Debug"
        }
    ]
}

tasks.json

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "Build Kernel Debug",
            "command": "./scripts/run-qemu.sh",
            "args": [
                "-debug"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                {
                    "pattern": [
                        {
                            "regexp": ".",
                            "file": 1,
                            "location": 2,
                            "message": 3
                        }
                    ],
                    "background": {
                        "activeOnStart": true,
                        "beginsPattern": ".",
                        "endsPattern": ".",
                    }
                }
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "调试器生成的任务。",
            "isBackground": true,
        }
    ],
    "version": "2.0.0"
}

Debugger Logs

1: (283) ->=thread-group-added,id="i1"

1: (284) ->~"GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1\n"

1: (285) ->~"Copyright (C) 2022 Free Software Foundation, Inc.\n"

1: (285) ->~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law."

1: (285) ->~"\nType \"show copying\" and \"show warranty\" for details.\n"

1: (285) ->~"This GDB was configured as \"x86_64-linux-gnu\".\n"

1: (285) ->~"Type \"show configuration\" for configuration details.\n"

1: (285) ->~"For bug reporting instructions, please see:\n"

1: (285) ->~"<https://www.gnu.org/software/gdb/bugs/>.\n"

1: (285) ->~"Find the GDB manual and other documentation resources online at:\n    <http://www.gnu.org/software/gdb/documentation/>."

1: (285) ->~"\n\n"

1: (286) ->~"For help, type \"help\".\n"

1: (286) ->~"Type \"apropos word\" to search for commands related to \"word\".\n"

1: (286) ->=cmd-param-changed,param="auto-load safe-path",value="/"

1: (286) ->~"The target architecture is set to \"i386:x86-64:intel\".\n"

1: (286) ->=cmd-param-changed,param="architecture",value="i386:x86-64:intel"

1: (286) ->~"add symbol table from file \"/home/wang/Documents/vmm/hypervisor-from-scatch/build/linux/x86_64/debug/myhypervisor.ko\" at\n"

1: (286) ->~"\t.text_addr = 0xffffffffc0000000\n"

1: (290) ->(gdb)

1: (293) <-1001-gdb-set mi-async on

1: (294) ->1001^done

1: (294) ->(gdb)

1: (298) 1001: elapsed time 6

1: (311) <-1002-enable-pretty-printing

1: (311) ->1002^done

1: (311) ->(gdb)

1: (311) 1002: elapsed time 0

1: (311) <-1003-gdb-set architecture i386:x86-64:intel

1: (312) ->~"The target architecture is set to \"i386:x86-64:intel\".\n"

1: (312) ->1003^done

1: (312) ->(gdb)

1: (312) 1003: elapsed time 0

1: (312) <-1004-gdb-set disassembly-flavor intel

1: (313) ->1004^done

1: (313) ->(gdb)

1: (313) 1004: elapsed time 0

1: (316) <-1005-interpreter-exec console "source /home/wang/Documents/vmm/hypervisor-from-scatch/.gdbinit"

1: (317) ->~"Redefine command \"adddbg\"? (y or n) [answered Y; input not from terminal]\n"

1: (317) ->~"Redefine command \"addsym\"? (y or n) [answered Y; input not from terminal]\n"

1: (318) ->~"The target architecture is set to \"i386:x86-64:intel\".\n"

1: (318) ->~"add symbol table from file \"/home/wang/Documents/vmm/hypervisor-from-scatch/build/linux/x86_64/debug/myhypervisor.ko\" at\n"

1: (318) ->~"\t.text_addr = 0xffffffffc0000000\n"

1: (323) ->1005^done

1: (323) ->(gdb)

1: (323) 1005: elapsed time 6

1: (324) <-1006-interpreter-exec console "hbreak start_kernel"

1: (327) ->&"Function \"start_kernel\" not defined.\n"

1: (328) ->~"Make hw breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]\n"

1: (328) ->1006^done

1: (328) ->(gdb)

1: (328) 1006: elapsed time 4

1: (329) <-1007-interpreter-exec console "hb kernel/src/open_close.c:113"

1: (337) ->&"No hardware breakpoint support in the target.\n"

1: (337) ->1007^error,msg="No hardware breakpoint support in the target."

1: (337) ->(gdb)

1: (341) 1007: elapsed time 11

1: (344) Send Event AD7MessageEvent

1: (345) <--gdb-exit

1: (346) ->^exit

1: (350) <-logout

Other Extensions

No response

Additional Information

run-qemu.sh

#!/bin/sh

export HOST_PORT=4920;

echo "**** Running QEMU SSH on port ${HOST_PORT} ****";

export SMP=2;
export QEMU=/home/wang/Documents/vmm/qemu-7.2.6/build/qemu-system-x86_64;
export KERNEL=/home/wang/Documents/vmm/build/linux.build/arch/x86_64/boot/bzImage;
export ROOTFS=/home/wang/Documents/vmm/disk.ext2;


while [ "$1" != "" ]; do
    if [ "$1" = "-debug" ];
    then
        echo "**** GDB port $((HOST_PORT + 1)) ****";
        DEBUG="-gdb tcp::$((HOST_PORT + 1)) -S -d in_asm -D debug.log";
    fi;
    if [ "$1" = "-smp" ];
    then
        SMP="$2";
        shift;
    fi;
    shift;
done;

$QEMU \
 $DEBUG \
 -m 4G \
 -cpu host -enable-kvm \
 -nographic \
 -kernel $KERNEL \
 -append "nokaslr console=ttyS0 ro root=/dev/sda"   \
 -drive file=$ROOTFS,format=raw \
 -netdev user,id=net0,net=192.168.100.1/24,dhcpstart=192.168.100.128,hostfwd=tcp::${HOST_PORT}-:22 \
 -device e1000,netdev=net0 \
 -smp $SMP 

gdbinit

define adddbg
    hb kernel/src/open_close.c:113
    hb start_kernel
end

define addsym
    add-symbol-file  /home/wang/Documents/vmm/hypervisor-from-scatch/build/linux/x86_64/debug/myhypervisor.ko $arg0
end

set architecture i386:x86-64:intel
# target remote :4921
# file /home/wang/Documents/vmm/build/linux.build/vmlinux


addsym 0xffffffffc0000000
# adddbg

I believe the reason for this bug is that when vscode is debugging, it first loads .gdbinit, then executes the setupCommand defined in launch.json, and finally executes target remote :4921 and file /home/wang/Documents/vmm/build/linux.build/vmlinux. This works fine for software breakpoints, but does not work properly for hardware breakpoints.

We cannot attempt to set a hardware breakpoint before executing target remote :4921. Is there a way to execute additional GDB commands after executing target remote :4921? Perhaps we can mimic the setupCommands field in launch.json and add a postCommands field.

We cannot attempt to set a hardware breakpoint before executing target remote :4921. Is there a way to execute additional GDB commands after executing target remote :4921? Perhaps we can mimic the setupCommands field in launch.json and add a postCommands field.

I think you're right. I also need this. I need to first connect to the target, then load binary onto the target, then set breakpoints.