QEMU.js: hadda halis ah oo wata WASM

Mar baan go’aansaday madadaalo cadee dib u rogida hawsha oo baro sida loo soo saaro JavaScript (si sax ah, Asm.js) koodka mashiinka. QEMU ayaa loo doortay tijaabada, muddo kadibna maqaal ayaa lagu qoray Habr. Faallooyinka waxaa la igula taliyay inaan dib u sameeyo mashruuca WebAssembly, oo xitaa naftayda ka tago ku dhawaad ​​dhammaatay Anigu si uun ma rabin mashruuca ... Shaqadu way socotay, laakiin si tartiib tartiib ah, iyo hadda, dhawaanahan maqaalkaas ayaa soo muuqday faallo mowduuca "Sidee ku dhammaatay?" Anigoo ka jawaabaya jawaabtayda faahfaahsan, waxaan maqlay "Tani waxay u egtahay maqaal." Waa hagaag, haddii aad awooddo, waxaa jiri doona maqaal. Waxaa laga yaabaa in qof uu u arko inuu faa'iido leeyahay. Halkaa akhristuhu wuxuu ka baran doonaa xaqiiqooyin ku saabsan naqshadaynta jiilka koodka QEMU, iyo sidoo kale sida loo qoro isku-dubarid wakhti-in-waqti ah ee codsiga shabakadda.

hawlaha

Tan iyo markii aan hore u bartay sida "si uun" dekedda QEMU ee JavaScript, markan waxaa la go'aamiyay in la sameeyo si xikmad leh oo aan ku celin qaladaad hore.

Khaladaadka nambarka koowaad: laanta ka timid barta sii deynta

Khaladkaygii ugu horreeyay wuxuu ahaa in aan fargeeto noocayga ka soo qaatay nooca sare ee 2.4.1. Markaa waxay iila muuqatay fikrad wanaagsan: haddii dhibicda la sii daayo, markaa waxay u badan tahay inay ka xasilloon tahay 2.4 fudud, iyo xitaa in ka sii badan laanta master. Tan iyo markii aan qorsheeyay inaan ku daro xaddi cadaalad ah oo kutaanadeyda ah, uma baahnin qof kale haba yaraatee. Malaha sidaas ayay noqotay. Laakiin halkan waa shay: QEMU ma istaagin, mararka qaarkoodna waxay xitaa ku dhawaaqeen hagaajinta koodhka la soo saaray ee boqolkiiba 10. "Haa, hadda waan qaboojin doonaa," Waxaan u maleeyay oo jebiyey. Halkan waxaan u baahanahay inaan samayno digression: sababtoo ah dabeecadda hal-threaded ee QEMU.js iyo xaqiiqda ah in QEMU asalka ah ma muujinayso maqnaanshaha multi-threading (taas oo ah, awoodda ay isku mar ku shaqeeyaan dhowr waddo code aan xiriir la lahayn, iyo Kaliya ma aha "isticmaal dhammaan kernels") ayaa muhiim u ah, hawlaha ugu muhiimsan ee duntu waxay ahayd inaan "soo saaro" si aan awood ugu yeesho inaan dibadda ka soo waco. Tani waxay abuurtay qaar ka mid ah dhibaatooyinka dabiiciga ah intii lagu jiray isku darka. Si kastaba ha ahaatee, xaqiiqda ah in qaar ka mid ah isbeddelada laanta master, kaas oo aan isku dayay in aan ku daro koodhkayga, ayaa sidoo kale cherry laga soo qaatay barta sii daynta (iyo sidaas darteed laantayda) sidoo kale malaha kuma darin ku habboonaanta.

Guud ahaan, waxaan go'aansaday in ay wali macno samaynayso in la tuuro prototype-ka, la kala diro qaybo ka mid ah oo aan ka dhiso nooc cusub oo xoq ah oo ku salaysan wax cusub oo hadda laga bilaabo. master.

Khaladka nambarka labaad: Habka TLP

Nuxur ahaan, tani maaha qalad, guud ahaan, waa kaliya sifo abuurista mashruuc xaaladaha isfaham la'aanta buuxda ee labadaba "halkee iyo sida loo guuro?" iyo guud ahaan "ma heli doonaa halkaas?" Xaaladahan barnaamujyo qallafsan waxay ahayd doorasho xaq ah, laakiin, dabiiciyan, ma aanan rabin inaan ku celiyo si aan loo baahnayn. Markan waxaan rabay inaan u sameeyo si xikmad leh: atomiga wax-ka-qabashada, koodhka miyir-qabka ah ayaa isbeddelaya (oo ma "xarigga xarfaha random ilaa ay ka soo ururiyaan ( digniino)", sida Linus Torvalds mar ka sheegay qof, sida laga soo xigtay Wikiquote), iwm.

