windows环境下vscode调试chrome/v8 js&c++代码

方法一,直接构建d8

d8是v8引擎的独立调试shell,编译速度很快,用于调试v8引擎的内部行为。

autoninja -C out/Default d8

1. 项目结构

|-- src
| |-- out
| | |-- Default
| | | |-- d8.exe
| | | |-- v8.dll
| | | |-- v8.dll.pdb
| |-- example
| | |-- test.js
| |-- .vscode
| | |-- launch.json

如果.pdb文件不存在,无法从二进制文件映射回源码,说明编译的时候没有启用debug模式。
gn gen默认开启debug模式(is_debug = true),symbol_level = 1,代表生成基本符号,但不包括内联函数和局部变量。如果需要生成完整符号,需要设置

gn gen out/Default --args="symbol_level=2"

2. 相关代码

// test.js
function add(a, b) {
  return a + b;
}
// %DebugPrint(add); // 打印对象信息
%SystemBreak(); // 触发断点
add(1, 2);
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug d8",
      "type": "cppvsdbg", // 使用 Visual Studio 调试器
      "request": "launch",
      "program": "${workspaceFolder}/out/Default/d8.exe",
      "args": [
        "--allow-natives-syntax", // 允许内置调试命令(如 %DebugPrint)
        "${file}" // 调试当前打开的 JS 文件
      ],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [],
      "externalConsole": true,
      "symbolSearchPath": "out/Default", // 指向调试符号目录
      "sourceFileMap": {
        "/": "${workspaceFolder}" // 确保源码路径正确映射
      },
      "console": "externalTerminal", // 显式指定外部终端(部分系统需要)
      "internalConsoleOptions": "neverOpen", // 禁用 VSCode 内部控制台
      "inputRedirection": true // 允许输入重定向(部分调试器支持)
    },
  ]
}

vscode的C/C++扩展默认配置为MinGW/Cygwin,而chrome基于Calng-cl + MSVC链接器构建,所以需要指定调试器为cppvsdbg(微软调试器)。

3. 执行步骤

1- 安装c/c++扩展
c/c++扩展

2- 编写.vscode/launch.json
3- 在v8\src\runtime\runtime-test.cc文件中的RUNTIME_FUNCTION(Runtime_SystemBreak)函数内打上断点
c++断点

4- debug窗口点击运行图标,调试程序会停在RUNTIME_FUNCTION(Runtime_SystemBreak)处。

方法二,构建chrome

包含所有组件,构建速度很慢,调试步骤也会繁琐很多

autoninja -C out/Default chrome

1. 项目结构

|-- src
| |-- out
| | |-- Default
| | | |-- chrome.exe
| | | |-- v8.dll
| | | |-- v8.dll.pdb
| |-- example
| | |-- test.html
| | |-- test.js
| |-- .vscode
| | |-- launch.json

如果.pdb文件不存在,无法从二进制文件映射回源码,说明编译的时候没有启用debug模式。
gn gen默认开启debug模式(is_debug = true),symbol_level = 1,代表生成基本符号,但不包括内联函数和局部变量。如果需要生成完整符号,需要设置

gn gen out/Default --args="symbol_level=2"

2. 相关代码

// test.js
function add(a, b) {
  return a + b;
}
// %DebugPrint(add); // 打印对象信息
%SystemBreak(); // 触发断点
add(1, 2);
<!-- test.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="test.js"></script>
  </body>
</html>
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to Chrome Renderer",
      "type": "cppvsdbg",
      "request": "attach",
      "processId": "${command:pickProcess}",
      "program": "${workspaceFolder}/out/Debug/chrome.exe",
      "symbolSearchPath": "${workspaceFolder}/out/Debug/**/*.pdb"
    }
  ]
}

vscode的C/C++扩展默认配置为MinGW/Cygwin,而chrome基于Calng-cl + MSVC链接器构建,所以需要指定调试器为cppvsdbg(微软调试器)。

3. 执行步骤

1)启动chrome

out/Default/chrome.exe --no-sandbox --renderer-startup-dialog --disable-hang-monitor --js-flags="--allow-natives-syntax"    

以下是启动 Chrome 时使用的各个参数及其作用的详细解释:


1. --no-sandbox

