ogwasm.pas 251 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441
  1. {
  2. Copyright (c) 2021 by Nikolay Nikolov
  3. Contains the WebAssembly binary module format reader and writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogwasm;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,cpubase,
  25. { assembler }
  26. aasmbase,assemble,aasmcpu,
  27. { WebAssembly module format definitions }
  28. wasmbase,
  29. { output }
  30. ogbase,
  31. owbase;
  32. type
  33. TWasmObjSymbolExtraData = class;
  34. TGlobalInitializer = record
  35. case typ:TWasmBasicType of
  36. wbt_i32: (init_i32: Int32);
  37. wbt_i64: (init_i64: Int64);
  38. wbt_f32: (init_f32: Single);
  39. wbt_f64: (init_f64: Double);
  40. end;
  41. { TWasmObjSymbolLinkingData }
  42. TWasmObjSymbolLinkingData = class
  43. public
  44. ImportModule: string;
  45. ImportName: string;
  46. FuncType: TWasmFuncType;
  47. ExeFunctionIndex: Integer;
  48. ExeIndirectFunctionTableIndex: Integer;
  49. ExeTypeIndex: Integer;
  50. ExeTagIndex: Integer;
  51. GlobalType: TWasmBasicType;
  52. GlobalIsMutable: Boolean;
  53. GlobalInitializer: TGlobalInitializer;
  54. IsExported: Boolean;
  55. ExportName: ansistring;
  56. constructor Create;
  57. destructor Destroy;override;
  58. end;
  59. { TWasmObjSymbol }
  60. TWasmObjSymbol = class(TObjSymbol)
  61. FuncIndex: Integer;
  62. SymbolIndex: Integer;
  63. GlobalIndex: Integer;
  64. TagIndex: Integer;
  65. AliasOf: string;
  66. ExtraData: TWasmObjSymbolExtraData;
  67. LinkingData: TWasmObjSymbolLinkingData;
  68. TlsGlobalSym: TWasmObjSymbol;
  69. TlsDataSym: TWasmObjSymbol;
  70. constructor create(AList:TFPHashObjectList;const AName:string);override;
  71. destructor Destroy;override;
  72. function IsAlias: Boolean;
  73. end;
  74. { TWasmObjRelocation }
  75. TWasmObjRelocation = class(TObjRelocation)
  76. public
  77. TypeIndex: Integer;
  78. Addend: LongInt;
  79. { used during linking }
  80. FuncType: TWasmFuncType;
  81. ExeTypeIndex: Integer;
  82. IsFunctionOffsetI32: Boolean;
  83. constructor CreateTypeIndex(ADataOffset:TObjSectionOfs; ATypeIndex: Integer);
  84. constructor CreateFuncType(ADataOffset:TObjSectionOfs; AFuncType: TWasmFuncType);
  85. destructor Destroy;override;
  86. end;
  87. { TWasmObjSymbolExtraData }
  88. TWasmObjSymbolExtraData = class(TFPHashObject)
  89. TypeIdx: Integer;
  90. ExceptionTagTypeIdx: Integer;
  91. ImportModule: string;
  92. ImportName: string;
  93. ExportName: string;
  94. GlobalType: TWasmBasicType;
  95. GlobalIsImmutable: Boolean;
  96. Locals: array of TWasmBasicType;
  97. EncodedLocals: tdynamicarray;
  98. constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  99. destructor Destroy; override;
  100. procedure AddLocals(alocals: TWasmLocalsDynArray);
  101. end;
  102. { TWasmObjSection }
  103. TWasmObjSection = class(TObjSection)
  104. public
  105. SegIdx: Integer;
  106. SegSymIdx: Integer;
  107. SegOfs: qword;
  108. FileSectionOfs: qword;
  109. MainFuncSymbol: TWasmObjSymbol;
  110. CustomSectionIdx: Integer;
  111. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
  112. function IsCode: Boolean;
  113. function IsData: Boolean;
  114. function IsDebug: Boolean;
  115. end;
  116. { TWasmFuncTypeTable }
  117. TWasmFuncTypeTable = class
  118. private
  119. FFuncTypes: array of TWasmFuncType;
  120. function GetCount: Integer;
  121. function GetItem(Index: Integer): TWasmFuncType;
  122. public
  123. destructor Destroy; override;
  124. function AddOrGetFuncType(wft: TWasmFuncType): integer;
  125. procedure WriteTo(d: tdynamicarray);
  126. property Count: Integer read GetCount;
  127. property Items[Index: Integer]: TWasmFuncType read GetItem; default;
  128. end;
  129. { TWasmObjData }
  130. TWasmObjData = class(TObjData)
  131. private
  132. FFuncTypes: TWasmFuncTypeTable;
  133. FObjSymbolsExtraDataList: TFPHashObjectList;
  134. FLastFuncName: string;
  135. function is_smart_section(atype:TAsmSectiontype):boolean;
  136. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  137. public
  138. constructor create(const n:string);override;
  139. destructor destroy; override;
  140. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  141. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  142. function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
  143. function globalref(asmsym:TAsmSymbol):TObjSymbol;
  144. function ExceptionTagRef(asmsym:TAsmSymbol):TObjSymbol;
  145. procedure DeclareGlobalType(gt: tai_globaltype);
  146. procedure DeclareFuncType_Pass0(ft: tai_functype);
  147. procedure DeclareFuncType_Pass1(ft: tai_functype);
  148. procedure DeclareFuncType_Pass2(ft: tai_functype);
  149. procedure DeclareTagType(tt: tai_tagtype);
  150. procedure DeclareExportName(en: tai_export_name);
  151. procedure DeclareImportModule(aim: tai_import_module);
  152. procedure DeclareImportName(ain: tai_import_name);
  153. procedure DeclareLocals_Pass0(al: tai_local);
  154. procedure DeclareLocals_Pass1(al: tai_local);
  155. procedure WriteLocals_Pass2(al: tai_local);
  156. procedure symbolpairdefine(akind: TSymbolPairKind;const asym, avalue: string);override;
  157. property FuncTypes: TWasmFuncTypeTable read FFuncTypes;
  158. end;
  159. { TWasmObjOutput }
  160. TWasmObjOutput = class(tObjOutput)
  161. private
  162. FData: TWasmObjData;
  163. FWasmRelocationCodeTable: tdynamicarray;
  164. FWasmRelocationCodeTableEntriesCount: Integer;
  165. FWasmRelocationDataTable: tdynamicarray;
  166. FWasmRelocationDataTableEntriesCount: Integer;
  167. FWasmRelocationDebugFrameTable: tdynamicarray;
  168. FWasmRelocationDebugFrameTableEntriesCount: Integer;
  169. FWasmRelocationDebugInfoTable: tdynamicarray;
  170. FWasmRelocationDebugInfoTableEntriesCount: Integer;
  171. FWasmRelocationDebugLineTable: tdynamicarray;
  172. FWasmRelocationDebugLineTableEntriesCount: Integer;
  173. FWasmRelocationDebugAbbrevTable: tdynamicarray;
  174. FWasmRelocationDebugAbbrevTableEntriesCount: Integer;
  175. FWasmRelocationDebugArangesTable: tdynamicarray;
  176. FWasmRelocationDebugArangesTableEntriesCount: Integer;
  177. FWasmRelocationDebugRangesTable: tdynamicarray;
  178. FWasmRelocationDebugRangesTableEntriesCount: Integer;
  179. FWasmRelocationDebugStrTable: tdynamicarray;
  180. FWasmRelocationDebugStrTableEntriesCount: Integer;
  181. FWasmSymbolTable: tdynamicarray;
  182. FWasmSymbolTableEntriesCount: Integer;
  183. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  184. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  185. FWasmLinkingSubsections: array [low(TWasmLinkingSubsectionType)..high(TWasmLinkingSubsectionType)] of tdynamicarray;
  186. procedure WriteWasmSection(wsid: TWasmSectionID);
  187. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  188. function IsExternalFunction(sym: TObjSymbol): Boolean;
  189. function IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  190. procedure WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  191. procedure WriteSymbolTable;
  192. procedure WriteRelocationCodeTable(CodeSectionIndex: Integer);
  193. procedure WriteRelocationDataTable(DataSectionIndex: Integer);
  194. procedure MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  195. procedure WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  196. procedure DoRelocations;
  197. procedure WriteRelocations;
  198. function FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  199. protected
  200. function writeData(Data:TObjData):boolean;override;
  201. public
  202. constructor create(AWriter:TObjectWriter);override;
  203. destructor destroy;override;
  204. end;
  205. { TWasmObjInput }
  206. TWasmObjInput = class(TObjInput)
  207. private
  208. FFuncTypes: array of TWasmFuncType;
  209. public
  210. constructor create;override;
  211. destructor Destroy;override;
  212. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  213. function ReadObjData(AReader:TObjectreader;out ObjData:TObjData):boolean;override;
  214. end;
  215. { TWasmExeOutput }
  216. TWasmExeOutput = class(TExeOutput)
  217. private
  218. const
  219. DataSections: array [1..3] of string = (
  220. '.rodata',
  221. '.data',
  222. 'fpc.resources');
  223. WasmPageSize = 65536;
  224. type
  225. TCustomSectionNameMapEntry = record
  226. idx: UInt32;
  227. name: string;
  228. end;
  229. TCustomSectionNameMap = array of TCustomSectionNameMapEntry;
  230. private
  231. FImports: TFPHashObjectList;
  232. FFuncTypes: TWasmFuncTypeTable;
  233. FFunctionImports: array of record
  234. ModName: ansistring;
  235. Name: ansistring;
  236. TypeIdx: uint32;
  237. end;
  238. FTagImports: array of record
  239. end;
  240. FIndirectFunctionTable: array of record
  241. FuncIdx: Integer;
  242. end;
  243. FRelocationPass: Integer;
  244. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  245. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  246. FWasmNameSubsections: array [TWasmNameSubsectionType] of tdynamicarray;
  247. FStackPointerSym: TWasmObjSymbol;
  248. FTlsBaseSym: TWasmObjSymbol;
  249. FTlsSizeSym: TWasmObjSymbol;
  250. FTlsAlignSym: TWasmObjSymbol;
  251. FInitTlsFunctionSym: TWasmObjSymbol;
  252. FInitSharedMemoryFunctionSym: TWasmObjSymbol;
  253. FMinMemoryPages,
  254. FMaxMemoryPages: Integer;
  255. { use for the Name section }
  256. FFunctionNameMap: TCustomSectionNameMap;
  257. FGlobalNameMap: TCustomSectionNameMap;
  258. FDataNameMap: TCustomSectionNameMap;
  259. FTagNameMap: TCustomSectionNameMap;
  260. procedure AddToNameMap(var nm: TCustomSectionNameMap; aidx: UInt32; const aname: string);
  261. procedure AddToFunctionNameMap(aidx: UInt32; const aname: string);
  262. procedure AddToGlobalNameMap(aidx: UInt32; const aname: string);
  263. procedure AddToDataNameMap(aidx: UInt32; const aname: string);
  264. procedure AddToTagNameMap(aidx: UInt32; const aname: string);
  265. procedure WriteWasmSection(wsid: TWasmSectionID);
  266. procedure WriteWasmSectionIfNotEmpty(wsid: TWasmSectionID);
  267. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  268. procedure PrepareImports;
  269. procedure PrepareFunctions;
  270. procedure PrepareTags;
  271. function AddOrGetIndirectFunctionTableIndex(FuncIdx: Integer): integer;
  272. procedure SetStackPointer;
  273. procedure SetTlsSizeAlignAndBase;
  274. procedure SetThreadVarGlobalsInitValues;
  275. procedure GenerateCode_InitTls;
  276. procedure GenerateCode_InitSharedMemory;
  277. procedure GenerateCode_InvokeHelper;
  278. procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
  279. procedure WriteMap_TypeSection;
  280. procedure WriteMap_IndirectFunctionTable;
  281. protected
  282. function writeData:boolean;override;
  283. procedure DoRelocationFixup(objsec:TObjSection);override;
  284. public
  285. constructor create;override;
  286. destructor destroy;override;
  287. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  288. procedure AfterUnusedSectionRemoval;override;
  289. procedure MemPos_ExeSection(const aname:string);override;
  290. procedure Load_Symbol(const aname: string);override;
  291. end;
  292. { TWasmAssembler }
  293. TWasmAssembler = class(tinternalassembler)
  294. constructor create(info: pasminfo; smart:boolean);override;
  295. end;
  296. implementation
  297. uses
  298. cutils,verbose,version,globals,fmodule,ogmap;
  299. const
  300. StackPointerSymStr='__stack_pointer';
  301. procedure WriteUleb5(d: tdynamicarray; v: uint64);
  302. var
  303. b: byte;
  304. i: Integer;
  305. begin
  306. for i:=1 to 5 do
  307. begin
  308. b:=byte(v) and 127;
  309. v:=v shr 7;
  310. if i<>5 then
  311. b:=b or 128;
  312. d.write(b,1);
  313. end;
  314. end;
  315. procedure WriteUleb5(d: tobjsection; v: uint64);
  316. var
  317. b: byte;
  318. i: Integer;
  319. begin
  320. for i:=1 to 5 do
  321. begin
  322. b:=byte(v) and 127;
  323. v:=v shr 7;
  324. if i<>5 then
  325. b:=b or 128;
  326. d.write(b,1);
  327. end;
  328. end;
  329. procedure WriteSleb5(d: tdynamicarray; v: int64);
  330. var
  331. b: byte;
  332. i: Integer;
  333. begin
  334. for i:=1 to 5 do
  335. begin
  336. b:=byte(v) and 127;
  337. v:=SarInt64(v,7);
  338. if i<>5 then
  339. b:=b or 128;
  340. d.write(b,1);
  341. end;
  342. end;
  343. procedure WriteSleb5(d: tobjsection; v: int64);
  344. var
  345. b: byte;
  346. i: Integer;
  347. begin
  348. for i:=1 to 5 do
  349. begin
  350. b:=byte(v) and 127;
  351. v:=SarInt64(v,7);
  352. if i<>5 then
  353. b:=b or 128;
  354. d.write(b,1);
  355. end;
  356. end;
  357. procedure WriteUleb(d: tdynamicarray; v: uint64);
  358. var
  359. b: byte;
  360. begin
  361. repeat
  362. b:=byte(v) and 127;
  363. v:=v shr 7;
  364. if v<>0 then
  365. b:=b or 128;
  366. d.write(b,1);
  367. until v=0;
  368. end;
  369. procedure WriteUleb(d: tobjsection; v: uint64);
  370. var
  371. b: byte;
  372. begin
  373. repeat
  374. b:=byte(v) and 127;
  375. v:=v shr 7;
  376. if v<>0 then
  377. b:=b or 128;
  378. d.write(b,1);
  379. until v=0;
  380. end;
  381. procedure WriteUleb(w: TObjectWriter; v: uint64);
  382. var
  383. b: byte;
  384. begin
  385. repeat
  386. b:=byte(v) and 127;
  387. v:=v shr 7;
  388. if v<>0 then
  389. b:=b or 128;
  390. w.write(b,1);
  391. until v=0;
  392. end;
  393. procedure WriteSleb(d: tdynamicarray; v: int64);
  394. var
  395. b: byte;
  396. Done: Boolean=false;
  397. begin
  398. repeat
  399. b:=byte(v) and 127;
  400. v:=SarInt64(v,7);
  401. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  402. Done:=true
  403. else
  404. b:=b or 128;
  405. d.write(b,1);
  406. until Done;
  407. end;
  408. procedure WriteSleb(d: tobjsection; v: int64);
  409. var
  410. b: byte;
  411. Done: Boolean=false;
  412. begin
  413. repeat
  414. b:=byte(v) and 127;
  415. v:=SarInt64(v,7);
  416. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  417. Done:=true
  418. else
  419. b:=b or 128;
  420. d.write(b,1);
  421. until Done;
  422. end;
  423. function UlebEncodingSize(v: uint64): Integer;
  424. var
  425. b: byte;
  426. begin
  427. Result:=0;
  428. repeat
  429. b:=byte(v) and 127;
  430. v:=v shr 7;
  431. if v<>0 then
  432. b:=b or 128;
  433. Inc(Result);
  434. until v=0;
  435. end;
  436. {$ifdef FPC_LITTLE_ENDIAN}
  437. procedure WriteF32LE(d: tdynamicarray; v: Single);
  438. begin
  439. d.write(v,4);
  440. end;
  441. procedure WriteF64LE(d: tdynamicarray; v: Double);
  442. begin
  443. d.write(v,8);
  444. end;
  445. {$else FPC_LITTLE_ENDIAN}
  446. procedure WriteF32LE(d: tdynamicarray; v: Single);
  447. var
  448. tmpI: UInt32;
  449. begin
  450. Move(v,tmpI,4);
  451. tmpI:=SwapEndian(tmpI);
  452. d.write(tmpI,4);
  453. end;
  454. procedure WriteF64LE(d: tdynamicarray; v: Double);
  455. var
  456. tmpI: UInt64;
  457. begin
  458. Move(v,tmpI,8);
  459. tmpI:=SwapEndian(tmpI);
  460. d.write(tmpI,8);
  461. end;
  462. {$endif FPC_LITTLE_ENDIAN}
  463. procedure WriteByte(d: tdynamicarray; b: byte);
  464. begin
  465. d.write(b,1);
  466. end;
  467. procedure WriteName(d: tdynamicarray; const s: string);
  468. begin
  469. WriteUleb(d,Length(s));
  470. d.writestr(s);
  471. end;
  472. procedure WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  473. begin
  474. WriteByte(dest,encode_wasm_basic_type(wbt));
  475. end;
  476. procedure WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  477. var
  478. i: Integer;
  479. begin
  480. WriteUleb(dest,Length(wrt));
  481. for i:=low(wrt) to high(wrt) do
  482. WriteWasmBasicType(dest,wrt[i]);
  483. end;
  484. function ReadUleb(d: tdynamicarray): uint64;
  485. var
  486. b: byte;
  487. shift:integer;
  488. begin
  489. b:=0;
  490. result:=0;
  491. shift:=0;
  492. repeat
  493. d.read(b,1);
  494. result:=result or (uint64(b and 127) shl shift);
  495. inc(shift,7);
  496. until (b and 128)=0;
  497. end;
  498. function ReadSleb(d: tdynamicarray): int64;
  499. var
  500. b: byte;
  501. shift:integer;
  502. begin
  503. b:=0;
  504. result:=0;
  505. shift:=0;
  506. repeat
  507. d.read(b,1);
  508. result:=result or (uint64(b and 127) shl shift);
  509. inc(shift,7);
  510. until (b and 128)=0;
  511. {$ifopt Q+}
  512. {$define overflowon}
  513. {$Q-}
  514. {$endif}
  515. {$ifopt R+}
  516. {$define rangeon}
  517. {$R-}
  518. {$endif}
  519. if (b and 64)<>0 then
  520. result:=result or (high(uint64) shl shift);
  521. end;
  522. {$ifdef overflowon}
  523. {$Q+}
  524. {$undef overflowon}
  525. {$endif}
  526. {$ifdef rangeon}
  527. {$R+}
  528. {$undef rangeon}
  529. {$endif}
  530. procedure AddSleb5(d: tdynamicarray; v: int64);
  531. var
  532. q: Int64;
  533. p: LongWord;
  534. begin
  535. p:=d.Pos;
  536. q:=ReadSleb(d);
  537. q:=q+v;
  538. d.seek(p);
  539. WriteSleb5(d,q);
  540. end;
  541. procedure AddUleb5(d: tdynamicarray; v: int64);
  542. var
  543. q: UInt64;
  544. p: LongWord;
  545. begin
  546. p:=d.Pos;
  547. q:=ReadUleb(d);
  548. q:=q+v;
  549. d.seek(p);
  550. WriteUleb5(d,q);
  551. end;
  552. procedure AddInt32(d: tdynamicarray; v: int32);
  553. var
  554. q: int32;
  555. p: LongWord;
  556. begin
  557. p:=d.Pos;
  558. d.read(q,4);
  559. {$ifdef FPC_BIG_ENDIAN}
  560. q:=SwapEndian(q);
  561. {$endif FPC_BIG_ENDIAN}
  562. q:=q+v;
  563. {$ifdef FPC_BIG_ENDIAN}
  564. q:=SwapEndian(q);
  565. {$endif FPC_BIG_ENDIAN}
  566. d.seek(p);
  567. d.write(q,4);
  568. end;
  569. procedure CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  570. var
  571. buf: array [0..4095] of byte;
  572. bs: Integer;
  573. begin
  574. while size>0 do
  575. begin
  576. if size<SizeOf(buf) then
  577. bs:=Integer(size)
  578. else
  579. bs:=SizeOf(buf);
  580. src.read(buf,bs);
  581. dest.write(buf,bs);
  582. dec(size,bs);
  583. end;
  584. end;
  585. procedure WriteZeros(dest: tdynamicarray; size: QWord);
  586. var
  587. buf : array[0..1023] of byte;
  588. bs: Integer;
  589. begin
  590. fillchar(buf,sizeof(buf),0);
  591. while size>0 do
  592. begin
  593. if size<SizeOf(buf) then
  594. bs:=Integer(size)
  595. else
  596. bs:=SizeOf(buf);
  597. dest.write(buf,bs);
  598. dec(size,bs);
  599. end;
  600. end;
  601. {****************************************************************************
  602. TWasmObjSymbolLinkingData
  603. ****************************************************************************}
  604. constructor TWasmObjSymbolLinkingData.Create;
  605. begin
  606. ExeFunctionIndex:=-1;
  607. ExeIndirectFunctionTableIndex:=-1;
  608. ExeTypeIndex:=-1;
  609. ExeTagIndex:=-1;
  610. end;
  611. destructor TWasmObjSymbolLinkingData.Destroy;
  612. begin
  613. FuncType.Free;
  614. inherited Destroy;
  615. end;
  616. {****************************************************************************
  617. TWasmObjRelocation
  618. ****************************************************************************}
  619. constructor TWasmObjRelocation.CreateTypeIndex(ADataOffset: TObjSectionOfs; ATypeIndex: Integer);
  620. begin
  621. DataOffset:=ADataOffset;
  622. Symbol:=nil;
  623. OrgSize:=0;
  624. Group:=nil;
  625. ObjSection:=nil;
  626. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  627. TypeIndex:=ATypeIndex;
  628. FuncType:=nil;
  629. ExeTypeIndex:=-1;
  630. end;
  631. constructor TWasmObjRelocation.CreateFuncType(ADataOffset: TObjSectionOfs; AFuncType: TWasmFuncType);
  632. begin
  633. DataOffset:=ADataOffset;
  634. Symbol:=nil;
  635. OrgSize:=0;
  636. Group:=nil;
  637. ObjSection:=nil;
  638. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  639. TypeIndex:=-1;
  640. ExeTypeIndex:=-1;
  641. FuncType:=TWasmFuncType.Create(AFuncType);
  642. end;
  643. destructor TWasmObjRelocation.Destroy;
  644. begin
  645. FuncType.Free;
  646. inherited Destroy;
  647. end;
  648. {****************************************************************************
  649. TWasmObjSymbol
  650. ****************************************************************************}
  651. constructor TWasmObjSymbol.create(AList: TFPHashObjectList; const AName: string);
  652. begin
  653. inherited create(AList,AName);
  654. FuncIndex:=-1;
  655. SymbolIndex:=-1;
  656. GlobalIndex:=-1;
  657. TagIndex:=-1;
  658. AliasOf:='';
  659. ExtraData:=nil;
  660. LinkingData:=TWasmObjSymbolLinkingData.Create;
  661. end;
  662. destructor TWasmObjSymbol.Destroy;
  663. begin
  664. LinkingData.Free;
  665. inherited Destroy;
  666. end;
  667. function TWasmObjSymbol.IsAlias: Boolean;
  668. begin
  669. result:=AliasOf<>'';
  670. end;
  671. {****************************************************************************
  672. TWasmObjSymbolExtraData
  673. ****************************************************************************}
  674. constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  675. begin
  676. EncodedLocals:=nil;
  677. inherited Create(HashObjectList,s);
  678. TypeIdx:=-1;
  679. ExceptionTagTypeIdx:=-1;
  680. end;
  681. destructor TWasmObjSymbolExtraData.Destroy;
  682. begin
  683. EncodedLocals.Free;
  684. inherited Destroy;
  685. end;
  686. procedure TWasmObjSymbolExtraData.AddLocals(alocals: TWasmLocalsDynArray);
  687. var
  688. i,
  689. rle_entries,
  690. cnt: Integer;
  691. lasttype: TWasmBasicType;
  692. begin
  693. Locals:=alocals;
  694. if Assigned(EncodedLocals) then
  695. internalerror(2024081502);
  696. EncodedLocals:=tdynamicarray.Create(64);
  697. if Length(Locals)=0 then
  698. begin
  699. WriteUleb(EncodedLocals,0);
  700. exit;
  701. end;
  702. rle_entries:=1;
  703. for i:=low(Locals)+1 to high(Locals) do
  704. if Locals[i]<>Locals[i-1] then
  705. inc(rle_entries);
  706. WriteUleb(EncodedLocals,rle_entries);
  707. lasttype:=Locals[Low(Locals)];
  708. cnt:=1;
  709. for i:=low(Locals)+1 to high(Locals) do
  710. if Locals[i]=Locals[i-1] then
  711. inc(cnt)
  712. else
  713. begin
  714. WriteUleb(EncodedLocals,cnt);
  715. WriteWasmBasicType(EncodedLocals,lasttype);
  716. lasttype:=Locals[i];
  717. cnt:=1;
  718. end;
  719. WriteUleb(EncodedLocals,cnt);
  720. WriteWasmBasicType(EncodedLocals,lasttype);
  721. end;
  722. {****************************************************************************
  723. TWasmObjSection
  724. ****************************************************************************}
  725. constructor TWasmObjSection.create(AList: TFPHashObjectList; const Aname: string; Aalign: longint; Aoptions: TObjSectionOptions);
  726. begin
  727. inherited create(AList, Aname, Aalign, Aoptions);
  728. SegIdx:=-1;
  729. SegSymIdx:=-1;
  730. CustomSectionIdx:=-1;
  731. MainFuncSymbol:=nil;
  732. end;
  733. function TWasmObjSection.IsCode: Boolean;
  734. const
  735. CodePrefix = '.text';
  736. begin
  737. result:=(Length(Name)>=Length(CodePrefix)) and
  738. (Copy(Name,1,Length(CodePrefix))=CodePrefix);
  739. end;
  740. function TWasmObjSection.IsData: Boolean;
  741. begin
  742. result:=not (IsCode or IsDebug);
  743. end;
  744. function TWasmObjSection.IsDebug: Boolean;
  745. const
  746. DebugPrefix = '.debug';
  747. begin
  748. result:=(Length(Name)>=Length(DebugPrefix)) and
  749. (Copy(Name,1,Length(DebugPrefix))=DebugPrefix);
  750. end;
  751. {****************************************************************************
  752. TWasmFuncTypeTable
  753. ****************************************************************************}
  754. function TWasmFuncTypeTable.GetCount: Integer;
  755. begin
  756. Result:=Length(FFuncTypes);
  757. end;
  758. function TWasmFuncTypeTable.GetItem(Index: Integer): TWasmFuncType;
  759. begin
  760. if (Index<Low(FFuncTypes)) or (Index>High(FFuncTypes)) then
  761. internalerror(2023123101);
  762. Result:=FFuncTypes[Index];
  763. end;
  764. destructor TWasmFuncTypeTable.Destroy;
  765. var
  766. i: Integer;
  767. begin
  768. for i:=low(FFuncTypes) to high(FFuncTypes) do
  769. begin
  770. FFuncTypes[i].free;
  771. FFuncTypes[i]:=nil;
  772. end;
  773. end;
  774. function TWasmFuncTypeTable.AddOrGetFuncType(wft: TWasmFuncType): integer;
  775. var
  776. i: Integer;
  777. begin
  778. for i:=low(FFuncTypes) to high(FFuncTypes) do
  779. if wft.Equals(FFuncTypes[i]) then
  780. exit(i);
  781. result:=Length(FFuncTypes);
  782. SetLength(FFuncTypes,result+1);
  783. FFuncTypes[result]:=TWasmFuncType.Create(wft);
  784. end;
  785. procedure TWasmFuncTypeTable.WriteTo(d: tdynamicarray);
  786. var
  787. types_count, i: Integer;
  788. begin
  789. types_count:=Count;
  790. WriteUleb(d,types_count);
  791. for i:=0 to types_count-1 do
  792. with Items[i] do
  793. begin
  794. WriteByte(d,$60);
  795. WriteWasmResultType(d,params);
  796. WriteWasmResultType(d,results);
  797. end;
  798. end;
  799. {****************************************************************************
  800. TWasmObjData
  801. ****************************************************************************}
  802. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  803. begin
  804. { For bss we need to set some flags that are target dependent,
  805. it is easier to disable it for smartlinking. It doesn't take up
  806. filespace }
  807. result:=not(target_info.system in systems_darwin) and
  808. create_smartlink_sections and
  809. (atype<>sec_toc) and
  810. (atype<>sec_user) and
  811. { on embedded systems every byte counts, so smartlink bss too }
  812. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  813. end;
  814. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  815. const aname: string; aorder: TAsmSectionOrder): string;
  816. const
  817. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  818. '.text',
  819. '.data',
  820. { why doesn't .rodata work? (FK) }
  821. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  822. { vtables (and anything else containing relocations), otherwise those are }
  823. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  824. { vtable for a class called Window: }
  825. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  826. { TODO: .data.ro not yet working}
  827. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  828. '.rodata',
  829. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  830. '.data',
  831. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  832. '.rodata',
  833. '.bss',
  834. '.tbss',
  835. '.pdata',
  836. '', { stubs }
  837. '__DATA,__nl_symbol_ptr',
  838. '__DATA,__la_symbol_ptr',
  839. '__DATA,__mod_init_func',
  840. '__DATA,__mod_term_func',
  841. '.stab',
  842. '.stabstr',
  843. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  844. '.eh_frame',
  845. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges','.debug_loc','.debug_loclists',
  846. '.fpc',
  847. '.toc',
  848. '.init',
  849. '.fini',
  850. '.objc_class',
  851. '.objc_meta_class',
  852. '.objc_cat_cls_meth',
  853. '.objc_cat_inst_meth',
  854. '.objc_protocol',
  855. '.objc_string_object',
  856. '.objc_cls_meth',
  857. '.objc_inst_meth',
  858. '.objc_cls_refs',
  859. '.objc_message_refs',
  860. '.objc_symbols',
  861. '.objc_category',
  862. '.objc_class_vars',
  863. '.objc_instance_vars',
  864. '.objc_module_info',
  865. '.objc_class_names',
  866. '.objc_meth_var_types',
  867. '.objc_meth_var_names',
  868. '.objc_selector_strs',
  869. '.objc_protocol_ext',
  870. '.objc_class_ext',
  871. '.objc_property',
  872. '.objc_image_info',
  873. '.objc_cstring_object',
  874. '.objc_sel_fixup',
  875. '__DATA,__objc_data',
  876. '__DATA,__objc_const',
  877. '.objc_superrefs',
  878. '__DATA, __datacoal_nt,coalesced',
  879. '.objc_classlist',
  880. '.objc_nlclasslist',
  881. '.objc_catlist',
  882. '.obcj_nlcatlist',
  883. '.objc_protolist',
  884. '.stack',
  885. '.heap',
  886. '.gcc_except_table',
  887. '.ARM.attributes'
  888. );
  889. var
  890. sep : string[3];
  891. secname : string;
  892. begin
  893. secname:=secnames[atype];
  894. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  895. begin
  896. result:=secname+'.'+aname;
  897. exit;
  898. end;
  899. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  900. Thus, data which normally goes into .rodata and .rodata_norel sections must
  901. end up in .data section }
  902. if (atype in [sec_rodata,sec_rodata_norel]) and
  903. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  904. secname:='.data';
  905. { Windows correctly handles reallocations in readonly sections }
  906. if (atype=sec_rodata) and
  907. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  908. secname:='.rodata';
  909. { section type user gives the user full controll on the section name }
  910. if atype=sec_user then
  911. secname:=aname;
  912. if is_smart_section(atype) and (aname<>'') then
  913. begin
  914. case aorder of
  915. secorder_begin :
  916. sep:='.b_';
  917. secorder_end :
  918. sep:='.z_';
  919. else
  920. sep:='.n_';
  921. end;
  922. result:=secname+sep+aname
  923. end
  924. else
  925. result:=secname;
  926. end;
  927. constructor TWasmObjData.create(const n: string);
  928. begin
  929. inherited;
  930. CObjSection:=TWasmObjSection;
  931. CObjSymbol:=TWasmObjSymbol;
  932. FObjSymbolsExtraDataList:=TFPHashObjectList.Create;
  933. FFuncTypes:=TWasmFuncTypeTable.Create;
  934. end;
  935. destructor TWasmObjData.destroy;
  936. var
  937. i: Integer;
  938. begin
  939. FObjSymbolsExtraDataList.Free;
  940. FFuncTypes.Free;
  941. inherited destroy;
  942. end;
  943. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  944. const aname: string; aorder: TAsmSectionOrder): string;
  945. begin
  946. if (atype=sec_fpc) or
  947. ((atype=sec_threadvar) and not (ts_wasm_threads in current_settings.targetswitches)) then
  948. atype:=sec_data;
  949. Result:=sectionname_gas(atype, aname, aorder);
  950. end;
  951. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  952. p: TObjSymbol; Reloctype: TObjRelocationType);
  953. const
  954. leb_zero: array[0..4] of byte=($80,$80,$80,$80,$00);
  955. var
  956. objreloc: TWasmObjRelocation;
  957. begin
  958. if CurrObjSec=nil then
  959. internalerror(200403072);
  960. { workaround crash, when generating debug info for threadvars, when multithreading is turned off.
  961. todo: ensure the debug info for threadvars is actually correct, once we've got WebAssembly debug info working in general }
  962. if (Reloctype=RELOC_DTPOFF) and not (ts_wasm_threads in current_settings.targetswitches) then
  963. Reloctype:=RELOC_ABSOLUTE;
  964. objreloc:=nil;
  965. case Reloctype of
  966. RELOC_FUNCTION_INDEX_LEB:
  967. begin
  968. if Data<>0 then
  969. internalerror(2021092502);
  970. if len<>5 then
  971. internalerror(2021092503);
  972. if not assigned(p) then
  973. internalerror(2021092504);
  974. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  975. CurrObjSec.ObjRelocations.Add(objreloc);
  976. writebytes(leb_zero,5);
  977. end;
  978. RELOC_MEMORY_ADDR_LEB,
  979. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  980. begin
  981. if (Reloctype=RELOC_MEMORY_ADDR_LEB) and (Data<0) then
  982. internalerror(2021092602);
  983. if len<>5 then
  984. internalerror(2021092503);
  985. if not assigned(p) then
  986. internalerror(2021092504);
  987. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  988. objreloc.Addend:=Data;
  989. CurrObjSec.ObjRelocations.Add(objreloc);
  990. if RelocType=RELOC_MEMORY_ADDR_LEB then
  991. WriteUleb5(CurrObjSec,Data)
  992. else
  993. WriteSleb5(CurrObjSec,Data);
  994. end;
  995. RELOC_ABSOLUTE:
  996. begin
  997. if len<>4 then
  998. internalerror(2021092607);
  999. if not assigned(p) then
  1000. internalerror(2021092608);
  1001. if (p.objsection<>nil) and TWasmObjSection(p.objsection).IsDebug and
  1002. (p.bind<>AB_COMMON) and (p.bind<>AB_EXTERNAL) then
  1003. begin
  1004. objreloc:=TWasmObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,RELOC_ABSOLUTE);
  1005. objreloc.Addend:=Data+p.Address;
  1006. CurrObjSec.ObjRelocations.Add(objreloc);
  1007. {inc(data,p.address);}
  1008. data:=0;
  1009. Data:=NtoLE(Data);
  1010. writebytes(Data,4);
  1011. end
  1012. else
  1013. begin
  1014. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1015. objreloc.Addend:=Data;
  1016. CurrObjSec.ObjRelocations.Add(objreloc);
  1017. Data:=NtoLE(Data);
  1018. writebytes(Data,4);
  1019. end;
  1020. end;
  1021. RELOC_TYPE_INDEX_LEB:
  1022. begin
  1023. if len<>5 then
  1024. internalerror(2021092612);
  1025. if assigned(p) then
  1026. internalerror(2021092613);
  1027. objreloc:=TWasmObjRelocation.CreateTypeIndex(CurrObjSec.Size,Data);
  1028. CurrObjSec.ObjRelocations.Add(objreloc);
  1029. WriteUleb5(CurrObjSec,Data);
  1030. end;
  1031. RELOC_GLOBAL_INDEX_LEB:
  1032. begin
  1033. if len<>5 then
  1034. internalerror(2021092701);
  1035. if Data<>0 then
  1036. internalerror(2021092702);
  1037. if not assigned(p) then
  1038. internalerror(2021092703);
  1039. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1040. CurrObjSec.ObjRelocations.Add(objreloc);
  1041. WriteUleb5(CurrObjSec,0);
  1042. end;
  1043. RELOC_TAG_INDEX_LEB:
  1044. begin
  1045. if len<>5 then
  1046. internalerror(2021092712);
  1047. if Data<>0 then
  1048. internalerror(2021092713);
  1049. if not assigned(p) then
  1050. internalerror(2021092714);
  1051. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1052. CurrObjSec.ObjRelocations.Add(objreloc);
  1053. WriteSleb5(CurrObjSec,0);
  1054. end;
  1055. else
  1056. internalerror(2021092501);
  1057. end;
  1058. end;
  1059. function TWasmObjData.AddOrCreateObjSymbolExtraData(const symname: TSymStr): TWasmObjSymbolExtraData;
  1060. begin
  1061. result:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(symname));
  1062. if not assigned(result) then
  1063. result:=TWasmObjSymbolExtraData.Create(FObjSymbolsExtraDataList,symname);
  1064. end;
  1065. function TWasmObjData.globalref(asmsym: TAsmSymbol): TObjSymbol;
  1066. begin
  1067. if assigned(asmsym) then
  1068. begin
  1069. if (asmsym.typ<>AT_WASM_GLOBAL) and (asmsym.typ<>AT_TLS) then
  1070. internalerror(2021092706);
  1071. result:=symbolref(asmsym);
  1072. result.typ:=asmsym.typ;
  1073. end
  1074. else
  1075. result:=nil;
  1076. end;
  1077. function TWasmObjData.ExceptionTagRef(asmsym: TAsmSymbol): TObjSymbol;
  1078. begin
  1079. if assigned(asmsym) then
  1080. begin
  1081. if asmsym.typ<>AT_WASM_EXCEPTION_TAG then
  1082. internalerror(2021092707);
  1083. result:=symbolref(asmsym);
  1084. result.typ:=AT_WASM_EXCEPTION_TAG;
  1085. end
  1086. else
  1087. result:=nil;
  1088. end;
  1089. procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype);
  1090. var
  1091. ObjSymExtraData: TWasmObjSymbolExtraData;
  1092. ObjSym: TObjSymbol;
  1093. begin
  1094. if not gt.is_external then
  1095. begin
  1096. ObjSym:=symboldefine(gt.sym);
  1097. ObjSym.typ:=AT_WASM_GLOBAL;
  1098. end;
  1099. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(gt.globalname);
  1100. ObjSymExtraData.GlobalType:=gt.gtype;
  1101. ObjSymExtraData.GlobalIsImmutable:=gt.immutable;
  1102. end;
  1103. procedure TWasmObjData.DeclareFuncType_Pass0(ft: tai_functype);
  1104. var
  1105. i: Integer;
  1106. ObjSymExtraData: TWasmObjSymbolExtraData;
  1107. begin
  1108. FLastFuncName:=ft.funcname;
  1109. i:=FFuncTypes.AddOrGetFuncType(ft.functype);
  1110. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ft.funcname);
  1111. ObjSymExtraData.TypeIdx:=i;
  1112. end;
  1113. procedure TWasmObjData.DeclareFuncType_Pass1(ft: tai_functype);
  1114. begin
  1115. FLastFuncName:=ft.funcname;
  1116. end;
  1117. procedure TWasmObjData.DeclareFuncType_Pass2(ft: tai_functype);
  1118. begin
  1119. FLastFuncName:=ft.funcname;
  1120. end;
  1121. procedure TWasmObjData.DeclareTagType(tt: tai_tagtype);
  1122. var
  1123. ObjSymExtraData: TWasmObjSymbolExtraData;
  1124. ft: TWasmFuncType;
  1125. i: Integer;
  1126. begin
  1127. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(tt.tagname);
  1128. ft:=TWasmFuncType.Create([],tt.params);
  1129. i:=FFuncTypes.AddOrGetFuncType(ft);
  1130. ft.free;
  1131. ObjSymExtraData.ExceptionTagTypeIdx:=i;
  1132. end;
  1133. procedure TWasmObjData.DeclareExportName(en: tai_export_name);
  1134. var
  1135. ObjSymExtraData: TWasmObjSymbolExtraData;
  1136. begin
  1137. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(en.intname);
  1138. ObjSymExtraData.ExportName:=en.extname;
  1139. end;
  1140. procedure TWasmObjData.DeclareImportModule(aim: tai_import_module);
  1141. var
  1142. ObjSymExtraData: TWasmObjSymbolExtraData;
  1143. begin
  1144. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(aim.symname);
  1145. ObjSymExtraData.ImportModule:=aim.importmodule;
  1146. end;
  1147. procedure TWasmObjData.DeclareImportName(ain: tai_import_name);
  1148. var
  1149. ObjSymExtraData: TWasmObjSymbolExtraData;
  1150. begin
  1151. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ain.symname);
  1152. ObjSymExtraData.ImportName:=ain.importname;
  1153. end;
  1154. procedure TWasmObjData.DeclareLocals_Pass0(al: tai_local);
  1155. var
  1156. ObjSymExtraData: TWasmObjSymbolExtraData;
  1157. begin
  1158. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1159. ObjSymExtraData.AddLocals(al.locals);
  1160. alloc(ObjSymExtraData.EncodedLocals.size);
  1161. end;
  1162. procedure TWasmObjData.DeclareLocals_Pass1(al: tai_local);
  1163. var
  1164. ObjSymExtraData: TWasmObjSymbolExtraData;
  1165. begin
  1166. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1167. alloc(ObjSymExtraData.EncodedLocals.size);
  1168. end;
  1169. procedure TWasmObjData.WriteLocals_Pass2(al: tai_local);
  1170. var
  1171. ObjSymExtraData: TWasmObjSymbolExtraData;
  1172. d: tdynamicarray;
  1173. buf: array [0..4095] of byte;
  1174. bs,size: Integer;
  1175. begin
  1176. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1177. d:=ObjSymExtraData.EncodedLocals;
  1178. d.seek(0);
  1179. size:=d.size;
  1180. while size>0 do
  1181. begin
  1182. if size<SizeOf(buf) then
  1183. bs:=Integer(size)
  1184. else
  1185. bs:=SizeOf(buf);
  1186. d.read(buf,bs);
  1187. writebytes(buf,bs);
  1188. dec(size,bs);
  1189. end;
  1190. end;
  1191. procedure TWasmObjData.symbolpairdefine(akind: TSymbolPairKind; const asym, avalue: string);
  1192. var
  1193. valsym: TObjSymbol;
  1194. aliassym: TWasmObjSymbol;
  1195. begin
  1196. valsym:=CreateSymbol(avalue);
  1197. aliassym:=TWasmObjSymbol(symboldefine(asym,valsym.bind,valsym.typ));
  1198. aliassym.AliasOf:=valsym.Name;
  1199. end;
  1200. {****************************************************************************
  1201. TWasmObjOutput
  1202. ****************************************************************************}
  1203. procedure TWasmObjOutput.WriteWasmSection(wsid: TWasmSectionID);
  1204. var
  1205. b: byte;
  1206. begin
  1207. b:=ord(wsid);
  1208. Writer.write(b,1);
  1209. WriteUleb(Writer,FWasmSections[wsid].size);
  1210. Writer.writearray(FWasmSections[wsid]);
  1211. end;
  1212. procedure TWasmObjOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  1213. var
  1214. b: byte;
  1215. begin
  1216. b:=0;
  1217. Writer.write(b,1);
  1218. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  1219. Writer.writearray(FWasmCustomSections[wcst]);
  1220. end;
  1221. function TWasmObjOutput.IsExternalFunction(sym: TObjSymbol): Boolean;
  1222. var
  1223. ExtraData: TWasmObjSymbolExtraData;
  1224. begin
  1225. if sym.bind=AB_EXTERNAL then
  1226. begin
  1227. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  1228. result:=(ExtraData<>nil) and (ExtraData.TypeIdx<>-1);
  1229. end
  1230. else
  1231. result:=false;
  1232. end;
  1233. function TWasmObjOutput.IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  1234. var
  1235. ExtraData: TWasmObjSymbolExtraData;
  1236. begin
  1237. if (sym.typ=AT_FUNCTION) and not sym.IsAlias then
  1238. begin
  1239. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  1240. result:=(ExtraData<>nil) and (ExtraData.ExportName<>'');
  1241. end
  1242. else
  1243. result:=false;
  1244. end;
  1245. procedure TWasmObjOutput.WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  1246. var
  1247. ObjSymExtraData: TWasmObjSymbolExtraData;
  1248. ObjSection: TWasmObjSection;
  1249. codelen: QWord;
  1250. begin
  1251. ObjSymExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1252. ObjSection:=TWasmObjSection(objsym.objsection);
  1253. ObjSection.Data.seek(objsym.address);
  1254. codelen:=objsym.size;
  1255. WriteUleb(dest,codelen);
  1256. ObjSection.FileSectionOfs:=dest.size-objsym.offset;
  1257. CopyDynamicArray(ObjSection.Data,dest,codelen);
  1258. end;
  1259. procedure TWasmObjOutput.WriteSymbolTable;
  1260. begin
  1261. WriteUleb(FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTableEntriesCount);
  1262. FWasmSymbolTable.seek(0);
  1263. CopyDynamicArray(FWasmSymbolTable,FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTable.size);
  1264. end;
  1265. procedure TWasmObjOutput.WriteRelocationCodeTable(CodeSectionIndex: Integer);
  1266. begin
  1267. WriteUleb(FWasmCustomSections[wcstRelocCode],CodeSectionIndex);
  1268. WriteUleb(FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTableEntriesCount);
  1269. FWasmRelocationCodeTable.seek(0);
  1270. CopyDynamicArray(FWasmRelocationCodeTable,FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTable.size);
  1271. end;
  1272. procedure TWasmObjOutput.WriteRelocationDataTable(DataSectionIndex: Integer);
  1273. begin
  1274. WriteUleb(FWasmCustomSections[wcstRelocData],DataSectionIndex);
  1275. WriteUleb(FWasmCustomSections[wcstRelocData],FWasmRelocationDataTableEntriesCount);
  1276. FWasmRelocationDataTable.seek(0);
  1277. CopyDynamicArray(FWasmRelocationDataTable,FWasmCustomSections[wcstRelocData],FWasmRelocationDataTable.size);
  1278. end;
  1279. procedure TWasmObjOutput.MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  1280. begin
  1281. if EntriesCount>0 then
  1282. begin
  1283. WriteUleb(FWasmCustomSections[cst],SectionIndex);
  1284. WriteUleb(FWasmCustomSections[cst],EntriesCount);
  1285. Table.seek(0);
  1286. CopyDynamicArray(Table,FWasmCustomSections[cst],Table.size);
  1287. WriteWasmCustomSection(cst);
  1288. end;
  1289. end;
  1290. procedure TWasmObjOutput.WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  1291. begin
  1292. if FWasmLinkingSubsections[wlst].size>0 then
  1293. begin
  1294. WriteByte(FWasmCustomSections[wcstLinking],Ord(wlst));
  1295. WriteUleb(FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1296. FWasmLinkingSubsections[wlst].seek(0);
  1297. CopyDynamicArray(FWasmLinkingSubsections[wlst],FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1298. end;
  1299. end;
  1300. procedure TWasmObjOutput.DoRelocations;
  1301. var
  1302. si, ri: Integer;
  1303. objsec: TWasmObjSection;
  1304. objrel: TWasmObjRelocation;
  1305. begin
  1306. for si:=0 to FData.ObjSectionList.Count-1 do
  1307. begin
  1308. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1309. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1310. begin
  1311. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1312. case objrel.typ of
  1313. RELOC_FUNCTION_INDEX_LEB:
  1314. begin
  1315. if not assigned(objrel.symbol) then
  1316. internalerror(2021092509);
  1317. objsec.Data.seek(objrel.DataOffset);
  1318. if TWasmObjSymbol(objrel.symbol).FuncIndex<0 then
  1319. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1320. else
  1321. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).FuncIndex);
  1322. end;
  1323. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1324. begin
  1325. if not assigned(objrel.symbol) then
  1326. internalerror(2021092605);
  1327. if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1328. begin
  1329. objsec.Data.seek(objrel.DataOffset);
  1330. AddSleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1331. end;
  1332. end;
  1333. RELOC_MEMORY_ADDR_LEB:
  1334. begin
  1335. if not assigned(objrel.symbol) then
  1336. internalerror(2021092606);
  1337. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1338. internalerror(2021092628);
  1339. if objrel.symbol.bind<>AB_EXTERNAL then
  1340. begin
  1341. objsec.Data.seek(objrel.DataOffset);
  1342. AddUleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1343. end;
  1344. end;
  1345. RELOC_ABSOLUTE:
  1346. begin
  1347. if assigned(objrel.ObjSection) then
  1348. begin
  1349. { todo: should we do something here? }
  1350. //Writeln('todo: section relocation');
  1351. end
  1352. else if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1353. begin
  1354. objsec.Data.seek(objrel.DataOffset);
  1355. AddInt32(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1356. end;
  1357. end;
  1358. RELOC_TYPE_INDEX_LEB:
  1359. ;
  1360. RELOC_GLOBAL_INDEX_LEB:
  1361. begin
  1362. if not assigned(objrel.symbol) then
  1363. internalerror(2021092509);
  1364. objsec.Data.seek(objrel.DataOffset);
  1365. if TWasmObjSymbol(objrel.symbol).GlobalIndex<0 then
  1366. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1367. else
  1368. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
  1369. end;
  1370. RELOC_TAG_INDEX_LEB:
  1371. begin
  1372. if not assigned(objrel.symbol) then
  1373. internalerror(2021092716);
  1374. objsec.Data.seek(objrel.DataOffset);
  1375. if TWasmObjSymbol(objrel.symbol).TagIndex<0 then
  1376. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1377. else
  1378. WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
  1379. end;
  1380. else
  1381. internalerror(2021092510);
  1382. end;
  1383. end;
  1384. end;
  1385. end;
  1386. procedure TWasmObjOutput.WriteRelocations;
  1387. var
  1388. si, ri: Integer;
  1389. objsec: TWasmObjSection;
  1390. objrel: TWasmObjRelocation;
  1391. relout: tdynamicarray;
  1392. relcount: PInteger;
  1393. FuncSym: TWasmObjSymbol;
  1394. begin
  1395. for si:=0 to FData.ObjSectionList.Count-1 do
  1396. begin
  1397. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1398. if objsec.IsCode then
  1399. begin
  1400. relout:=FWasmRelocationCodeTable;
  1401. relcount:=@FWasmRelocationCodeTableEntriesCount;
  1402. end
  1403. else if objsec.IsData then
  1404. begin
  1405. relout:=FWasmRelocationDataTable;
  1406. relcount:=@FWasmRelocationDataTableEntriesCount;
  1407. end
  1408. else if objsec.IsDebug then
  1409. begin
  1410. case objsec.Name of
  1411. '.debug_frame':
  1412. begin
  1413. relout:=FWasmRelocationDebugFrameTable;
  1414. relcount:=@FWasmRelocationDebugFrameTableEntriesCount;
  1415. end;
  1416. '.debug_info':
  1417. begin
  1418. relout:=FWasmRelocationDebugInfoTable;
  1419. relcount:=@FWasmRelocationDebugInfoTableEntriesCount;
  1420. end;
  1421. '.debug_line':
  1422. begin
  1423. relout:=FWasmRelocationDebugLineTable;
  1424. relcount:=@FWasmRelocationDebugLineTableEntriesCount;
  1425. end;
  1426. '.debug_abbrev':
  1427. begin
  1428. relout:=FWasmRelocationDebugAbbrevTable;
  1429. relcount:=@FWasmRelocationDebugAbbrevTableEntriesCount;
  1430. end;
  1431. '.debug_aranges':
  1432. begin
  1433. relout:=FWasmRelocationDebugArangesTable;
  1434. relcount:=@FWasmRelocationDebugArangesTableEntriesCount;
  1435. end;
  1436. '.debug_ranges':
  1437. begin
  1438. relout:=FWasmRelocationDebugRangesTable;
  1439. relcount:=@FWasmRelocationDebugRangesTableEntriesCount;
  1440. end;
  1441. '.debug_str':
  1442. begin
  1443. relout:=FWasmRelocationDebugStrTable;
  1444. relcount:=@FWasmRelocationDebugStrTableEntriesCount;
  1445. end;
  1446. else
  1447. internalerror(2022071601);
  1448. end;
  1449. end
  1450. else
  1451. continue;
  1452. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1453. begin
  1454. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1455. case objrel.typ of
  1456. RELOC_FUNCTION_INDEX_LEB:
  1457. begin
  1458. if not assigned(objrel.symbol) then
  1459. internalerror(2021092508);
  1460. Inc(relcount^);
  1461. WriteByte(relout,Ord(R_WASM_FUNCTION_INDEX_LEB));
  1462. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1463. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1464. end;
  1465. RELOC_MEMORY_ADDR_LEB:
  1466. begin
  1467. if not assigned(objrel.symbol) then
  1468. internalerror(2021092603);
  1469. Inc(relcount^);
  1470. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1471. internalerror(2021092628);
  1472. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_LEB));
  1473. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1474. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1475. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1476. end;
  1477. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1478. begin
  1479. if not assigned(objrel.symbol) then
  1480. internalerror(2021092604);
  1481. Inc(relcount^);
  1482. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1483. begin
  1484. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_SLEB));
  1485. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1486. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1487. end
  1488. else
  1489. begin
  1490. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_SLEB));
  1491. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1492. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1493. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1494. end;
  1495. end;
  1496. RELOC_ABSOLUTE:
  1497. begin
  1498. // todo: figure this out, why do these exist?
  1499. //if assigned(objrel.symbol) and not assigned(objrel.symbol.objsection) then
  1500. // Writeln('!!! ', objrel.symbol.name);
  1501. if assigned(objrel.objsection) then
  1502. begin
  1503. Inc(relcount^);
  1504. WriteByte(relout,Ord(R_WASM_SECTION_OFFSET_I32));
  1505. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1506. if (TWasmObjSection(objrel.objsection).SegSymIdx<0) then
  1507. message1(asmw_e_illegal_unset_index,objrel.objsection.name)
  1508. else
  1509. WriteUleb(relout,TWasmObjSection(objrel.objsection).SegSymIdx);
  1510. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1511. end
  1512. else if (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION)) and not objsec.IsDebug then
  1513. begin
  1514. Inc(relcount^);
  1515. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_I32));
  1516. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1517. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1518. end
  1519. else if assigned(objrel.symbol) and assigned(objrel.symbol.objsection) and TWasmObjSection(objrel.symbol.objsection).IsCode then
  1520. begin
  1521. Inc(relcount^);
  1522. WriteByte(relout,Ord(R_WASM_FUNCTION_OFFSET_I32));
  1523. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1524. FuncSym:=FindFunctionSymbol(TWasmObjSymbol(objrel.Symbol));
  1525. if FuncSym.SymbolIndex<0 then
  1526. message1(asmw_e_illegal_unset_index,FuncSym.Name)
  1527. else
  1528. WriteUleb(relout,FuncSym.SymbolIndex);
  1529. WriteSleb(relout,objrel.Addend+objrel.symbol.address) { addend to add to the address }
  1530. end
  1531. else if assigned(objrel.symbol) and (objrel.symbol.typ=AT_WASM_GLOBAL) then
  1532. begin
  1533. Inc(relcount^);
  1534. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_I32));
  1535. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1536. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1537. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1538. else
  1539. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1540. end
  1541. else
  1542. begin
  1543. Inc(relcount^);
  1544. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_I32));
  1545. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1546. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1547. begin
  1548. Writeln(objrel.symbol.objsection.Name, ' ', objrel.symbol.name, ' ', objsec.Name);
  1549. message1(asmw_e_illegal_unset_index,objrel.symbol.name);
  1550. end
  1551. else
  1552. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1553. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1554. end;
  1555. end;
  1556. RELOC_TYPE_INDEX_LEB:
  1557. begin
  1558. Inc(relcount^);
  1559. WriteByte(relout,Ord(R_WASM_TYPE_INDEX_LEB));
  1560. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1561. WriteUleb(relout,objrel.TypeIndex);
  1562. end;
  1563. RELOC_GLOBAL_INDEX_LEB:
  1564. begin
  1565. if not assigned(objrel.symbol) then
  1566. internalerror(2021092704);
  1567. Inc(relcount^);
  1568. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_LEB));
  1569. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1570. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1571. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1572. else
  1573. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1574. end;
  1575. RELOC_TAG_INDEX_LEB:
  1576. begin
  1577. if not assigned(objrel.symbol) then
  1578. internalerror(2021092717);
  1579. Inc(relcount^);
  1580. WriteByte(relout,Ord(R_WASM_TAG_INDEX_LEB));
  1581. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1582. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1583. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1584. else
  1585. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1586. end;
  1587. else
  1588. internalerror(2021092507);
  1589. end;
  1590. end;
  1591. end;
  1592. end;
  1593. function TWasmObjOutput.FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  1594. begin
  1595. Result:=TWasmObjSection(Symbol.objsection).MainFuncSymbol;
  1596. end;
  1597. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  1598. var
  1599. section_nr: Integer;
  1600. procedure MaybeAddDebugSectionToSymbolTable(st: TWasmCustomDebugSectionType; var debug_section_nr: Integer);
  1601. var
  1602. objsec: TWasmObjSection;
  1603. begin
  1604. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1605. if Assigned(objsec) then
  1606. begin
  1607. debug_section_nr:=section_nr;
  1608. Inc(section_nr);
  1609. objsec.SegSymIdx:=FWasmSymbolTableEntriesCount;
  1610. objsec.CustomSectionIdx:=debug_section_nr;
  1611. Inc(FWasmSymbolTableEntriesCount);
  1612. WriteByte(FWasmSymbolTable,Ord(SYMTAB_SECTION));
  1613. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL);
  1614. WriteUleb(FWasmSymbolTable,debug_section_nr);
  1615. end;
  1616. end;
  1617. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  1618. var
  1619. objsec: TWasmObjSection;
  1620. begin
  1621. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1622. if Assigned(objsec) then
  1623. begin
  1624. if oso_Data in objsec.SecOptions then
  1625. begin
  1626. objsec.Data.seek(0);
  1627. CopyDynamicArray(objsec.Data,FWasmCustomSections[st],objsec.Size);
  1628. end
  1629. else
  1630. WriteZeros(FWasmCustomSections[st],objsec.Size);
  1631. WriteWasmCustomSection(st);
  1632. end;
  1633. end;
  1634. var
  1635. i: Integer;
  1636. objsec: TWasmObjSection;
  1637. segment_count: Integer = 0;
  1638. cur_seg_ofs: qword = 0;
  1639. imports_count, NextImportFunctionIndex, NextFunctionIndex,
  1640. code_section_nr, data_section_nr,
  1641. debug_abbrev_section_nr,debug_info_section_nr,debug_str_section_nr,
  1642. debug_line_section_nr,debug_frame_section_nr,debug_aranges_section_nr,
  1643. debug_ranges_section_nr,
  1644. NextGlobalIndex, NextTagIndex: Integer;
  1645. import_globals_count: Integer = 0;
  1646. globals_count: Integer = 0;
  1647. import_functions_count: Integer = 0;
  1648. export_functions_count: Integer = 0;
  1649. functions_count: Integer = 0;
  1650. import_exception_tags_count: Integer = 0;
  1651. exception_tags_count: Integer = 0;
  1652. objsym, ObjSymAlias: TWasmObjSymbol;
  1653. cust_sec: TWasmCustomSectionType;
  1654. SegmentFlags, SymbolFlags: UInt64;
  1655. begin
  1656. FData:=TWasmObjData(Data);
  1657. { each custom sections starts with its name }
  1658. for cust_sec in TWasmCustomSectionType do
  1659. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  1660. WriteUleb(FWasmCustomSections[wcstLinking],2); { linking metadata version }
  1661. for i:=0 to Data.ObjSymbolList.Count-1 do
  1662. begin
  1663. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1664. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1665. if objsym.bind=AB_EXTERNAL then
  1666. Inc(import_exception_tags_count)
  1667. else
  1668. Inc(exception_tags_count);
  1669. if objsym.typ=AT_WASM_GLOBAL then
  1670. if objsym.bind=AB_EXTERNAL then
  1671. Inc(import_globals_count)
  1672. else
  1673. Inc(globals_count);
  1674. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1675. Inc(import_globals_count);
  1676. if IsExternalFunction(objsym) then
  1677. Inc(import_functions_count);
  1678. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1679. begin
  1680. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  1681. Inc(functions_count);
  1682. end;
  1683. if IsExportedFunction(objsym) then
  1684. Inc(export_functions_count);
  1685. end;
  1686. FData.FFuncTypes.WriteTo(FWasmSections[wsiType]);
  1687. for i:=0 to Data.ObjSectionList.Count-1 do
  1688. begin
  1689. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  1690. if objsec.IsCode then
  1691. objsec.SegIdx:=-1
  1692. else if objsec.IsData then
  1693. begin
  1694. objsec.SegIdx:=segment_count;
  1695. objsec.SegOfs:=cur_seg_ofs;
  1696. Inc(segment_count);
  1697. Inc(cur_seg_ofs,objsec.Size);
  1698. end;
  1699. end;
  1700. imports_count:=2+import_globals_count+import_functions_count+import_exception_tags_count;
  1701. WriteUleb(FWasmSections[wsiImport],imports_count);
  1702. { import memories }
  1703. WriteName(FWasmSections[wsiImport],'env');
  1704. WriteName(FWasmSections[wsiImport],'__linear_memory');
  1705. WriteByte(FWasmSections[wsiImport],$02); { mem }
  1706. WriteByte(FWasmSections[wsiImport],$00); { min }
  1707. WriteUleb(FWasmSections[wsiImport],1); { 1 page }
  1708. { import globals }
  1709. NextGlobalIndex:=0;
  1710. for i:=0 to Data.ObjSymbolList.Count-1 do
  1711. begin
  1712. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1713. if (objsym.bind=AB_EXTERNAL) and (objsym.typ=AT_WASM_GLOBAL) then
  1714. begin
  1715. objsym.GlobalIndex:=NextGlobalIndex;
  1716. Inc(NextGlobalIndex);
  1717. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1718. if objsym.ExtraData.ImportModule<>'' then
  1719. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1720. else
  1721. WriteName(FWasmSections[wsiImport],'env');
  1722. WriteName(FWasmSections[wsiImport],objsym.Name);
  1723. WriteByte(FWasmSections[wsiImport],$03); { global }
  1724. WriteWasmBasicType(FWasmSections[wsiImport],objsym.ExtraData.GlobalType);
  1725. if objsym.ExtraData.GlobalIsImmutable then
  1726. WriteByte(FWasmSections[wsiImport],$00) { const }
  1727. else
  1728. WriteByte(FWasmSections[wsiImport],$01); { var }
  1729. end
  1730. else if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1731. begin
  1732. objsym.GlobalIndex:=NextGlobalIndex;
  1733. Inc(NextGlobalIndex);
  1734. objsym.ExtraData:=nil;
  1735. WriteName(FWasmSections[wsiImport],'GOT.mem');
  1736. WriteName(FWasmSections[wsiImport],objsym.Name);
  1737. WriteByte(FWasmSections[wsiImport],$03); { global }
  1738. WriteWasmBasicType(FWasmSections[wsiImport],wbt_i32); { i32 }
  1739. WriteByte(FWasmSections[wsiImport],$01); { var }
  1740. end;
  1741. end;
  1742. { import functions }
  1743. NextImportFunctionIndex:=0;
  1744. for i:=0 to Data.ObjSymbolList.Count-1 do
  1745. begin
  1746. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1747. if IsExternalFunction(objsym) then
  1748. begin
  1749. objsym.FuncIndex:=NextImportFunctionIndex;
  1750. Inc(NextImportFunctionIndex);
  1751. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1752. if objsym.ExtraData.ImportModule<>'' then
  1753. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1754. else
  1755. WriteName(FWasmSections[wsiImport],'env');
  1756. WriteName(FWasmSections[wsiImport],objsym.Name);
  1757. WriteByte(FWasmSections[wsiImport],$00); { func }
  1758. WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1759. end;
  1760. end;
  1761. { import tables }
  1762. WriteName(FWasmSections[wsiImport],'env');
  1763. WriteName(FWasmSections[wsiImport],'__indirect_function_table');
  1764. WriteByte(FWasmSections[wsiImport],$01); { table }
  1765. WriteByte(FWasmSections[wsiImport],$70); { funcref }
  1766. WriteByte(FWasmSections[wsiImport],$00); { min }
  1767. WriteUleb(FWasmSections[wsiImport],1); { 1 }
  1768. { import tags }
  1769. NextTagIndex:=0;
  1770. for i:=0 to Data.ObjSymbolList.Count-1 do
  1771. begin
  1772. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1773. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind=AB_EXTERNAL) then
  1774. begin
  1775. objsym.TagIndex:=NextTagIndex;
  1776. Inc(NextTagIndex);
  1777. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1778. if objsym.ExtraData.ImportModule<>'' then
  1779. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1780. else
  1781. WriteName(FWasmSections[wsiImport],'env');
  1782. WriteName(FWasmSections[wsiImport],objsym.Name);
  1783. WriteByte(FWasmSections[wsiImport],$04); { tag }
  1784. WriteByte(FWasmSections[wsiImport],$00); { exception }
  1785. WriteUleb(FWasmSections[wsiImport],objsym.ExtraData.ExceptionTagTypeIdx);
  1786. end;
  1787. end;
  1788. WriteUleb(FWasmSections[wsiFunction],functions_count);
  1789. NextFunctionIndex:=NextImportFunctionIndex;
  1790. for i:=0 to Data.ObjSymbolList.Count-1 do
  1791. begin
  1792. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1793. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1794. begin
  1795. objsym.FuncIndex:=NextFunctionIndex;
  1796. Inc(NextFunctionIndex);
  1797. WriteUleb(FWasmSections[wsiFunction],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1798. end;
  1799. end;
  1800. if exception_tags_count>0 then
  1801. begin
  1802. WriteUleb(FWasmSections[wsiTag],exception_tags_count);
  1803. for i:=0 to Data.ObjSymbolList.Count-1 do
  1804. begin
  1805. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1806. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind<>AB_EXTERNAL) then
  1807. begin
  1808. objsym.TagIndex:=NextTagIndex;
  1809. Inc(NextTagIndex);
  1810. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1811. WriteByte(FWasmSections[wsiTag],$00); { exception }
  1812. WriteUleb(FWasmSections[wsiTag],objsym.ExtraData.ExceptionTagTypeIdx);
  1813. end;
  1814. end;
  1815. end;
  1816. if globals_count>0 then
  1817. begin
  1818. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  1819. for i:=0 to Data.ObjSymbolList.Count-1 do
  1820. begin
  1821. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1822. if (objsym.typ=AT_WASM_GLOBAL) and (objsym.bind<>AB_EXTERNAL) then
  1823. begin
  1824. objsym.GlobalIndex:=NextGlobalIndex;
  1825. Inc(NextGlobalIndex);
  1826. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1827. WriteWasmBasicType(FWasmSections[wsiGlobal],objsym.ExtraData.GlobalType);
  1828. if objsym.ExtraData.GlobalIsImmutable then
  1829. WriteByte(FWasmSections[wsiGlobal],$00) { const }
  1830. else
  1831. WriteByte(FWasmSections[wsiGlobal],$01); { var }
  1832. { init expr }
  1833. case objsym.ExtraData.GlobalType of
  1834. wbt_i32:
  1835. begin
  1836. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  1837. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1838. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1839. end;
  1840. wbt_i64:
  1841. begin
  1842. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  1843. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1844. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1845. end;
  1846. wbt_f32:
  1847. begin
  1848. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  1849. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE single precision floating point format) }
  1850. WriteByte(FWasmSections[wsiGlobal],$00);
  1851. WriteByte(FWasmSections[wsiGlobal],$00);
  1852. WriteByte(FWasmSections[wsiGlobal],$00);
  1853. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1854. end;
  1855. wbt_f64:
  1856. begin
  1857. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  1858. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE double precision floating point format) }
  1859. WriteByte(FWasmSections[wsiGlobal],$00);
  1860. WriteByte(FWasmSections[wsiGlobal],$00);
  1861. WriteByte(FWasmSections[wsiGlobal],$00);
  1862. WriteByte(FWasmSections[wsiGlobal],$00);
  1863. WriteByte(FWasmSections[wsiGlobal],$00);
  1864. WriteByte(FWasmSections[wsiGlobal],$00);
  1865. WriteByte(FWasmSections[wsiGlobal],$00);
  1866. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1867. end;
  1868. wbt_externref:
  1869. begin
  1870. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null extern }
  1871. WriteByte(FWasmSections[wsiGlobal],$6F);
  1872. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1873. end;
  1874. wbt_funcref:
  1875. begin
  1876. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null func }
  1877. WriteByte(FWasmSections[wsiGlobal],$70);
  1878. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1879. end;
  1880. else
  1881. internalerror(2022052801);
  1882. end;
  1883. end;
  1884. end;
  1885. end;
  1886. if export_functions_count>0 then
  1887. begin
  1888. WriteUleb(FWasmSections[wsiExport],export_functions_count);
  1889. for i:=0 to Data.ObjSymbolList.Count-1 do
  1890. begin
  1891. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1892. if IsExportedFunction(objsym) then
  1893. begin
  1894. WriteName(FWasmSections[wsiExport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).ExportName);
  1895. WriteByte(FWasmSections[wsiExport],0); { func }
  1896. if (objsym.FuncIndex<0) then
  1897. message1(asmw_e_illegal_unset_index,objsym.name)
  1898. else
  1899. WriteUleb(FWasmSections[wsiExport],objsym.FuncIndex);
  1900. end;
  1901. end;
  1902. end;
  1903. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  1904. Writer.write(WasmVersion,SizeOf(WasmVersion));
  1905. if ts_wasm_threads in current_settings.targetswitches then
  1906. begin
  1907. WriteUleb(FWasmCustomSections[wcstTargetFeatures],4);
  1908. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1909. WriteName(FWasmCustomSections[wcstTargetFeatures],'atomics');
  1910. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1911. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1912. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1913. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1914. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1915. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1916. end
  1917. else
  1918. begin
  1919. WriteUleb(FWasmCustomSections[wcstTargetFeatures],3);
  1920. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1921. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1922. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1923. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1924. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1925. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1926. end;
  1927. { Write the producers section:
  1928. https://github.com/WebAssembly/tool-conventions/blob/main/ProducersSection.md }
  1929. WriteUleb(FWasmCustomSections[wcstProducers],2);
  1930. WriteName(FWasmCustomSections[wcstProducers],'language');
  1931. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1932. WriteName(FWasmCustomSections[wcstProducers],'Pascal');
  1933. WriteName(FWasmCustomSections[wcstProducers],'');
  1934. WriteName(FWasmCustomSections[wcstProducers],'processed-by');
  1935. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1936. WriteName(FWasmCustomSections[wcstProducers],'Free Pascal Compiler (FPC)');
  1937. WriteName(FWasmCustomSections[wcstProducers],full_version_string+' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname);
  1938. code_section_nr:=-1;
  1939. data_section_nr:=-1;
  1940. debug_abbrev_section_nr:=-1;
  1941. debug_info_section_nr:=-1;
  1942. debug_str_section_nr:=-1;
  1943. debug_line_section_nr:=-1;
  1944. debug_frame_section_nr:=-1;
  1945. debug_aranges_section_nr:=-1;
  1946. debug_ranges_section_nr:=-1;
  1947. section_nr:=0;
  1948. WriteWasmSection(wsiType);
  1949. Inc(section_nr);
  1950. WriteWasmSection(wsiImport);
  1951. Inc(section_nr);
  1952. WriteWasmSection(wsiFunction);
  1953. Inc(section_nr);
  1954. if exception_tags_count>0 then
  1955. begin
  1956. WriteWasmSection(wsiTag);
  1957. Inc(section_nr);
  1958. end;
  1959. if globals_count>0 then
  1960. begin
  1961. WriteWasmSection(wsiGlobal);
  1962. Inc(section_nr);
  1963. end;
  1964. if export_functions_count>0 then
  1965. begin
  1966. WriteWasmSection(wsiExport);
  1967. Inc(section_nr);
  1968. end;
  1969. { determine the section numbers for the datacount, code, data and debug sections ahead of time }
  1970. if segment_count>0 then
  1971. Inc(section_nr); { the DataCount section }
  1972. code_section_nr:=section_nr; { the Code section }
  1973. Inc(section_nr);
  1974. if segment_count>0 then
  1975. begin
  1976. data_section_nr:=section_nr; { the Data section }
  1977. Inc(section_nr);
  1978. end;
  1979. { the debug sections }
  1980. MaybeAddDebugSectionToSymbolTable(wcstDebugAbbrev,debug_abbrev_section_nr);
  1981. MaybeAddDebugSectionToSymbolTable(wcstDebugInfo,debug_info_section_nr);
  1982. MaybeAddDebugSectionToSymbolTable(wcstDebugStr,debug_str_section_nr);
  1983. MaybeAddDebugSectionToSymbolTable(wcstDebugLine,debug_line_section_nr);
  1984. MaybeAddDebugSectionToSymbolTable(wcstDebugFrame,debug_frame_section_nr);
  1985. MaybeAddDebugSectionToSymbolTable(wcstDebugAranges,debug_aranges_section_nr);
  1986. MaybeAddDebugSectionToSymbolTable(wcstDebugRanges,debug_ranges_section_nr);
  1987. for i:=0 to Data.ObjSymbolList.Count-1 do
  1988. begin
  1989. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1990. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1991. begin
  1992. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1993. Inc(FWasmSymbolTableEntriesCount);
  1994. WriteByte(FWasmSymbolTable,Ord(SYMTAB_EVENT));
  1995. if objsym.bind=AB_GLOBAL then
  1996. WriteUleb(FWasmSymbolTable,0)
  1997. else if objsym.bind=AB_LOCAL then
  1998. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL)
  1999. else if objsym.bind=AB_EXTERNAL then
  2000. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED)
  2001. else if objsym.bind=AB_WEAK then
  2002. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_WEAK)
  2003. else
  2004. internalerror(2021092715);
  2005. if (objsym.TagIndex<0) then
  2006. message1(asmw_e_illegal_unset_index,objsym.name)
  2007. else
  2008. WriteUleb(FWasmSymbolTable,objsym.TagIndex);
  2009. if objsym.bind<>AB_EXTERNAL then
  2010. WriteName(FWasmSymbolTable,objsym.Name);
  2011. end
  2012. else if objsym.typ=AT_WASM_GLOBAL then
  2013. begin
  2014. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2015. Inc(FWasmSymbolTableEntriesCount);
  2016. WriteByte(FWasmSymbolTable,Ord(SYMTAB_GLOBAL));
  2017. if objsym.bind=AB_EXTERNAL then
  2018. begin
  2019. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  2020. if (objsym.GlobalIndex<0) then
  2021. message1(asmw_e_illegal_unset_index,objsym.name)
  2022. else
  2023. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  2024. end
  2025. else
  2026. begin
  2027. WriteUleb(FWasmSymbolTable,0);
  2028. if (objsym.GlobalIndex<0) then
  2029. message1(asmw_e_illegal_unset_index,objsym.name)
  2030. else
  2031. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  2032. WriteName(FWasmSymbolTable,objsym.Name);
  2033. end;
  2034. end
  2035. else if IsExternalFunction(objsym) then
  2036. begin
  2037. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2038. Inc(FWasmSymbolTableEntriesCount);
  2039. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  2040. if objsym.ExtraData.ImportModule<>'' then
  2041. begin
  2042. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED or WASM_SYM_EXPLICIT_NAME);
  2043. if (objsym.FuncIndex<0) then
  2044. message1(asmw_e_illegal_unset_index,objsym.name)
  2045. else
  2046. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2047. WriteName(FWasmSymbolTable,objsym.Name);
  2048. end
  2049. else
  2050. begin
  2051. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  2052. if (objsym.FuncIndex<0) then
  2053. message1(asmw_e_illegal_unset_index,objsym.name)
  2054. else
  2055. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2056. end;
  2057. end
  2058. else if objsym.typ=AT_FUNCTION then
  2059. begin
  2060. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2061. Inc(FWasmSymbolTableEntriesCount);
  2062. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  2063. if objsym.IsAlias then
  2064. begin
  2065. ObjSymAlias:=TWasmObjSymbol(Data.ObjSymbolList.Find(objsym.AliasOf));
  2066. ObjSym.FuncIndex:=ObjSymAlias.FuncIndex;
  2067. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPLICIT_NAME or WASM_SYM_NO_STRIP);
  2068. WriteUleb(FWasmSymbolTable,ObjSymAlias.FuncIndex);
  2069. end
  2070. else
  2071. begin
  2072. if IsExportedFunction(objsym) then
  2073. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPORTED)
  2074. else
  2075. WriteUleb(FWasmSymbolTable,0);
  2076. if (objsym.FuncIndex<0) then
  2077. message1(asmw_e_illegal_unset_index,objsym.name)
  2078. else
  2079. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2080. end;
  2081. WriteName(FWasmSymbolTable,objsym.Name);
  2082. end
  2083. else if (objsym.typ in [AT_DATA,AT_TLS,AT_METADATA]) or ((objsym.typ=AT_NONE) and (objsym.bind=AB_EXTERNAL)) then
  2084. begin
  2085. if (objsym.bind<>AB_EXTERNAL) and TWasmObjSection(objsym.objsection).IsDebug then
  2086. begin
  2087. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2088. Inc(FWasmSymbolTableEntriesCount);
  2089. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FPC_CUSTOM));
  2090. if objsym.bind=AB_GLOBAL then
  2091. SymbolFlags:=0
  2092. else if objsym.bind=AB_LOCAL then
  2093. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  2094. else if objsym.bind=AB_EXTERNAL then
  2095. SymbolFlags:=WASM_SYM_UNDEFINED
  2096. else
  2097. internalerror(2024090701);
  2098. WriteUleb(FWasmSymbolTable,SymbolFlags);
  2099. WriteName(FWasmSymbolTable,objsym.Name);
  2100. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).CustomSectionIdx);
  2101. WriteUleb(FWasmSymbolTable,objsym.offset);
  2102. WriteUleb(FWasmSymbolTable,objsym.size);
  2103. end
  2104. else
  2105. begin
  2106. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2107. Inc(FWasmSymbolTableEntriesCount);
  2108. WriteByte(FWasmSymbolTable,Ord(SYMTAB_DATA));
  2109. if objsym.bind=AB_GLOBAL then
  2110. SymbolFlags:=0
  2111. else if objsym.bind=AB_LOCAL then
  2112. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  2113. else if objsym.bind=AB_EXTERNAL then
  2114. SymbolFlags:=WASM_SYM_UNDEFINED
  2115. else
  2116. internalerror(2021092506);
  2117. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  2118. SymbolFlags:=(SymbolFlags and not WASM_SYM_BINDING_LOCAL) or WASM_SYM_TLS;
  2119. WriteUleb(FWasmSymbolTable,SymbolFlags);
  2120. WriteName(FWasmSymbolTable,objsym.Name);
  2121. if objsym.bind<>AB_EXTERNAL then
  2122. begin
  2123. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).SegIdx);
  2124. WriteUleb(FWasmSymbolTable,objsym.offset);
  2125. WriteUleb(FWasmSymbolTable,objsym.size);
  2126. end;
  2127. end;
  2128. end;
  2129. end;
  2130. DoRelocations;
  2131. if segment_count>0 then
  2132. begin
  2133. WriteUleb(FWasmSections[wsiData],segment_count);
  2134. WriteUleb(FWasmSections[wsiDataCount],segment_count);
  2135. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],segment_count);
  2136. for i:=0 to Data.ObjSectionList.Count-1 do
  2137. begin
  2138. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  2139. if objsec.IsData then
  2140. begin
  2141. WriteName(FWasmLinkingSubsections[WASM_SEGMENT_INFO],objsec.Name);
  2142. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],BsrQWord(objsec.SecAlign));
  2143. SegmentFlags:=0;
  2144. if (ts_wasm_threads in current_settings.targetswitches) and
  2145. (oso_threadvar in objsec.SecOptions) then
  2146. SegmentFlags:=SegmentFlags or WASM_SEG_FLAG_TLS;
  2147. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],SegmentFlags); { flags }
  2148. WriteByte(FWasmSections[wsiData],0);
  2149. WriteByte(FWasmSections[wsiData],$41);
  2150. WriteSleb(FWasmSections[wsiData],objsec.SegOfs);
  2151. WriteByte(FWasmSections[wsiData],$0b);
  2152. WriteUleb(FWasmSections[wsiData],objsec.Size);
  2153. objsec.FileSectionOfs:=FWasmSections[wsiData].size;
  2154. if oso_Data in objsec.SecOptions then
  2155. begin
  2156. objsec.Data.seek(0);
  2157. CopyDynamicArray(objsec.Data,FWasmSections[wsiData],objsec.Size);
  2158. end
  2159. else
  2160. begin
  2161. WriteZeros(FWasmSections[wsiData],objsec.Size);
  2162. end;
  2163. end;
  2164. end;
  2165. end;
  2166. WriteUleb(FWasmSections[wsiCode],functions_count);
  2167. for i:=0 to Data.ObjSymbolList.Count-1 do
  2168. begin
  2169. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  2170. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  2171. WriteFunctionCode(FWasmSections[wsiCode],objsym);
  2172. end;
  2173. if segment_count>0 then
  2174. WriteWasmSection(wsiDataCount);
  2175. WriteWasmSection(wsiCode);
  2176. if segment_count>0 then
  2177. WriteWasmSection(wsiData);
  2178. MaybeWriteDebugSection(wcstDebugAbbrev);
  2179. MaybeWriteDebugSection(wcstDebugInfo);
  2180. MaybeWriteDebugSection(wcstDebugStr);
  2181. MaybeWriteDebugSection(wcstDebugLine);
  2182. MaybeWriteDebugSection(wcstDebugFrame);
  2183. MaybeWriteDebugSection(wcstDebugAranges);
  2184. MaybeWriteDebugSection(wcstDebugRanges);
  2185. WriteRelocations;
  2186. WriteSymbolTable;
  2187. WriteLinkingSubsection(WASM_SYMBOL_TABLE);
  2188. if segment_count>0 then
  2189. WriteLinkingSubsection(WASM_SEGMENT_INFO);
  2190. WriteRelocationCodeTable(code_section_nr);
  2191. if segment_count>0 then
  2192. WriteRelocationDataTable(data_section_nr);
  2193. WriteWasmCustomSection(wcstLinking);
  2194. Inc(section_nr);
  2195. WriteWasmCustomSection(wcstRelocCode);
  2196. Inc(section_nr);
  2197. if segment_count>0 then
  2198. begin
  2199. WriteWasmCustomSection(wcstRelocData);
  2200. Inc(section_nr);
  2201. end;
  2202. MaybeWriteRelocationDebugTable(wcstRelocDebugAbbrev,debug_abbrev_section_nr,FWasmRelocationDebugAbbrevTableEntriesCount,FWasmRelocationDebugAbbrevTable);
  2203. MaybeWriteRelocationDebugTable(wcstRelocDebugInfo,debug_info_section_nr,FWasmRelocationDebugInfoTableEntriesCount,FWasmRelocationDebugInfoTable);
  2204. MaybeWriteRelocationDebugTable(wcstRelocDebugStr,debug_str_section_nr,FWasmRelocationDebugStrTableEntriesCount,FWasmRelocationDebugStrTable);
  2205. MaybeWriteRelocationDebugTable(wcstRelocDebugLine,debug_line_section_nr,FWasmRelocationDebugLineTableEntriesCount,FWasmRelocationDebugLineTable);
  2206. MaybeWriteRelocationDebugTable(wcstRelocDebugFrame,debug_frame_section_nr,FWasmRelocationDebugFrameTableEntriesCount,FWasmRelocationDebugFrameTable);
  2207. MaybeWriteRelocationDebugTable(wcstRelocDebugAranges,debug_aranges_section_nr,FWasmRelocationDebugArangesTableEntriesCount,FWasmRelocationDebugArangesTable);
  2208. MaybeWriteRelocationDebugTable(wcstRelocDebugRanges,debug_ranges_section_nr,FWasmRelocationDebugRangesTableEntriesCount,FWasmRelocationDebugRangesTable);
  2209. WriteWasmCustomSection(wcstProducers);
  2210. Inc(section_nr);
  2211. WriteWasmCustomSection(wcstTargetFeatures);
  2212. Inc(section_nr);
  2213. result:=true;
  2214. end;
  2215. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  2216. var
  2217. i: TWasmSectionID;
  2218. j: TWasmCustomSectionType;
  2219. k: TWasmLinkingSubsectionType;
  2220. begin
  2221. inherited;
  2222. cobjdata:=TWasmObjData;
  2223. for i in TWasmSectionID do
  2224. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  2225. for j in TWasmCustomSectionType do
  2226. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  2227. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  2228. FWasmLinkingSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  2229. FWasmSymbolTable:=tdynamicarray.create(SectionDataMaxGrow);
  2230. FWasmSymbolTableEntriesCount:=0;
  2231. FWasmRelocationCodeTable:=tdynamicarray.create(SectionDataMaxGrow);
  2232. FWasmRelocationCodeTableEntriesCount:=0;
  2233. FWasmRelocationDataTable:=tdynamicarray.create(SectionDataMaxGrow);
  2234. FWasmRelocationDataTableEntriesCount:=0;
  2235. FWasmRelocationDebugFrameTable:=tdynamicarray.create(SectionDataMaxGrow);
  2236. FWasmRelocationDebugFrameTableEntriesCount:=0;
  2237. FWasmRelocationDebugInfoTable:=tdynamicarray.create(SectionDataMaxGrow);
  2238. FWasmRelocationDebugInfoTableEntriesCount:=0;
  2239. FWasmRelocationDebugLineTable:=tdynamicarray.create(SectionDataMaxGrow);
  2240. FWasmRelocationDebugLineTableEntriesCount:=0;
  2241. FWasmRelocationDebugAbbrevTable:=tdynamicarray.create(SectionDataMaxGrow);
  2242. FWasmRelocationDebugAbbrevTableEntriesCount:=0;
  2243. FWasmRelocationDebugArangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  2244. FWasmRelocationDebugArangesTableEntriesCount:=0;
  2245. FWasmRelocationDebugRangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  2246. FWasmRelocationDebugRangesTableEntriesCount:=0;
  2247. FWasmRelocationDebugStrTable:=tdynamicarray.create(SectionDataMaxGrow);
  2248. FWasmRelocationDebugStrTableEntriesCount:=0;
  2249. end;
  2250. destructor TWasmObjOutput.destroy;
  2251. var
  2252. i: TWasmSectionID;
  2253. j: TWasmCustomSectionType;
  2254. k: TWasmLinkingSubsectionType;
  2255. begin
  2256. for i in TWasmSectionID do
  2257. FWasmSections[i].Free;
  2258. for j in TWasmCustomSectionType do
  2259. FWasmCustomSections[j].Free;
  2260. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  2261. FWasmLinkingSubsections[k].Free;
  2262. FWasmSymbolTable.Free;
  2263. FWasmRelocationCodeTable.Free;
  2264. FWasmRelocationDataTable.Free;
  2265. FWasmRelocationDebugFrameTable.Free;
  2266. FWasmRelocationDebugInfoTable.Free;
  2267. FWasmRelocationDebugLineTable.Free;
  2268. FWasmRelocationDebugAbbrevTable.Free;
  2269. FWasmRelocationDebugArangesTable.Free;
  2270. FWasmRelocationDebugRangesTable.Free;
  2271. FWasmRelocationDebugStrTable.Free;
  2272. inherited destroy;
  2273. end;
  2274. {****************************************************************************
  2275. TWasmObjInput
  2276. ****************************************************************************}
  2277. constructor TWasmObjInput.create;
  2278. begin
  2279. inherited create;
  2280. cobjdata:=TWasmObjData;
  2281. end;
  2282. destructor TWasmObjInput.Destroy;
  2283. var
  2284. i: Integer;
  2285. begin
  2286. for i:=low(FFuncTypes) to high(FFuncTypes) do
  2287. begin
  2288. FFuncTypes[i].free;
  2289. FFuncTypes[i]:=nil;
  2290. end;
  2291. inherited Destroy;
  2292. end;
  2293. class function TWasmObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  2294. var
  2295. ModuleMagic: array [0..3] of Byte;
  2296. ModuleVersion: array [0..3] of Byte;
  2297. i: Integer;
  2298. begin
  2299. result:=false;
  2300. if not AReader.read(ModuleMagic,4) then
  2301. exit;
  2302. for i:=0 to 3 do
  2303. if ModuleMagic[i]<>WasmModuleMagic[i] then
  2304. exit;
  2305. if not AReader.read(ModuleVersion,4) then
  2306. exit;
  2307. for i:=0 to 3 do
  2308. if ModuleVersion[i]<>WasmVersion[i] then
  2309. exit;
  2310. result:=true;
  2311. end;
  2312. function TWasmObjInput.ReadObjData(AReader: TObjectreader; out ObjData: TObjData): boolean;
  2313. type
  2314. TLimits = record
  2315. Min, Max: uint32;
  2316. HasMax: Boolean;
  2317. end;
  2318. var
  2319. SectionIndex: Integer = -1;
  2320. SectionId: Byte;
  2321. SectionSize: uint32;
  2322. SectionStart: LongInt;
  2323. CheckSectionBounds: Boolean;
  2324. TypeSectionRead: Boolean = false;
  2325. ImportSectionRead: Boolean = false;
  2326. FunctionSectionRead: Boolean = false;
  2327. GlobalSectionRead: Boolean = false;
  2328. ExportSectionRead: Boolean = false;
  2329. ElementSectionRead: Boolean = false;
  2330. TagSectionRead: Boolean = false;
  2331. CodeSectionRead: Boolean = false;
  2332. DataSectionRead: Boolean = false;
  2333. DataCountSectionRead: Boolean = false;
  2334. SegmentInfoSectionRead: Boolean = false;
  2335. SymbolTableSectionRead: Boolean = false;
  2336. CodeSectionIndex: Integer = -1;
  2337. DataSectionIndex: Integer = -1;
  2338. DebugSectionIndex: array [TWasmCustomDebugSectionType] of Integer = (-1,-1,-1,-1,-1,-1,-1);
  2339. FuncTypes: array of record
  2340. IsImport: Boolean;
  2341. ImportName: ansistring;
  2342. ImportModName: ansistring;
  2343. typidx: uint32;
  2344. IsExported: Boolean;
  2345. ExportName: ansistring;
  2346. end;
  2347. FuncTypeImportsCount: uint32;
  2348. TableTypes: array of record
  2349. IsImport: Boolean;
  2350. ImportName: ansistring;
  2351. ImportModName: ansistring;
  2352. reftype: TWasmBAsicType;
  2353. limits: TLimits;
  2354. IsExported: Boolean;
  2355. ExportName: ansistring;
  2356. end;
  2357. TableTypeImportsCount: uint32;
  2358. MemTypes: array of record
  2359. IsImport: Boolean;
  2360. ImportName: ansistring;
  2361. ImportModName: ansistring;
  2362. limits: TLimits;
  2363. IsExported: Boolean;
  2364. ExportName: ansistring;
  2365. end;
  2366. MemTypeImportsCount: uint32;
  2367. GlobalTypes: array of record
  2368. IsImport: Boolean;
  2369. ImportName: ansistring;
  2370. ImportModName: ansistring;
  2371. valtype: TWasmBasicType;
  2372. IsMutable: Boolean;
  2373. IsExported: Boolean;
  2374. ExportName: ansistring;
  2375. GlobalInit: TGlobalInitializer;
  2376. end;
  2377. GlobalTypeImportsCount: uint32;
  2378. TagTypes: array of record
  2379. IsImport: Boolean;
  2380. ImportName: ansistring;
  2381. ImportModName: ansistring;
  2382. TagAttr: Byte;
  2383. TagTypeIdx: uint32;
  2384. IsExported: Boolean;
  2385. ExportName: ansistring;
  2386. end;
  2387. TagTypeImportsCount: uint32;
  2388. CodeSegments: array of record
  2389. CodeSectionOffset: uint32;
  2390. CodeSize: uint32;
  2391. DataPos: LongInt;
  2392. SegName: ansistring;
  2393. SegIsExported: Boolean;
  2394. end;
  2395. DataSegments: array of record
  2396. DataSectionOffset: uint32;
  2397. Active: Boolean;
  2398. MemIdx: uint32;
  2399. Len: uint32;
  2400. Offset: int32;
  2401. DataPos: LongInt;
  2402. SegName: ansistring;
  2403. SegAlignment: uint32;
  2404. SegFlags: uint32;
  2405. end;
  2406. SymbolTable: array of record
  2407. SymFlags: uint32;
  2408. TargetSection: uint32;
  2409. SymIndex: uint32;
  2410. SymOffset: uint32;
  2411. SymSize: uint32;
  2412. SymCustomSectionIndex: uint32;
  2413. SymCustomSectionType: TWasmCustomDebugSectionType;
  2414. SymKind: TWasmSymbolType;
  2415. SymName: ansistring;
  2416. ObjSym: TWasmObjSymbol;
  2417. ObjSec: TWasmObjSection;
  2418. end;
  2419. { meaning of first index: }
  2420. { table 0 is code relocs }
  2421. { table 1 is data relocs }
  2422. { tables 2.. are custom section relocs for debug sections }
  2423. RelocationTable: array of array of record
  2424. RelocType: TWasmRelocationType;
  2425. RelocOffset: uint32;
  2426. RelocIndex: uint32;
  2427. RelocAddend: int32;
  2428. end;
  2429. function FindDebugSectionByIndex(SectionIndex: Integer; out res: TWasmCustomDebugSectionType): Boolean;
  2430. var
  2431. ds: TWasmCustomDebugSectionType;
  2432. begin
  2433. for ds in TWasmCustomDebugSectionType do
  2434. if DebugSectionIndex[ds]=SectionIndex then
  2435. begin
  2436. Res:=ds;
  2437. Result:=True;
  2438. exit;
  2439. end;
  2440. Res:=low(TWasmCustomDebugSectionType);
  2441. Result:=False;
  2442. end;
  2443. function ReadSection: Boolean;
  2444. function read(out b;len:longint):boolean;
  2445. begin
  2446. result:=false;
  2447. if not CheckSectionBounds or ((AReader.Pos+len)<=(SectionStart+SectionSize)) then
  2448. result:=AReader.read(b,len)
  2449. else
  2450. begin
  2451. { trying to read beyond the end of the section }
  2452. AReader.read(b,SectionStart+SectionSize-AReader.Pos);
  2453. result:=false;
  2454. end;
  2455. end;
  2456. function ReadUleb(out v: uint64): boolean;
  2457. var
  2458. b: byte;
  2459. shift:integer;
  2460. begin
  2461. result:=false;
  2462. b:=0;
  2463. v:=0;
  2464. shift:=0;
  2465. repeat
  2466. if not read(b,1) then
  2467. exit;
  2468. v:=v or (uint64(b and 127) shl shift);
  2469. inc(shift,7);
  2470. until (b and 128)=0;
  2471. result:=true;
  2472. end;
  2473. function ReadUleb32(out v: uint32): boolean;
  2474. var
  2475. vv: uint64;
  2476. begin
  2477. result:=false;
  2478. v:=default(uint32);
  2479. if not ReadUleb(vv) then
  2480. exit;
  2481. if vv>high(uint32) then
  2482. exit;
  2483. v:=vv;
  2484. result:=true;
  2485. end;
  2486. function ReadSleb(out v: int64): boolean;
  2487. var
  2488. b: byte;
  2489. shift:integer;
  2490. begin
  2491. result:=false;
  2492. b:=0;
  2493. v:=0;
  2494. shift:=0;
  2495. repeat
  2496. if not read(b,1) then
  2497. exit;
  2498. v:=v or (uint64(b and 127) shl shift);
  2499. inc(shift,7);
  2500. until (b and 128)=0;
  2501. {$ifopt Q+}
  2502. {$define overflowon}
  2503. {$Q-}
  2504. {$endif}
  2505. {$ifopt R+}
  2506. {$define rangeon}
  2507. {$R-}
  2508. {$endif}
  2509. if (b and 64)<>0 then
  2510. v:=v or (high(uint64) shl shift);
  2511. result:=true;
  2512. end;
  2513. {$ifdef overflowon}
  2514. {$Q+}
  2515. {$undef overflowon}
  2516. {$endif}
  2517. {$ifdef rangeon}
  2518. {$R+}
  2519. {$undef rangeon}
  2520. {$endif}
  2521. function ReadSleb32(out v: int32): boolean;
  2522. var
  2523. vv: int64;
  2524. begin
  2525. result:=false;
  2526. v:=default(int32);
  2527. if not ReadSleb(vv) then
  2528. exit;
  2529. if (vv>high(int32)) or (vv<low(int32)) then
  2530. exit;
  2531. v:=vv;
  2532. result:=true;
  2533. end;
  2534. function ReadName(out v: ansistring): boolean;
  2535. var
  2536. len: uint32;
  2537. begin
  2538. result:=false;
  2539. if not ReadUleb32(len) then
  2540. exit;
  2541. SetLength(v,len);
  2542. if len>0 then
  2543. result:=read(v[1],len)
  2544. else
  2545. result:=true;
  2546. end;
  2547. function ReadCustomSection: Boolean;
  2548. function ReadRelocationSection: Boolean;
  2549. var
  2550. TargetSection, RelocCount: uint32;
  2551. i: Integer;
  2552. RelocTableIndex: Integer;
  2553. ds: TWasmCustomDebugSectionType;
  2554. begin
  2555. Result:=False;
  2556. if not ReadUleb32(TargetSection) then
  2557. begin
  2558. InputError('Error reading the index of the target section of a relocation section');
  2559. exit;
  2560. end;
  2561. if TargetSection=CodeSectionIndex then
  2562. RelocTableIndex:=0
  2563. else if TargetSection=DataSectionIndex then
  2564. RelocTableIndex:=1
  2565. else
  2566. begin
  2567. RelocTableIndex:=-1;
  2568. for ds:=Low(DebugSectionIndex) to High(DebugSectionIndex) do
  2569. if DebugSectionIndex[ds]=TargetSection then
  2570. begin
  2571. RelocTableIndex:=2+(Ord(ds)-Ord(Low(TWasmCustomDebugSectionType)));
  2572. break;
  2573. end;
  2574. if RelocTableIndex=-1 then
  2575. begin
  2576. InputError('Relocation found for a custom section, that is not supported');
  2577. exit;
  2578. end;
  2579. end;
  2580. if not ReadUleb32(RelocCount) then
  2581. begin
  2582. InputError('Error reading the relocation entries count from a relocation section');
  2583. exit;
  2584. end;
  2585. SetLength(RelocationTable[RelocTableIndex],RelocCount);
  2586. for i:=0 to RelocCount-1 do
  2587. with RelocationTable[RelocTableIndex,i] do
  2588. begin
  2589. if not Read(RelocType,1) then
  2590. begin
  2591. InputError('Error reading the relocation type of a relocation entry');
  2592. exit;
  2593. end;
  2594. if not (RelocType in [R_WASM_FUNCTION_INDEX_LEB,
  2595. R_WASM_MEMORY_ADDR_LEB,
  2596. R_WASM_TABLE_INDEX_SLEB,
  2597. R_WASM_MEMORY_ADDR_SLEB,
  2598. R_WASM_SECTION_OFFSET_I32,
  2599. R_WASM_TABLE_INDEX_I32,
  2600. R_WASM_FUNCTION_OFFSET_I32,
  2601. R_WASM_MEMORY_ADDR_I32,
  2602. R_WASM_TYPE_INDEX_LEB,
  2603. R_WASM_GLOBAL_INDEX_LEB,
  2604. R_WASM_TAG_INDEX_LEB,
  2605. R_WASM_GLOBAL_INDEX_I32]) then
  2606. begin
  2607. InputError('Unsupported relocation type: ' + tostr(Ord(RelocType)));
  2608. exit;
  2609. end;
  2610. if not ReadUleb32(RelocOffset) then
  2611. begin
  2612. InputError('Error reading the relocation offset of a relocation entry');
  2613. exit;
  2614. end;
  2615. if not ReadUleb32(RelocIndex) then
  2616. begin
  2617. InputError('Error reading the relocation index of a relocation entry');
  2618. exit;
  2619. end;
  2620. if RelocType in [R_WASM_FUNCTION_OFFSET_I32,R_WASM_SECTION_OFFSET_I32,R_WASM_MEMORY_ADDR_LEB,R_WASM_MEMORY_ADDR_SLEB,R_WASM_MEMORY_ADDR_I32] then
  2621. begin
  2622. if not ReadSleb32(RelocAddend) then
  2623. begin
  2624. InputError('Error reading the relocation addend of a relocation entry');
  2625. exit;
  2626. end;
  2627. end;
  2628. if (RelocType in [
  2629. R_WASM_SECTION_OFFSET_I32,
  2630. R_WASM_FUNCTION_INDEX_LEB,
  2631. R_WASM_TABLE_INDEX_SLEB,
  2632. R_WASM_TABLE_INDEX_I32,
  2633. R_WASM_MEMORY_ADDR_LEB,
  2634. R_WASM_MEMORY_ADDR_SLEB,
  2635. R_WASM_MEMORY_ADDR_I32,
  2636. R_WASM_FUNCTION_OFFSET_I32,
  2637. R_WASM_GLOBAL_INDEX_LEB,
  2638. R_WASM_GLOBAL_INDEX_I32]) and (RelocIndex>High(SymbolTable)) then
  2639. begin
  2640. InputError('Relocation index outside the bounds of the symbol table');
  2641. exit;
  2642. end;
  2643. if (RelocType=R_WASM_TYPE_INDEX_LEB) and (RelocIndex>High(FFuncTypes)) then
  2644. begin
  2645. InputError('Relocation index of R_WASM_TYPE_INDEX_LEB outside the bounds of the func types, defined in the func section of the module');
  2646. exit;
  2647. end;
  2648. if (RelocType=R_WASM_SECTION_OFFSET_I32) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_SECTION) then
  2649. begin
  2650. InputError('R_WASM_SECTION_OFFSET_I32 must point to a SYMTAB_SECTION symbol');
  2651. exit;
  2652. end;
  2653. if (RelocType in [R_WASM_GLOBAL_INDEX_LEB,R_WASM_GLOBAL_INDEX_I32]) and
  2654. not ((SymbolTable[RelocIndex].SymKind=SYMTAB_GLOBAL) or
  2655. ((ts_wasm_threads in current_settings.targetswitches) and
  2656. (SymbolTable[RelocIndex].SymKind=SYMTAB_DATA) and
  2657. ((SymbolTable[RelocIndex].SymFlags and WASM_SYM_TLS)<>0))) then
  2658. begin
  2659. if ts_wasm_threads in current_settings.targetswitches then
  2660. InputError('Relocation must point to a SYMTAB_GLOBAL symbol or a SYMTAB_DATA symbol with the WASM_SYM_TLS flag set')
  2661. else
  2662. InputError('Relocation must point to a SYMTAB_GLOBAL symbol');
  2663. exit;
  2664. end;
  2665. if (RelocType=R_WASM_TAG_INDEX_LEB) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_EVENT) then
  2666. begin
  2667. InputError('Relocation must point to a SYMTAB_EVENT symbol');
  2668. exit;
  2669. end;
  2670. if (RelocType in [
  2671. R_WASM_FUNCTION_INDEX_LEB,
  2672. R_WASM_TABLE_INDEX_SLEB,
  2673. R_WASM_TABLE_INDEX_I32,
  2674. R_WASM_FUNCTION_OFFSET_I32]) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_FUNCTION) then
  2675. begin
  2676. InputError('Relocation must point to a SYMTAB_FUNCTION symbol');
  2677. exit;
  2678. end;
  2679. if (RelocType in [
  2680. R_WASM_MEMORY_ADDR_LEB,
  2681. R_WASM_MEMORY_ADDR_SLEB,
  2682. R_WASM_MEMORY_ADDR_I32]) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_DATA) then
  2683. begin
  2684. InputError('Relocation must point to a SYMTAB_DATA symbol');
  2685. exit;
  2686. end;
  2687. end;
  2688. if AReader.Pos<>(SectionStart+SectionSize) then
  2689. begin
  2690. InputError('Unexpected relocation section size');
  2691. exit;
  2692. end;
  2693. Result:=True;
  2694. end;
  2695. function ReadLinkingSection: Boolean;
  2696. function ReadSegmentInfo: Boolean;
  2697. var
  2698. SegmentCount: uint32;
  2699. i: Integer;
  2700. begin
  2701. Result:=False;
  2702. if SegmentInfoSectionRead then
  2703. begin
  2704. InputError('The WASM_SEGMENT_INFO subsection is duplicated');
  2705. exit;
  2706. end;
  2707. SegmentInfoSectionRead:=True;
  2708. if not ReadUleb32(SegmentCount) then
  2709. begin
  2710. InputError('Error reading the segment count from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2711. exit;
  2712. end;
  2713. if SegmentCount<>Length(DataSegments) then
  2714. begin
  2715. InputError('Segment count in the WASM_SEGMENT_INFO subsection does not match the data count in the data section');
  2716. exit;
  2717. end;
  2718. for i:=0 to SegmentCount-1 do
  2719. with DataSegments[i] do
  2720. begin
  2721. if not ReadName(SegName) then
  2722. begin
  2723. InputError('Error reading segment name from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2724. exit;
  2725. end;
  2726. if not ReadUleb32(SegAlignment) then
  2727. begin
  2728. InputError('Error reading segment alignment from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2729. exit;
  2730. end;
  2731. if not ReadUleb32(SegFlags) then
  2732. begin
  2733. InputError('Error reading segment flags from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2734. exit;
  2735. end;
  2736. end;
  2737. if AReader.Pos<>(SectionStart+SectionSize) then
  2738. begin
  2739. InputError('Unexpected WASM_SEGMENT_INFO section size');
  2740. exit;
  2741. end;
  2742. Result:=True;
  2743. end;
  2744. function ReadSymbolTable: Boolean;
  2745. var
  2746. SymCount: uint32;
  2747. i: Integer;
  2748. SymKindName: string;
  2749. SymKindB: Byte;
  2750. begin
  2751. Result:=False;
  2752. if SymbolTableSectionRead then
  2753. begin
  2754. InputError('The WASM_SYMBOL_TABLE subsection is duplicated');
  2755. exit;
  2756. end;
  2757. SymbolTableSectionRead:=True;
  2758. if not ReadUleb32(SymCount) then
  2759. begin
  2760. InputError('Error reading the symbol count from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2761. exit;
  2762. end;
  2763. SetLength(SymbolTable,SymCount);
  2764. for i:=0 to SymCount-1 do
  2765. with SymbolTable[i] do
  2766. begin
  2767. if not Read(SymKindB,1) then
  2768. begin
  2769. InputError('Error reading symbol type from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2770. exit;
  2771. end;
  2772. if SymKindB>Ord(High(TWasmSymbolType)) then
  2773. begin
  2774. InputError('Unsupported symbol type from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2775. exit;
  2776. end;
  2777. SymKind:=TWasmSymbolType(SymKindB);
  2778. if not ReadUleb32(SymFlags) then
  2779. begin
  2780. InputError('Error reading symbol flags from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2781. exit;
  2782. end;
  2783. case SymKind of
  2784. SYMTAB_FUNCTION,
  2785. SYMTAB_GLOBAL,
  2786. SYMTAB_EVENT,
  2787. SYMTAB_TABLE:
  2788. begin
  2789. WriteStr(SymKindName, SymKind);
  2790. if not ReadUleb32(SymIndex) then
  2791. begin
  2792. InputError('Error reading the index of a ' + SymKindName + ' symbol');
  2793. exit;
  2794. end;
  2795. if ((SymKind=SYMTAB_FUNCTION) and (SymIndex>high(FuncTypes))) or
  2796. ((SymKind=SYMTAB_EVENT) and (SymIndex>high(TagTypes))) then
  2797. begin
  2798. InputError('Symbol index too high');
  2799. exit;
  2800. end;
  2801. if ((SymFlags and WASM_SYM_EXPLICIT_NAME)<>0) or
  2802. ((SymFlags and WASM_SYM_UNDEFINED)=0) then
  2803. begin
  2804. if not ReadName(SymName) then
  2805. begin
  2806. InputError('Error reading symbol name of a ' + SymKindName + ' symbol');
  2807. exit;
  2808. end;
  2809. end;
  2810. end;
  2811. SYMTAB_DATA:
  2812. begin
  2813. if not ReadName(SymName) then
  2814. begin
  2815. InputError('Error reading symbol name of a SYMTAB_DATA symbol');
  2816. exit;
  2817. end;
  2818. if (SymFlags and WASM_SYM_UNDEFINED)=0 then
  2819. begin
  2820. if not ReadUleb32(SymIndex) then
  2821. begin
  2822. InputError('Error reading the data segment index of a SYMTAB_DATA symbol');
  2823. exit;
  2824. end;
  2825. if SymIndex>high(DataSegments) then
  2826. begin
  2827. InputError('Data segment index of SYMTAB_DATA symbol out of bounds');
  2828. exit;
  2829. end;
  2830. if not ReadUleb32(SymOffset) then
  2831. begin
  2832. InputError('Error reading the offset of a SYMTAB_DATA symbol');
  2833. exit;
  2834. end;
  2835. if not ReadUleb32(SymSize) then
  2836. begin
  2837. InputError('Error reading the size of a SYMTAB_DATA symbol');
  2838. exit;
  2839. end;
  2840. end;
  2841. end;
  2842. SYMTAB_FPC_CUSTOM:
  2843. begin
  2844. if not ReadName(SymName) then
  2845. begin
  2846. InputError('Error reading symbol name of a SYMTAB_FPC_CUSTOM symbol');
  2847. exit;
  2848. end;
  2849. if (SymFlags and WASM_SYM_UNDEFINED)=0 then
  2850. begin
  2851. if not ReadUleb32(SymCustomSectionIndex) then
  2852. begin
  2853. InputError('Error reading the custom section index of a SYMTAB_FPC_CUSTOM symbol');
  2854. exit;
  2855. end;
  2856. if not FindDebugSectionByIndex(SymCustomSectionIndex,SymCustomSectionType) then
  2857. begin
  2858. InputError('Custom section index of SYMTAB_FPC_CUSTOM symbol not pointing to a debug section');
  2859. exit;
  2860. end;
  2861. if not ReadUleb32(SymOffset) then
  2862. begin
  2863. InputError('Error reading the offset of a SYMTAB_FPC_CUSTOM symbol');
  2864. exit;
  2865. end;
  2866. if not ReadUleb32(SymSize) then
  2867. begin
  2868. InputError('Error reading the size of a SYMTAB_FPC_CUSTOM symbol');
  2869. exit;
  2870. end;
  2871. end;
  2872. end;
  2873. SYMTAB_SECTION:
  2874. begin
  2875. if not ReadUleb32(TargetSection) then
  2876. begin
  2877. InputError('Error reading the target section of a SYMTAB_SECTION symbol');
  2878. exit;
  2879. end;
  2880. end;
  2881. end;
  2882. end;
  2883. if AReader.Pos<>(SectionStart+SectionSize) then
  2884. begin
  2885. InputError('Unexpected WASM_SYMBOL_TABLE section size');
  2886. exit;
  2887. end;
  2888. Result:=True;
  2889. end;
  2890. const
  2891. ExpectedVersion = 2;
  2892. var
  2893. Version, SubsectionSize, SaveSectionSize: uint32;
  2894. SubsectionType: Byte;
  2895. SaveSectionStart: LongInt;
  2896. begin
  2897. Result:=False;
  2898. if not ReadUleb32(Version) then
  2899. begin
  2900. InputError('Error reading the version of the ''linking'' section');
  2901. exit;
  2902. end;
  2903. if Version<>ExpectedVersion then
  2904. begin
  2905. InputError('The ''linking'' section has an unsupported version (expected version ' + tostr(ExpectedVersion) + ', got version ' + tostr(Version) + ')');
  2906. exit;
  2907. end;
  2908. while AReader.Pos<(SectionStart+SectionSize) do
  2909. begin
  2910. if not read(SubsectionType, 1) then
  2911. begin
  2912. InputError('Error reading subsection type in the ''linking'' section');
  2913. exit;
  2914. end;
  2915. if not ReadUleb32(SubsectionSize) then
  2916. begin
  2917. InputError('Error reading subsection size in the ''linking'' section');
  2918. exit;
  2919. end;
  2920. if (AReader.Pos+SubsectionSize)>(SectionStart+SectionSize) then
  2921. begin
  2922. InputError('Subsection size exceeds bounds of its parent ''linking'' section');
  2923. exit;
  2924. end;
  2925. SaveSectionStart:=SectionStart;
  2926. SaveSectionSize:=SectionSize;
  2927. SectionStart:=AReader.Pos;
  2928. SectionSize:=SubsectionSize;
  2929. case SubsectionType of
  2930. Byte(WASM_SEGMENT_INFO):
  2931. if not ReadSegmentInfo then
  2932. begin
  2933. InputError('Error reading the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2934. exit;
  2935. end;
  2936. Byte(WASM_SYMBOL_TABLE):
  2937. if not ReadSymbolTable then
  2938. begin
  2939. InputError('Error reading the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2940. exit;
  2941. end;
  2942. else
  2943. begin
  2944. InputError('Unsupported ''linking'' section subsection type ' + tostr(SubsectionType));
  2945. exit;
  2946. end;
  2947. end;
  2948. AReader.Seek(SectionStart+SectionSize);
  2949. SectionStart:=SaveSectionStart;
  2950. SectionSize:=SaveSectionSize;
  2951. end;
  2952. result:=True;
  2953. end;
  2954. function ReadProducersSection: Boolean;
  2955. begin
  2956. Result:=False;
  2957. end;
  2958. function ReadTargetFeaturesSection: Boolean;
  2959. begin
  2960. Result:=False;
  2961. end;
  2962. function ReadDebugSection(const SectionName: string; SectionType: TWasmCustomDebugSectionType): Boolean;
  2963. var
  2964. ObjSec: TObjSection;
  2965. begin
  2966. Result:=False;
  2967. if DebugSectionIndex[SectionType]<>-1 then
  2968. begin
  2969. InputError('Duplicated debug section: ' + SectionName);
  2970. exit;
  2971. end;
  2972. DebugSectionIndex[SectionType]:=SectionIndex;
  2973. ObjSec:=ObjData.createsection(SectionName,1,[oso_Data,oso_debug],false);
  2974. ObjSec.DataPos:=AReader.Pos;
  2975. ObjSec.Size:=SectionStart+SectionSize-AReader.Pos;
  2976. Result:=True;
  2977. end;
  2978. const
  2979. RelocationSectionPrefix = 'reloc.';
  2980. var
  2981. SectionName: ansistring;
  2982. begin
  2983. Result:=False;
  2984. ReadName(SectionName);
  2985. if Copy(SectionName,1,Length(RelocationSectionPrefix)) = RelocationSectionPrefix then
  2986. begin
  2987. if not ReadRelocationSection then
  2988. begin
  2989. InputError('Error reading the relocation section ''' + SectionName + '''');
  2990. exit;
  2991. end;
  2992. end
  2993. else
  2994. case SectionName of
  2995. 'linking':
  2996. if not ReadLinkingSection then
  2997. begin
  2998. InputError('Error reading the ''linking'' section');
  2999. exit;
  3000. end;
  3001. 'producers':
  3002. Result:=ReadProducersSection;
  3003. 'target_features':
  3004. Result:=ReadTargetFeaturesSection;
  3005. '.debug_frame':
  3006. if not ReadDebugSection(SectionName, wcstDebugFrame) then
  3007. begin
  3008. InputError('Error reading section ' + SectionName);
  3009. exit;
  3010. end;
  3011. '.debug_info':
  3012. if not ReadDebugSection(SectionName, wcstDebugInfo) then
  3013. begin
  3014. InputError('Error reading section ' + SectionName);
  3015. exit;
  3016. end;
  3017. '.debug_line':
  3018. if not ReadDebugSection(SectionName, wcstDebugLine) then
  3019. begin
  3020. InputError('Error reading section ' + SectionName);
  3021. exit;
  3022. end;
  3023. '.debug_abbrev':
  3024. if not ReadDebugSection(SectionName, wcstDebugAbbrev) then
  3025. begin
  3026. InputError('Error reading section ' + SectionName);
  3027. exit;
  3028. end;
  3029. '.debug_aranges':
  3030. if not ReadDebugSection(SectionName, wcstDebugAranges) then
  3031. begin
  3032. InputError('Error reading section ' + SectionName);
  3033. exit;
  3034. end;
  3035. '.debug_ranges':
  3036. if not ReadDebugSection(SectionName, wcstDebugRanges) then
  3037. begin
  3038. InputError('Error reading section ' + SectionName);
  3039. exit;
  3040. end;
  3041. '.debug_str':
  3042. if not ReadDebugSection(SectionName, wcstDebugStr) then
  3043. begin
  3044. InputError('Error reading section ' + SectionName);
  3045. exit;
  3046. end;
  3047. else
  3048. InputError('Unsupported custom section: ''' + SectionName + '''');
  3049. end;
  3050. Result:=True;
  3051. end;
  3052. function ReadTypeSection: Boolean;
  3053. var
  3054. FuncTypesCount, ParamsCount, ResultsCount: uint32;
  3055. FuncTypeId, WasmTypeId: Byte;
  3056. i, j: Integer;
  3057. wbt: TWasmBasicType;
  3058. begin
  3059. Result:=False;
  3060. if TypeSectionRead then
  3061. begin
  3062. InputError('Type section is duplicated');
  3063. exit;
  3064. end;
  3065. TypeSectionRead:=True;
  3066. if not ReadUleb32(FuncTypesCount) then
  3067. begin
  3068. InputError('Error reading the func types count');
  3069. exit;
  3070. end;
  3071. SetLength(FFuncTypes,FuncTypesCount);
  3072. for i:=0 to FuncTypesCount - 1 do
  3073. begin
  3074. FFuncTypes[i]:=TWasmFuncType.Create([],[]);
  3075. if not AReader.read(FuncTypeId,1) then
  3076. begin
  3077. InputError('Error reading the function type identifier');
  3078. exit;
  3079. end;
  3080. if FuncTypeId<>$60 then
  3081. begin
  3082. InputError('Incorrect function type identifier (expected $60, got $' + HexStr(FuncTypeId,2) + ')');
  3083. exit;
  3084. end;
  3085. if not ReadUleb32(ParamsCount) then
  3086. begin
  3087. InputError('Error reading the function parameters count');
  3088. exit;
  3089. end;
  3090. for j:=0 to ParamsCount-1 do
  3091. begin
  3092. if not AReader.read(WasmTypeId,1) then
  3093. begin
  3094. InputError('Error reading a function parameter basic type');
  3095. exit;
  3096. end;
  3097. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  3098. begin
  3099. InputError('Unknown function parameter basic type: $' + HexStr(WasmTypeId,2));
  3100. exit;
  3101. end;
  3102. FFuncTypes[i].add_param(wbt);
  3103. end;
  3104. if not ReadUleb32(ResultsCount) then
  3105. begin
  3106. InputError('Error reading the function results count');
  3107. exit;
  3108. end;
  3109. for j:=0 to ResultsCount-1 do
  3110. begin
  3111. if not AReader.read(WasmTypeId,1) then
  3112. begin
  3113. InputError('Error reading a function result basic type');
  3114. exit;
  3115. end;
  3116. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  3117. begin
  3118. InputError('Unknown function result basic type: $' + HexStr(WasmTypeId,2));
  3119. exit;
  3120. end;
  3121. FFuncTypes[i].add_result(wbt);
  3122. end;
  3123. end;
  3124. if AReader.Pos<>(SectionStart+SectionSize) then
  3125. begin
  3126. InputError('Unexpected type section size');
  3127. exit;
  3128. end;
  3129. Result:=true;
  3130. end;
  3131. function ReadImportSection: Boolean;
  3132. var
  3133. ImportsCount: uint32;
  3134. i: Integer;
  3135. ModName, Name: ansistring;
  3136. ImportType, TableElemTyp, TableLimitsKind, MemoryLimitsKind,
  3137. GlobalType, GlobalMutabilityType: Byte;
  3138. begin
  3139. Result:=False;
  3140. if ImportSectionRead then
  3141. begin
  3142. InputError('Import section is duplicated');
  3143. exit;
  3144. end;
  3145. ImportSectionRead:=True;
  3146. if not ReadUleb32(ImportsCount) then
  3147. begin
  3148. InputError('Error reading the imports count');
  3149. exit;
  3150. end;
  3151. for i:=0 to ImportsCount-1 do
  3152. begin
  3153. if not ReadName(ModName) then
  3154. begin
  3155. InputError('Error reading import module name');
  3156. exit;
  3157. end;
  3158. if not ReadName(Name) then
  3159. begin
  3160. InputError('Error import name');
  3161. exit;
  3162. end;
  3163. if not AReader.Read(ImportType,1) then
  3164. begin
  3165. InputError('Error reading import type');
  3166. exit;
  3167. end;
  3168. case ImportType of
  3169. $00: { func }
  3170. begin
  3171. Inc(FuncTypeImportsCount);
  3172. SetLength(FuncTypes,FuncTypeImportsCount);
  3173. with FuncTypes[FuncTypeImportsCount-1] do
  3174. begin
  3175. IsImport:=True;
  3176. ImportName:=Name;
  3177. ImportModName:=ModName;
  3178. if not ReadUleb32(typidx) then
  3179. begin
  3180. InputError('Error reading type index for func import');
  3181. exit;
  3182. end;
  3183. if typidx>high(FFuncTypes) then
  3184. begin
  3185. InputError('Type index in func import exceeds bounds of the types table');
  3186. exit;
  3187. end;
  3188. end;
  3189. end;
  3190. $01: { table }
  3191. begin
  3192. Inc(TableTypeImportsCount);
  3193. SetLength(TableTypes,TableTypeImportsCount);
  3194. with TableTypes[TableTypeImportsCount-1] do
  3195. begin
  3196. IsImport:=True;
  3197. ImportName:=Name;
  3198. ImportModName:=ModName;
  3199. if not AReader.read(TableElemTyp,1) then
  3200. begin
  3201. InputError('Error reading table element type for table import');
  3202. exit;
  3203. end;
  3204. if not decode_wasm_basic_type(TableElemTyp,reftype) then
  3205. begin
  3206. InputError('Invalid table element type for table import: $' + HexStr(TableElemTyp,2));
  3207. exit;
  3208. end;
  3209. if not (reftype in WasmReferenceTypes) then
  3210. begin
  3211. InputError('Table element type for table import must be a reference type');
  3212. exit;
  3213. end;
  3214. if not AReader.read(TableLimitsKind,1) then
  3215. begin
  3216. InputError('Error reading table limits kind for table import');
  3217. exit;
  3218. end;
  3219. case TableLimitsKind of
  3220. $00:
  3221. begin
  3222. limits.HasMax:=False;
  3223. limits.Max:=high(limits.Max);
  3224. if not ReadUleb32(limits.min) then
  3225. begin
  3226. InputError('Error reading table limits min for table import');
  3227. exit;
  3228. end;
  3229. end;
  3230. $01:
  3231. begin
  3232. limits.HasMax:=True;
  3233. if not ReadUleb32(limits.min) then
  3234. begin
  3235. InputError('Error reading table limits min for table import');
  3236. exit;
  3237. end;
  3238. if not ReadUleb32(limits.max) then
  3239. begin
  3240. InputError('Error reading table limits max for table import');
  3241. exit;
  3242. end;
  3243. if limits.min>limits.max then
  3244. begin
  3245. InputError('Table limits min exceed table limits max in table import');
  3246. exit;
  3247. end;
  3248. end;
  3249. else
  3250. begin
  3251. InputError('Unsupported table limits kind for table import: $' + HexStr(TableLimitsKind,2));
  3252. exit;
  3253. end;
  3254. end;
  3255. end;
  3256. end;
  3257. $02: { mem }
  3258. begin
  3259. Inc(MemTypeImportsCount);
  3260. SetLength(MemTypes,MemTypeImportsCount);
  3261. with MemTypes[MemTypeImportsCount-1] do
  3262. begin
  3263. IsImport:=True;
  3264. ImportName:=Name;
  3265. ImportModName:=ModName;
  3266. if not AReader.read(MemoryLimitsKind,1) then
  3267. begin
  3268. InputError('Error reading memory limits kind for memory import');
  3269. exit;
  3270. end;
  3271. case MemoryLimitsKind of
  3272. $00:
  3273. begin
  3274. limits.HasMax:=False;
  3275. limits.Max:=high(limits.Max);
  3276. if not ReadUleb32(limits.min) then
  3277. begin
  3278. InputError('Error reading memory limits min for memory import');
  3279. exit;
  3280. end;
  3281. end;
  3282. $01:
  3283. begin
  3284. limits.HasMax:=True;
  3285. if not ReadUleb32(limits.min) then
  3286. begin
  3287. InputError('Error reading memory limits min for memory import');
  3288. exit;
  3289. end;
  3290. if not ReadUleb32(limits.max) then
  3291. begin
  3292. InputError('Error reading memory limits max for memory import');
  3293. exit;
  3294. end;
  3295. if limits.Min>limits.Max then
  3296. begin
  3297. InputError('Memory limits min exceed memory limits max in memory import');
  3298. exit;
  3299. end;
  3300. end;
  3301. else
  3302. begin
  3303. InputError('Unsupported memory limits kind for memory import: $' + HexStr(MemoryLimitsKind,2));
  3304. exit;
  3305. end;
  3306. end;
  3307. end;
  3308. end;
  3309. $03: { global }
  3310. begin
  3311. Inc(GlobalTypeImportsCount);
  3312. SetLength(GlobalTypes,GlobalTypeImportsCount);
  3313. with GlobalTypes[GlobalTypeImportsCount-1] do
  3314. begin
  3315. IsImport:=True;
  3316. ImportName:=Name;
  3317. ImportModName:=ModName;
  3318. if not AReader.read(GlobalType,1) then
  3319. begin
  3320. InputError('Error reading global type for global import');
  3321. exit;
  3322. end;
  3323. if not decode_wasm_basic_type(GlobalType,valtype) then
  3324. begin
  3325. InputError('Unsupported global type for global import: ' + HexStr(GlobalType,2));
  3326. exit;
  3327. end;
  3328. if not AReader.read(GlobalMutabilityType,1) then
  3329. begin
  3330. InputError('Error reading global mutability flag for global import');
  3331. exit;
  3332. end;
  3333. case GlobalMutabilityType of
  3334. $00:
  3335. IsMutable:=False;
  3336. $01:
  3337. IsMutable:=True;
  3338. else
  3339. begin
  3340. InputError('Unknown global mutability flag for global import: $' + HexStr(GlobalMutabilityType,2));
  3341. exit;
  3342. end;
  3343. end;
  3344. end;
  3345. end;
  3346. $04: { tag }
  3347. begin
  3348. Inc(TagTypeImportsCount);
  3349. SetLength(TagTypes,TagTypeImportsCount);
  3350. with TagTypes[TagTypeImportsCount-1] do
  3351. begin
  3352. IsImport:=True;
  3353. ImportName:=Name;
  3354. ImportModName:=ModName;
  3355. if not Read(TagAttr,1) then
  3356. begin
  3357. InputError('Error reading import tag attribute');
  3358. exit;
  3359. end;
  3360. if not ReadUleb32(TagTypeIdx) then
  3361. begin
  3362. InputError('Error reading import tag type index');
  3363. exit;
  3364. end;
  3365. if TagTypeIdx>high(FFuncTypes) then
  3366. begin
  3367. InputError('Type index in tag import exceeds bounds of the types table');
  3368. exit;
  3369. end;
  3370. end;
  3371. end;
  3372. else
  3373. begin
  3374. InputError('Unknown import type: $' + HexStr(ImportType,2));
  3375. exit;
  3376. end;
  3377. end;
  3378. end;
  3379. if AReader.Pos<>(SectionStart+SectionSize) then
  3380. begin
  3381. InputError('Unexpected import section size');
  3382. exit;
  3383. end;
  3384. Result:=true;
  3385. end;
  3386. function ReadFunctionSection: Boolean;
  3387. var
  3388. FunctionsCount: uint32;
  3389. i: Integer;
  3390. begin
  3391. Result:=False;
  3392. if FunctionSectionRead then
  3393. begin
  3394. InputError('Function section is duplicated');
  3395. exit;
  3396. end;
  3397. FunctionSectionRead:=True;
  3398. if not ReadUleb32(FunctionsCount) then
  3399. begin
  3400. InputError('Error reading the functions count');
  3401. exit;
  3402. end;
  3403. SetLength(FuncTypes, FuncTypeImportsCount + FunctionsCount);
  3404. for i:=0 to FunctionsCount-1 do
  3405. with FuncTypes[i + FuncTypeImportsCount] do
  3406. begin
  3407. IsImport:=False;
  3408. if not ReadUleb32(typidx) then
  3409. begin
  3410. InputError('Error reading type index for function');
  3411. exit;
  3412. end;
  3413. if typidx>high(FFuncTypes) then
  3414. begin
  3415. InputError('Type index in the function section exceeds bounds of the types table');
  3416. exit;
  3417. end;
  3418. end;
  3419. if AReader.Pos<>(SectionStart+SectionSize) then
  3420. begin
  3421. InputError('Unexpected function section size');
  3422. exit;
  3423. end;
  3424. Result:=true;
  3425. end;
  3426. function ReadGlobalSection: Boolean;
  3427. function ParseExpr(out Init: TGlobalInitializer): Boolean;
  3428. var
  3429. B, B2: Byte;
  3430. tmpU32: UInt32;
  3431. tmpU64: UInt64;
  3432. begin
  3433. Result:=False;
  3434. repeat
  3435. if not Read(B, 1) then
  3436. exit;
  3437. case B of
  3438. $0B: { end }
  3439. ;
  3440. $41: { i32.const }
  3441. begin
  3442. Init.typ:=wbt_i32;
  3443. if not ReadSleb32(Init.init_i32) then
  3444. exit;
  3445. end;
  3446. $42: { i64.const }
  3447. begin
  3448. Init.typ:=wbt_i64;
  3449. if not ReadSleb(Init.init_i64) then
  3450. exit;
  3451. end;
  3452. $43: { f32.const }
  3453. begin
  3454. Init.typ:=wbt_f32;
  3455. if not Read(tmpU32, 4) then
  3456. exit;
  3457. {$ifdef FPC_BIG_ENDIAN}
  3458. tmpU32:=SwapEndian(tmpU32);
  3459. {$endif FPC_BIG_ENDIAN}
  3460. Move(tmpU32,Init.init_f32,4);
  3461. end;
  3462. $44: { f64.const }
  3463. begin
  3464. Init.typ:=wbt_f64;
  3465. if not Read(tmpU64, 8) then
  3466. exit;
  3467. {$ifdef FPC_BIG_ENDIAN}
  3468. tmpU64:=SwapEndian(tmpU64);
  3469. {$endif FPC_BIG_ENDIAN}
  3470. Move(tmpU64,Init.init_f64,8);
  3471. end;
  3472. $D0: { ref.null }
  3473. begin
  3474. if not Read(B2, 1) then
  3475. exit;
  3476. if not decode_wasm_basic_type(B2, Init.typ) then
  3477. exit;
  3478. if not (Init.typ in WasmReferenceTypes) then
  3479. exit;
  3480. end;
  3481. else
  3482. begin
  3483. InputError('Unsupported opcode in global initializer');
  3484. exit;
  3485. end;
  3486. end;
  3487. until b = $0B;
  3488. Result:=True;
  3489. end;
  3490. var
  3491. GlobalsCount: uint32;
  3492. i: Integer;
  3493. vt: Byte;
  3494. mut: Byte;
  3495. begin
  3496. Result:=False;
  3497. if GlobalSectionRead then
  3498. begin
  3499. InputError('Global section is duplicated');
  3500. exit;
  3501. end;
  3502. GlobalSectionRead:=True;
  3503. if not ReadUleb32(GlobalsCount) then
  3504. begin
  3505. InputError('Error reading the globals count from the global section');
  3506. exit;
  3507. end;
  3508. SetLength(GlobalTypes,Length(GlobalTypes)+GlobalsCount);
  3509. for i:=0 to GlobalsCount-1 do
  3510. with GlobalTypes[i + GlobalTypeImportsCount] do
  3511. begin
  3512. if not read(vt,1) then
  3513. begin
  3514. InputError('Error reading the type of a global from the global section');
  3515. exit;
  3516. end;
  3517. if not decode_wasm_basic_type(vt,valtype) then
  3518. begin
  3519. InputError('Unsupported type of global in the global section');
  3520. exit;
  3521. end;
  3522. if not read(mut,1) then
  3523. begin
  3524. InputError('Error reading the mutability flag of a global in the global section');
  3525. exit;
  3526. end;
  3527. case mut of
  3528. $00:
  3529. IsMutable:=False;
  3530. $01:
  3531. IsMutable:=True;
  3532. else
  3533. begin
  3534. InputError('Unsupported value (' + tostr(mut) + ') for the mutability flag of a global in the global section');
  3535. exit;
  3536. end;
  3537. end;
  3538. if not ParseExpr(GlobalInit) then
  3539. begin
  3540. InputError('Error parsing the global initializer expression in the global section');
  3541. exit;
  3542. end;
  3543. if GlobalInit.typ<>valtype then
  3544. begin
  3545. InputError('Initializer expression for global produces a type, which does not match the type of the global');
  3546. exit;
  3547. end;
  3548. end;
  3549. if AReader.Pos<>(SectionStart+SectionSize) then
  3550. begin
  3551. InputError('Unexpected global section size');
  3552. exit;
  3553. end;
  3554. Result:=True;
  3555. end;
  3556. function ReadExportSection: Boolean;
  3557. var
  3558. ExportsCount, FuncIdx, TableIdx, MemIdx, GlobalIdx, TagIdx: uint32;
  3559. i: Integer;
  3560. Name: ansistring;
  3561. ExportType: Byte;
  3562. begin
  3563. Result:=False;
  3564. if ExportSectionRead then
  3565. begin
  3566. InputError('Export section is duplicated');
  3567. exit;
  3568. end;
  3569. ExportSectionRead:=True;
  3570. if not ReadUleb32(ExportsCount) then
  3571. begin
  3572. InputError('Error reading the exports count from the export section');
  3573. exit;
  3574. end;
  3575. for i:=0 to ExportsCount-1 do
  3576. begin
  3577. if not ReadName(Name) then
  3578. begin
  3579. InputError('Error reading an export name from the export section');
  3580. exit;
  3581. end;
  3582. if not Read(ExportType,1) then
  3583. begin
  3584. InputError('Error reading an export type from the export section');
  3585. exit;
  3586. end;
  3587. case ExportType of
  3588. $00: { func }
  3589. begin
  3590. if not ReadUleb32(FuncIdx) then
  3591. begin
  3592. InputError('Error reading a func index from the export section');
  3593. exit;
  3594. end;
  3595. if FuncIdx>high(FuncTypes) then
  3596. begin
  3597. InputError('Func index too high in the export section');
  3598. exit;
  3599. end;
  3600. with FuncTypes[FuncIdx] do
  3601. begin
  3602. IsExported:=True;
  3603. ExportName:=Name;
  3604. end;
  3605. end;
  3606. $01: { table }
  3607. begin
  3608. if not ReadUleb32(TableIdx) then
  3609. begin
  3610. InputError('Error reading a table index from the export section');
  3611. exit;
  3612. end;
  3613. if TableIdx>high(TableTypes) then
  3614. begin
  3615. InputError('Table index too high in the export section');
  3616. exit;
  3617. end;
  3618. with TableTypes[TableIdx] do
  3619. begin
  3620. IsExported:=True;
  3621. ExportName:=Name;
  3622. end;
  3623. end;
  3624. $02: { mem }
  3625. begin
  3626. if not ReadUleb32(MemIdx) then
  3627. begin
  3628. InputError('Error reading a mem index from the export section');
  3629. exit;
  3630. end;
  3631. if MemIdx>high(MemTypes) then
  3632. begin
  3633. InputError('Mem index too high in the export section');
  3634. exit;
  3635. end;
  3636. with MemTypes[MemIdx] do
  3637. begin
  3638. IsExported:=True;
  3639. ExportName:=Name;
  3640. end;
  3641. end;
  3642. $03: { global }
  3643. begin
  3644. if not ReadUleb32(GlobalIdx) then
  3645. begin
  3646. InputError('Error reading a global index from the export section');
  3647. exit;
  3648. end;
  3649. if GlobalIdx>high(GlobalTypes) then
  3650. begin
  3651. InputError('Global index too high in the export section');
  3652. exit;
  3653. end;
  3654. with GlobalTypes[GlobalIdx] do
  3655. begin
  3656. IsExported:=True;
  3657. ExportName:=Name;
  3658. end;
  3659. end;
  3660. $04: { tag }
  3661. begin
  3662. if not ReadUleb32(TagIdx) then
  3663. begin
  3664. InputError('Error reading a tag index from the export section');
  3665. exit;
  3666. end;
  3667. if TagIdx>high(TagTypes) then
  3668. begin
  3669. InputError('Tag index too high in the export section');
  3670. exit;
  3671. end;
  3672. with TagTypes[TagIdx] do
  3673. begin
  3674. IsExported:=True;
  3675. ExportName:=Name;
  3676. end;
  3677. end;
  3678. else
  3679. begin
  3680. InputError('Unsupported export type in the export section: ' + tostr(ExportType));
  3681. exit;
  3682. end;
  3683. end;
  3684. end;
  3685. if AReader.Pos<>(SectionStart+SectionSize) then
  3686. begin
  3687. InputError('Unexpected export section size');
  3688. exit;
  3689. end;
  3690. Result:=True;
  3691. end;
  3692. function ReadElementSection: Boolean;
  3693. begin
  3694. Result:=False;
  3695. if ElementSectionRead then
  3696. begin
  3697. InputError('Element section is duplicated');
  3698. exit;
  3699. end;
  3700. ElementSectionRead:=True;
  3701. { We skip the element section for now }
  3702. { TODO: implement reading it (and linking of tables) }
  3703. Result:=True;
  3704. end;
  3705. function ReadTagSection: Boolean;
  3706. var
  3707. TagCount: uint32;
  3708. i: Integer;
  3709. begin
  3710. Result:=False;
  3711. if TagSectionRead then
  3712. begin
  3713. InputError('Tag section is duplicated');
  3714. exit;
  3715. end;
  3716. TagSectionRead:=True;
  3717. if not ReadUleb32(TagCount) then
  3718. begin
  3719. InputError('Error reading the tag count from the tag section');
  3720. exit;
  3721. end;
  3722. SetLength(TagTypes,Length(TagTypes)+TagCount);
  3723. for i:=0 to TagCount-1 do
  3724. with TagTypes[i + TagTypeImportsCount] do
  3725. begin
  3726. if not Read(TagAttr,1) then
  3727. begin
  3728. InputError('Error reading tag attribute');
  3729. exit;
  3730. end;
  3731. if not ReadUleb32(TagTypeIdx) then
  3732. begin
  3733. InputError('Error reading tag type index');
  3734. exit;
  3735. end;
  3736. if TagTypeIdx>high(FFuncTypes) then
  3737. begin
  3738. InputError('Type index in tag import exceeds bounds of the types table');
  3739. exit;
  3740. end;
  3741. end;
  3742. if AReader.Pos<>(SectionStart+SectionSize) then
  3743. begin
  3744. InputError('Unexpected tag section size');
  3745. exit;
  3746. end;
  3747. Result:=True;
  3748. end;
  3749. function ReadCodeSection: Boolean;
  3750. var
  3751. CodeEntriesCount: uint32;
  3752. i: Integer;
  3753. begin
  3754. Result:=False;
  3755. if CodeSectionRead then
  3756. begin
  3757. InputError('Code section is duplicated');
  3758. exit;
  3759. end;
  3760. CodeSectionRead:=True;
  3761. CodeSectionIndex:=SectionIndex;
  3762. if not ReadUleb32(CodeEntriesCount) then
  3763. begin
  3764. InputError('Error reading the code entries cound from the code section');
  3765. exit;
  3766. end;
  3767. if CodeEntriesCount <> (Length(FuncTypes) - FuncTypeImportsCount) then
  3768. begin
  3769. InputError('Code segment count in the code section does not match the function definition count in the function section');
  3770. exit;
  3771. end;
  3772. SetLength(CodeSegments,CodeEntriesCount);
  3773. for i:=0 to CodeEntriesCount-1 do
  3774. with CodeSegments[i] do
  3775. begin
  3776. if not ReadUleb32(CodeSize) then
  3777. begin
  3778. InputError('Error reading the code size of an entry in the code section');
  3779. exit;
  3780. end;
  3781. if (AReader.Pos+CodeSize)>(SectionStart+SectionSize) then
  3782. begin
  3783. InputError('Code segment exceeds the bounds of the code section');
  3784. exit;
  3785. end;
  3786. DataPos:=AReader.Pos;
  3787. CodeSectionOffset:=AReader.Pos-SectionStart;
  3788. AReader.Seek(AReader.Pos+CodeSize);
  3789. end;
  3790. if AReader.Pos<>(SectionStart+SectionSize) then
  3791. begin
  3792. InputError('Unexpected code section size');
  3793. exit;
  3794. end;
  3795. Result:=true;
  3796. end;
  3797. function ReadDataSection: Boolean;
  3798. function ReadExpr(out ExprV: int32): Boolean;
  3799. var
  3800. b: Byte;
  3801. begin
  3802. Result:=False;
  3803. if not Read(b,1) then
  3804. exit;
  3805. if b<>$41 then
  3806. begin
  3807. InputError('Only i32.const expressions supported');
  3808. exit;
  3809. end;
  3810. if not ReadSleb32(ExprV) then
  3811. exit;
  3812. if not Read(b,1) then
  3813. exit;
  3814. if b<>$0B then
  3815. begin
  3816. InputError('Only single const expressions supported');
  3817. exit;
  3818. end;
  3819. Result:=True;
  3820. end;
  3821. var
  3822. DataCount: uint32;
  3823. DataType: Byte;
  3824. i: Integer;
  3825. begin
  3826. Result:=False;
  3827. if DataSectionRead then
  3828. begin
  3829. InputError('Data section is duplicated');
  3830. exit;
  3831. end;
  3832. DataSectionRead:=True;
  3833. DataSectionIndex:=SectionIndex;
  3834. if not ReadUleb32(DataCount) then
  3835. begin
  3836. InputError('Error reading the data entries count from the data section');
  3837. exit;
  3838. end;
  3839. if DataCountSectionRead then
  3840. begin
  3841. if Length(DataSegments)<>DataCount then
  3842. begin
  3843. InputError('Data entries count in the data section do not match the number, specified in the data count section');
  3844. exit;
  3845. end;
  3846. end
  3847. else
  3848. SetLength(DataSegments,DataCount);
  3849. for i:=0 to DataCount-1 do
  3850. with DataSegments[i] do
  3851. begin
  3852. if not read(DataType, 1) then
  3853. begin
  3854. InputError('Error reading data type of segment from the data section');
  3855. exit;
  3856. end;
  3857. case DataType of
  3858. 0:
  3859. begin
  3860. Active:=True;
  3861. MemIdx:=0;
  3862. if not ReadExpr(Offset) then
  3863. begin
  3864. InputError('Error reading memory offset of segment from the data section');
  3865. exit;
  3866. end;
  3867. end;
  3868. 1:
  3869. Active:=False;
  3870. 2:
  3871. begin
  3872. Active:=True;
  3873. if not ReadUleb32(MemIdx) then
  3874. begin
  3875. InputError('Error reading MemIdx of segment from the data section');
  3876. exit;
  3877. end;
  3878. if not ReadExpr(Offset) then
  3879. begin
  3880. InputError('Error reading memory offset of segment from the data section');
  3881. exit;
  3882. end;
  3883. end;
  3884. else
  3885. begin
  3886. InputError('Unsupported data type of segment in the data section: ' + tostr(DataType));
  3887. exit;
  3888. end;
  3889. end;
  3890. if MemIdx<>0 then
  3891. begin
  3892. InputError('Memory index other than 0 not supported (got ' + tostr(MemIdx) + ')');
  3893. exit;
  3894. end;
  3895. if not Active then
  3896. begin
  3897. InputError('Passive memory segments not supported');
  3898. exit;
  3899. end;
  3900. if not ReadUleb32(Len) then
  3901. begin
  3902. InputError('Error reading data segment length');
  3903. exit;
  3904. end;
  3905. if (AReader.Pos+Len)>(SectionStart+SectionSize) then
  3906. begin
  3907. InputError('Data segment exceeds the bounds of the data section');
  3908. exit;
  3909. end;
  3910. DataPos:=AReader.Pos;
  3911. DataSectionOffset:=AReader.Pos-SectionStart;
  3912. AReader.Seek(AReader.Pos+Len);
  3913. end;
  3914. if AReader.Pos<>(SectionStart+SectionSize) then
  3915. begin
  3916. InputError('Unexpected data section size');
  3917. exit;
  3918. end;
  3919. Result:=true;
  3920. end;
  3921. function ReadDataCountSection: Boolean;
  3922. var
  3923. DataCount: uint32;
  3924. begin
  3925. Result:=False;
  3926. if DataCountSectionRead then
  3927. begin
  3928. InputError('Data count section is duplicated');
  3929. exit;
  3930. end;
  3931. DataCountSectionRead:=True;
  3932. if DataSectionRead then
  3933. begin
  3934. InputError('The data count section must occur before the data section');
  3935. exit;
  3936. end;
  3937. if not ReadUleb32(DataCount) then
  3938. begin
  3939. InputError('Error reading the data count from the data count section');
  3940. exit;
  3941. end;
  3942. if AReader.Pos<>(SectionStart+SectionSize) then
  3943. begin
  3944. InputError('Unexpected data count section size');
  3945. exit;
  3946. end;
  3947. SetLength(DataSegments, DataCount);
  3948. Result:=true;
  3949. end;
  3950. begin
  3951. Result:=False;
  3952. Inc(SectionIndex);
  3953. if not AReader.read(SectionId,1) then
  3954. begin
  3955. InputError('Error reading section ID');
  3956. exit;
  3957. end;
  3958. CheckSectionBounds:=false;
  3959. if not ReadUleb32(SectionSize) then
  3960. begin
  3961. InputError('Error reading section size');
  3962. exit;
  3963. end;
  3964. if (AReader.Pos+SectionSize)>AReader.size then
  3965. begin
  3966. InputError('Section exceeds beyond the end of file');
  3967. exit;
  3968. end;
  3969. SectionStart:=AReader.Pos;
  3970. CheckSectionBounds:=true;
  3971. case SectionId of
  3972. Byte(wsiCustom):
  3973. if not ReadCustomSection then
  3974. begin
  3975. InputError('Error encountered, while reading a custom section');
  3976. exit;
  3977. end;
  3978. Byte(wsiType):
  3979. if not ReadTypeSection then
  3980. begin
  3981. InputError('Error reading the type section');
  3982. exit;
  3983. end;
  3984. Byte(wsiImport):
  3985. if not ReadImportSection then
  3986. begin
  3987. InputError('Error reading the import section');
  3988. exit;
  3989. end;
  3990. Byte(wsiFunction):
  3991. if not ReadFunctionSection then
  3992. begin
  3993. InputError('Error reading the function section');
  3994. exit;
  3995. end;
  3996. Byte(wsiGlobal):
  3997. if not ReadGlobalSection then
  3998. begin
  3999. InputError('Error reading the global section');
  4000. exit;
  4001. end;
  4002. Byte(wsiExport):
  4003. if not ReadExportSection then
  4004. begin
  4005. InputError('Error reading the export section');
  4006. exit;
  4007. end;
  4008. Byte(wsiElement):
  4009. if not ReadElementSection then
  4010. begin
  4011. InputError('Error reading the element section');
  4012. exit;
  4013. end;
  4014. Byte(wsiTag):
  4015. if not ReadTagSection then
  4016. begin
  4017. InputError('Error reading the tag section');
  4018. exit;
  4019. end;
  4020. Byte(wsiCode):
  4021. if not ReadCodeSection then
  4022. begin
  4023. InputError('Error reading the code section');
  4024. exit;
  4025. end;
  4026. Byte(wsiData):
  4027. if not ReadDataSection then
  4028. begin
  4029. InputError('Error reading the data section');
  4030. exit;
  4031. end;
  4032. Byte(wsiDataCount):
  4033. begin
  4034. if not ReadDataCountSection then
  4035. begin
  4036. InputError('Error reading the data count section');
  4037. exit;
  4038. end;
  4039. end
  4040. else
  4041. begin
  4042. InputError('Unknown section: ' + ToStr(SectionId));
  4043. exit;
  4044. end;
  4045. end;
  4046. if SectionSize>0 then
  4047. AReader.seek(SectionStart+SectionSize);
  4048. Result:=True;
  4049. end;
  4050. function FindCodeSegment(Ofs: uint32): Integer;
  4051. var
  4052. L, R, M: Integer;
  4053. begin
  4054. L:=Low(CodeSegments);
  4055. R:=High(CodeSegments);
  4056. while L<=R do
  4057. begin
  4058. M:=(L+R) div 2;
  4059. if (CodeSegments[M].CodeSectionOffset+CodeSegments[M].CodeSize-1) < Ofs then
  4060. L:=M+1
  4061. else if CodeSegments[M].CodeSectionOffset > Ofs then
  4062. R:=M-1
  4063. else
  4064. begin
  4065. Result:=M;
  4066. exit;
  4067. end;
  4068. end;
  4069. Result:=-1;
  4070. end;
  4071. function FindDataSegment(Ofs: uint32): Integer;
  4072. var
  4073. L, R, M: Integer;
  4074. begin
  4075. L:=Low(DataSegments);
  4076. R:=High(DataSegments);
  4077. while L<=R do
  4078. begin
  4079. M:=(L+R) div 2;
  4080. if (DataSegments[M].DataSectionOffset+DataSegments[M].Len-1) < Ofs then
  4081. L:=M+1
  4082. else if DataSegments[M].DataSectionOffset > Ofs then
  4083. R:=M-1
  4084. else
  4085. begin
  4086. Result:=M;
  4087. exit;
  4088. end;
  4089. end;
  4090. Result:=-1;
  4091. end;
  4092. var
  4093. ModuleMagic: array [0..3] of Byte;
  4094. ModuleVersion: array [0..3] of Byte;
  4095. i, j, FirstCodeSegmentIdx, FirstDataSegmentIdx, SegI: Integer;
  4096. CurrSec, ObjSec: TObjSection;
  4097. BaseSectionOffset: UInt32;
  4098. ObjReloc: TWasmObjRelocation;
  4099. ds: TWasmCustomDebugSectionType;
  4100. begin
  4101. FReader:=AReader;
  4102. InputFileName:=AReader.FileName;
  4103. objdata:=CObjData.Create(InputFileName);
  4104. result:=false;
  4105. CodeSegments:=nil;
  4106. DataSegments:=nil;
  4107. SymbolTable:=nil;
  4108. RelocationTable:=nil;
  4109. SetLength(RelocationTable,2+(Ord(High(TWasmCustomDebugSectionType))-Ord(Low(TWasmCustomDebugSectionType))+1));
  4110. FuncTypes:=nil;
  4111. FuncTypeImportsCount:=0;
  4112. TableTypes:=nil;
  4113. TableTypeImportsCount:=0;
  4114. MemTypes:=nil;
  4115. MemTypeImportsCount:=0;
  4116. GlobalTypes:=nil;
  4117. GlobalTypeImportsCount:=0;
  4118. TagTypes:=nil;
  4119. TagTypeImportsCount:=0;
  4120. if not AReader.read(ModuleMagic,4) then
  4121. exit;
  4122. for i:=0 to 3 do
  4123. if ModuleMagic[i]<>WasmModuleMagic[i] then
  4124. exit;
  4125. if not AReader.read(ModuleVersion,4) then
  4126. exit;
  4127. for i:=0 to 3 do
  4128. if ModuleVersion[i]<>WasmVersion[i] then
  4129. exit;
  4130. while AReader.Pos<AReader.size do
  4131. if not ReadSection then
  4132. exit;
  4133. { fill the code segment names }
  4134. for i:=low(SymbolTable) to high(SymbolTable) do
  4135. with SymbolTable[i] do
  4136. if (SymKind=SYMTAB_FUNCTION) and ((SymFlags and WASM_SYM_UNDEFINED)=0) then
  4137. begin
  4138. if FuncTypes[SymIndex].IsImport then
  4139. begin
  4140. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_FUNCTION symbol, that is an import');
  4141. exit;
  4142. end;
  4143. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4144. begin
  4145. with CodeSegments[SymIndex-FuncTypeImportsCount] do
  4146. begin
  4147. SegName:='.text.n_'+SymName;
  4148. SegIsExported:=FuncTypes[SymIndex].IsExported;
  4149. end;
  4150. end;
  4151. end;
  4152. { create segments }
  4153. FirstCodeSegmentIdx:=ObjData.ObjSectionList.Count;
  4154. for i:=low(CodeSegments) to high(CodeSegments) do
  4155. with CodeSegments[i] do
  4156. begin
  4157. if SegName='' then
  4158. begin
  4159. InputError('Code section ' + tostr(i) + ' does not have a main symbol defined in the symbol table');
  4160. exit;
  4161. end;
  4162. if SegIsExported or not (cs_link_smart in current_settings.globalswitches) then
  4163. CurrSec:=ObjData.createsection(SegName,1,[oso_executable,oso_Data,oso_load,oso_keep],false)
  4164. else
  4165. CurrSec:=ObjData.createsection(SegName,1,[oso_executable,oso_Data,oso_load],false);
  4166. CurrSec.DataPos:=DataPos;
  4167. CurrSec.Size:=CodeSize;
  4168. end;
  4169. FirstDataSegmentIdx:=ObjData.ObjSectionList.Count;
  4170. for i:=low(DataSegments) to high(DataSegments) do
  4171. with DataSegments[i] do
  4172. if Active then
  4173. begin
  4174. if not (cs_link_smart in current_settings.globalswitches) then
  4175. CurrSec:=ObjData.createsection(SegName,1 shl SegAlignment,[oso_Data,oso_load,oso_write,oso_keep],false)
  4176. else
  4177. CurrSec:=ObjData.createsection(SegName,1 shl SegAlignment,[oso_Data,oso_load,oso_write],false);
  4178. CurrSec.DataPos:=DataPos;
  4179. CurrSec.MemPos:=Offset;
  4180. CurrSec.Size:=Len;
  4181. end;
  4182. ReadSectionContent(ObjData);
  4183. for i:=low(SymbolTable) to high(SymbolTable) do
  4184. with SymbolTable[i] do
  4185. case SymKind of
  4186. SYMTAB_DATA:
  4187. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4188. begin
  4189. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4190. objsym.bind:=AB_EXTERNAL;
  4191. if (SymFlags and WASM_SYM_TLS)<>0 then
  4192. begin
  4193. objsym.typ:=AT_TLS;
  4194. objsym.TlsGlobalSym:=TWasmObjSymbol(ObjData.CreateSymbol('GOT.mem.'+SymName));
  4195. objsym.TlsGlobalSym.TlsDataSym:=objsym;
  4196. objsym.TlsGlobalSym.bind:=AB_EXTERNAL;
  4197. objsym.TlsGlobalSym.typ:=AT_WASM_GLOBAL;
  4198. objsym.TlsGlobalSym.objsection:=nil;
  4199. objsym.TlsGlobalSym.offset:=0;
  4200. objsym.TlsGlobalSym.size:=1;
  4201. objsym.TlsGlobalSym.LinkingData.GlobalType:=wbt_i32;
  4202. objsym.TlsGlobalSym.LinkingData.GlobalIsMutable:=true;
  4203. end
  4204. else
  4205. objsym.typ:=AT_DATA;
  4206. objsym.objsection:=nil;
  4207. objsym.offset:=0;
  4208. objsym.size:=0;
  4209. end
  4210. else
  4211. begin
  4212. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4213. if (SymFlags and WASM_SYM_BINDING_LOCAL)<> 0 then
  4214. objsym.bind:=AB_LOCAL
  4215. else
  4216. objsym.bind:=AB_GLOBAL;
  4217. if (SymFlags and WASM_SYM_TLS)<>0 then
  4218. begin
  4219. objsym.typ:=AT_TLS;
  4220. objsym.TlsGlobalSym:=TWasmObjSymbol(ObjData.CreateSymbol('GOT.mem.'+SymName));
  4221. objsym.TlsGlobalSym.TlsDataSym:=objsym;
  4222. objsym.TlsGlobalSym.bind:=objsym.bind;
  4223. objsym.TlsGlobalSym.typ:=AT_WASM_GLOBAL;
  4224. objsym.TlsGlobalSym.objsection:=ObjData.createsection('.wasm_globals.n_'+objsym.TlsGlobalSym.Name,1,[oso_Data,oso_load],true);
  4225. if objsym.TlsGlobalSym.objsection.Size=0 then
  4226. objsym.TlsGlobalSym.objsection.WriteZeros(1);
  4227. TWasmObjSection(objsym.TlsGlobalSym.objsection).MainFuncSymbol:=objsym.TlsGlobalSym;
  4228. objsym.TlsGlobalSym.offset:=0;
  4229. objsym.TlsGlobalSym.size:=1;
  4230. objsym.TlsGlobalSym.LinkingData.GlobalType:=wbt_i32;
  4231. objsym.TlsGlobalSym.LinkingData.GlobalIsMutable:=true;
  4232. end
  4233. else
  4234. objsym.typ:=AT_DATA;
  4235. objsym.objsection:=TObjSection(ObjData.ObjSectionList[FirstDataSegmentIdx+SymIndex]);
  4236. objsym.offset:=SymOffset;
  4237. objsym.size:=SymSize;
  4238. end;
  4239. SYMTAB_FPC_CUSTOM:
  4240. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4241. begin
  4242. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4243. objsym.bind:=AB_EXTERNAL;
  4244. if (SymFlags and WASM_SYM_TLS)<>0 then
  4245. internalerror(2024080702);
  4246. objsym.typ:=AT_DATA;
  4247. objsym.objsection:=nil;
  4248. objsym.offset:=0;
  4249. objsym.size:=0;
  4250. end
  4251. else
  4252. begin
  4253. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4254. if (SymFlags and WASM_SYM_BINDING_LOCAL)<> 0 then
  4255. objsym.bind:=AB_LOCAL
  4256. else
  4257. objsym.bind:=AB_GLOBAL;
  4258. if (SymFlags and WASM_SYM_TLS)<>0 then
  4259. internalerror(2024080703);
  4260. objsym.typ:=AT_DATA;
  4261. objsym.objsection:=TObjSection(ObjData.ObjSectionList.Find(WasmCustomSectionName[SymCustomSectionType]));
  4262. objsym.offset:=SymOffset;
  4263. objsym.size:=SymSize;
  4264. end;
  4265. SYMTAB_FUNCTION:
  4266. begin
  4267. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4268. begin
  4269. if not FuncTypes[SymIndex].IsImport then
  4270. begin
  4271. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_FUNCTION symbol, that is not an import');
  4272. exit;
  4273. end;
  4274. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4275. begin
  4276. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4277. objsym.bind:=AB_EXTERNAL;
  4278. objsym.typ:=AT_FUNCTION;
  4279. objsym.objsection:=nil;
  4280. objsym.offset:=0;
  4281. objsym.size:=0;
  4282. objsym.LinkingData.ImportModule:=FuncTypes[SymIndex].ImportModName;
  4283. objsym.LinkingData.ImportName:=FuncTypes[SymIndex].ImportName;
  4284. end
  4285. else
  4286. begin
  4287. if FuncTypes[SymIndex].ImportModName = 'env' then
  4288. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(FuncTypes[SymIndex].ImportName))
  4289. else
  4290. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(FuncTypes[SymIndex].ImportModName + '.' + FuncTypes[SymIndex].ImportName));
  4291. objsym.bind:=AB_EXTERNAL;
  4292. objsym.typ:=AT_FUNCTION;
  4293. objsym.objsection:=nil;
  4294. objsym.offset:=0;
  4295. objsym.size:=0;
  4296. end;
  4297. end
  4298. else
  4299. begin
  4300. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4301. objsym.bind:=AB_GLOBAL;
  4302. objsym.typ:=AT_FUNCTION;
  4303. objsym.objsection:=TObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SymIndex-FuncTypeImportsCount]);
  4304. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4305. TWasmObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SymIndex-FuncTypeImportsCount]).MainFuncSymbol:=objsym;
  4306. objsym.offset:=0;
  4307. objsym.size:=objsym.objsection.Size;
  4308. end;
  4309. objsym.LinkingData.FuncType:=TWasmFuncType.Create(FFuncTypes[FuncTypes[SymIndex].typidx]);
  4310. objsym.LinkingData.IsExported:=FuncTypes[SymIndex].IsExported;
  4311. objsym.LinkingData.ExportName:=FuncTypes[SymIndex].ExportName;
  4312. end;
  4313. SYMTAB_GLOBAL:
  4314. begin
  4315. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4316. begin
  4317. if not GlobalTypes[SymIndex].IsImport then
  4318. begin
  4319. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_GLOBAL symbol, that is not an import');
  4320. exit;
  4321. end;
  4322. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4323. begin
  4324. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4325. objsym.bind:=AB_EXTERNAL;
  4326. objsym.typ:=AT_WASM_GLOBAL;
  4327. objsym.objsection:=nil;
  4328. objsym.offset:=0;
  4329. objsym.size:=1;
  4330. objsym.LinkingData.ImportModule:=GlobalTypes[SymIndex].ImportModName;
  4331. objsym.LinkingData.ImportName:=GlobalTypes[SymIndex].ImportName;
  4332. end
  4333. else
  4334. begin
  4335. if GlobalTypes[SymIndex].ImportModName = 'env' then
  4336. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportName))
  4337. else
  4338. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportModName + '.' + GlobalTypes[SymIndex].ImportName));
  4339. objsym.bind:=AB_EXTERNAL;
  4340. objsym.typ:=AT_WASM_GLOBAL;
  4341. objsym.objsection:=nil;
  4342. objsym.offset:=0;
  4343. objsym.size:=1;
  4344. end;
  4345. end
  4346. else
  4347. begin
  4348. if GlobalTypes[SymIndex].IsImport then
  4349. begin
  4350. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_GLOBAL symbol, that is an import');
  4351. exit;
  4352. end;
  4353. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4354. objsym.bind:=AB_GLOBAL;
  4355. objsym.typ:=AT_WASM_GLOBAL;
  4356. objsym.objsection:=ObjData.createsection('.wasm_globals.n_'+SymName,1,[oso_Data,oso_load],true);
  4357. if objsym.objsection.Size=0 then
  4358. objsym.objsection.WriteZeros(1);
  4359. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4360. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  4361. objsym.offset:=0;
  4362. objsym.size:=1;
  4363. objsym.LinkingData.GlobalInitializer:=GlobalTypes[SymIndex].GlobalInit;
  4364. end;
  4365. objsym.LinkingData.GlobalType:=GlobalTypes[SymIndex].valtype;
  4366. objsym.LinkingData.GlobalIsMutable:=GlobalTypes[SymIndex].IsMutable;
  4367. objsym.LinkingData.IsExported:=GlobalTypes[SymIndex].IsExported;
  4368. objsym.LinkingData.ExportName:=GlobalTypes[SymIndex].ExportName;
  4369. end;
  4370. SYMTAB_SECTION:
  4371. begin
  4372. for ds:=Low(DebugSectionIndex) to High(DebugSectionIndex) do
  4373. if DebugSectionIndex[ds]=TargetSection then
  4374. begin
  4375. ObjSec:=TWasmObjSection(ObjData.findsection(WasmCustomSectionName[ds]));
  4376. break;
  4377. end;
  4378. if ObjSec=nil then
  4379. begin
  4380. InputError('SYMTAB_SECTION entry points to an unsupported section');
  4381. exit;
  4382. end;
  4383. end;
  4384. SYMTAB_EVENT:
  4385. begin
  4386. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4387. begin
  4388. if not TagTypes[SymIndex].IsImport then
  4389. begin
  4390. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_EVENT symbol, that is not an import');
  4391. exit;
  4392. end;
  4393. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4394. begin
  4395. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4396. objsym.bind:=AB_EXTERNAL;
  4397. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4398. objsym.objsection:=nil;
  4399. objsym.offset:=0;
  4400. objsym.size:=1;
  4401. objsym.LinkingData.ImportModule:=TagTypes[SymIndex].ImportModName;
  4402. objsym.LinkingData.ImportName:=TagTypes[SymIndex].ImportName;
  4403. end
  4404. else
  4405. begin
  4406. if GlobalTypes[SymIndex].ImportModName = 'env' then
  4407. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportName))
  4408. else
  4409. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportModName + '.' + GlobalTypes[SymIndex].ImportName));
  4410. objsym.bind:=AB_EXTERNAL;
  4411. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4412. objsym.objsection:=nil;
  4413. objsym.offset:=0;
  4414. objsym.size:=1;
  4415. end;
  4416. end
  4417. else
  4418. begin
  4419. if TagTypes[SymIndex].IsImport then
  4420. begin
  4421. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_EVENT symbol, that is an import');
  4422. exit;
  4423. end;
  4424. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4425. if (symflags and WASM_SYM_BINDING_WEAK) <> 0 then
  4426. objsym.bind:=AB_WEAK_EXTERNAL
  4427. else if (symflags and WASM_SYM_BINDING_LOCAL) <> 0 then
  4428. objsym.bind:=AB_LOCAL
  4429. else
  4430. objsym.bind:=AB_GLOBAL;
  4431. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4432. objsym.objsection:=ObjData.createsection('.wasm_tags.n_'+SymName,1,[oso_Data,oso_load],true);
  4433. if objsym.objsection.Size=0 then
  4434. objsym.objsection.WriteZeros(1);
  4435. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4436. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  4437. objsym.offset:=0;
  4438. objsym.size:=1;
  4439. end;
  4440. objsym.LinkingData.FuncType:=TWasmFuncType.Create(FFuncTypes[TagTypes[SymIndex].TagTypeIdx]);
  4441. objsym.LinkingData.IsExported:=TagTypes[SymIndex].IsExported;
  4442. objsym.LinkingData.ExportName:=TagTypes[SymIndex].ExportName;
  4443. end;
  4444. SYMTAB_TABLE:
  4445. {TODO};
  4446. end;
  4447. for j:=0 to high(RelocationTable) do
  4448. for i:=0 to high(RelocationTable[j]) do
  4449. with RelocationTable[j,i] do
  4450. begin
  4451. case j of
  4452. 0:
  4453. begin
  4454. SegI:=FindCodeSegment(RelocOffset);
  4455. if SegI=-1 then
  4456. begin
  4457. InputError('Relocation offset not found in code segment');
  4458. Exit;
  4459. end;
  4460. BaseSectionOffset:=CodeSegments[SegI].CodeSectionOffset;
  4461. ObjSec:=TObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SegI]);
  4462. end;
  4463. 1:
  4464. begin
  4465. SegI:=FindDataSegment(RelocOffset);
  4466. if SegI=-1 then
  4467. begin
  4468. InputError('Relocation offset not found in data segment');
  4469. Exit;
  4470. end;
  4471. BaseSectionOffset:=DataSegments[SegI].DataSectionOffset;
  4472. ObjSec:=TObjSection(ObjData.ObjSectionList[FirstDataSegmentIdx+SegI]);
  4473. end;
  4474. 2..2+(Ord(High(TWasmCustomDebugSectionType))-Ord(Low(TWasmCustomDebugSectionType))):
  4475. begin
  4476. BaseSectionOffset:=0;
  4477. ObjSec:=ObjData.findsection(WasmCustomSectionName[TWasmCustomSectionType((j-2)+Ord(Low(TWasmCustomDebugSectionType)))]);
  4478. end;
  4479. else
  4480. internalerror(2023122801);
  4481. end;
  4482. case RelocType of
  4483. R_WASM_FUNCTION_INDEX_LEB:
  4484. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_FUNCTION_INDEX_LEB));
  4485. R_WASM_TABLE_INDEX_SLEB:
  4486. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB));
  4487. R_WASM_TABLE_INDEX_I32:
  4488. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE));
  4489. R_WASM_MEMORY_ADDR_LEB:
  4490. begin
  4491. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_LEB);
  4492. ObjReloc.Addend:=RelocAddend;
  4493. ObjSec.ObjRelocations.Add(ObjReloc);
  4494. end;
  4495. R_WASM_MEMORY_ADDR_SLEB:
  4496. begin
  4497. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB);
  4498. ObjReloc.Addend:=RelocAddend;
  4499. ObjSec.ObjRelocations.Add(ObjReloc);
  4500. end;
  4501. R_WASM_MEMORY_ADDR_I32:
  4502. begin
  4503. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE);
  4504. ObjReloc.Addend:=RelocAddend;
  4505. ObjSec.ObjRelocations.Add(ObjReloc);
  4506. end;
  4507. R_WASM_TYPE_INDEX_LEB:
  4508. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateFuncType(RelocOffset-BaseSectionOffset,FFuncTypes[RelocIndex]));
  4509. R_WASM_FUNCTION_OFFSET_I32:
  4510. begin
  4511. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE);
  4512. ObjReloc.Addend:=RelocAddend;
  4513. ObjReloc.IsFunctionOffsetI32:=True;
  4514. ObjSec.ObjRelocations.Add(ObjReloc);
  4515. end;
  4516. R_WASM_SECTION_OFFSET_I32:
  4517. begin
  4518. ObjReloc:=TWasmObjRelocation.CreateSection(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSec,RELOC_ABSOLUTE);
  4519. ObjReloc.Addend:=RelocAddend;
  4520. ObjSec.ObjRelocations.Add(ObjReloc);
  4521. end;
  4522. R_WASM_GLOBAL_INDEX_LEB:
  4523. begin
  4524. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_GLOBAL_INDEX_LEB));
  4525. if Assigned(SymbolTable[RelocIndex].ObjSym.TlsGlobalSym) then
  4526. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym.TlsGlobalSym,RELOC_GLOBAL_INDEX_LEB));
  4527. end;
  4528. R_WASM_GLOBAL_INDEX_I32:
  4529. begin
  4530. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE));
  4531. if Assigned(SymbolTable[RelocIndex].ObjSym.TlsGlobalSym) then
  4532. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym.TlsGlobalSym,RELOC_ABSOLUTE));
  4533. end;
  4534. R_WASM_TAG_INDEX_LEB:
  4535. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_TAG_INDEX_LEB));
  4536. else
  4537. internalerror(2023122802);
  4538. end;
  4539. end;
  4540. Result:=True;
  4541. end;
  4542. {****************************************************************************
  4543. TWasmExeOutput
  4544. ****************************************************************************}
  4545. procedure TWasmExeOutput.AddToNameMap(var nm: TCustomSectionNameMap; aidx: UInt32; const aname: string);
  4546. begin
  4547. SetLength(nm,Length(nm)+1);
  4548. with nm[High(nm)] do
  4549. begin
  4550. idx:=aidx;
  4551. name:=aname;
  4552. end;
  4553. end;
  4554. procedure TWasmExeOutput.AddToFunctionNameMap(aidx: UInt32; const aname: string);
  4555. begin
  4556. AddToNameMap(FFunctionNameMap,aidx,aname);
  4557. end;
  4558. procedure TWasmExeOutput.AddToGlobalNameMap(aidx: UInt32; const aname: string);
  4559. begin
  4560. AddToNameMap(FGlobalNameMap,aidx,aname);
  4561. end;
  4562. procedure TWasmExeOutput.AddToDataNameMap(aidx: UInt32; const aname: string);
  4563. begin
  4564. AddToNameMap(FDataNameMap,aidx,aname);
  4565. end;
  4566. procedure TWasmExeOutput.AddToTagNameMap(aidx: UInt32; const aname: string);
  4567. begin
  4568. AddToNameMap(FTagNameMap,aidx,aname);
  4569. end;
  4570. procedure TWasmExeOutput.WriteWasmSection(wsid: TWasmSectionID);
  4571. var
  4572. b: byte;
  4573. begin
  4574. b:=ord(wsid);
  4575. Writer.write(b,1);
  4576. WriteUleb(Writer,FWasmSections[wsid].size);
  4577. Writer.writearray(FWasmSections[wsid]);
  4578. end;
  4579. procedure TWasmExeOutput.WriteWasmSectionIfNotEmpty(wsid: TWasmSectionID);
  4580. begin
  4581. if FWasmSections[wsid].size>0 then
  4582. WriteWasmSection(wsid);
  4583. end;
  4584. procedure TWasmExeOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  4585. var
  4586. b: byte;
  4587. begin
  4588. b:=0;
  4589. Writer.write(b,1);
  4590. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  4591. Writer.writearray(FWasmCustomSections[wcst]);
  4592. end;
  4593. function TWasmExeOutput.writeData: boolean;
  4594. procedure WriteImportSection;
  4595. var
  4596. imports_count,
  4597. memory_imports: SizeInt;
  4598. i: Integer;
  4599. begin
  4600. if assigned(exemap) then
  4601. exemap.AddHeader('Import section');
  4602. if ts_wasm_threads in current_settings.targetswitches then
  4603. memory_imports:=1
  4604. else
  4605. memory_imports:=0;
  4606. imports_count:=Length(FFunctionImports)+memory_imports;
  4607. WriteUleb(FWasmSections[wsiImport],imports_count);
  4608. if ts_wasm_threads in current_settings.targetswitches then
  4609. begin
  4610. WriteName(FWasmSections[wsiImport],'env');
  4611. WriteName(FWasmSections[wsiImport],'memory');
  4612. WriteByte(FWasmSections[wsiImport],$02); { mem }
  4613. WriteByte(FWasmSections[wsiImport],$03); { shared }
  4614. WriteUleb(FWasmSections[wsiImport],FMinMemoryPages);
  4615. WriteUleb(FWasmSections[wsiImport],Max(FMinMemoryPages,FMaxMemoryPages)); { max pages }
  4616. if assigned(exemap) then
  4617. exemap.Add(' Memory[0] pages: initial='+tostr(FMinMemoryPages)+' max='+tostr(Max(FMinMemoryPages,FMaxMemoryPages))+' shared <- env.memory');
  4618. end;
  4619. for i:=0 to Length(FFunctionImports)-1 do
  4620. with FFunctionImports[i] do
  4621. begin
  4622. WriteName(FWasmSections[wsiImport],ModName);
  4623. WriteName(FWasmSections[wsiImport],Name);
  4624. WriteByte(FWasmSections[wsiImport],$00); { func }
  4625. WriteUleb(FWasmSections[wsiImport],TypeIdx);
  4626. if assigned(exemap) then
  4627. exemap.Add(' Function['+tostr(i)+'] sig='+tostr(TypeIdx)+' <- '+ModName+'.'+Name);
  4628. end;
  4629. end;
  4630. procedure WriteCodeSegments;
  4631. var
  4632. i: Integer;
  4633. exesec: TExeSection;
  4634. objsec: TWasmObjSection;
  4635. begin
  4636. exesec:=FindExeSection('.text');
  4637. if not assigned(exesec) then
  4638. internalerror(2023123102);
  4639. if not (oso_Data in exesec.SecOptions) then
  4640. internalerror(2023123103);
  4641. WriteUleb(FWasmSections[wsiFunction],exesec.ObjSectionList.Count);
  4642. WriteUleb(FWasmSections[wsiCode],exesec.ObjSectionList.Count);
  4643. for i:=0 to exesec.ObjSectionList.Count-1 do
  4644. begin
  4645. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4646. if not (oso_data in objsec.secoptions) then
  4647. internalerror(2023123104);
  4648. if not assigned(objsec.data) then
  4649. internalerror(2023123105);
  4650. if objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex<>(i+Length(FFunctionImports)) then
  4651. internalerror(2024010101);
  4652. WriteUleb(FWasmSections[wsiFunction],objsec.MainFuncSymbol.LinkingData.ExeTypeIndex);
  4653. WriteUleb(FWasmSections[wsiCode],objsec.Data.size);
  4654. objsec.Data.seek(0);
  4655. CopyDynamicArray(objsec.Data,FWasmSections[wsiCode],objsec.Data.size);
  4656. end;
  4657. end;
  4658. procedure WriteDataSegments;
  4659. procedure WriteExeSection(exesec: TExeSection);
  4660. var
  4661. i: Integer;
  4662. objsec: TObjSection;
  4663. exesecdatapos: LongWord;
  4664. dpos, pad: QWord;
  4665. begin
  4666. AddToDataNameMap(Length(FDataNameMap),exesec.Name);
  4667. if ts_wasm_threads in current_settings.targetswitches then
  4668. WriteByte(FWasmSections[wsiData],1) { mode passive }
  4669. else
  4670. begin
  4671. WriteByte(FWasmSections[wsiData],0); { mode active, memory 0, offset e }
  4672. WriteByte(FWasmSections[wsiData],$41); { i32.const }
  4673. WriteSleb(FWasmSections[wsiData],longint(exesec.MemPos));
  4674. WriteByte(FWasmSections[wsiData],$0B); { end }
  4675. end;
  4676. WriteUleb(FWasmSections[wsiData],exesec.Size);
  4677. exesecdatapos:=FWasmSections[wsiData].size;
  4678. for i:=0 to exesec.ObjSectionList.Count-1 do
  4679. begin
  4680. objsec:=TObjSection(exesec.ObjSectionList[i]);
  4681. if not (oso_data in objsec.secoptions) then
  4682. internalerror(2024010104);
  4683. if not assigned(objsec.data) then
  4684. internalerror(2024010105);
  4685. dpos:=objsec.MemPos-exesec.MemPos+exesecdatapos;
  4686. pad:=dpos-FWasmSections[wsiData].size;
  4687. { objsection must be within SecAlign bytes from the previous one }
  4688. if (dpos<FWasmSections[wsiData].Size) or
  4689. (pad>=max(objsec.SecAlign,1)) then
  4690. internalerror(2024010106);
  4691. writeZeros(FWasmSections[wsiData],pad);
  4692. objsec.data.seek(0);
  4693. CopyDynamicArray(objsec.data,FWasmSections[wsiData],objsec.data.size);
  4694. end;
  4695. if (FWasmSections[wsiData].size-exesecdatapos)<>exesec.Size then
  4696. internalerror(2024010107);
  4697. end;
  4698. var
  4699. DataCount: Integer;
  4700. DataSecName: string;
  4701. ExeSec: TExeSection;
  4702. begin
  4703. DataCount:=0;
  4704. for DataSecName in DataSections do
  4705. begin
  4706. ExeSec:=FindExeSection(DataSecName);
  4707. if Assigned(ExeSec) and (ExeSec.Size>0) then
  4708. Inc(DataCount);
  4709. end;
  4710. WriteUleb(FWasmSections[wsiDataCount],DataCount);
  4711. WriteUleb(FWasmSections[wsiData],DataCount);
  4712. for DataSecName in DataSections do
  4713. begin
  4714. ExeSec:=FindExeSection(DataSecName);
  4715. if Assigned(ExeSec) and (ExeSec.Size>0) then
  4716. WriteExeSection(ExeSec);
  4717. end;
  4718. end;
  4719. procedure WriteTableAndElemSections;
  4720. const
  4721. TableCount=1;
  4722. var
  4723. i: Integer;
  4724. begin
  4725. { Table section }
  4726. WriteUleb(FWasmSections[wsiTable],TableCount);
  4727. { table 0 }
  4728. { table type }
  4729. WriteByte(FWasmSections[wsiTable],encode_wasm_basic_type(wbt_funcref));
  4730. { table limits }
  4731. WriteByte(FWasmSections[wsiTable],$01); { has min & max }
  4732. WriteUleb(FWasmSections[wsiTable],Length(FIndirectFunctionTable)); { min }
  4733. WriteUleb(FWasmSections[wsiTable],Length(FIndirectFunctionTable)); { max }
  4734. { Elem section }
  4735. WriteUleb(FWasmSections[wsiElement],1); { 1 element segment }
  4736. { element segment 0 }
  4737. WriteByte(FWasmSections[wsiElement],0); { type funcref, init((ref.func y) end)*, mode active <table 0, offset e> }
  4738. { e:expr }
  4739. WriteByte(FWasmSections[wsiElement],$41); { i32.const }
  4740. WriteSleb(FWasmSections[wsiElement],1); { starting from 1 (table entry 0 is ref.null) }
  4741. WriteByte(FWasmSections[wsiElement],$0B); { end }
  4742. { y*:vec(funcidx) }
  4743. WriteUleb(FWasmSections[wsiElement],Length(FIndirectFunctionTable)-1);
  4744. for i:=1 to Length(FIndirectFunctionTable)-1 do
  4745. WriteUleb(FWasmSections[wsiElement],FIndirectFunctionTable[i].FuncIdx);
  4746. end;
  4747. procedure WriteGlobalSection;
  4748. var
  4749. exesec: TExeSection;
  4750. globals_count, i: Integer;
  4751. objsec: TWasmObjSection;
  4752. begin
  4753. exesec:=FindExeSection('.wasm_globals');
  4754. if not assigned(exesec) then
  4755. internalerror(2024010112);
  4756. globals_count:=exesec.ObjSectionList.Count;
  4757. if globals_count<>exesec.Size then
  4758. internalerror(2024010113);
  4759. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  4760. for i:=0 to exesec.ObjSectionList.Count-1 do
  4761. begin
  4762. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4763. WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(objsec.MainFuncSymbol.LinkingData.GlobalType));
  4764. if objsec.MainFuncSymbol.LinkingData.GlobalIsMutable then
  4765. WriteByte(FWasmSections[wsiGlobal],1)
  4766. else
  4767. WriteByte(FWasmSections[wsiGlobal],0);
  4768. { initializer expr }
  4769. with objsec.MainFuncSymbol.LinkingData.GlobalInitializer do
  4770. case typ of
  4771. wbt_i32:
  4772. begin
  4773. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  4774. WriteSleb(FWasmSections[wsiGlobal],init_i32);
  4775. end;
  4776. wbt_i64:
  4777. begin
  4778. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  4779. WriteSleb(FWasmSections[wsiGlobal],init_i64);
  4780. end;
  4781. wbt_f32:
  4782. begin
  4783. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  4784. WriteF32LE(FWasmSections[wsiGlobal],init_f32);
  4785. end;
  4786. wbt_f64:
  4787. begin
  4788. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  4789. WriteF64LE(FWasmSections[wsiGlobal],init_f64);
  4790. end;
  4791. wbt_funcref,
  4792. wbt_externref:
  4793. begin
  4794. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null }
  4795. WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(typ));
  4796. end;
  4797. else
  4798. internalerror(2024010114);
  4799. end;
  4800. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  4801. { add entry for the name section }
  4802. AddToGlobalNameMap(i,objsec.MainFuncSymbol.Name);
  4803. end;
  4804. end;
  4805. procedure WriteTagSection;
  4806. var
  4807. exesec: TExeSection;
  4808. tags_count, i: Integer;
  4809. objsec: TWasmObjSection;
  4810. begin
  4811. exesec:=FindExeSection('.wasm_tags');
  4812. if not assigned(exesec) then
  4813. exit;
  4814. tags_count:=exesec.ObjSectionList.Count;
  4815. if tags_count<>exesec.Size then
  4816. internalerror(2024010702);
  4817. if tags_count=0 then
  4818. exit;
  4819. WriteUleb(FWasmSections[wsiTag],tags_count);
  4820. for i:=0 to exesec.ObjSectionList.Count-1 do
  4821. begin
  4822. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4823. WriteByte(FWasmSections[wsiTag],0);
  4824. WriteUleb(FWasmSections[wsiTag],objsec.MainFuncSymbol.LinkingData.ExeTypeIndex);
  4825. AddToTagNameMap(i,objsec.MainFuncSymbol.Name);
  4826. end;
  4827. end;
  4828. procedure WriteExportSection;
  4829. const
  4830. MemoryExportsCount=1;
  4831. var
  4832. FunctionExportsCount: Integer;
  4833. ExportsCount: Integer;
  4834. textsec: TExeSection;
  4835. i: Integer;
  4836. objsec: TWasmObjSection;
  4837. begin
  4838. if assigned(exemap) then
  4839. exemap.AddHeader('Export section');
  4840. FunctionExportsCount:=0;
  4841. textsec:=FindExeSection('.text');
  4842. if not assigned(textsec) then
  4843. internalerror(2024010115);
  4844. for i:=0 to textsec.ObjSectionList.Count-1 do
  4845. begin
  4846. objsec:=TWasmObjSection(textsec.ObjSectionList[i]);
  4847. if objsec.MainFuncSymbol.LinkingData.IsExported then
  4848. Inc(FunctionExportsCount)
  4849. end;
  4850. ExportsCount:=MemoryExportsCount+FunctionExportsCount;
  4851. WriteUleb(FWasmSections[wsiExport],ExportsCount);
  4852. { export 0 }
  4853. WriteName(FWasmSections[wsiExport],'memory');
  4854. WriteByte(FWasmSections[wsiExport],$02); { mem }
  4855. WriteUleb(FWasmSections[wsiExport],0); { memidx = 0 }
  4856. if assigned(exemap) then
  4857. exemap.Add(' Memory[0] -> "memory"');
  4858. for i:=0 to textsec.ObjSectionList.Count-1 do
  4859. begin
  4860. objsec:=TWasmObjSection(textsec.ObjSectionList[i]);
  4861. if objsec.MainFuncSymbol.LinkingData.IsExported then
  4862. begin
  4863. WriteName(FWasmSections[wsiExport],objsec.MainFuncSymbol.LinkingData.ExportName);
  4864. WriteByte(FWasmSections[wsiExport],$00); { func }
  4865. WriteUleb(FWasmSections[wsiExport],objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex); { funcidx }
  4866. if assigned(exemap) then
  4867. exemap.Add(' Function['+tostr(objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex)+'] -> "'+objsec.MainFuncSymbol.LinkingData.ExportName+'"');
  4868. end;
  4869. end;
  4870. end;
  4871. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  4872. var
  4873. exesec: TExeSection;
  4874. begin
  4875. exesec:=FindExeSection(WasmCustomSectionName[st]);
  4876. if assigned(exesec) then
  4877. begin
  4878. WriteExeSectionToDynArray(exesec,FWasmCustomSections[st]);
  4879. WriteWasmCustomSection(st);
  4880. end;
  4881. end;
  4882. procedure WriteNameMap(const nm: TCustomSectionNameMap; dest: tdynamicarray);
  4883. var
  4884. i: Integer;
  4885. begin
  4886. WriteUleb(dest,Length(nm));
  4887. for i:=low(nm) to high(nm) do
  4888. with nm[i] do
  4889. begin
  4890. WriteUleb(dest,idx);
  4891. WriteName(dest,name);
  4892. end;
  4893. end;
  4894. procedure WriteNameSubsection(wnst: TWasmNameSubsectionType);
  4895. begin
  4896. if FWasmNameSubsections[wnst].size>0 then
  4897. begin
  4898. WriteByte(FWasmCustomSections[wcstName],Ord(wnst));
  4899. WriteUleb(FWasmCustomSections[wcstName],FWasmNameSubsections[wnst].size);
  4900. FWasmNameSubsections[wnst].seek(0);
  4901. CopyDynamicArray(FWasmNameSubsections[wnst],FWasmCustomSections[wcstName],FWasmNameSubsections[wnst].size);
  4902. end;
  4903. end;
  4904. procedure WriteNameSection;
  4905. begin
  4906. WriteName(FWasmNameSubsections[wnstModuleName],current_module.exefilename);
  4907. WriteNameSubsection(wnstModuleName);
  4908. WriteNameMap(FFunctionNameMap,FWasmNameSubsections[wnstFunctionNames]);
  4909. WriteNameSubsection(wnstFunctionNames);
  4910. WriteNameMap(FGlobalNameMap,FWasmNameSubsections[wnstGlobalNames]);
  4911. WriteNameSubsection(wnstGlobalNames);
  4912. WriteNameMap(FDataNameMap,FWasmNameSubsections[wnstDataNames]);
  4913. WriteNameSubsection(wnstDataNames);
  4914. if Length(FTagNameMap)>0 then
  4915. begin
  4916. WriteNameMap(FTagNameMap,FWasmNameSubsections[wnstTagNames]);
  4917. WriteNameSubsection(wnstTagNames);
  4918. end;
  4919. end;
  4920. var
  4921. cust_sec: TWasmCustomSectionType;
  4922. begin
  4923. result:=false;
  4924. FMaxMemoryPages:=align(maxheapsize,WasmPageSize) div WasmPageSize;
  4925. { each custom sections starts with its name }
  4926. for cust_sec in TWasmCustomSectionType do
  4927. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  4928. SetStackPointer;
  4929. SetTlsSizeAlignAndBase;
  4930. SetThreadVarGlobalsInitValues;
  4931. GenerateCode_InitTls;
  4932. GenerateCode_InitSharedMemory;
  4933. FFuncTypes.WriteTo(FWasmSections[wsiType]);
  4934. WriteImportSection;
  4935. WriteCodeSegments;
  4936. WriteDataSegments;
  4937. WriteTableAndElemSections;
  4938. WriteGlobalSection;
  4939. WriteTagSection;
  4940. if not (ts_wasm_threads in current_settings.targetswitches) then
  4941. begin
  4942. if assigned(exemap) then
  4943. exemap.AddHeader('Memory section');
  4944. WriteUleb(FWasmSections[wsiMemory],1);
  4945. if FMaxMemoryPages>=FMinMemoryPages then
  4946. begin
  4947. WriteByte(FWasmSections[wsiMemory],1);
  4948. WriteUleb(FWasmSections[wsiMemory],FMinMemoryPages);
  4949. WriteUleb(FWasmSections[wsiMemory],FMaxMemoryPages);
  4950. if assigned(exemap) then
  4951. exemap.Add(' Memory[0] pages: initial='+tostr(FMinMemoryPages)+' max='+tostr(FMaxMemoryPages));
  4952. end
  4953. else
  4954. begin
  4955. WriteByte(FWasmSections[wsiMemory],0);
  4956. WriteUleb(FWasmSections[wsiMemory],FMinMemoryPages);
  4957. if assigned(exemap) then
  4958. exemap.Add(' Memory[0] pages: initial='+tostr(FMinMemoryPages));
  4959. end;
  4960. end;
  4961. WriteExportSection;
  4962. if ts_wasm_threads in current_settings.targetswitches then
  4963. WriteUleb(FWasmSections[wsiStart],FInitSharedMemoryFunctionSym.LinkingData.ExeFunctionIndex);
  4964. WriteNameSection;
  4965. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  4966. Writer.write(WasmVersion,SizeOf(WasmVersion));
  4967. WriteWasmSection(wsiType);
  4968. WriteWasmSection(wsiImport);
  4969. WriteWasmSection(wsiFunction);
  4970. WriteWasmSection(wsiTable);
  4971. if not (ts_wasm_threads in current_settings.targetswitches) then
  4972. WriteWasmSection(wsiMemory);
  4973. WriteWasmSectionIfNotEmpty(wsiTag);
  4974. WriteWasmSection(wsiGlobal);
  4975. WriteWasmSection(wsiExport);
  4976. if ts_wasm_threads in current_settings.targetswitches then
  4977. WriteWasmSection(wsiStart);
  4978. WriteWasmSection(wsiElement);
  4979. WriteWasmSection(wsiDataCount);
  4980. WriteWasmSection(wsiCode);
  4981. WriteWasmSection(wsiData);
  4982. MaybeWriteDebugSection(wcstDebugAbbrev);
  4983. MaybeWriteDebugSection(wcstDebugInfo);
  4984. MaybeWriteDebugSection(wcstDebugStr);
  4985. MaybeWriteDebugSection(wcstDebugLine);
  4986. MaybeWriteDebugSection(wcstDebugFrame);
  4987. MaybeWriteDebugSection(wcstDebugAranges);
  4988. MaybeWriteDebugSection(wcstDebugRanges);
  4989. WriteWasmCustomSection(wcstName);
  4990. result := true;
  4991. end;
  4992. procedure TWasmExeOutput.DoRelocationFixup(objsec: TObjSection);
  4993. procedure writeUInt32LE(v: uint32);
  4994. begin
  4995. {$ifdef FPC_BIG_ENDIAN}
  4996. v:=SwapEndian(v);
  4997. {$endif FPC_BIG_ENDIAN}
  4998. objsec.data.write(v,4);
  4999. end;
  5000. var
  5001. i: Integer;
  5002. objreloc: TWasmObjRelocation;
  5003. objsym: TWasmObjSymbol;
  5004. begin
  5005. for i:=0 to objsec.ObjRelocations.Count-1 do
  5006. begin
  5007. objreloc:=TWasmObjRelocation(objsec.ObjRelocations[i]);
  5008. if assigned(objreloc.symbol) then
  5009. begin
  5010. objsym:=TWasmObjSymbol(objreloc.symbol);
  5011. case objreloc.typ of
  5012. RELOC_FUNCTION_INDEX_LEB:
  5013. begin
  5014. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5015. internalerror(2024010103);
  5016. if FRelocationPass=2 then
  5017. begin
  5018. objsec.Data.seek(objreloc.DataOffset);
  5019. WriteUleb5(objsec.Data,objsym.LinkingData.ExeFunctionIndex);
  5020. end;
  5021. end;
  5022. RELOC_ABSOLUTE:
  5023. begin
  5024. case objsym.typ of
  5025. AT_FUNCTION:
  5026. begin
  5027. if objreloc.IsFunctionOffsetI32 then
  5028. begin
  5029. { R_WASM_FUNCTION_OFFSET_I32 }
  5030. if FRelocationPass=2 then
  5031. begin
  5032. objsec.Data.seek(objreloc.DataOffset);
  5033. writeUInt32LE(UInt32(objsym.objsection.MemPos+objreloc.Addend));
  5034. end;
  5035. end
  5036. else
  5037. begin
  5038. { R_WASM_TABLE_INDEX_I32 }
  5039. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5040. internalerror(2024010103);
  5041. case FRelocationPass of
  5042. 1:
  5043. if objsym.LinkingData.ExeIndirectFunctionTableIndex=-1 then
  5044. objsym.LinkingData.ExeIndirectFunctionTableIndex:=AddOrGetIndirectFunctionTableIndex(objsym.LinkingData.ExeFunctionIndex);
  5045. 2:
  5046. begin
  5047. objsec.Data.seek(objreloc.DataOffset);
  5048. writeUInt32LE(UInt32(objsym.LinkingData.ExeIndirectFunctionTableIndex));
  5049. end;
  5050. end;
  5051. end;
  5052. end;
  5053. AT_DATA:
  5054. begin
  5055. if objreloc.IsFunctionOffsetI32 then
  5056. internalerror(2024010602);
  5057. if FRelocationPass=2 then
  5058. begin
  5059. objsec.Data.seek(objreloc.DataOffset);
  5060. writeUInt32LE(UInt32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5061. end;
  5062. end;
  5063. AT_TLS:
  5064. begin
  5065. if objreloc.IsFunctionOffsetI32 then
  5066. internalerror(2024010602);
  5067. if FRelocationPass=2 then
  5068. begin
  5069. objsec.Data.seek(objreloc.DataOffset);
  5070. writeUInt32LE(UInt32((objsym.offset+objsym.objsection.MemPos-objsym.objsection.ExeSection.MemPos)+objreloc.Addend));
  5071. end;
  5072. end;
  5073. AT_WASM_GLOBAL:
  5074. begin
  5075. if objreloc.IsFunctionOffsetI32 then
  5076. internalerror(2024010602);
  5077. if FRelocationPass=2 then
  5078. begin
  5079. objsec.Data.seek(objreloc.DataOffset);
  5080. writeUInt32LE(UInt32(objsym.offset+objsym.objsection.MemPos));
  5081. end;
  5082. end;
  5083. else
  5084. internalerror(2024010108);
  5085. end;
  5086. end;
  5087. RELOC_MEMORY_ADDR_LEB:
  5088. begin
  5089. if objsym.typ<>AT_DATA then
  5090. internalerror(2024010109);
  5091. if FRelocationPass=2 then
  5092. begin
  5093. objsec.Data.seek(objreloc.DataOffset);
  5094. WriteUleb5(objsec.Data,UInt32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5095. end;
  5096. end;
  5097. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  5098. begin
  5099. case objsym.typ of
  5100. AT_FUNCTION:
  5101. begin
  5102. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5103. internalerror(2024010103);
  5104. case FRelocationPass of
  5105. 1:
  5106. if objsym.LinkingData.ExeIndirectFunctionTableIndex=-1 then
  5107. objsym.LinkingData.ExeIndirectFunctionTableIndex:=AddOrGetIndirectFunctionTableIndex(objsym.LinkingData.ExeFunctionIndex);
  5108. 2:
  5109. begin
  5110. objsec.Data.seek(objreloc.DataOffset);
  5111. WriteSleb5(objsec.Data,Int32(objsym.LinkingData.ExeIndirectFunctionTableIndex));
  5112. end;
  5113. end;
  5114. end;
  5115. AT_DATA:
  5116. begin
  5117. if FRelocationPass=2 then
  5118. begin
  5119. objsec.Data.seek(objreloc.DataOffset);
  5120. WriteSleb5(objsec.Data,Int32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5121. end;
  5122. end;
  5123. else
  5124. internalerror(2024010110);
  5125. end;
  5126. end;
  5127. RELOC_GLOBAL_INDEX_LEB:
  5128. if objsym.typ=AT_WASM_GLOBAL then
  5129. begin
  5130. if FRelocationPass=2 then
  5131. begin
  5132. objsec.Data.seek(objreloc.DataOffset);
  5133. WriteUleb5(objsec.Data,UInt32(objsym.offset+objsym.objsection.MemPos));
  5134. end;
  5135. end
  5136. else if (ts_wasm_threads in current_settings.targetswitches) and
  5137. (objsym.typ=AT_TLS) then
  5138. begin
  5139. { Nothing to do here. A second RELOC_GLOBAL_INDEX_LEB
  5140. relocation, overlaid on top of this one, pointing to
  5141. an AT_WASM_GLOBAL should have already done the job. }
  5142. end
  5143. else
  5144. internalerror(2024010111);
  5145. RELOC_TAG_INDEX_LEB:
  5146. begin
  5147. if objsym.typ<>AT_WASM_EXCEPTION_TAG then
  5148. internalerror(2024010708);
  5149. if FRelocationPass=2 then
  5150. begin
  5151. objsec.Data.seek(objreloc.DataOffset);
  5152. WriteUleb5(objsec.Data,UInt32(objsym.offset+objsym.objsection.MemPos));
  5153. end;
  5154. end;
  5155. else
  5156. internalerror(2024010109);
  5157. end;
  5158. end
  5159. else if assigned(objreloc.objsection) then
  5160. begin
  5161. if objreloc.typ<>RELOC_ABSOLUTE then
  5162. internalerror(2024010601);
  5163. if FRelocationPass=2 then
  5164. begin
  5165. objsec.Data.seek(objreloc.DataOffset);
  5166. writeUInt32LE(UInt32((objreloc.objsection.MemPos)+objreloc.Addend));
  5167. end;
  5168. end
  5169. else if objreloc.typ=RELOC_TYPE_INDEX_LEB then
  5170. begin
  5171. case FRelocationPass of
  5172. 1:
  5173. objreloc.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(objreloc.FuncType);
  5174. 2:
  5175. begin
  5176. objsec.Data.seek(objreloc.DataOffset);
  5177. WriteUleb5(objsec.Data,objreloc.ExeTypeIndex);
  5178. end;
  5179. end;
  5180. end
  5181. else
  5182. internalerror(2024010110);
  5183. end;
  5184. end;
  5185. constructor TWasmExeOutput.create;
  5186. var
  5187. i: TWasmSectionID;
  5188. j: TWasmCustomSectionType;
  5189. k: TWasmNameSubsectionType;
  5190. begin
  5191. inherited create;
  5192. CObjData:=TWasmObjData;
  5193. SectionMemAlign:=16;
  5194. MaxMemPos:=$FFFFFFFF;
  5195. FFuncTypes:=TWasmFuncTypeTable.Create;
  5196. for i in TWasmSectionID do
  5197. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  5198. for j in TWasmCustomSectionType do
  5199. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  5200. for k:=low(FWasmNameSubsections) to high(FWasmNameSubsections) do
  5201. FWasmNameSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  5202. SetLength(FIndirectFunctionTable,1);
  5203. FIndirectFunctionTable[0].FuncIdx:=-1;
  5204. end;
  5205. destructor TWasmExeOutput.destroy;
  5206. var
  5207. i: TWasmSectionID;
  5208. j: TWasmCustomSectionType;
  5209. k: TWasmNameSubsectionType;
  5210. begin
  5211. for i in TWasmSectionID do
  5212. FWasmSections[i].Free;
  5213. for j in TWasmCustomSectionType do
  5214. FWasmCustomSections[j].Free;
  5215. for k:=low(FWasmNameSubsections) to high(FWasmNameSubsections) do
  5216. FWasmNameSubsections[k].Free;
  5217. FFuncTypes.Free;
  5218. inherited destroy;
  5219. end;
  5220. procedure TWasmExeOutput.GenerateLibraryImports(ImportLibraryList: TFPHashObjectList);
  5221. var
  5222. i, j: Integer;
  5223. ImportLibrary: TImportLibrary;
  5224. ImportSymbol: TImportSymbol;
  5225. exesym: TExeSymbol;
  5226. begin
  5227. { Here map import symbols to exe symbols and create necessary sections.
  5228. Actual import generation is done after unused sections (and symbols) are removed. }
  5229. FImports:=ImportLibraryList;
  5230. for i:=0 to ImportLibraryList.Count-1 do
  5231. begin
  5232. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  5233. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  5234. begin
  5235. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  5236. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  5237. if assigned(exesym) and
  5238. (exesym.State<>symstate_defined) then
  5239. begin
  5240. ImportSymbol.CachedExeSymbol:=exesym;
  5241. exesym.State:=symstate_defined;
  5242. end;
  5243. end;
  5244. end;
  5245. PackUnresolvedExeSymbols('after module imports');
  5246. end;
  5247. procedure TWasmExeOutput.AfterUnusedSectionRemoval;
  5248. begin
  5249. PrepareImports;
  5250. PrepareFunctions;
  5251. PrepareTags;
  5252. if Assigned(exemap) then
  5253. WriteMap_TypeSection;
  5254. { we do an extra preliminary relocation pass, in order to prepare the
  5255. indices for the Type section and the Table section. This is required
  5256. by GenerateCode_InvokeHelper. }
  5257. FRelocationPass:=1;
  5258. FixupRelocations;
  5259. { in pass 2, we do the actual relocation fixups. No need to call
  5260. FixupRelocations here, since it'll be called in
  5261. TInternalLinker.RunLinkScript, after this method finishes. We only
  5262. set the FRelocationPass variable here, so DoRelocationFixup knows
  5263. which pass it is. }
  5264. FRelocationPass:=2;
  5265. { This needs to be done before pass 2 of the relocation fixups, because
  5266. it'll generate code, thus it'll move the offsets of the functions that
  5267. follow it in the Code section, and we want our DWARF debug info to
  5268. contain correct code offsets. }
  5269. GenerateCode_InvokeHelper;
  5270. if Assigned(exemap) then
  5271. WriteMap_IndirectFunctionTable;
  5272. end;
  5273. procedure TWasmExeOutput.MemPos_ExeSection(const aname: string);
  5274. const
  5275. DebugPrefix = '.debug_';
  5276. var
  5277. ExeSec: TExeSection;
  5278. i: Integer;
  5279. objsec: TObjSection;
  5280. firstdatasec: string;
  5281. begin
  5282. { WebAssembly is a Harvard architecture.
  5283. Data lives in a separate address space, so start addressing back from 0
  5284. (the LLVM leaves the first 1024 bytes in the data segment empty, so we
  5285. start at 1024). }
  5286. if ts_wasm_threads in current_settings.targetswitches then
  5287. firstdatasec:='.tbss'
  5288. else
  5289. firstdatasec:='.rodata';
  5290. if aname=firstdatasec then
  5291. begin
  5292. CurrMemPos:=1024;
  5293. inherited;
  5294. end
  5295. else if aname='.text' then
  5296. begin
  5297. CurrMemPos:=0;
  5298. ExeSec:=FindExeSection(aname);
  5299. if not assigned(ExeSec) then
  5300. exit;
  5301. exesec.MemPos:=CurrMemPos;
  5302. CurrMemPos:=CurrMemPos+UlebEncodingSize(exesec.ObjSectionList.Count);
  5303. { set position of object ObjSections }
  5304. for i:=0 to exesec.ObjSectionList.Count-1 do
  5305. begin
  5306. objsec:=TObjSection(exesec.ObjSectionList[i]);
  5307. CurrMemPos:=CurrMemPos+UlebEncodingSize(objsec.Size);
  5308. CurrMemPos:=objsec.setmempos(CurrMemPos);
  5309. end;
  5310. { calculate size of the section }
  5311. exesec.Size:=CurrMemPos-exesec.MemPos;
  5312. end
  5313. else if (aname='.wasm_globals') or (aname='.wasm_tags') or
  5314. (Copy(aname,1,Length(DebugPrefix))=DebugPrefix) then
  5315. begin
  5316. CurrMemPos:=0;
  5317. inherited;
  5318. end
  5319. else
  5320. inherited;
  5321. end;
  5322. procedure TWasmExeOutput.Load_Symbol(const aname: string);
  5323. begin
  5324. if aname=StackPointerSymStr then
  5325. begin
  5326. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5327. FStackPointerSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5328. FStackPointerSym.size:=1;
  5329. FStackPointerSym.ObjSection.WriteZeros(1);
  5330. TWasmObjSection(FStackPointerSym.ObjSection).MainFuncSymbol:=FStackPointerSym;
  5331. FStackPointerSym.LinkingData.GlobalType:=wbt_i32;
  5332. FStackPointerSym.LinkingData.GlobalIsMutable:=True;
  5333. FStackPointerSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5334. FStackPointerSym.LinkingData.GlobalInitializer.init_i32:=0;
  5335. end
  5336. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_base') then
  5337. begin
  5338. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5339. FTlsBaseSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5340. FTlsBaseSym.size:=1;
  5341. FTlsBaseSym.ObjSection.WriteZeros(1);
  5342. TWasmObjSection(FTlsBaseSym.ObjSection).MainFuncSymbol:=FTlsBaseSym;
  5343. FTlsBaseSym.LinkingData.GlobalType:=wbt_i32;
  5344. FTlsBaseSym.LinkingData.GlobalIsMutable:=True;
  5345. FTlsBaseSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5346. FTlsBaseSym.LinkingData.GlobalInitializer.init_i32:=0;
  5347. end
  5348. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_size') then
  5349. begin
  5350. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5351. FTlsSizeSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5352. FTlsSizeSym.size:=1;
  5353. FTlsSizeSym.ObjSection.WriteZeros(1);
  5354. TWasmObjSection(FTlsSizeSym.ObjSection).MainFuncSymbol:=FTlsSizeSym;
  5355. FTlsSizeSym.LinkingData.GlobalType:=wbt_i32;
  5356. FTlsSizeSym.LinkingData.GlobalIsMutable:=False;
  5357. FTlsSizeSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5358. FTlsSizeSym.LinkingData.GlobalInitializer.init_i32:=0;
  5359. end
  5360. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_align') then
  5361. begin
  5362. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5363. FTlsAlignSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5364. FTlsAlignSym.size:=1;
  5365. FTlsAlignSym.ObjSection.WriteZeros(1);
  5366. TWasmObjSection(FTlsAlignSym.ObjSection).MainFuncSymbol:=FTlsAlignSym;
  5367. FTlsAlignSym.LinkingData.GlobalType:=wbt_i32;
  5368. FTlsAlignSym.LinkingData.GlobalIsMutable:=False;
  5369. FTlsAlignSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5370. FTlsAlignSym.LinkingData.GlobalInitializer.init_i32:=0;
  5371. end
  5372. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__wasm_init_tls') then
  5373. begin
  5374. internalObjData.createsection('*'+aname,0,[]);
  5375. FInitTlsFunctionSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION));
  5376. TWasmObjSection(FInitTlsFunctionSym.ObjSection).MainFuncSymbol:=FInitTlsFunctionSym;
  5377. FInitTlsFunctionSym.LinkingData.FuncType:=TWasmFuncType.Create([wbt_i32],[]);
  5378. end
  5379. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__fpc_wasm_init_shared_memory') then
  5380. begin
  5381. internalObjData.createsection('*'+aname,0,[]);
  5382. FInitSharedMemoryFunctionSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION));
  5383. TWasmObjSection(FInitSharedMemoryFunctionSym.ObjSection).MainFuncSymbol:=FInitSharedMemoryFunctionSym;
  5384. FInitSharedMemoryFunctionSym.ObjSection.SecOptions:=FInitSharedMemoryFunctionSym.ObjSection.SecOptions+[oso_keep];
  5385. FInitSharedMemoryFunctionSym.LinkingData.FuncType:=TWasmFuncType.Create([],[]);
  5386. end
  5387. else
  5388. inherited;
  5389. end;
  5390. procedure TWasmExeOutput.PrepareImports;
  5391. function AddFunctionImport(const libname,symname:TCmdStr; functype: TWasmFuncType): Integer;
  5392. begin
  5393. SetLength(FFunctionImports,Length(FFunctionImports)+1);
  5394. Result:=High(FFunctionImports);
  5395. if assigned(exemap) then
  5396. exemap.Add(' Importing Function[' + tostr(Result) + '] ' + symname + functype.ToString);
  5397. with FFunctionImports[Result] do
  5398. begin
  5399. ModName:=libname;
  5400. Name:=symname;
  5401. TypeIdx:=FFuncTypes.AddOrGetFuncType(functype);
  5402. end;
  5403. end;
  5404. var
  5405. i, j: Integer;
  5406. ImportLibrary: TImportLibrary;
  5407. ImportSymbol: TImportSymbol;
  5408. exesym: TExeSymbol;
  5409. newdll: Boolean;
  5410. fsym: TWasmObjSymbol;
  5411. objdata: TObjData;
  5412. begin
  5413. for i:=0 to FImports.Count-1 do
  5414. begin
  5415. ImportLibrary:=TImportLibrary(FImports[i]);
  5416. newdll:=False;
  5417. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  5418. begin
  5419. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  5420. exesym:=ImportSymbol.CachedExeSymbol;
  5421. if assigned(exesym) and
  5422. exesym.Used then
  5423. begin
  5424. if (not newdll) and assigned(exemap) then
  5425. begin
  5426. exemap.Add('');
  5427. exemap.Add('Importing from module '+ImportLibrary.Name);
  5428. end;
  5429. newdll:=True;
  5430. TWasmObjSymbol(exesym.ObjSymbol).LinkingData.ExeFunctionIndex:=
  5431. AddFunctionImport(ImportLibrary.Name,ImportSymbol.Name,TWasmObjSymbol(exesym.ObjSymbol).LinkingData.FuncType);
  5432. AddToFunctionNameMap(TWasmObjSymbol(exesym.ObjSymbol).LinkingData.ExeFunctionIndex,ImportSymbol.MangledName);
  5433. end;
  5434. end;
  5435. end;
  5436. { set ExeFunctionIndex to the alias symbols as well }
  5437. for i:=0 to ObjDataList.Count-1 do
  5438. begin
  5439. objdata:=TObjData(ObjDataList[i]);
  5440. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5441. begin
  5442. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5443. if (fsym.LinkingData.ExeFunctionIndex=-1) and assigned(fsym.exesymbol) and (TWasmObjSymbol(fsym.exesymbol.ObjSymbol).LinkingData.ExeFunctionIndex<>-1) then
  5444. fsym.LinkingData.ExeFunctionIndex:=TWasmObjSymbol(fsym.exesymbol.ObjSymbol).LinkingData.ExeFunctionIndex;
  5445. end;
  5446. end;
  5447. end;
  5448. procedure TWasmExeOutput.PrepareFunctions;
  5449. var
  5450. i, j: Integer;
  5451. exesec: TExeSection;
  5452. objsec: TWasmObjSection;
  5453. fsym: TWasmObjSymbol;
  5454. objdata: TObjData;
  5455. begin
  5456. if assigned(exemap) then
  5457. begin
  5458. exemap.Add('');
  5459. exemap.Add('Functions, defined in this module:');
  5460. end;
  5461. exesec:=FindExeSection('.text');
  5462. if not assigned(exesec) then
  5463. internalerror(2023123106);
  5464. for i:=0 to exesec.ObjSectionList.Count-1 do
  5465. begin
  5466. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5467. fsym:=objsec.MainFuncSymbol;
  5468. if not assigned(fsym) then
  5469. internalerror(2023123107);
  5470. if not assigned(fsym.LinkingData.FuncType) then
  5471. internalerror(2023123108);
  5472. if fsym.LinkingData.ExeFunctionIndex<>-1 then
  5473. internalerror(2023123109);
  5474. if fsym.LinkingData.ExeTypeIndex<>-1 then
  5475. internalerror(2023123109);
  5476. fsym.LinkingData.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(fsym.LinkingData.FuncType);
  5477. fsym.LinkingData.ExeFunctionIndex:=i+Length(FFunctionImports);
  5478. if assigned(exemap) then
  5479. begin
  5480. exemap.Add(' Function[' + tostr(fsym.LinkingData.ExeFunctionIndex) + '] ' + fsym.Name + fsym.LinkingData.FuncType.ToString);
  5481. end;
  5482. AddToFunctionNameMap(fsym.LinkingData.ExeFunctionIndex,fsym.Name);
  5483. end;
  5484. { set ExeFunctionIndex to the alias symbols as well }
  5485. for i:=0 to ObjDataList.Count-1 do
  5486. begin
  5487. objdata:=TObjData(ObjDataList[i]);
  5488. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5489. begin
  5490. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5491. if assigned(fsym.objsection) and fsym.objsection.USed and (fsym.typ=AT_FUNCTION) and (fsym.LinkingData.ExeFunctionIndex=-1) then
  5492. begin
  5493. fsym.LinkingData.ExeFunctionIndex:=TWasmObjSection(fsym.objsection).MainFuncSymbol.LinkingData.ExeFunctionIndex;
  5494. if fsym.LinkingData.ExeFunctionIndex=-1 then
  5495. internalerror(2024010102);
  5496. end;
  5497. end;
  5498. end;
  5499. end;
  5500. procedure TWasmExeOutput.PrepareTags;
  5501. var
  5502. exesec: TExeSection;
  5503. i, j: Integer;
  5504. objsec: TWasmObjSection;
  5505. fsym: TWasmObjSymbol;
  5506. objdata: TObjData;
  5507. begin
  5508. exesec:=FindExeSection('.wasm_tags');
  5509. if not assigned(exesec) then
  5510. exit;
  5511. if assigned(exemap) then
  5512. begin
  5513. exemap.Add('');
  5514. exemap.Add('Tags, defined in this module:');
  5515. end;
  5516. for i:=0 to exesec.ObjSectionList.Count-1 do
  5517. begin
  5518. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5519. fsym:=objsec.MainFuncSymbol;
  5520. if not assigned(fsym) then
  5521. internalerror(2024010703);
  5522. if not assigned(fsym.LinkingData.FuncType) then
  5523. internalerror(2024010704);
  5524. if fsym.LinkingData.ExeTagIndex<>-1 then
  5525. internalerror(2024010705);
  5526. if fsym.LinkingData.ExeTypeIndex<>-1 then
  5527. internalerror(2024010706);
  5528. fsym.LinkingData.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(fsym.LinkingData.FuncType);
  5529. fsym.LinkingData.ExeTagIndex:=i+Length(FTagImports);
  5530. if assigned(exemap) then
  5531. begin
  5532. exemap.Add(' Tag[' + tostr(fsym.LinkingData.ExeTagIndex) + '] ' + fsym.Name + fsym.LinkingData.FuncType.ToString);
  5533. end;
  5534. end;
  5535. { set ExeTagIndex to the alias symbols as well }
  5536. for i:=0 to ObjDataList.Count-1 do
  5537. begin
  5538. objdata:=TObjData(ObjDataList[i]);
  5539. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5540. begin
  5541. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5542. if assigned(fsym.objsection) and fsym.objsection.USed and (fsym.typ=AT_WASM_EXCEPTION_TAG) and (fsym.LinkingData.ExeTagIndex=-1) then
  5543. begin
  5544. fsym.LinkingData.ExeTagIndex:=TWasmObjSection(fsym.objsection).MainFuncSymbol.LinkingData.ExeTagIndex;
  5545. if fsym.LinkingData.ExeTagIndex=-1 then
  5546. internalerror(2024010707);
  5547. end;
  5548. end;
  5549. end;
  5550. end;
  5551. function TWasmExeOutput.AddOrGetIndirectFunctionTableIndex(FuncIdx: Integer): integer;
  5552. var
  5553. i: Integer;
  5554. begin
  5555. for i:=1 to length(FIndirectFunctionTable)-1 do
  5556. if FIndirectFunctionTable[i].FuncIdx=FuncIdx then
  5557. begin
  5558. Result:=i;
  5559. exit;
  5560. end;
  5561. SetLength(FIndirectFunctionTable,Length(FIndirectFunctionTable)+1);
  5562. Result:=High(FIndirectFunctionTable);
  5563. FIndirectFunctionTable[Result].FuncIdx:=FuncIdx;
  5564. end;
  5565. procedure TWasmExeOutput.SetStackPointer;
  5566. var
  5567. BssSec: TExeSection;
  5568. StackStart, InitialStackPtrAddr: QWord;
  5569. begin
  5570. BssSec:=FindExeSection('.bss');
  5571. InitialStackPtrAddr := (BssSec.MemPos+BssSec.Size+stacksize+15) and (not 15);
  5572. FMinMemoryPages := Max(
  5573. QWord(Align(QWord(InitialStackPtrAddr),QWord(WasmPageSize)) div WasmPageSize),
  5574. QWord(Align(QWord(heapsize),QWord(WasmPageSize)) div WasmPageSize));
  5575. FStackPointerSym.LinkingData.GlobalInitializer.init_i32:=Int32(InitialStackPtrAddr);
  5576. end;
  5577. procedure TWasmExeOutput.SetTlsSizeAlignAndBase;
  5578. var
  5579. TBssSec: TExeSection;
  5580. begin
  5581. if not (ts_wasm_threads in current_settings.targetswitches) then
  5582. exit;
  5583. TBssSec:=FindExeSection('.tbss');
  5584. FTlsSizeSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.Size);
  5585. FTlsAlignSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.SecAlign);
  5586. FTlsBaseSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.MemPos);
  5587. end;
  5588. procedure TWasmExeOutput.SetThreadVarGlobalsInitValues;
  5589. var
  5590. exesec: TExeSection;
  5591. i: Integer;
  5592. objsec: TWasmObjSection;
  5593. objsym: TWasmObjSymbol;
  5594. begin
  5595. if not (ts_wasm_threads in current_settings.targetswitches) then
  5596. exit;
  5597. exesec:=FindExeSection('.wasm_globals');
  5598. if not assigned(exesec) then
  5599. internalerror(2024010112);
  5600. for i:=0 to exesec.ObjSectionList.Count-1 do
  5601. begin
  5602. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5603. objsym:=objsec.MainFuncSymbol;
  5604. if Assigned(objsym.TlsDataSym) then
  5605. begin
  5606. objsym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5607. objsym.LinkingData.GlobalInitializer.init_i32:=objsym.TlsDataSym.offset+objsym.TlsDataSym.objsection.MemPos;
  5608. end;
  5609. end;
  5610. end;
  5611. procedure TWasmExeOutput.GenerateCode_InitTls;
  5612. var
  5613. Sec: TObjSection;
  5614. globalexesec: TExeSection;
  5615. i: Integer;
  5616. globalobjsec: TWasmObjSection;
  5617. globalobjsym: TWasmObjSymbol;
  5618. OffsetInTls: QWord;
  5619. begin
  5620. if not (ts_wasm_threads in current_settings.targetswitches) then
  5621. exit;
  5622. globalexesec:=FindExeSection('.wasm_globals');
  5623. if not assigned(globalexesec) then
  5624. internalerror(2024010112);
  5625. Sec:=FInitTlsFunctionSym.objsection;
  5626. Sec.SecOptions:=Sec.SecOptions+[oso_Data];
  5627. { locals }
  5628. Sec.writeUInt8($00);
  5629. { local.get 0 }
  5630. Sec.writeUInt16BE($2000);
  5631. { global.set $__tls_base }
  5632. Sec.writeUInt8($24);
  5633. WriteUleb(sec,FTlsBaseSym.offset+FTlsBaseSym.objsection.MemPos);
  5634. for i:=0 to globalexesec.ObjSectionList.Count-1 do
  5635. begin
  5636. globalobjsec:=TWasmObjSection(globalexesec.ObjSectionList[i]);
  5637. globalobjsym:=globalobjsec.MainFuncSymbol;
  5638. if Assigned(globalobjsym.TlsDataSym) then
  5639. begin
  5640. OffsetInTls:=globalobjsym.TlsDataSym.offset+globalobjsym.TlsDataSym.objsection.MemPos-globalobjsym.TlsDataSym.objsection.ExeSection.MemPos;
  5641. { local.get 0 }
  5642. Sec.writeUInt16BE($2000);
  5643. if OffsetInTls<>0 then
  5644. begin
  5645. { i32.const $OffsetInTls }
  5646. Sec.writeUInt8($41);
  5647. WriteSleb(Sec,Int32(OffsetInTls));
  5648. { i32.add }
  5649. Sec.writeUInt8($6A);
  5650. end;
  5651. { global.set y }
  5652. Sec.writeUInt8($24);
  5653. WriteUleb(sec,globalobjsym.offset+globalobjsym.objsection.MemPos);
  5654. end;
  5655. end;
  5656. Sec.writeUInt8($0B); { end }
  5657. end;
  5658. procedure TWasmExeOutput.GenerateCode_InitSharedMemory;
  5659. const
  5660. InitFlagOfs=256;
  5661. var
  5662. Sec: TObjSection;
  5663. DataSecName: string;
  5664. DataSecIdx: Integer;
  5665. ExeSec: TExeSection;
  5666. begin
  5667. if not (ts_wasm_threads in current_settings.targetswitches) then
  5668. exit;
  5669. Sec:=FInitSharedMemoryFunctionSym.objsection;
  5670. Sec.SecOptions:=Sec.SecOptions+[oso_Data];
  5671. { locals }
  5672. Sec.writeUInt8($00);
  5673. { block }
  5674. Sec.writeUInt16BE($0240);
  5675. { block }
  5676. Sec.writeUInt16BE($0240);
  5677. { block }
  5678. Sec.writeUInt16BE($0240);
  5679. { i32.const $InitFlag }
  5680. Sec.writeUInt8($41);
  5681. WriteSleb(sec,InitFlagOfs);
  5682. { i32.const 0 }
  5683. Sec.writeUInt16BE($4100);
  5684. { i32.const 1 }
  5685. Sec.writeUInt16BE($4101);
  5686. { i32.atomic.rmw.cmpxchg 2 0 }
  5687. Sec.writeUInt32BE($fe480200);
  5688. { br_table 0 1 2 }
  5689. Sec.writebytes(#$0e#$02#$00#$01#$02);
  5690. { end }
  5691. Sec.writeUInt8($0B);
  5692. DataSecIdx:=-1;
  5693. for DataSecName in DataSections do
  5694. begin
  5695. ExeSec:=FindExeSection(DataSecName);
  5696. if Assigned(ExeSec) and (ExeSec.Size>0) then
  5697. begin
  5698. Inc(DataSecIdx);
  5699. { i32.const $memPos }
  5700. Sec.writeUInt8($41);
  5701. WriteSleb(sec,Int32(ExeSec.MemPos));
  5702. { i32.const 0 }
  5703. Sec.writeUInt16BE($4100);
  5704. { i32.const size }
  5705. Sec.writeUInt8($41);
  5706. WriteSleb(sec,Int32(ExeSec.Size));
  5707. { memory.init $DataSecIdx 0 }
  5708. Sec.writeUInt16BE($fc08);
  5709. WriteUleb(sec,DataSecIdx);
  5710. Sec.writeUInt8(0);
  5711. end;
  5712. end;
  5713. { i32.const $InitFlag }
  5714. Sec.writeUInt8($41);
  5715. WriteSleb(sec,InitFlagOfs);
  5716. { i32.const 2 }
  5717. Sec.writeUInt16BE($4102);
  5718. { i32.atomic.store 2 0 }
  5719. Sec.writeUInt32BE($fe170200);
  5720. { i32.const $InitFlag }
  5721. Sec.writeUInt8($41);
  5722. WriteSleb(sec,InitFlagOfs);
  5723. { i32.const 4294967295 }
  5724. Sec.writeUInt16BE($417f);
  5725. { memory.atomic.notify 2 0 }
  5726. Sec.writeUInt32BE($fe000200);
  5727. { drop }
  5728. Sec.writeUInt8($1A);
  5729. { br 1 }
  5730. Sec.writeUInt16BE($0C01);
  5731. { end }
  5732. Sec.writeUInt8($0B);
  5733. { i32.const $InitFlag }
  5734. Sec.writeUInt8($41);
  5735. WriteSleb(sec,InitFlagOfs);
  5736. { i32.const 1 }
  5737. Sec.writeUInt16BE($4101);
  5738. { i64.const -1 }
  5739. Sec.writeUInt16BE($427f);
  5740. { memory.atomic.wait32 2 0 }
  5741. Sec.writeUInt32BE($fe010200);
  5742. { drop }
  5743. Sec.writeUInt8($1A);
  5744. { end }
  5745. Sec.writeUInt8($0B);
  5746. DataSecIdx:=-1;
  5747. for DataSecName in DataSections do
  5748. begin
  5749. ExeSec:=FindExeSection(DataSecName);
  5750. if Assigned(ExeSec) and (ExeSec.Size>0) then
  5751. begin
  5752. Inc(DataSecIdx);
  5753. { data.drop $DataSecIdx }
  5754. Sec.writeUInt16BE($fc09);
  5755. WriteUleb(sec,DataSecIdx);
  5756. end;
  5757. end;
  5758. { end }
  5759. Sec.writeUInt8($0B);
  5760. end;
  5761. procedure TWasmExeOutput.GenerateCode_InvokeHelper;
  5762. var
  5763. Sec: TObjSection;
  5764. IndirectFunctionTableMap: array of Integer;
  5765. procedure InvokeFuncType(typidx: Integer; islast: Boolean);
  5766. var
  5767. ft: TWasmFuncType;
  5768. i, nextofs: Integer;
  5769. begin
  5770. ft:=FFuncTypes[typidx];
  5771. for i:=0 to Length(ft.results)-1 do
  5772. { local.get 2 }
  5773. Sec.writeUInt16BE($2002);
  5774. nextofs:=0;
  5775. for i:=0 to Length(ft.params)-1 do
  5776. begin
  5777. { local.get 1 }
  5778. Sec.writeUInt16BE($2001);
  5779. case ft.params[i] of
  5780. wbt_i32:
  5781. begin
  5782. { i32.load nextofs }
  5783. Sec.writeUInt16BE($2802);
  5784. WriteUleb(Sec, nextofs);
  5785. Inc(nextofs,4);
  5786. end;
  5787. wbt_i64:
  5788. begin
  5789. { i64.load nextofs }
  5790. Sec.writeUInt16BE($2902);
  5791. WriteUleb(Sec, nextofs);
  5792. Inc(nextofs,8);
  5793. end;
  5794. wbt_f32:
  5795. begin
  5796. { f32.load nextofs }
  5797. Sec.writeUInt16BE($2A02);
  5798. WriteUleb(Sec, nextofs);
  5799. Inc(nextofs,4);
  5800. end;
  5801. wbt_f64:
  5802. begin
  5803. { f64.load nextofs }
  5804. Sec.writeUInt16BE($2B02);
  5805. WriteUleb(Sec, nextofs);
  5806. Inc(nextofs,8);
  5807. end;
  5808. wbt_v128:
  5809. begin
  5810. { v128.load nextofs }
  5811. Sec.writeUInt16BE($FD00);
  5812. Sec.writeUInt8($02); { align: 4 bytes }
  5813. WriteUleb(Sec, nextofs);
  5814. Inc(nextofs,16);
  5815. end;
  5816. wbt_externref,
  5817. wbt_funcref:
  5818. begin
  5819. { unreachable }
  5820. Sec.writeUInt8($00);
  5821. end;
  5822. else
  5823. internalerror(2025012501);
  5824. end;
  5825. end;
  5826. { local.get 0 }
  5827. Sec.writeUInt16BE($2000);
  5828. { call_indirect }
  5829. Sec.writeUInt8($11);
  5830. WriteUleb(Sec,typidx);
  5831. Sec.writeUInt8($0); { table index 0 }
  5832. nextofs:=0;
  5833. for i:=0 to Length(ft.results)-1 do
  5834. begin
  5835. case ft.results[i] of
  5836. wbt_i32:
  5837. begin
  5838. { i32.store nextofs }
  5839. Sec.writeUInt16BE($3602);
  5840. WriteUleb(Sec, nextofs);
  5841. Inc(nextofs,4);
  5842. end;
  5843. wbt_i64:
  5844. begin
  5845. { i64.store nextofs }
  5846. Sec.writeUInt16BE($3702);
  5847. WriteUleb(Sec, nextofs);
  5848. Inc(nextofs,8);
  5849. end;
  5850. wbt_f32:
  5851. begin
  5852. { f32.store nextofs }
  5853. Sec.writeUInt16BE($3802);
  5854. WriteUleb(Sec, nextofs);
  5855. Inc(nextofs,4);
  5856. end;
  5857. wbt_f64:
  5858. begin
  5859. { f64.store nextofs }
  5860. Sec.writeUInt16BE($3902);
  5861. WriteUleb(Sec, nextofs);
  5862. Inc(nextofs,8);
  5863. end;
  5864. wbt_v128:
  5865. begin
  5866. { v128.store nextofs }
  5867. Sec.writeUInt16BE($FD0B);
  5868. Sec.writeUInt8($02); { align: 4 bytes }
  5869. WriteUleb(Sec, nextofs);
  5870. Inc(nextofs,16);
  5871. end;
  5872. wbt_externref,
  5873. wbt_funcref:
  5874. begin
  5875. { unreachable }
  5876. Sec.writeUInt8($00);
  5877. end;
  5878. else
  5879. internalerror(2025012501);
  5880. end;
  5881. end;
  5882. if not islast then
  5883. { return }
  5884. Sec.writeUInt8($0F);
  5885. end;
  5886. function FuncIdx2TypeIdx(fi: Integer): Integer;
  5887. var
  5888. exesec: TExeSection;
  5889. objsec: TWasmObjSection;
  5890. fsym: TWasmObjSymbol;
  5891. begin
  5892. if fi<Length(FFunctionImports) then
  5893. Result:=FFunctionImports[fi].TypeIdx
  5894. else
  5895. begin
  5896. exesec:=FindExeSection('.text');
  5897. if not assigned(exesec) then
  5898. internalerror(2023123106);
  5899. objsec:=TWasmObjSection(exesec.ObjSectionList[fi-Length(FFunctionImports)]);
  5900. fsym:=objsec.MainFuncSymbol;
  5901. Result:=fsym.LinkingData.ExeTypeIndex;
  5902. end;
  5903. end;
  5904. procedure WriteBrTable(l,h: Integer; addend: Integer=0);
  5905. const
  5906. { max len of br_table instruction }
  5907. MaxLen=1000;
  5908. var
  5909. i, len, m: Integer;
  5910. begin
  5911. { local.get 0 }
  5912. Sec.writeUInt16BE($2000);
  5913. len:=h-l+1;
  5914. if len<=MaxLen then
  5915. begin
  5916. if l>0 then
  5917. begin
  5918. { i32.const l }
  5919. Sec.writeUInt8($41);
  5920. WriteSleb(sec,l);
  5921. { i32.sub }
  5922. Sec.writeUInt8($6B);
  5923. end;
  5924. { br_table }
  5925. Sec.writeUInt8($0E);
  5926. if h=high(IndirectFunctionTableMap) then
  5927. begin
  5928. WriteUleb(Sec,len);
  5929. for i:=l to h do
  5930. WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
  5931. WriteUleb(Sec,addend);
  5932. end
  5933. else
  5934. begin
  5935. WriteUleb(Sec,len-1);
  5936. for i:=l to h do
  5937. WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
  5938. end;
  5939. end
  5940. else
  5941. begin
  5942. m:=(l+h) div 2;
  5943. { i32.const m }
  5944. Sec.writeUInt8($41);
  5945. WriteSleb(sec,m);
  5946. { i32.lt_u }
  5947. Sec.writeUInt8($49);
  5948. { if }
  5949. Sec.writeUInt16BE($0440);
  5950. WriteBrTable(l,m-1,addend+1);
  5951. { else }
  5952. Sec.writeUInt8($05);
  5953. WriteBrTable(m,h,addend+1);
  5954. { end }
  5955. Sec.writeUInt8($0B);
  5956. end;
  5957. end;
  5958. var
  5959. exesym: TExeSymbol;
  5960. objsym: TObjSymbol;
  5961. i, j, TypIdx: Integer;
  5962. InvokableTypeIndices: array of Integer;
  5963. begin
  5964. exesym:=TExeSymbol(ExeSymbolList.Find('fpc_wasm_invoke_helper'));
  5965. if not Assigned(exesym) then
  5966. exit;
  5967. SetLength(IndirectFunctionTableMap, Length(FIndirectFunctionTable));
  5968. SetLength(InvokableTypeIndices, 1);
  5969. InvokableTypeIndices[0] := -1;
  5970. for i:=1 to Length(FIndirectFunctionTable)-1 do
  5971. begin
  5972. IndirectFunctionTableMap[i]:=0;
  5973. TypIdx := FuncIdx2TypeIdx(FIndirectFunctionTable[i].FuncIdx);
  5974. for j := 1 to Length(InvokableTypeIndices)-1 do
  5975. if InvokableTypeIndices[j]=TypIdx then
  5976. begin
  5977. IndirectFunctionTableMap[i]:=j;
  5978. break;
  5979. end;
  5980. if IndirectFunctionTableMap[i]=0 then
  5981. begin
  5982. SetLength(InvokableTypeIndices,Length(InvokableTypeIndices)+1);
  5983. InvokableTypeIndices[High(InvokableTypeIndices)]:=TypIdx;
  5984. IndirectFunctionTableMap[i]:=High(InvokableTypeIndices);
  5985. end;
  5986. end;
  5987. objsym:=exesym.ObjSymbol;
  5988. Sec:=objsym.objsection;
  5989. Sec.Size:=0;
  5990. Sec.Data.reset;
  5991. { locals }
  5992. Sec.writeUInt8($00);
  5993. for i:=1 to Length(InvokableTypeIndices)-1 do
  5994. { block }
  5995. Sec.writeUInt16BE($0240);
  5996. { block }
  5997. Sec.writeUInt16BE($0240);
  5998. { local.get 0 + br_table }
  5999. WriteBrTable(low(IndirectFunctionTableMap),high(IndirectFunctionTableMap));
  6000. { end }
  6001. Sec.writeUInt8($0B);
  6002. { unreachable }
  6003. Sec.writeUInt8($00);
  6004. for i:=1 to Length(InvokableTypeIndices)-1 do
  6005. begin
  6006. { end }
  6007. Sec.writeUInt8($0B);
  6008. InvokeFuncType(InvokableTypeIndices[i],i=(Length(InvokableTypeIndices)-1));
  6009. end;
  6010. { end }
  6011. Sec.writeUInt8($0B);
  6012. end;
  6013. procedure TWasmExeOutput.WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
  6014. var
  6015. exesecdatapos: LongWord;
  6016. i: Integer;
  6017. objsec: TObjSection;
  6018. dpos, pad: QWord;
  6019. begin
  6020. exesecdatapos:=dynarr.size;
  6021. for i:=0 to exesec.ObjSectionList.Count-1 do
  6022. begin
  6023. objsec:=TObjSection(exesec.ObjSectionList[i]);
  6024. if not (oso_data in objsec.secoptions) then
  6025. internalerror(2024010104);
  6026. if not assigned(objsec.data) then
  6027. internalerror(2024010105);
  6028. dpos:=objsec.MemPos-exesec.MemPos+exesecdatapos;
  6029. pad:=dpos-dynarr.size;
  6030. { objsection must be within SecAlign bytes from the previous one }
  6031. if (dpos<dynarr.Size) or
  6032. (pad>=max(objsec.SecAlign,1)) then
  6033. internalerror(2024010106);
  6034. writeZeros(dynarr,pad);
  6035. objsec.data.seek(0);
  6036. CopyDynamicArray(objsec.data,dynarr,objsec.data.size);
  6037. end;
  6038. if (dynarr.size-exesecdatapos)<>exesec.Size then
  6039. internalerror(2024010107);
  6040. end;
  6041. procedure TWasmExeOutput.WriteMap_TypeSection;
  6042. var
  6043. i: Integer;
  6044. begin
  6045. exemap.AddHeader('Type section');
  6046. for i:=0 to FFuncTypes.Count-1 do
  6047. exemap.Add(' Type[' + tostr(i) + '] ' + FFuncTypes.Items[i].ToString);
  6048. end;
  6049. procedure TWasmExeOutput.WriteMap_IndirectFunctionTable;
  6050. var
  6051. i: Integer;
  6052. begin
  6053. exemap.AddHeader('Indirect function table');
  6054. for i:=1 to High(FIndirectFunctionTable) do
  6055. exemap.Add(' Elem[' + tostr(i) + '] = Function[' + tostr(FIndirectFunctionTable[i].FuncIdx) + ']');
  6056. end;
  6057. {****************************************************************************
  6058. TWasmAssembler
  6059. ****************************************************************************}
  6060. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  6061. begin
  6062. inherited;
  6063. CObjOutput:=TWasmObjOutput;
  6064. end;
  6065. {*****************************************************************************
  6066. Initialize
  6067. *****************************************************************************}
  6068. {$ifdef wasm32}
  6069. const
  6070. as_wasm32_wasm_info : tasminfo =
  6071. (
  6072. id : as_wasm32_wasm;
  6073. idtxt : 'WASM';
  6074. asmbin : '';
  6075. asmcmd : '';
  6076. supported_targets : [system_wasm32_embedded,system_wasm32_wasi];
  6077. flags : [af_outputbinary,af_smartlink_sections];
  6078. labelprefix : '..@';
  6079. labelmaxlen : -1;
  6080. comment : '; ';
  6081. dollarsign: '$';
  6082. );
  6083. {$endif wasm32}
  6084. initialization
  6085. {$ifdef wasm32}
  6086. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  6087. {$endif wasm32}
  6088. end.