Khaladka nambarka seddexaad: gelida biyaha adigoon aqoon ford

Weli si buuxda ugamaanan takhalusin tan, laakiin hadda waxaan go'aansaday inaanan raacin jidka ugu yar ee iska caabinta gabi ahaanba, oo aan sameeyo "sida qof weyn," oo ah, qor dhabarkayga TCG meel xoq ah, si aanay u dhicin. in la yiraahdo mar dambe, "Haa, tani waa dabcan, si tartiib tartiib ah, laakiin wax walba ma xakameyn karo - taasi waa sida TCI u qoran tahay..." Waxaa intaa dheer, tani markii hore waxay u muuqatay xal cad, tan iyo Waxaan abuuraa koodka binary. Sida ay yiraahdaan, "Ghent waa la soo ururiyeyу, laakiin ma aha midkaas": koodka, dabcan, waa binary, laakiin xakamaynta si fudud looguma wareejin karo - waa in si cad loogu riixaa browserka si loo ururiyo, taasoo keentay shay gaar ah oo ka yimid adduunka JS, kaas oo weli u baahan in la sameeyo. meel ku badbaadi. Si kastaba ha noqotee, qaab dhismeedka caadiga ah ee RISC, inta aan fahmayo, xaalad caadi ah ayaa ah baahida loo qabo in si cad dib loogu habeeyo kaydka tilmaamaha ee koodhka dib loo soo cusbooneysiiyay - haddii tani aysan ahayn waxa aan u baahanahay, markaa, xaalad kasta, way dhowdahay. Intaa waxaa dheer, isku daygii ugu dambeeyay, waxaan ka bartay in xakameyntu aysan u muuqan in loo wareejiyo bartamaha tarjumaadda, markaa uma baahnid runtii bytecode oo laga tarjumay wax kasta, oo waxaan si fudud uga dhalin karnaa shaqada Qaaxada. .

Way yimaadeen oo laaday

In kasta oo aan bilaabay dib u qorida koodka bishii Luulyo, laad sixir ah ayaa soo booday iyada oo aan la dareemin: inta badan waraaqaha GitHub waxay u yimaadaan ogaysiisyo ku saabsan jawaabaha Arrimaha iyo Soo jiidashada codsiyada, laakiin halkan, si lama filaan ah ku sheeg dunta Binaryen sida qemu dhabarka dambe macnaha guud, "Wuxuu sameeyay wax sidaas oo kale ah, laga yaabee inuu wax yiraahdo." Waxaan ka hadlaynay adeegsiga maktabadda Emscripten ee la xiriirta Binaryen si loo abuuro WASM JIT. Hagaag, waxaan idhi inaad halkaas ku haysato shatiga Apache 2.0, QEMU guud ahaanna waxaa lagu qaybiyaa GPLv2, mana aha kuwo aad u socon kara. Isla markiiba waxaa soo baxday in shatiga uu noqon karo si uun u hagaaji (Ma aqaano: laga yaabee in la beddelo, laga yaabee laba shati, laga yaabee wax kale...). Tani, dabcan, way iga farxisay, sababtoo ah wakhtigaas waxaan horeyba u eegay si dhow qaabka binary WebAssembly, oo waxaan ahaa mid murugo leh oo aan la fahmi karin. Waxa kale oo jirtay laybareer oo cuni doonta baloogyada aasaasiga ah ee garaafka kala-guurka, soo saari doonta bytecode, oo xitaa ku dhex wadi doonta turjubaanka laftiisa, haddii loo baahdo.

Kadibna wax badan ayaa jiray warqad Liiska boostada ee QEMU, laakiin tani waa wax badan oo ku saabsan su'aasha, "Yaa u baahan si kastaba?" Waana si lama filaan ah, waxaa soo baxday in loo baahan yahay. Ugu yaraan, waxaad isku xoqin kartaan fursadahan soo socda ee isticmaalka, haddii ay u shaqeyso si ka badan ama ka yar si dhakhso ah:

  • bilaabista wax waxbarasho iyada oo aan haba yaraatee wax rakibin
  • Virtualization on iOS, halkaas oo, sida laga soo xigtay xanta, codsiga kaliya ee xaq u leh in ay code jiilka ee Daqsi waa engine JS ah (tani waa run?)
  • muujinta mini-OS - hal-floppy, gudaha ku dhex jira, dhammaan noocyada firmware-ka, iwm.

