V8 环境搭建

前言

早就想入门V8了,但是之前环境配置搞了好几次都没成功,所以就放弃了。之前一直想着给虚拟机搭全局VPN ,但是其实根本没那么麻烦。

准备

Ubuntu 18.04:据说该版本是最匹配V8的,当然也有说最好用 20.04 的,有条件的都配一配吧,我电脑不行就只搞个 18.04 的了

使虚拟机能够访问外网,具体见我之前的文章:虚拟机共享主机代理

配置

安装相关依赖

bash 复制代码
sudo apt install bison cdbs curl flex g++ git python vim pkg-config

安装 depot_tools

bash 复制代码
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
echo 'export PATH=$PATH:"/path/to/depot_tools"' >> ~/.bashrc

安装 ninja

bash 复制代码
git clone https://github.com/ninja-build/ninja.git
cd ninja && ./configure.py --bootstrap && cd ..
echo 'export PATH=$PATH:"/path/to/ninja"' >> ~/.bashrc

下拉V8并编译

bash 复制代码
fetch v8
cd v8
# 如果是要调洞的话,就要在这里切到有漏洞的那个commit
# 如果编译最新版的话,就不用这行命令
git reset --hard [commit hash with vulnerability]
# gclient sync 用来下载一些其他需要的东西,
gclient sync
# 编译 debug 版本
tools/dev/v8gen.py x64.debug
ninja -C out.gn/x64.debug
# ninja -C out.gn/x64.debug d8 # 加上 d8 表示只编译 d8
# 编译 release 版本
tools/dev/v8gen.py x64.release
ninja -C out.gn/x64.release

最后编译出来的 d8./out.gn/x64.debug/./out.gn/x64.release/ 目录下

一般在 ./out.gn/args.gn 默认生成的 release 版本选项加上:

bash 复制代码
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true

编译V8时遇到的问题

1)tools/dev/v8gen.py x64.release 时报错

bash 复制代码
Hint: You can raise verbosity (-vv) to see the output of failed commands.

Traceback (most recent call last):
  File "tools/dev/v8gen.py", line 309, in <module>
    sys.exit(gen.main())
  File "tools/dev/v8gen.py", line 303, in main
    return self._options.func()
  File "tools/dev/v8gen.py", line 169, in cmd_gen
    gn_outdir,
  File "tools/dev/v8gen.py", line 213, in _call_cmd
    stderr=subprocess.STDOUT,
  File "/usr/lib/python3.6/subprocess.py", line 336, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.6/subprocess.py", line 418, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/usr/bin/python3', '-u', 'tools/mb/mb.py', 'gen', '-f', 'infra/mb/mb_config.pyl', '-m', 'developer_default', '-b', 'x64.release', 'out.gn/x64.release']' returned non-zero exit status 1.

安装 libglib2.0-dev 即可

bash 复制代码
sudo apt-get install libglib2.0-dev

2)ninja -C out.gn/x64.release 报错

bash 复制代码
Traceback (most recent call last):
  File "/home/xiaozaya/rubbish/depot_tools/ninja.py", line 14, in <module>
    import gclient_paths
  File "/home/xiaozaya/rubbish/depot_tools/gclient_paths.py", line 154, in <module>
    @functools.lru_cache
  File "/usr/lib/python3.6/functools.py", line 477, in lru_cache
    raise TypeError('Expected maxsize to be an integer or None')
TypeError: Expected maxsize to be an integer or None

修改对应的代码即可,比如这里就直接去修改 "/home/xiaozaya/rubbish/depot_tools/gclient_paths.py" 的 154 行的代码,主要修改j就是:加上 (maxsize=128, typed=False)

python 复制代码
# @functools.lru_cache ==> @functools.lru_cache(maxsize=128, typed=False)

这里不只一处错误,反正根据报错进行相应的修改就行了

调试

gdb 插件

v8 自带gdb插件,可以让我们更加方便的使用gdb来调试v8,在 ~/.gdbinit 内添加以下两行即可使用:

bash 复制代码
source /path/to/v8/tools/gdbinit
source /path/to/v8/tools/gdb-v8-support.py

用的较多的是 job $value 这个命令。如果 $value 是个 带标记的指针,则会显示 JSObject 在内存中的表示,输出与 %DebugPrint() 类似。

其他命令可以在 tools/gdbinit 中查看

这里我启动 gdb 时存在一个问题说 jl 别名已经存在,查看 tools/gdbinit 发现:

bash 复制代码
#alias jlh = print-v8-local
alias jl = print-v8-local

所以这里注释掉一个就行了

natives-syntax 启动参数

d8 带 --allow-natives-syntax 启动参数的话,则可以在 js 脚本中写一些调试用的函数,这些函数通常以 % 开头,如 %DebugPrint() 显示对象信息,%DebugPrintPtr() 显示指针指向的对象信息,%SystemBreak() 下断点等。在 src/runtime/runtime.h 中可以找到所有的 natives syntax

Turbolizer 搭建

turbolizer 是一个可视化分析 JS 优化的工具,对于 ubu 18.04 得更新一下 node.js

bash 复制代码
sudo apt-get install curl python-software-properties
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install nodejs

然后安装并启动 turbolizer

bash 复制代码
cd v8/tools/turbolizer
npm i
npm run-script build
python -m SimpleHTTPServer

接着用 chrome 浏览器访问 ip:8000 就能用了,这里最好挂下t子,这样快一些

注:这里找到一个直接安装的

bash 复制代码
sudo apt install npm
cd /path/to/v8/tools/turbolizer
sudo npm install n -g
sudo n 16.20.0 # sudo n latest
sudo npm i
sudo npm run-script build

最后也是 python -m SimpleHTTPServer 起一个 http 服务即可