如何查看v8生成的机器码?

IT技术 javascript code-generation v8
2021-03-20 20:36:17

有人知道我如何查看v8从 Javascript 生成的实际机器代码吗?我已经到了Script::Compile()src/api.cc但我不知道从那里去哪里。

5个回答

我不知道如何从 C++ 代码中调用反汇编程序,但是有一种快速而肮脏的方法可以从 shell 中进行反汇编。

首先,使用反汇编器支持编译 v8:

scons [your v8 build options here] disassembler=on sample=shell

现在您可以使用“--print_code”选项调用shell:

./shell --print_code hello.js

这应该给你这样的东西:

--- Raw source ---
print("hello world");

--- Code ---
kind = FUNCTION
Instructions (size = 134)
0x2ad0a77ceea0     0  55             push rbp
0x2ad0a77ceea1     1  488bec         REX.W movq rbp,rsp
0x2ad0a77ceea4     4  56             push rsi
0x2ad0a77ceea5     5  57             push rdi
0x2ad0a77ceea6     6  49ba59c13da9d02a0000 REX.W movq r10,0x2ad0a93dc159    ;; object: 0xa93dc159 <undefined>
0x2ad0a77ceeb0    16  4952           REX.W push r10
0x2ad0a77ceeb2    18  49ba688b700000000000 REX.W movq r10,0x708b68
0x2ad0a77ceebc    28  493b22         REX.W cmpq rsp,[r10]
0x2ad0a77ceebf    31  0f824e000000   jc 115  (0x2ad0a77cef13)
0x2ad0a77ceec5    37  488b462f       REX.W movq rax,[rsi+0x2f]
0x2ad0a77ceec9    41  4883ec18       REX.W subq rsp,0xlx
0x2ad0a77ceecd    45  49ba094b3ea9d02a0000 REX.W movq r10,0x2ad0a93e4b09    ;; object: 0xa93e4b09 <String[5]: print>
0x2ad0a77ceed7    55  4c8955e0       REX.W movq [rbp-0x20],r10
0x2ad0a77ceedb    59  488945d8       REX.W movq [rbp-0x28],rax
0x2ad0a77ceedf    63  49ba014d3ea9d02a0000 REX.W movq r10,0x2ad0a93e4d01    ;; object: 0xa93e4d01 <String[11]: hello world>
0x2ad0a77ceee9    73  4c8955d0       REX.W movq [rbp-0x30],r10
0x2ad0a77ceeed    77  49baa06c7ba7d02a0000 REX.W movq r10,0x2ad0a77b6ca0    ;; debug: statement 0
                                 ;; code: contextual, CALL_IC, UNINITIALIZED, argc = 1
0x2ad0a77ceef7    87  49ffd2         REX.W call r10
0x2ad0a77ceefa    90  488b75f8       REX.W movq rsi,[rbp-0x8]
0x2ad0a77ceefe    94  4883c408       REX.W addq rsp,0xlx
0x2ad0a77cef02    98  488945e8       REX.W movq [rbp-0x18],rax
0x2ad0a77cef06   102  488be5         REX.W movq rsp,rbp      ;; js return
0x2ad0a77cef09   105  5d             pop rbp
0x2ad0a77cef0a   106  c20800         ret 0x8
0x2ad0a77cef0d   109  cc             int3
0x2ad0a77cef0e   110  cc             int3
0x2ad0a77cef0f   111  cc             int3
0x2ad0a77cef10   112  cc             int3
0x2ad0a77cef11   113  cc             int3
0x2ad0a77cef12   114  cc             int3
0x2ad0a77cef13   115  49ba60657ba7d02a0000 REX.W movq r10,0x2ad0a77b6560    ;; code: STUB, StackCheck, minor: 0
0x2ad0a77cef1d   125  49ffd2         REX.W call r10
0x2ad0a77cef20   128  488b7df0       REX.W movq rdi,[rbp-0x10]
0x2ad0a77cef24   132  eb9f           jmp 37  (0x2ad0a77ceec5)

RelocInfo (size = 10)
0x2ad0a77ceea8  embedded object  (0xa93dc159 <undefined>)
0x2ad0a77ceecf  embedded object  (0xa93e4b09 <String[5]: print>)
0x2ad0a77ceee1  embedded object  (0xa93e4d01 <String[11]: hello world>)
0x2ad0a77ceeed  statement position  (0)
0x2ad0a77ceeef  code target (context) (CALL_IC)  (0x2ad0a77b6ca0)
0x2ad0a77cef06  js return
0x2ad0a77cef15  code target (STUB)  (0x2ad0a77b6560)

hello world

当然,您的输出会有所不同。以上来自为Linux x64编译的v8主干。

您需要使用反汇编器支持构建 v8。

下载 v8 源代码。

git clone https://chromium.googlesource.com/v8/v8.git

使用反汇编器支持构建。

make dependencies
make ia32.release objectprint=on disassembler=on

使用某些标志调用 d8 (v8 shell),具体取决于您想要什么。

out/ia32.release/d8 --code-comments --print-code <app.js>

以供参考:

  • --code-comments:包括代码注释。
  • --print-code:将代码打印到stdout
  • --print-code-stubs:打印代码存根。
  • --print-opt-code:打印优化代码。
  • --trace-hydrogen:将 IR(中间表示)代码打印到 Hydrogen.cfg。这个文件可以用Java 的 C1Visualizer打开
抱歉我不行。我不再使用 V8,所以我不知道最新的 args 的名称是什么。随着时间的推移,答案会过时是很正常的。如果另一个用户想要发布一个带有更新回复的新答案,当然非常欢迎她这样做(并且肯定会得到一些积分)。
2021-04-22 20:36:17
所有这些选项在最新的 V8 中都无效,您能否更新您的答案以反映最新的 args?
2021-05-09 20:36:17

尝试使用 NodeJS 或 Chrome:

  1. -print-opt-code: 优化编译器生成的代码。
  2. -print-bytecode: 解释器生成的字节码。
  3. -trace-opt-trace-depot:哪些功能是(去)优化的。

查看@Franziska Hinkelmann 的这篇文章:

https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775

另外你也可以试试

D8:它将帮助您编译V8和查看从 JavaScript 生成的汇编代码。

有关用法和详细信息:

http://www.mattzeunert.com/2015/08/19/viewing-assembly-code-generated-by-v8.html

谢谢!这真的很整洁!
2021-05-07 20:36:17

你走对了路,我想。

看起来您需要从 Script::Compile 到 Compiler::Compile,这将引导您到代码生成器(codegen*.cc 和 .h)。

所有这些都是为了说,看看 codegen-ia32.cc,如果你在构建时定义 ENABLE_DISASSSEMBLER,你的反汇编应该被打印出来,我想。

当然,所有这一切都只是快速浏览我在这里拥有的源的旧副本,所以 YMMV,但我认为这应该可行。

(再次查看您的帖子,我看到您正在寻找机器语言,而不是汇编程序——我不确定,但如果您想要汇编代码输出而不是反汇编,则可能需要修改逻辑)

看看v8_root/build/features.gypi,您会发现与反汇编器相关的以及 V8 的许多其他编译时功能开关。