2

出于学习目的,我试图在从 IonMonkey 进行 JIT 编译后找出变量的内存地址(IonMonkey 是 SpiderMonkey 的一部分,Mozilla 的 Javascript 引擎)

到目前为止,我一直遵循这些说明https://developer.mozilla.org/en-US/docs/SpiderMonkey/Hacking_Tips#Printing_the_generated_assembly_code_(from_gdb)

我使用 GDB,并使用 2 个不同的测试文件运行相同的过程。

   function f(a, b) { return a + b; }
   var shell = "AAAA";
   for (var  i = 0; i < 1000000; i++){ f( shell[0], shell[1] ); }

和这个:

function f(a, b) { return a + b; }
var shell = "AAAA";
for (var  i = 0; i < 1000000; i++){ f( shell[1], shell[1] ); }

我相信这样我会发现生成的代码之间的差异并找出“shell”变量的位置。问题是生成的代码完全一样。我还尝试了不同版本的简单函数,例如减号或打印,但生成的代码完全不同。

任何人都可以提出任何建议,以便我可以获得变量的内存地址吗?

汇编生成的代码是

  0x7ffff7ff3ac8:   mov    0x20(%rsp),%r10
   0x7ffff7ff3acd:   shr    $0x2f,%r10
   0x7ffff7ff3ad1:   cmp    $0x1fff2,%r10d
   0x7ffff7ff3ad8:   je     0x7ffff7ff3ae3
   0x7ffff7ff3ade:   jmpq   0x7ffff7ff3b85
   0x7ffff7ff3ae3:   mov    0x28(%rsp),%r10
   0x7ffff7ff3ae8:   shr    $0x2f,%r10
   0x7ffff7ff3aec:   cmp    $0x1fff5,%r10d
   0x7ffff7ff3af3:   je     0x7ffff7ff3afe
   0x7ffff7ff3af9:   jmpq   0x7ffff7ff3b85
   0x7ffff7ff3afe:   mov    0x30(%rsp),%r10
   0x7ffff7ff3b03:   shr    $0x2f,%r10
   0x7ffff7ff3b07:   cmp    $0x1fff5,%r10d
   0x7ffff7ff3b0e:   je     0x7ffff7ff3b19
   0x7ffff7ff3b14:   jmpq   0x7ffff7ff3b85
   0x7ffff7ff3b19:   mov    0x28(%rsp),%r8
   0x7ffff7ff3b1e:   movabs $0x7fffffffffff,%rax
   0x7ffff7ff3b28:   and    %r8,%rax
   0x7ffff7ff3b2b:   mov    0x30(%rsp),%r9
   0x7ffff7ff3b30:   movabs $0x7fffffffffff,%rdi
   0x7ffff7ff3b3a:   and    %r9,%rdi
   0x7ffff7ff3b3d:   mov    $0x1670b78,%r11d
   0x7ffff7ff3b43:   mov    (%r11),%rcx
   0x7ffff7ff3b46:   cmp    %rcx,%rsp
   0x7ffff7ff3b49:   jbe    0x7ffff7ff3b8f
   0x7ffff7ff3b4f:   callq  0x7ffff7ff39a0
   0x7ffff7ff3b54:   test   %rbp,%rbp
   0x7ffff7ff3b57:   je     0x7ffff7ff3bd6
   0x7ffff7ff3b5d:   movabs $0xfffa800000000000,%rcx
   0x7ffff7ff3b67:   or     %rbp,%rcx
   0x7ffff7ff3b6a:   retq   
   0x7ffff7ff3b6b:   nop
                     ...
   0x7ffff7ff3b72:   nop
   0x7ffff7ff3b73:   movabs $0xffffffffffffffff,%r11
   0x7ffff7ff3b7d:   push   %r11
   0x7ffff7ff3b7f:   callq  0x7ffff7fe9400
   0x7ffff7ff3b84:   int3   
   0x7ffff7ff3b85:   pushq  $0x0
   0x7ffff7ff3b8a:   jmpq   0x7ffff7ff3c40
   0x7ffff7ff3b8f:   sub    $0x28,%rsp
   0x7ffff7ff3b93:   mov    %r9,0x20(%rsp)
   0x7ffff7ff3b98:   mov    %r8,0x18(%rsp)
   0x7ffff7ff3b9d:   mov    %rdi,0x10(%rsp)
   0x7ffff7ff3ba2:   mov    %rcx,0x8(%rsp)
   0x7ffff7ff3ba7:   mov    %rax,(%rsp)
   0x7ffff7ff3bab:   pushq  $0x280
   0x7ffff7ff3bb0:   callq  0x7ffff7fee880
   0x7ffff7ff3bb5:   mov    0x20(%rsp),%r9
   0x7ffff7ff3bba:   mov    0x18(%rsp),%r8
   0x7ffff7ff3bbf:   mov    0x10(%rsp),%rdi
   0x7ffff7ff3bc4:   mov    0x8(%rsp),%rcx
   0x7ffff7ff3bc9:   mov    (%rsp),%rax
   0x7ffff7ff3bcd:   add    $0x28,%rsp
   0x7ffff7ff3bd1:   jmpq   0x7ffff7ff3b4f
   0x7ffff7ff3bd6:   sub    $0x40,%rsp
   0x7ffff7ff3bda:   mov    %r9,0x38(%rsp)
   0x7ffff7ff3bdf:   mov    %r8,0x30(%rsp)
   0x7ffff7ff3be4:   mov    %rdi,0x28(%rsp)
   0x7ffff7ff3be9:   mov    %rsi,0x20(%rsp)
   0x7ffff7ff3bee:   mov    %rbx,0x18(%rsp)
   0x7ffff7ff3bf3:   mov    %rdx,0x10(%rsp)
   0x7ffff7ff3bf8:   mov    %rcx,0x8(%rsp)
   0x7ffff7ff3bfd:   mov    %rax,(%rsp)
   0x7ffff7ff3c01:   push   %rdi
   0x7ffff7ff3c02:   push   %rax
   0x7ffff7ff3c03:   pushq  $0x500
   0x7ffff7ff3c08:   callq  0x7ffff7fec370
   0x7ffff7ff3c0d:   mov    %rax,%rbp
   0x7ffff7ff3c10:   mov    0x38(%rsp),%r9
   0x7ffff7ff3c15:   mov    0x30(%rsp),%r8
   0x7ffff7ff3c1a:   mov    0x28(%rsp),%rdi
   0x7ffff7ff3c1f:   mov    0x20(%rsp),%rsi
   0x7ffff7ff3c24:   mov    0x18(%rsp),%rbx
   0x7ffff7ff3c29:   mov    0x10(%rsp),%rdx
   0x7ffff7ff3c2e:   mov    0x8(%rsp),%rcx
   0x7ffff7ff3c33:   mov    (%rsp),%rax
   0x7ffff7ff3c37:   add    $0x40,%rsp
   0x7ffff7ff3c3b:   jmpq   0x7ffff7ff3b5d
   0x7ffff7ff3c40:   pushq  $0x0
   0x7ffff7ff3c45:   jmpq   0x7ffff7fe9008
   0x7ffff7ff3c4a:   hlt    