Astaamaha Runtime Browser

Sidaan horayba u sheegay, QEMU waxay ku xidhan tahay wax badan, laakiin browserku ma haysto. Waa hagaag, taasi waa, maya... Markii hore ma aysan jirin gabi ahaanba, ka dibna WebWorkers ayaa soo muuqday - illaa iyo inta aan fahmay, tani waa multithreading oo ku salaysan fariinta gudbinta. iyada oo aan la wadaagin doorsoomayaal. Dabcan, tani waxay abuurtaa dhibaatooyin la taaban karo marka la xareynayo koodka jira ee ku salaysan qaabka xusuusta la wadaago. Kadib, cadaadis dadweyne, ayaa sidoo kale lagu fuliyay magaca SharedArrayBuffers. Si tartiib tartiib ah ayaa loo soo bandhigay, waxay u dabaaldegeen furitaanka biraawsarka kala duwan, ka dib waxay u dabaaldegeen sanadka cusub, ka dibna Meltdown ... Intaa ka dib waxay ku soo gebogebeeyeen in ay adag tahay ama ay yareeyaan qiyaasta wakhtiga, laakiin iyada oo la kaashanayo xusuusta la wadaago iyo a dunta kordhinaysa miiska, waa isku mid si sax ah ayay u shaqayn doontaa. Markaa waxaanu ku curyaaminay isku xidhka badan ee xusuusta la wadaago. Waxay u muuqataa in markii dambe ay dib u soo celiyeen, laakiin, sida ay ku caddaatay tijaabadii ugu horreysay, waxaa jirta nolol la'aan, haddii ay sidaas tahay, waxaan isku dayi doonaa inaan sameyno annaga oo aan ku tiirsaneyn multithreading.

Tilmaamaha labaad waa suurtogalnimada wax-is-daba-marin heer-hoose ah oo lagu dhejiyay: si fudud uma qaadan kartid, ma badbaadin kartid macnaha hadda jira oo aad u beddesho mid cusub oo leh xirmo cusub. Xirmada wicitaanka waxaa maamula mashiinka farsamada ee JS. Waxay u egtahay, waa maxay dhibaatadu, maadaama aan wali go'aansanay inaan si buuxda gacanta ugu maamulno socodka hore? Xaqiiqdu waxay tahay in xannibaadda I/O ee QEMU lagu hirgeliyay iyada oo loo marayo coroutines, waana halka ay wax-ka-qabashada heerka hoose ku iman karto. Nasiib wanaag, Emscipten waxa ay hore u ka koobnayd hannaan hawl-gallo aan kala sooc lahayn, xataa laba: Asyncify и Turjubaanka. Midka ugu horreeya wuxuu ka shaqeeyaa qulqulo weyn oo ku jira koodhka JavaScript ee la soo saaray oo hadda lama taageero. Midda labaad waa "habka saxda ah" ee hadda jira oo ka shaqeeya jiilka bytecode ee turjubaanka waddaniga ah. Waxay u shaqeysaa, dabcan, si tartiib tartiib ah, laakiin ma jabinayso koodka. Run, taageerada loo yaqaan 'coutines' ee habkan waa in si madax-bannaan wax loogu qaybiyaa (waxaa hore u jiray coroutines loo qoray Asyncify waxaana jiray hirgelinta ku dhawaad ​​​​ API isku mid ah oo loogu talagalay Emterpreter, kaliya waxaad u baahan tahay inaad ku xidho).

