[分享] LiteJIT - 支援 X86/RISC-V 的 JIT

看板CompilerDev作者 (靜夜)時間2年前 (2021/07/12 03:13), 編輯推噓2(207)
留言9則, 2人參與, 2年前最新討論串1/1
https://github.com/Lipraxde/LiteJIT 以前念書時為了在 RISC-V 上跑 binary translator 臨時做的 JIT,能夠把 C、object file 讀進來,做完 relocation 後拿來跑。 目前可以支援的有 X86、RISC-V,RISC-V 的部分當時我是用 native compiler 編,直接 跑在 HiFive Unleashed 上,近幾天試了 cross compiler,發現 RISC-V relocation type 的命名似乎不太一樣,編不起來 Orz。 從 C 到執行的流程差不多是這樣:   C -> execlp call cc -> load temp.o -> relocation 編譯 C 程式碼的部分其實是用 execlp 去呼叫 cc,編譯成 temp.o,我實際上做的部分只 有將 temp.o 讀進來,然後做 relocation。 大概介紹一下將 object file 讀進來會發生的事, 1. 最一開始呢,LiteJIT 會先要一塊空的 memory 當 code cache: ┌─────────────────────────────┐ |                             | │            Free space            │ |                             | └─────────────────────────────┘ ↑                             ↑ got_ptr text_ptr 2. 拿到要跑的 object file 後,透過移動 text_ptr 來 allcoate memory,將所有有 SHF_ALLOC flag 的 section 複製進 cache: ┌──────────────────────┬──────┐ |                      |      | │            Free space     │ data / text│ |                      |      | └──────────────────────┴──────┘ ↑                      ↑ got_ptr text_ptr 雖然叫 text_ptr,不過實際上不管 data / text 都會透過它來 allocate。 3. 接著做 relocation,有幾種情形,如果不需要 GOT、PLT 的話就直接做, 3.a. 需要 GOT entry 的時候,透過移動 got_ptr 來 allocate GOT entry: ┌───┬──────────────────┬──────┐ | New |                  |      | │ GOT |        Free space     │ data / text│ |entry |                  |      | └───┴──────────────────┴──────┘     ↑                  ↑ got_ptr text_ptr 3.b. 需要 PLT entry 的時候,移動 text_ptr 來要一塊空間輸出 PLT entry: ┌───┬──────────────┬───┬──────┐ | New |              | New |      | │ GOT |        Free space | PLT │ data / text│ |entry |              | entry|      | └───┴──────────────┴───┴──────┘     ↑              ↑ got_ptr text_ptr 並把要輸出的指令寫到 PLT entry 裡。 4. Relocation 後 code cache 裡面大概會像這樣: ┌─────┬──────────┬─────┬──────┐ |     |          |     |      | │  GOT  |      Free spa|  PLT  │ data / text│ |     |          |     |      | └─────┴──────────┴─────┴──────┘       ↑          ↑ got_ptr text_ptr 這時候就可以去查 symbol (function) 來呼叫了,當然還可以繼續加 object file。 5. 當 got_ptr、text_ptr 撞在一起的時候,表示 code cache 裡面已經沒空間了,加入 新的 object file 會失敗,這時候要 create 一個新的 LiteJIT XD。 結語: 當初在做 LiteJIT 的時候只是想讓 binary translator 能夠在 RISC-V 上跑 DBT,因為 用 LLVM 做的關係,object file 可以生現成的出來,不過那時 LLVM 的 JIT 還不支援 RISC-V (不知道現在行不行)。 一開始先從 X86 的 relocation 開始做,沒記錯的話 LiteJIT 裡 X86 relocation 的部 分是我看文件慢慢弄出來的,後來一邊看各種 linker 的實作、弄 RISC-V 的 relocation 時,發現我其實可以直接抄 LLVM Linker (lld) 底下 ELF/Arch/RISCV.cpp 裡的東西就好 (基本上可以直接照搬),省了我不少功夫,感謝 PkmX 大大 XD。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 180.177.0.100 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/CompilerDev/M.1626030790.A.BC9.html

07/12 12:10, 2年前 , 1F
感覺很像現在 LLVM Orc JIT 的object layer在做的事
07/12 12:10, 1F

07/12 12:10, 2年前 , 2F
推推!
07/12 12:10, 2F

07/12 18:40, 2年前 , 3F
確實是 object layer 在做的事。其實在做 LiteJIT 更早
07/12 18:40, 3F

07/12 18:40, 2年前 , 4F
之前,有跟同實驗室的一位同學嘗試 port RISC-V,看能
07/12 18:40, 4F

07/12 18:40, 2年前 , 5F
不能讓 LLVM 可以直接支援 JIT RISC-V,不過那時好像在
07/12 18:40, 5F

07/12 18:40, 2年前 , 6F
插 stub、算 address 時遇到了些障礙,做出來的東西還
07/12 18:40, 6F

07/12 18:40, 2年前 , 7F
不夠用。比較熟 OrcJIT、relocation 後,覺得 OrcJIT
07/12 18:40, 7F

07/12 18:40, 2年前 , 8F
大部分功能不太需要、relocation 自己做比較快,所以就
07/12 18:40, 8F

07/12 18:40, 2年前 , 9F
沒去動 LLVM 了 XD
07/12 18:40, 9F
文章代碼(AID): #1WwqB6l9 (CompilerDev)