4

3 回答 3

3

最简单的方法是在启用调试的情况下构建引擎,然后使用IONFLAGSenv var:根据spew 处理代码,您可以启用像codegen.

于 2013-07-09T20:54:48.543 回答
0

我的猜测是你只是在看函数f,它只是添加了它的参数;快速跟踪代码,我注意到函数内只有一个反向分支,并且没有可能循环的流路。

看起来这个函数从堆栈中读取两个参数,对它们进行类型检查(如果类型检查失败,则进入解释器),在这些对象上调用一个函数,然后返回结果;“...”之后的所有内容都是错误处理代码。如果您想要更好的测试,请尝试将 for 循环推入它自己的函数中,并打印添加 shell[0] 和 shell[1] 的结果。

或者,您已经在使用 GDB... 在 JITed 代码中设置断点,然后戳它们。很有可能,该断点将被命中 1000000 次,并且每次的参数都是相同的。

最后,您可以使用 (x86/gas) 之类的序列获取当前指令指针:

call 1n
1: pop %eax

对于您的目的,这可能更容易:-)

于 2013-07-07T23:56:46.343 回答
0

这并不多,但我找到了一种定位简单整数变量和字符串的方法。

  1. 使用 gdb 运行 js shell
  2. 按照此处的说明放置断点
  3. 执行 ax/50i $pc-1 并开始!

对于整数:

Javascript代码

var sum =10;
for (var  i = 0; i < 100000 ; i++ ) { sum = sum + 1; }