作用
禁用 Chrome 的沙盒(Sandbox)安全机制
背景
Chrome 的沙盒机制通过隔离渲染进程(Renderer)和主进程(Browser)来限制恶意代码对系统的破坏。但调试时,沙盒可能会阻止调试器访问某些资源(如本地文件系统或特定系统调用)。
适用场景
• 调试需要访问本地文件或底层系统调用的代码。
• 解决因沙盒权限限制导致的调试失败问题。
风险提示
禁用沙盒会显著降低安全性,仅限调试环境使用,切勿在生产环境或日常浏览中启用!


2. --renderer-startup-dialog

作用
强制每个新的渲染进程(Renderer)启动时弹出一个对话框,显示进程的 PID(进程 ID)并等待用户确认后才继续执行。
适用场景
• 调试多进程架构下的渲染进程,确保在进程启动后立即附加调试器。
• 精准定位目标进程,避免附加到错误的 Renderer 实例。
操作流程

  1. 启动 Chrome 后,新开标签页或加载页面时会弹出 PID 对话框。
  2. 记录 PID,在调试器中附加到该进程。
  3. 点击对话框的 “OK” 恢复进程执行。

3. --disable-hang-monitor

作用
禁用 Chrome 的“页面无响应”监控功能
背景
Chrome 默认会检测页面是否卡死(如长时间未响应),并提示用户关闭页面。但在调试过程中,如果代码在断点处暂停或被调试器中断,Chrome 可能误判为页面挂起并强制终止进程。
适用场景
• 调试时需要长时间暂停进程(如断点调试或单步执行)。
• 避免调试会话被意外终止。


4. --js-flags="--allow-natives-syntax"

作用
允许在 JavaScript 中使用 V8 引擎的“内部函数”(以 % 开头的函数)
背景
V8 引擎提供了一系列内部调试函数(如 %DebugPrint%SystemBreak),但这些函数默认被隐藏,需通过此标志显式启用。
适用场景
• 调试 JavaScript 代码时,调用 V8 内部函数输出调试信息或触发断点。
• 分析对象内存布局、优化行为(如内联缓存状态)。
示例代码

// test.js
function test() {
  const obj = { a: 1 };
  %DebugPrint(obj);  // 输出对象内存地址和内部结构
  %SystemBreak();    // 触发调试断点
}
test();

参数使用注意事项
  1. 调试完成后移除参数
    --no-sandbox--disable-hang-monitor 会显著降低安全性或稳定性,调试结束后应从启动命令中移除。
  2. --renderer-startup-dialog 的副作用
    每个新标签页或 iframe 都会触发弹窗,可能导致调试流程中断。建议仅在需要时使用。
  3. V8 内部函数的版本依赖
    % 开头的函数可能因 V8 版本不同而变化,需参考对应版本的文档。

完整命令示例
out/Default/chrome.exe \
  --no-sandbox \                # 禁用沙盒
  --renderer-startup-dialog \   # 渲染进程启动时弹窗
  --disable-hang-monitor \       # 禁用挂起监控
  --js-flags="--allow-natives-syntax"  # 启用 V8 内部函数

通过合理组合这些参数,可以高效调试 Chrome 的渲染进程和 JavaScript 行为,同时避免调试过程中的干扰。

2)浏览器地址栏输入test.html的绝对路径

chrome地址栏

3)弹窗弹出pid,阻塞页面渲染

因为chrome是多进程的,如果直接用命令行启动chrome并自动打开test.html,会弹出多个弹窗提示不同的pid,没法确认test.html对应的pid究竟是哪个。用命令行启动chrome,但不自动打开test.html的话,其他无关标签/frame的pid弹窗会先弹出,手动输入test.html后弹出的弹窗就一定是test.html对应的pid。

4)附加调试器到进程

1- 安装c/c++扩展
c/c++扩展

2- 编写.vscode/launch.json
3- 在v8\src\runtime\runtime-test.cc文件中的RUNTIME_FUNCTION(Runtime_SystemBreak)函数内打上断点
c++断点

4- debug窗口点击运行图标,选择之前记录下的pid

5)点击弹窗的确认按钮,调试程序会停在c++断点处

6)如果需要给js代码打断点,需要打开开发者面板-source,打上断点后刷新页面,如果js断点在%SystemBreak()前,页面会停留在断点处,否则页面会显示一直在加载

js断点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值