Waqtigan xaadirka ah, weli ma aan suurtagelin in aan u kala qaybiyo koodka mid lagu soo ururiyey WASM oo lagu turjumay tarjumaadda, markaa qalabka xannibaya weli ma shaqeynin (eeg taxanaha soo socda, sida ay yiraahdaan ...). Taasi waa, dhamaadka waa inaad heshaa wax la mid ah shayga lakabka leh ee qosolka leh:

  • block I/O oo la turjumay. Hagaag, runtii ma filaysay in lagu daydo NVMe oo leh waxqabad hooyo? 🙂
  • koodka QEMU oo si istixgaliyay loo soo ururiyay (turjumaan, aalado kale oo lagu daydo, iwm
  • nambarka martida si firfircoon u ururiyay oo galay WASM

Astaamaha ilaha QEMU

Sidaad u badan tahay inaad horeba u qiyaastay, koodka ku dayashada qaab-dhismeedka martida iyo koodhka soo saarista tilmaamaha mishiinka martida loo yahay ayaa lagu kala saaray QEMU. Xaqiiqdii, way ka sii dhib yar tahay:

  • waxaa jira naqshadaha martida
  • waa dardargeliyayaasha, kuwaas oo ah, KVM for virtualization hardware on Linux (ee martida iyo nidaamyada martigeliyaha ku habboon midba midka kale), TCG ee jiilka code JIT meel kasta. Laga bilaabo QEMU 2.9, waxaa soo muuqday taageerada HAXM hardware virtualization standard ee Windows.faahfaahinta)
  • Haddii TCG la isticmaalo oo aan la isticmaalin qalabaynta qalabka, markaa waxay leedahay taageero jiil kood gaar ah oo loogu talagalay qaab dhismeedka martigeliyaha kasta, iyo sidoo kale turjumaanka caalamiga ah.
  • ... iyo waxyaalahaas oo dhan - ku dayashada durugsan, isdhexgalka isticmaalaha, guuritaanka, dib-u-ciyaarista, iwm.

Dhanka kale, ma ogtahay: QEMU ma ku dayan karto kumbuyuutarka oo dhan, laakiin sidoo kale processor-ka ee habka adeegsadaha gaarka ah ee kernel-ka martida loo yahay, kaas oo loo isticmaalo, tusaale ahaan, AFL fuzzer ee qalabka binary. Waxaa laga yaabaa in qof uu jeclaan lahaa inuu qaabkan hawlgalka QEMU u raro JS? 😉

Sida inta badan software-ka bilaashka ah ee muddada dheer taagnaa, QEMU waxa lagu dhisay wicitaanka configure и make. Aynu nidhaahno waxaad go'aansatey inaad wax ku darto: dhabarka TCG, hirgelinta dunta, shay kale. Ha ku degdegin inaad faraxdo/ka naxdo (xariiq ku xariiq sida ku habboon) rajada la xidhiidhka Autoconf - dhab ahaantii, configure QEMU's sida muuqata waa iskeed u qoran oo aan laga soo saarin wax.

WebAssembly

Haddaba waa maxay shaygan loo yaqaan WebAssembly (aka WASM)? Kani waa bedelka Asm.js, isaga oo aan iska dhigin in uu yahay koodka JavaScript sax ah. Taas bedelkeeda, waa binary oo la wanaajiyey, iyo xitaa si fudud u qorida shaandhada ma aha mid aad u fudud: isafgaradka, waxaa lagu kaydiyaa qaabka. LEB128.

Waxaa laga yaabaa inaad maqashay wax ku saabsan algorithm-ka dib-u-celinta ee Asm.js - tani waa dib-u-soo-celinta "heerka-sare" tilmaamaha xakamaynta socodka (taas oo ah, haddii-ka dibna-kale, loops, iwm.), kuwaas oo matoorada JS loogu talagalay, laga bilaabo heerka hoose ee LLVM IR, oo u dhow koodka mishiinka uu fuliyo processor-ku. Dabiici ahaan, matalaadda dhexe ee QEMU waxay ku dhowdahay tan labaad. Waxay u egtahay in halkan ay tahay, bytecode, dhammaadka cadaabku... Ka dibna waxaa jira blocks, haddii-ka dibna-kale iyo siddo!

Tanina waa sabab kale oo uu Binaryen faa'iido u leeyahay: waxay si dabiici ah u aqbali kartaa baloogyo heer sare ah oo u dhow waxa lagu kaydin lahaa WASM. Laakiin sidoo kale waxay soo saari kartaa koodka garaafyada blocks aasaasiga ah iyo kala guurka dhexdooda. Waa hagaag, waxaan horeyba u sheegay in ay qarinayso qaabka kaydinta WebAssembly ee ka dambeeya C/C ++ API ku habboon.

TCG

XAD asal ahaan backend for compiler C. Kadibna, sida muuqata, way u adkeysan wayday tartanka GCC, laakiin ugu dambeyntii waxay heshay booskeeda QEMU oo ah habka soo saarista code ee goobta martida loo yahay. Waxa kale oo jira dhabarka dambe ee TCG kaas oo soo saara xoogaa bytecode abstract ah, kaas oo isla markiiba uu fuliyo turjubaanka, laakiin waxaan go'aansaday inaan iska ilaaliyo isticmaalka wakhtigan. Si kastaba ha ahaatee, xaqiiqda ah in QEMU ay horeyba suurtogal u tahay in la suurtageliyo u gudubka TB-da ee la abuuray iyada oo loo marayo shaqada tcg_qemu_tb_exec, waxay ii noqotay mid faa'iido badan ii leh.