生成的代码

   0x7ffff7ff34a7:   movabs $0x7ffff5e4c060,%rax
   0x7ffff7ff34b1:   mov    0x10(%rax),%rax
   0x7ffff7ff34b5:   movabs $0x1670b98,%r11
   0x7ffff7ff34bf:   cmpl   $0x0,(%r11)
   0x7ffff7ff34c3:   jne    0x7ffff7ff3542
   0x7ffff7ff34c9:   mov    0x6c0(%rax),%ecx -- Load var i
   0x7ffff7ff34cf:   cmp    $0x186a0,%ecx    -- compare with 100000
   0x7ffff7ff34d5:   jge    0x7ffff7ff34fe   -- jump greater or equal [loop end]
   0x7ffff7ff34db:   mov    0x6b8(%rax),%edx -- load var sum
   0x7ffff7ff34e1:   add    $0x1,%edx        -- +1 to sum
   0x7ffff7ff34e4:   jo     0x7ffff7ff3561
   0x7ffff7ff34ea:   mov    %edx,0x6b8(%rax) -- store sum
   0x7ffff7ff34f0:   add    $0x1,%ecx        -- +1 to i
   0x7ffff7ff34f3:   mov    %ecx,0x6c0(%rax) -- store i
   0x7ffff7ff34f9:   jmpq   0x7ffff7ff34b5   -- continue loop
   0x7ffff7ff34fe:   movabs $0xfff9000000000000,%rcx
   0x7ffff7ff3508:   retq

现在我们检查内存

变量 i -- 0x1696230 + 0x6c0 = 0x16968f0 变量总和 -- 0x1696230 + 0x6b8 = 0x16968e8

0x00007ffff7ff34b5 (gdb) info registers rax 0x1696230
(gdb) x/w 0x16968f0:  0x0000044a
(gdb) x/w 0x16968e8:  0x00000454

0x0000044a = 十六进制(44a)= 十进制(1098) 0x00000454 = 十六进制(454)= 十进制(1108)

所以,这就是我们找到整数的内存地址的方法。

对于字符串:

Javascript代码

for (var  i = 0; i < 100000; i++){ shell="ABCDEFG" }

信息ASCII(“ABCDEFG”)=十六进制(41 42 43 44 45 46 47)

生成的代码

   0x7ffff7ff341f:   movabs $0x7ffff5e4c060,%rax
   0x7ffff7ff3429:   mov    0x10(%rax),%rax
   0x7ffff7ff342d:   movabs $0x1670b98,%r11
   0x7ffff7ff3437:   cmpl   $0x0,(%r11)       -- compare addr 0
   0x7ffff7ff343b:   jne    0x7ffff7ff34d7    -- jump not equal
   0x7ffff7ff3441:   mov    0x6b8(%rax),%ecx  -- load var i
   0x7ffff7ff3447:   cmp    $0x186a0,%ecx     -- compare i with 100000
   0x7ffff7ff344d:   jge    0x7ffff7ff3493    -- jump greater or equal [loop end]
   0x7ffff7ff3453:   jmpq   0x7ffff7ff3470    -- continue loop 
   0x7ffff7ff3458:   push   %rdx                                  
   0x7ffff7ff3459:   lea    0x6c0(%rax),%rdx                      
   0x7ffff7ff3460:   callq  0x7ffff7fe9a48                        
   0x7ffff7ff3465:   pop    %rdx                                  
   0x7ffff7ff3466:   jmpq   0x7ffff7ff3470                        
   0x7ffff7ff346b:   hlt                                          
   0x7ffff7ff3...:   hlt    -- filled with hlt                                          
   0x7ffff7ff346f:   hlt                                          
   0x7ffff7ff3470:   movabs $0xfffafffff5f3a280,%r11  -- Load address "shell"        
   0x7ffff7ff347a:   mov    %r11,0x6c0(%rax) -- store address to var shell 
   0x7ffff7ff3481:   mov    $0x1,%edx        
   0x7ffff7ff3486:   add    %ecx,%edx        -- +1 to i
   0x7ffff7ff3488:   mov    %edx,0x6b8(%rax) -- store var i
   0x7ffff7ff348e:   jmpq   0x7ffff7ff342d   -- continue loop
   0x7ffff7ff3493:   movabs $0xfff9000000000000,%rcx
   0x7ffff7ff349d:   retq

var 外壳 -- 0x1696230 + 0x6c0 = 0x16968f0

(gdb) info registers rax    0x1696230:  0xf5f3a280
(gdb) x/w 0x16968f0:    0xf5f3a280

(gdb) x/20w 0x7ffff5f3a280
0x7ffff5f3a280: 0x00000078  0x00000000  0xf5f3a290  0x00007fff
0x7ffff5f3a290: 0x00420041  0x00440043  0x00460045  0x00000047
0x7ffff5f3a2a0: 0x00000000  0x00000000  0x00000000  0x00000000

0x7ffff5f3a290: 0x00420041 0x00440043 0x00460045 0x00000047 我们得到了我们的字符串!

于 2013-07-12T10:43:07.250 回答