<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    V8環境搭建

    VSole2021-09-14 18:00:00

    為什么寫這個主題

    Chrome的重要地位不用贅述,V8不僅是chrome的核心組件,還是node.js等眾多軟件的核心組件,V8的重要程度亦不用多言。V8涉及的技術十分廣泛,包括了操作系統、編譯技術、計算機系統結構等多方面的知識,而網上的材料或零散或陳舊,給初學者造成了很大的困難,所以我準備寫一系列文章,從基礎入手,對V8內存分配、Isolate創建、handles概念、builtin、codegen、編譯等每個方面進行詳細講解,力求做到有概念層面的講解、有理論依據,又有代碼層面的說明、有事實論證。

    本節內容介紹

    本文是這個系列的第一篇,主要講解四部分內容:一、編譯工具鏈、V8編譯和調試;二、如何學習V8代碼最容易;三、以JavaScript元素(Element)為例,開啟V8源碼的學習之旅,起到拋磚引玉的作用;四、元素原理講解。

    本文所講的操作過程要求你的網絡能訪問谷歌,還要求你的cmd命令行也能通過http(s)訪問谷歌。

    一、下載、編譯、調試

    1.系統環境要求

    操作系統 win 10 64bit,VS2019社區版,git

    windows 10 SDK至少是10.0.19041以上版本,安裝SDK時不推薦用VS installer安裝,應該單獨下載SDK安裝包,原因是installer安裝的SDK文件不全。

    2.depot_tools工具

    它是v8的編譯工具鏈,下載代碼,編譯代碼都需要用到它。

    • 下載地址:https://storage.googleapis.com/chrome-infra/depot_tools.zip
    • 壓縮depot_tools.zip,用鼠標右鍵壓縮,注意:不要雙擊打開并從中拖拽出來
    • 把depot_tools加入到環境變量PATH中;添加系統變量DEPOT_TOOLS_WIN_TOOLCHAIN=0
    • 打開CMD終端(不是powershell,并且能通過http(s)訪問谷歌),執行gclient。它做一些初始化工作,與v8代碼無關,不作深入講解,可自行查閱源碼
    • gclient執行完畢,用where python查看depot_tools中的python.bat路徑信息,確保python.bat在環境變量PATH中的位置在系統中原有(如果有)的python環境位置前面

    3.下載代碼

    git的初始化

    > git config --global user.name "Name"  > git config --global user.email "address@mail.com"  > git config --global core.autocrlf false  > git config --global core.filemode false  > git config --global branch.autosetuprebase always
    

    下載V8代碼

    fetch v8  git pull origin master
    

    源碼不太大,用debug模式編譯后需要7G的硬盤空間,建議用固態硬盤,因為文件數量多,VS2019在掃描文件之間的引用關系時,固態很有優勢。

    生成GN工程文件

    > cd ~\v8\src #進入v8 src目錄  > gn gen --ide=vs out\default --args="is_component_build = true is_debug = true v8_optimized_debug = false"
    

    gn命令不是本文重點,可自行查閱,參數:is_debug = true 讓v8可以被調試,v8_optimized_debug = false 去掉對調試v8有干擾的代碼優化,這不會影響v8的正確性,只可能對性能有點影響,下文是我的編譯配置文件args.gn。

    is_component_build = true    is_debug = true    v8_optimized_debug = false    v8_use_snapshot = false
    

    4.編譯、調試

    用VS2019編譯V8

    在src\out\default下,能看到all.sln,雙擊打開,如圖-1。

    在解決方案資源管理器中,能看到v8_hello_world這個方案,鼠標右擊“設為啟動項目”,再次鼠標右擊“生成”,這樣就開始編譯了,在圖1下方的輸出窗口,能看到編譯過程。編譯時間長短要看機器性能:CPU和內存頻率、硬盤讀寫速度。

    上圖是跟蹤hello world的調用堆棧。

    總結,環境搭建過程中可能會出現意想不到的問題,多數都和SDK版本、環境變量有關,詳細查看出錯信息往往會得到答案。

    二、更容易入手的學習方法

    學代碼,肯定是可以調試、跟蹤最容易,V8代碼量大、結構復雜、類引用的層級關系多,要有一個合理的入口才好,v8的源碼都在src目錄下,如下圖。

    除了src目錄,我們看到還有一個samples目錄,它就是我們開始學習的地方,圖1中打開的文件(hello-world.cc)正是在這個目錄下,這個hello world程序是用C++編寫的,包括了啟動V8,然后運行一個javascript語言的hello world,還有一個加法運算。準確地說,V8是一個javascript虛擬機,這個hello word.cc中僅有”hello world”和加法算法是一個真正的javascript程序,其它的代碼都是為了運行javascript程序而做的準備工作(啟動V8虛擬機),包括了V8的創建、Isolate創建、handle創建,編譯,輸出hello world,再結束V8的全過程。這里只包括了V8最簡單最必要的功能集,所以,從跟蹤hello-world.cc入手學習V8是最簡單的。

    三、元素(Element)的調試跟蹤

    V8的啟動全過程涉及很多知識,本篇文章的作用為學習V8代碼起個頭,所以咱們聊聊相對簡單的元素(Element)初始化。通過元素的初始化,了解如何跟蹤V8代碼,以及了解V8的代碼風格。

    先來說什么是元素,Element是什么?先來看一個概念,{a:”foo”,b:”bar”},這個對象有兩個名字屬性(name properties),”a”和”b”,它們不能用數組下標索引,有下標索引屬性的,通常被稱為元素(Element),例如:[“foo”,”bar”],0位置是”foo”,1位置是”bar”。這在V8中的處理方式有很大的不同,先通過一張圖說明一下javascript對象在V8中的表現形式。

    從圖可以看出,在V8中javascript對象內部是分開做存儲的,name property和元素分開存儲的,也就是圖版中紅色標記的部分。我直接給出了在V8中定位元素代碼和調試跟蹤方法,見下圖。

    注意圖中文件的位置,和斷點,調試時就可以在這個位置停下來,這就是跟蹤方法,單步進入分析即可。

    四、元素(Element)原理及重要數據結構

    1.主要代碼和數據結構

    Element中的大量方法,例如pop或者slice方法等,大多都是用來對一段連續的地址空間進行操作的。ElementsAccessor是操作Element的基類,在Element上的每個操作都會對應到ElmentsAccessor。

    void ElementsAccessor::InitializeOncePerProcess() {  static ElementsAccessor* accessor_array[] = {#define ACCESSOR_ARRAY(Class, Kind, Store) new Class(),     ELEMENTS_LIST(ACCESSOR_ARRAY)//這里初化的宏義#undef ACCESSOR_ARRAY  };  STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==                kElementsKindCount);  elements_accessors_ = accessor_array;}
    

    代碼中的ACCESSOR_ARRAY和ELEMENTS_LIST兩個宏配合完成初始化,ELEMENTS_LIST中也能看到所有種類的Element,也就是Element kinds,如下圖所示。

    以FastPackedSmiElemntsAccessor為例進行分析,這個類從名字可以看出來它是連續存儲的Smi類型(V8中規定),連續存儲是指數據地址中沒有空洞,例如:a =[1,2,3],這就是packed(連續) Smi,b = [1,,3],這就是Holey Smi。何為Smi?就是小整數,以32位CPU為例說明,最低的一位(bit)是表示類型的,如果是1,則是指針,是0表示是Smi。

    FastPackedSmiElementsAccessor中沒有具體實現的功能, 我們直接看他的父類 FastSmiOrObjectElementsAccessor,這里有一些功能的實現,但目前看完這些功能,是沒有辦法在腦海中構建出一個Element結構來的,現在還為時尚早,因為這里只有Element的初始化,沒有講它是如何使用的,比如:slice方法是如何實現的,這里并沒有詳細說明,這里主要說明了初始化。接著看FastElementsAccessor這個父類,這里定義的功能實現比FastSmiOrObjectElementsAccessor中多,方法名中包含”Normailize”字樣的方法非常重要,因為任何一個Javascript中關于Element的操作方法(比如slice)的執行過程都與Normalize類方法有關,Normalize是Element的操作方法到最終實現之間的必經之路。

    NormalizeImpl是Normalize方法的具體實現,再進入下一個父類。

    最后給出類型的嵌套關系,如下圖。

    看完這些類中的各種方法,感覺方法之間無法關聯起來,這是正常的,因為到目前為止,我們還沒有進入方法的調用過程。

    2.從element.length看執行過程

    到目前為止,我們還只是看ELement的初始化過程,如果能讓所有的成員動起來,可以提高我們的學習效率,借助debug讓代碼動起來,如下圖。

    我們調試的是shell.cc,它的位置在samples\下,我們沒有使用hello world,改為使用shell.cc,只是因為shell的交互性更強,讓你看到”動起來”的效果更明顯,hello world依舊是最簡單的學習方式。調試之前要把這個工程編譯,看圖中右側的紅色標記,可以把這個工程設置為啟動項,然后生成,啟動debug后可以看到下面這個圖。

    這時,我們在elements.cc中下斷點,如下圖。

    在這樣圖中,能看到斷點,還有調用堆棧,從中能看到函數的調用過程,在shell窗口中執行如下指令。

    a=[1,2,3,4]a.length = 7 //特意改變數組長度,為了能觸發斷點
    

    這時就能夠復原上圖的堆棧了,你可以查看附近的相關代碼。

    3.數據結構Accessors

    我們先來看一下這個結構的部分源代碼。

    // Accessors contains all predefined proxy accessors.class Accessors : public AllStatic { public:#define ACCESSOR_GETTER_DECLARATION(_, accessor_name, AccessorName, ...) \  static void AccessorName##Getter(                                      \      v8::Local name,                                          \      const v8::PropertyCallbackInfo& info);  ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_GETTER_DECLARATION, /* not used */)#undef ACCESSOR_GETTER_DECLARATION
    #define ACCESSOR_SETTER_DECLARATION(accessor_name)          \  static void accessor_name(                                \      v8::Local name, v8::Local value, \      const v8::PropertyCallbackInfo& info);  ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION)#undef ACCESSOR_SETTER_DECLARATION...省略很多代碼... .......
    

    這個Accessors的作用是什么?通過上面的例子來說明:上面定義的a.length=5的執行過程是:需要先找到它的Accessors,然后才能到具體的setlength,這正好和V8的ElementsAccessor說明是對應的,如下圖。

    v8編譯程序
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    2021安洵杯PWN WP詳解
    2021-12-29 16:41:08
    做了2021安洵杯線上賽題目,總體來說題目有簡單有難的,難易程度合適,這次就做了pwn,把四道pwn題思路總結一下,重點是沒幾個人做出來的最后一道pwnsky,賽后做了復現。
    相關的應用程序或工具有: UART(Universal Asynchronous Receiver Transmitter,通用異步收發器): UBoot; Depthcharge; SPI (Serial Peripheral Interface,串行外設接口): Flashrom; I2C(Inter-Integrated Circuit,集成電路總線): i2cdetect;
    QEMU逃逸系列
    2022-12-01 09:19:27
    qemu用于模擬設備運行,而qemu逃逸漏洞多發于模擬pci設備中,漏洞形成一般是修改qemu-system代碼,所以漏洞存在于qemu-system文件內。而逃逸就是指利用漏洞從qemu-system模擬的這個小系統逃到主機內,從而在linux主機內達到命令執行的目的。
    10月23日,看雪第五屆安全開發者峰會于上海舉辦,歡迎各位蒞臨現場!
    V8環境搭建
    2021-09-14 18:00:00
    本文是這個系列的第一篇,主要講解四部分內容。
    《Chrome V8 Bug》系列文章的目的是解釋漏洞的產生原因,并向你展示這些漏洞如何影響 V8 的正確性。
    本文講解 Turbofan 的工作流程、梳理 PrepareJob、ExecuteJob 和 FinalizeJob 的主要功能以及重要數據結構。
    介紹Runtime 是一系列采用 C++ 語言編寫的功能方法,它實現了大量 JavaScript 運行期間需要的 native 功能。
    Builtin實現了V8中大量的核心功能,可見它的重要性。
    前言本系列的前十三篇文章,講解了V8執行Javascript時最基礎的工作流程和原理,包括詞法分析、語法分析、字節碼生成、Builtins方法、ignition執行單元,等等,達到了從零做起,入門學習的目的。接下來的文章將以問題為導向講解V8源碼,例如:以閉包技術、或垃圾回收為專題講解V8中的相關源碼。V8代碼過于龐大,以問題為導向可以使得學習主題更加明確、效果更好。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类