Si loogu daro TCG dhabarka dambe ee QEMU, waxaad u baahan tahay inaad abuurto hage-hoosaad tcg/<имя архитектуры> (kiiskan, tcg/binaryen), oo ka kooban laba fayl: tcg-target.h и tcg-target.inc.c и qori waa wax walba configure. Waxaad ku dhejin kartaa faylal kale, laakiin, sida aad ka qiyaasi karto magacyada labadan, labadoodaba meel baa lagu dari doonaa: mid sida faylka madaxa ee caadiga ah (waxaa lagu darayaa tcg/tcg.h, iyo mid ka mid ah ayaa hore ugu jira faylasha kale ee hagayaasha tcg, accel oo ma aha oo kaliya), kan kale - oo kaliya sida qayb ka mid ah koodka gudaha tcg/tcg.c, laakiin waxa ay heli kartaa hawlaheeda taagan.

Go'aansashada in aan waqti badan ku bixin doono baaritaanno faahfaahsan oo ku saabsan sida ay u shaqeyso, waxaan si fudud u koobiyeeyay "qalfoofyada" labadan faylal ee fulinta kale ee dhabarka, oo si daacad ah u muujinaya tan madaxa shatiga.

file tcg-target.h ka kooban yahay inta badan habayn qaabka #define-s:

  • Immisa diiwaangelin iyo ballac noocee ah ayaa ku jira qaab-dhismeedka bartilmaameedka (waxaan haynaa inta aan rabno, inta aan rabno - su'aashu waxay tahay wax badan oo ku saabsan waxa loo soo saari doono kood wax ku ool ah oo browserka ah ee qaab dhismeedka "si buuxda loo beegsanayo" ...)
  • toosinta tilmaamaha martida loo yahay: x86, iyo xitaa TCI, tilmaamuhu maaha kuwo isku mid ah, laakiin waxaan ku dhejin doonaa koodhka koodhka ma aha tilmaamo dhan, laakiin tilmaamayaasha dhismayaasha maktabadda Binaryen, markaa waxaan odhan doonaa: 4 bytes
  • Waa maxay tilmaamaha ikhtiyaariga ah ee dhabarku soo saari karo - waxaan ku darnaa wax kasta oo aan ka helno Binaryen, u ogolow dardargeliyaha intiisa kale u jebiyo kuwa fudud laftiisa
  • Waa maxay qiyaasta qiyaasta kaydka TLB ee ay codsatay dhabarka dambe. Xaqiiqdu waxay tahay in QEMU wax walbaa ay yihiin kuwo halis ah: in kasta oo ay jiraan hawlo caawiyayaal ah oo qabta culeyska / dukaanka iyadoo la tixgelinayo MMU-ga martida ah (halkee ayaan ahaan lahayn hadda la'aanteed?), Waxay kaydiyaan kaydkooda tarjumaada qaab dhismeed, habaynta kuwaas oo ku haboon in si toos ah loo dhexgeliyo blocks baahinta. Su'aashu waxay tahay, waa maxay kabitaanka dhismahan ee sida ugu hufan loogu farsameeyay amarro yar oo degdeg ah?
  • Halkan waxaad ku hagaajin kartaa ujeeddada hal ama laba diiwaan oo kaydsan, awood u yeel inaad wacdo TB adoo adeegsanaya hawl oo si ikhtiyaari ah u qeex dhowr yar inline-shaqooyinka sida flush_icache_range (laakin tani maahan kiiskeena)

file tcg-target.inc.c, Dabcan, inta badan waa ka weyn yahay cabbirka oo ka kooban dhowr hawlo qasab ah:

  • bilaabista, oo ay ku jiraan xayiraadaha tilmaamaha ku shaqayn kara hawlgallada. Si badheedh ah oo aan uga soo min guuriyay garab kale
  • shaqo qaadata hal tilmaame bytecode gudaha ah
  • Waxa kale oo aad halkan ku dhejin kartaa hawlaha kaalmaynta, waxa kale oo aad isticmaali kartaa hawlaha taagan tcg/tcg.c

Naftayda, waxaan doortay istiraatiijiyadan soo socota: ereyada ugu horreeya ee tarjumaadda soo socota, waxaan qoray afar tilmaame: calaamad bilaw ah (qiimo gaar ah oo ku yaal agagaarka 0xFFFFFFFF, kaas oo go'aamiyey xaaladda hadda ee Qaaxada), macnaha guud, cutubka la sameeyay, iyo lambarka sixirka ee cilladaha. Markii hore sumadda ayaa la geliyay 0xFFFFFFFF - nhalkaas oo n - tiro yar oo togan, mar kasta oo lagu fulinayo turjumaanka waxa ay korodhay 1. Markii la gaadhay 0xFFFFFFFE, iskudubarid ayaa dhacay, moduleka waxaa lagu keydiyay miiska shaqada, la soo galiyay "fure" yar, kaas oo dilku ka socday tcg_qemu_tb_exec, iyo moduleka waxaa laga saaray xusuusta QEMU.

Si aad u qeexdo qadiimiga, "Crutch, intee in le'eg ayaa ku xiran codkan wadnaha proger-ka...". Si kastaba ha ahaatee, xusuusta ayaa ka daadatay meel. Waxaa intaa dheer, waxa xasuusta maareysay QEMU! Waxaan haystay kood, markii aan qorayo tilmaanta soo socota (si fiican, taas oo ah, tilmaame), tirtiray kii isku xirka meeshan hore u joogay, laakiin tani ma caawin. Dhab ahaantii, kiiska ugu fudud, QEMU waxay u qoondaysaa xusuusta bilowga waxayna ku qortaa koodka la sameeyay. Marka kaydku dhamaado, koodka ayaa la tuurayaa oo ka xiga ayaa la bilaabayaa in lagu qoro meeshiisa.

Ka dib markii aan bartay koodka, waxaan ogaaday in khiyaamada leh lambarka sixirka ay ii ogolaatay inaanan ku guuldareysan burburinta burburka anigoo ku sii daaya shay khalad ah bakhaar aan la aqoon oo ku saabsan baska koowaad. Laakin yaa dib u qoraya kaydka si uu hadhow shaqadayda u dhaafo? Sida horumariyayaasha Emscripten ay ku taliyaan, markii aan dhibaato la kulmay, waxaan ku soo celiyay koodhka natiijada codsigii asalka ahaa, waxaan dhigay Mozilla Record-Replay on… a struct TranslationBlock oo leh tilmaanteeda. Qiyaas halkee... Taasi waa sax, wax yar ka hor xannibaadda saxda ah ee kaydinta. Anigoo taas gartay, waxaan go'aansaday in aan joojiyo isticmaalka biraha (ugu yaraan qaar), oo si fudud u tuuray nambarkii sixirka, oo aan u wareejiyay ereyada hadhay struct TranslationBlock, abuurista liis keli ah oo isku xidhan oo si degdeg ah loo mari karo marka kaydka tarjumaada dib loo dajiyo, oo uu xoreeyo xusuusta.

Qaar ka mid ah biraha ayaa hadhaya: tusaale ahaan, tilmaame calaamadeysan oo ku jira furaha koodhka - qaarkood waa fudud yihiin BinaryenExpressionRef, taas oo ah, waxay eegaan tibaaxaha u baahan in si toos ah loo geliyo block aasaasiga ah ee la abuuray, qayb ayaa ah shuruudaha kala-guurka ee u dhexeeya BBs, qayb ayaa ah meesha loo socdo. Hagaag, waxaa jira baloogyo loo diyaariyey Relooper kuwaas oo u baahan in lagu xidho iyada oo la raacayo shuruudaha. Si loo kala saaro, malo-awaalka waxaa loo isticmaalaa in dhamaantood ay ku siman yihiin ugu yaraan afar bytes, si aad si badbaado leh ugu isticmaali karto labada ugu yar ee muhiimka ah calaamadda, kaliya waxaad u baahan tahay inaad xasuusato inaad ka saarto haddii loo baahdo. Jid ahaan, calaamadaha noocan oo kale ah ayaa horay loogu isticmaalay QEMU si loo muujiyo sababta looga baxayo wareegga TCG.

Isticmaalka Binaryen

Modules WebAssembly waxay ka kooban yihiin hawlo, mid kasta oo ka mid ah wuxuu ka kooban yahay jidh, kaas oo ah tibaax. Odhaahyadu waa hawlgallo aan caadi ahayn iyo kuwa laba-jibbaaran, baloogyo ka kooban liisaska tibaaxaha kale, socodka xakamaynta, iwm. Sidii aan horayba u sheegay, socodka xakamaynta halkan waxaa loo habeeyey si sax ah sida laamo heer sare ah, wareegyo, wicitaano shaqo, iwm. Doodaha ku saabsan hawlaha laguma gudbiyo xidhmada, laakiin si cad, sida JS. Waxa kale oo jira doorsoomayaal caalami ah, laakiin anigu ma isticmaalin, markaa kuu sheegi maayo iyaga.

Hawlaha sidoo kale waxay leeyihiin doorsoomayaal maxalli ah, oo laga tiriyey eber, nooca: int32 / int64 / float / double. Xaaladdan oo kale, doorsoomayaasha n ee ugu horreeya n waa doodaha loo gudbiyay shaqada. Fadlan ogow in kasta oo wax kasta oo halkan ahi aanay ahayn mid gebi ahaanba hooseeya marka loo eego socodka kontoroolka, tiro-koobyadu wali ma wataan sifada “saxiixsan/aan saxeexin”: sida lambarku u dhaqmo waxay ku xidhan tahay xeerka hawlgalka.

Guud ahaan, Binaryen wuxuu bixiyaa fudud C-API: waxaad abuurtaa module ah, isaga ku jira samee tibaaxo - unary, binary, blocks ka tibaaxaha kale, socodka socodka, iwm. Markaa waxaad abuurtaa shaqo leh odhaah jidhkeeda ah. Haddii adiga, aniga oo kale, leh garaaf heer hoose ah oo ku-meel-gaadh ah, qaybta dib-u-celinta ayaa ku caawin doonta. Ilaa hadda sida aan fahamsanahay, waxaa suurtagal ah in la isticmaalo xakamaynta heerka sare ee qulqulka fulinta ee block, ilaa iyo inta aysan dhaafin xuduudaha xannibaadda - taas oo ah, waxaa suurtagal ah in la sameeyo waddo degdeg ah oo gudaha ah / gaabis ah. dariiqa laanta gudaha gudaha TLB cache code code, laakiin maaha in la farageliyo socodka kontoroolka "dibadda". Markaad xorayso dib-u-kicinta, baloogyadiisa waa la furayaa, marka aad furto cutubka, tibaaxaha, shaqooyinka, iwm. garoonka.

Si kastaba ha noqotee, haddii aad rabto inaad tarjumto koodhka duulista iyada oo aan loo baahnayn abuurista iyo tirtirka tusaale ahaan turjubaanka, waxaa laga yaabaa inay macno samaynayso inaad geliyo macquulkan faylka C++, oo halkaas si toos ah u maareyso dhammaan C++ API ee maktabadda, adigoo ka gudbaya diyaar- duubo laga sameeyay.

Markaas si aad u abuurto code aad u baahan tahay

// настроить глобальные параметры (можно поменять потом)
BinaryenSetAPITracing(0);

BinaryenSetOptimizeLevel(3);
BinaryenSetShrinkLevel(2);

// создать модуль
BinaryenModuleRef MODULE = BinaryenModuleCreate();

// описать типы функций (как создаваемых, так и вызываемых)
helper_type  BinaryenAddFunctionType(MODULE, "helper-func", BinaryenTypeInt32(), int32_helper_args, ARRAY_SIZE(int32_helper_args));
// (int23_helper_args приоб^Wсоздаются отдельно)

// сконструировать супер-мега выражение
// ... ну тут уж вы как-нибудь сами :)

// потом создать функцию
BinaryenAddFunction(MODULE, "tb_fun", tb_func_type, func_locals, FUNC_LOCALS_COUNT, expr);
BinaryenAddFunctionExport(MODULE, "tb_fun", "tb_fun");
...
BinaryenSetMemory(MODULE, (1 << 15) - 1, -1, NULL, NULL, NULL, NULL, NULL, 0, 0);
BinaryenAddMemoryImport(MODULE, NULL, "env", "memory", 0);
BinaryenAddTableImport(MODULE, NULL, "env", "tb_funcs");

// запросить валидацию и оптимизацию при желании
assert (BinaryenModuleValidate(MODULE));
BinaryenModuleOptimize(MODULE);

... haddii aan wax ilaaway, waan ka xumahay, tani waa kaliya si aan u matalo miisaanka, faahfaahintuna waxay ku jiraan dukumentiyada.

Oo hadda crack-fex-pex ayaa bilaabmaya, wax sidan oo kale ah:

static char buf[1 << 20];
BinaryenModuleOptimize(MODULE);
BinaryenSetMemory(MODULE, 0, -1, NULL, NULL, NULL, NULL, NULL, 0, 0);
int sz = BinaryenModuleWrite(MODULE, buf, sizeof(buf));
BinaryenModuleDispose(MODULE);
EM_ASM({
  var module = new WebAssembly.Module(new Uint8Array(wasmMemory.buffer, $0, $1));
  var fptr = $2;
  var instance = new WebAssembly.Instance(module, {
      'env': {
          'memory': wasmMemory,
          // ...
      }
  );
  // и вот уже у вас есть instance!
}, buf, sz);

Si si uun loogu xidho adduunyada QEMU iyo JS isla mar ahaantaana loo helo hawlaha la soo ururiyey si degdeg ah, waxaa la sameeyay hannaan (jad shaqo oo loogu talagalay soo dejinta furaha), hawlaha la soo saaray ayaa la dhigay halkaas Si dhakhso ah loo xisaabiyo tusaha, tusaha barta tarjumaadda ereyada eber ayaa markii hore loo isticmaalay sidiisa, laakiin ka dib tusaha la xisaabiyay iyadoo la isticmaalayo qaacidada this bilaabay inuu si fudud u galo goobta struct TranslationBlock.

By habka, demo (hadda haysta shati mugdi ah) Kaliya si fiican ayuu uga shaqeeyaa Firefox. Soosaarayaasha Chrome waxay ahaayeen si uun diyaar uma aha xaqiiqda ah in qof doonayo inuu abuuro in ka badan kun xaaladood oo ah modules WebAssembly, si ay si fudud u qoondeeyay gigabyte ah meel ciwaanka dalwaddii mid kasta ...

Waa intaas hadda. Waxaa laga yaabaa inay jiri doonto maqaal kale haddii qof uu xiiseynayo. Magac ahaan, waxaa jira hadhaa ugu yaraan kaliya ka dhig qalabka xannibaadda inay shaqeeyaan. Waxa kale oo laga yaabaa inay macno samaynayso in la sameeyo isku-dubaridyada WebAssembly modules-ka, sida caadada u ah adduunka JS, maadaama uu jiro weli turjubaan samayn kara waxaas oo dhan ilaa qaybta waddaniga ahi diyaar yahay.

Ugu dambayntii halxidhaale: Waxaad ku soo ururisay binary on a 32-bit architecture ah, laakiin code, iyada oo loo marayo hawlaha xusuusta, fuula ka Binaryen, meel on raso, ama meel kale oo ka mid ah 2 GB ee sare ee 32-bit cinwaanka booska. Dhibaatadu waxay tahay marka laga eego dhinaca Binaryen kani waxa uu gelayaa ciwaanka aad u wayn. Sidee looga gudbi karaa tan?

Sida adminka

Ma aanan dhamaanin tijaabinta tan, laakiin fikradayda ugu horeysay waxay ahayd "Ka waran haddii aan rakibo 32-bit Linux?" Kadibna qaybta sare ee booska ciwaanka waxaa degi doona kernel-ka. Su'aasha kaliya ayaa ah imisa ayaa lagu qabsan doonaa: 1 ama 2 Gb.

Habka barnaamijka (ikhtiyaarka loogu talagalay xirfadlayaasha)

Aynu ku afuufo xumbo xagga sare ee meesha ciwaanka. Aniga naftayda ma fahmin sababta ay u shaqeyso - halkaas horay waa in ay jiraan xidhmo. Laakiin "Waxaan nahay xirfadleyaal: wax walba waa inoo shaqeeyaan, laakiin qofna ma garanayo sababta..."

// 2gbubble.c
// Usage: LD_PRELOAD=2gbubble.so <program>

#include <sys/mman.h>
#include <assert.h>

void __attribute__((constructor)) constr(void)
{
  assert(MAP_FAILED != mmap(1u >> 31, (1u >> 31) - (1u >> 20), PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
}

Waa run in aysan ku habboonayn Valgrind, laakiin, nasiib wanaag, Valgrind lafteedu waxay si wax ku ool ah u riixdaa qof walba halkaas :)

Waxaa laga yaabaa in qof uu sharaxaad fiican ka bixiyo sida uu u shaqeeyo code-ka taydu...

Source: www.habr.com

Add a comment