v8 学习基础

主要是v8对象基础的概念。

0x01 v8是什么

简而言之,v8就是js的解释器。

V8由很多子模块构成,其中,有几个最重要的模块:

  • Parser:负责将JavaScript源码转换为Abstract Syntax Tree (AST)
  • Ignition:interpreter,即解释器,负责将AST转换为Bytecode,解释执行Bytecode;同时收集TurboFan优化编译所需的信息,比如函数参数的类型
  • TurboFan:compiler,即编译器,利用Ignitio所收集的类型信息,将Bytecode转换为优化的汇编代码
  • Orinoco:garbage collector,垃圾回收模块,负责将程序不再需要的内存空间回收

Parser、Ignition、Turbofan协作将JS源码最终编译成汇编代码

v8结构图

0x02 v8 中JS对象结构

在下面的代码中定义了a,b两个对象,下面在调试中观察下里面的数据和结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Foo1 () {}
var a = new Foo1();
var b = new Foo1();

a.name = 'name-a';
a.text = 'aaa';
b.name = 'name-b';
b.text = 'bbb';
a[1] = "a-1";
a[2] = "a-2";

%DebugPrint(a); //d8中用来打印object内存信息
%DebugPrint(b); //d8中用来打印object内存信息
%SystemBreak(); //d8中用来中断,调试

2.1 使用谷歌浏览器观察

首先先在谷歌开发工具中键入上面的代码,然后在Memory中拍摄快照

v8结构图

我们大致可以看出来,对于a它有两个属性,分别是nametext,这两个属性直接保存在对象结构中。还有两个字符串”a-1”和”a-2”,他们作为元素,保存在了elements中。

`

因此暂时可以猜测,对象中保存的数据有两种形式: 一种是不需要索引的,称为属性, 另一种是需要索引的,称为元素

2.2 在ubuntu中编译v8观察

让我们单独看a打印出来的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
DebugPrint: 0x1c6808148b91: [JS_OBJECT_TYPE]
- map: 0x1c68083074fd <Map(HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x1c6808148b0d <Object map = 0x1c68083074ad>
- elements: 0x1c6808148c81 <FixedArray[19]> [HOLEY_ELEMENTS]
- properties: 0x1c6808042229 <FixedArray[0]>
- All own properties (excluding elements): {
0x1c68080447d5: [String] in ReadOnlySpace: #name: 0x1c68082d2591 <String[6]: #name-a> (const data field 0), location: in-object //name属性
0x1c68082d25a5: [String] in OldSpace: #text: 0x1c68082d25b5 <String[3]: #aaa> (const data field 1), location: in-object //text属性
}
- elements: 0x1c6808148c81 <FixedArray[19]> {
0: 0x1c6808042429 <the_hole> //element中的元素
1: 0x1c68082d25e9 <String[3]: #a-1>
2: 0x1c68082d25f9 <String[3]: #a-2>
3-18: 0x1c6808042429 <the_hole>
}
0x1c68083074fd: [Map]
- type: JS_OBJECT_TYPE //实例类型
- instance size: 52 //实例大小
- inobject properties: 10 //对象内属性存储空间(包含未使用的slots)
- elements kind: HOLEY_ELEMENTS
- unused property fields: 8 //未使用的属性slot数
- enum length: invalid
- stable_map //对象当前处于快速模式(dictionary_map:字典模式)
- back pointer: 0x1c68083074d5 <Map(HOLEY_ELEMENTS)>
- prototype_validity cell: 0x1c68082d2939 <Cell value= 0>
- instance descriptors (own) #2: 0x1c6808148c59 <DescriptorArray[2]>
- prototype: 0x1c6808148b0d <Object map = 0x1c68083074ad>
- constructor: 0x1c68082d2835 <JSFunction Foo1 (sfi = 0x1c68082d26ad)>
- dependent code: 0x1c68080421b5 <Other heap object (WEAK_FIXED_ARRAY_TYPE)>
- construction counter: 5

在v8中打印出的结构更确认了我们上面的猜测,并且更多看到了一些东西。比如map。

还有一些其它的

prototype prototype
elements 对象元素
length 元素个数
properties 属性

结构图如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 elements  ----> +------------------------+
| MAP +<---------+
+------------------------+ |
| element 1 | |
+------------------------+ |
| element 2 | |
| ...... | |
| element n | |
ArrayObject ---->-------------------------+ |
| map | |
+------------------------+ |
| prototype | |
+------------------------+ |
| elements | |
| +----------+
+------------------------+
| length |
+------------------------+
| properties |
+------------------------+

0x03 v8环境搭建

3.1代理配置

首先在本地的小飞机中,选项设置-》本地代理设置-》开启本地代理-》选择端口

配置git代理,后面的ip采用自己宿主机的,端口采用上一步设置的端口,虚拟机配置采用nat模式

1
git config --global http.proxy http://192.168.235.1:1080

配置环境变量,进行全局代理

1
2
export http_proxy="http://192.168.235.1:1080"
export https_proxy=$http_proxy

下载工具,并设置环境变量(注意此处环境变量的路径与你下载的路径是否相同

1
2
3
4
5
6
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
echo 'export PATH=$PATH:"$HOME/depot_tools"' >> ~/.bashrc

git clone https://github.com/ninja-build/ninja.git
cd ninja && ./configure.py --bootstrap && cd ..
echo 'export PATH=$PATH:"$HOME/ninja"' >> ~/.bashrc

编译v8.

1
fetch v8 && cd v8
1
2
3
4
5
6
7
8
9
gclient sync
#更新
git reset --hard [commit hash with vulnerability]
#切换版本

tools/dev/v8gen.py x64.debug
ninja -C out.gn/x64.debug [d8]
#d8参数表示只编译d8
#debug->release编译release版本

启动

1
2
3
4
5
6
7
./out.gn/x64.release/d8
#启动d8交互shell
./out.gn/x64.release/d8 test.js
#运行test.js
./out.gn/x64.debug/d8
./out.gn/x64.debug/shell
./out.gn/x64.debug/d8 test.js

调试工具,这个gdbinit如果没有的话需要从网上自行下载

1
2
echo 'source /home/w4rd3n/v8/tools/gdbinit' >> ~/.gdbinit
echo 'source /home/w4rd3n/v8/tools/gdb-v8-support.py' >> ~/.gdbinit
-------------本文结束感谢您的阅读-------------
+ +