aot_emit_aot_file.c 157 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_emit_aot_file.h"
  6. #include "../aot/aot_runtime.h"
  7. #define PUT_U64_TO_ADDR(addr, value) \
  8. do { \
  9. union { \
  10. uint64 val; \
  11. uint32 parts[2]; \
  12. } u; \
  13. u.val = (value); \
  14. ((uint32 *)(addr))[0] = u.parts[0]; \
  15. ((uint32 *)(addr))[1] = u.parts[1]; \
  16. } while (0)
  17. #define CHECK_SIZE(size) \
  18. do { \
  19. if (size == (uint32)-1) { \
  20. aot_set_last_error("get symbol size failed."); \
  21. return (uint32)-1; \
  22. } \
  23. } while (0)
  24. /* Internal function in object file */
  25. typedef struct AOTObjectFunc {
  26. char *func_name;
  27. /* text offset of aot_func#n */
  28. uint64 text_offset;
  29. /* text offset of aot_func_internal#n */
  30. uint64 text_offset_of_aot_func_internal;
  31. } AOTObjectFunc;
  32. /* Symbol table list node */
  33. typedef struct AOTSymbolNode {
  34. struct AOTSymbolNode *next;
  35. uint32 str_len;
  36. char *symbol;
  37. } AOTSymbolNode;
  38. typedef struct AOTSymbolList {
  39. AOTSymbolNode *head;
  40. AOTSymbolNode *end;
  41. uint32 len;
  42. } AOTSymbolList;
  43. /* AOT object data */
  44. struct AOTObjectData {
  45. AOTCompContext *comp_ctx;
  46. LLVMMemoryBufferRef mem_buf;
  47. LLVMBinaryRef binary;
  48. AOTTargetInfo target_info;
  49. void *text;
  50. uint32 text_size;
  51. void *text_unlikely;
  52. uint32 text_unlikely_size;
  53. void *text_hot;
  54. uint32 text_hot_size;
  55. /* literal data and size */
  56. void *literal;
  57. uint32 literal_size;
  58. AOTObjectDataSection *data_sections;
  59. uint32 data_sections_count;
  60. AOTObjectFunc *funcs;
  61. uint32 func_count;
  62. AOTSymbolList symbol_list;
  63. AOTRelocationGroup *relocation_groups;
  64. uint32 relocation_group_count;
  65. const char *stack_sizes_section_name;
  66. uint32 stack_sizes_offset;
  67. uint32 *stack_sizes;
  68. };
  69. #if 0
  70. static void dump_buf(uint8 *buf, uint32 size, char *title)
  71. {
  72. int i;
  73. printf("------ %s -------", title);
  74. for (i = 0; i < size; i++) {
  75. if ((i % 16) == 0)
  76. printf("\n");
  77. printf("%02x ", (unsigned char)buf[i]);
  78. }
  79. printf("\n\n");
  80. }
  81. #endif
  82. static bool
  83. is_32bit_binary(const AOTObjectData *obj_data)
  84. {
  85. /* bit 1: 0 is 32-bit, 1 is 64-bit */
  86. return obj_data->target_info.bin_type & 2 ? false : true;
  87. }
  88. static bool
  89. is_little_endian_binary(const AOTObjectData *obj_data)
  90. {
  91. /* bit 0: 0 is little-endian, 1 is big-endian */
  92. return obj_data->target_info.bin_type & 1 ? false : true;
  93. }
  94. static bool
  95. str_starts_with(const char *str, const char *prefix)
  96. {
  97. size_t len_pre = strlen(prefix), len_str = strlen(str);
  98. return (len_str >= len_pre) && !memcmp(str, prefix, len_pre);
  99. }
  100. static uint32
  101. get_file_header_size()
  102. {
  103. /* magic number (4 bytes) + version (4 bytes) */
  104. return sizeof(uint32) + sizeof(uint32);
  105. }
  106. static uint32
  107. get_string_size(AOTCompContext *comp_ctx, const char *s)
  108. {
  109. /* string size (2 bytes) + string content + '\0' */
  110. return (uint32)sizeof(uint16) + (uint32)strlen(s) + 1;
  111. }
  112. static uint32
  113. get_target_info_section_size()
  114. {
  115. return sizeof(AOTTargetInfo);
  116. }
  117. static uint32
  118. get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
  119. InitializerExpression *expr);
  120. static uint32
  121. get_mem_init_data_size(AOTCompContext *comp_ctx, AOTMemInitData *mem_init_data)
  122. {
  123. /* init expr type (4 bytes)
  124. * + init expr value (4 bytes, valid value can only be i32/get_global)
  125. * + byte count (4 bytes) + bytes */
  126. uint32 total_size =
  127. (uint32)(get_init_expr_size(comp_ctx, comp_ctx->comp_data,
  128. &mem_init_data->offset)
  129. + sizeof(uint32) + mem_init_data->byte_count);
  130. /* bulk_memory enabled:
  131. is_passive (4 bytes) + memory_index (4 bytes)
  132. bulk memory disabled:
  133. placeholder (4 bytes) + placeholder (4 bytes)
  134. */
  135. total_size += (sizeof(uint32) + sizeof(uint32));
  136. return total_size;
  137. }
  138. static uint32
  139. get_mem_init_data_list_size(AOTCompContext *comp_ctx,
  140. AOTMemInitData **mem_init_data_list,
  141. uint32 mem_init_data_count)
  142. {
  143. AOTMemInitData **mem_init_data = mem_init_data_list;
  144. uint32 size = 0, i;
  145. for (i = 0; i < mem_init_data_count; i++, mem_init_data++) {
  146. size = align_uint(size, 4);
  147. size += get_mem_init_data_size(comp_ctx, *mem_init_data);
  148. }
  149. return size;
  150. }
  151. static uint32
  152. get_import_memory_size(AOTCompData *comp_data)
  153. {
  154. /* currently we only emit import_memory_count = 0 */
  155. return sizeof(uint32);
  156. }
  157. static uint32
  158. get_memory_size(AOTCompData *comp_data)
  159. {
  160. /* memory_count + count * (flags + num_bytes_per_page +
  161. init_page_count + max_page_count) */
  162. return (uint32)(sizeof(uint32)
  163. + comp_data->memory_count * sizeof(uint32) * 4);
  164. }
  165. static uint32
  166. get_mem_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  167. {
  168. /* import_memory_size + memory_size
  169. + init_data_count + init_data_list */
  170. return get_import_memory_size(comp_data) + get_memory_size(comp_data)
  171. + (uint32)sizeof(uint32)
  172. + get_mem_init_data_list_size(comp_ctx,
  173. comp_data->mem_init_data_list,
  174. comp_data->mem_init_data_count);
  175. }
  176. static uint32
  177. get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
  178. InitializerExpression *expr)
  179. {
  180. /* init_expr_type */
  181. uint32 size = sizeof(uint32);
  182. #if WASM_ENABLE_GC != 0
  183. WASMModule *module = comp_data->wasm_module;
  184. #endif
  185. bh_assert(expr != NULL);
  186. /* + init value size */
  187. switch (expr->init_expr_type) {
  188. case INIT_EXPR_NONE:
  189. /* no init value, used in table initializer */
  190. break;
  191. case INIT_EXPR_TYPE_I32_CONST:
  192. case INIT_EXPR_TYPE_F32_CONST:
  193. case INIT_EXPR_TYPE_GET_GLOBAL:
  194. size += sizeof(uint32);
  195. break;
  196. case INIT_EXPR_TYPE_I64_CONST:
  197. case INIT_EXPR_TYPE_F64_CONST:
  198. size += sizeof(uint64);
  199. break;
  200. case INIT_EXPR_TYPE_V128_CONST:
  201. size += sizeof(uint64) * 2;
  202. break;
  203. case INIT_EXPR_TYPE_FUNCREF_CONST:
  204. case INIT_EXPR_TYPE_REFNULL_CONST:
  205. /* ref_index */
  206. size += sizeof(uint32);
  207. break;
  208. #if WASM_ENABLE_GC != 0
  209. case INIT_EXPR_TYPE_I31_NEW:
  210. /* i32 */
  211. size += sizeof(uint32);
  212. break;
  213. case INIT_EXPR_TYPE_STRUCT_NEW:
  214. {
  215. uint32 i;
  216. WASMStructNewInitValues *struct_new_init_values =
  217. (WASMStructNewInitValues *)expr->u.unary.v.data;
  218. /* type_index + field_count + fields */
  219. size += sizeof(uint32) + sizeof(uint32);
  220. bh_assert(struct_new_init_values->type_idx < module->type_count);
  221. for (i = 0; i < struct_new_init_values->count; i++) {
  222. WASMStructType *struct_type =
  223. (WASMStructType *)
  224. module->types[struct_new_init_values->type_idx];
  225. uint32 field_size;
  226. bh_assert(struct_type);
  227. bh_assert(struct_type->field_count
  228. == struct_new_init_values->count);
  229. field_size = wasm_value_type_size_internal(
  230. struct_type->fields[i].field_type, comp_ctx->pointer_size);
  231. if (field_size < sizeof(uint32))
  232. field_size = sizeof(uint32);
  233. size += field_size;
  234. }
  235. break;
  236. }
  237. case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
  238. /* type_index */
  239. size += sizeof(uint32);
  240. break;
  241. case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
  242. /* array_elem_type + type_index + len */
  243. size += sizeof(uint32) * 3;
  244. break;
  245. case INIT_EXPR_TYPE_ARRAY_NEW:
  246. case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
  247. {
  248. WASMArrayNewInitValues *array_new_init_values =
  249. (WASMArrayNewInitValues *)expr->u.unary.v.data;
  250. WASMArrayType *array_type = NULL;
  251. uint32 value_count;
  252. array_type =
  253. (WASMArrayType *)module->types[array_new_init_values->type_idx];
  254. bh_assert(array_type);
  255. bh_assert(array_new_init_values->type_idx < module->type_count);
  256. value_count =
  257. (expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED)
  258. ? array_new_init_values->length
  259. : 1;
  260. /* array_elem_type + type_index + len + elems */
  261. size += sizeof(uint32) * 3
  262. + (uint64)wasm_value_type_size_internal(
  263. array_type->elem_type, comp_ctx->pointer_size)
  264. * value_count;
  265. break;
  266. }
  267. #endif /* end of WASM_ENABLE_GC != 0 */
  268. #if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
  269. case INIT_EXPR_TYPE_I32_ADD:
  270. case INIT_EXPR_TYPE_I32_SUB:
  271. case INIT_EXPR_TYPE_I32_MUL:
  272. case INIT_EXPR_TYPE_I64_ADD:
  273. case INIT_EXPR_TYPE_I64_SUB:
  274. case INIT_EXPR_TYPE_I64_MUL:
  275. {
  276. size +=
  277. get_init_expr_size(comp_ctx, comp_data, expr->u.binary.l_expr);
  278. size +=
  279. get_init_expr_size(comp_ctx, comp_data, expr->u.binary.r_expr);
  280. break;
  281. }
  282. #endif
  283. default:
  284. bh_assert(0);
  285. }
  286. return size;
  287. }
  288. static uint32
  289. get_table_init_data_size(AOTCompContext *comp_ctx,
  290. AOTTableInitData *table_init_data)
  291. {
  292. uint32 size, i;
  293. /*
  294. * mode (4 bytes), elem_type (4 bytes)
  295. *
  296. * table_index(4 bytes)
  297. */
  298. size = (uint32)(sizeof(uint32) * 2 + sizeof(uint32))
  299. /* Size of WasmRefType - inner padding (ref type + nullable +
  300. heap_type) */
  301. + 8;
  302. size += get_init_expr_size(comp_ctx, comp_ctx->comp_data,
  303. &table_init_data->offset);
  304. /* + value count/func index count (4 bytes) + init_values */
  305. size += sizeof(uint32);
  306. for (i = 0; i < table_init_data->value_count; i++) {
  307. size += get_init_expr_size(comp_ctx, comp_ctx->comp_data,
  308. &table_init_data->init_values[i]);
  309. }
  310. return size;
  311. }
  312. static uint32
  313. get_table_init_data_list_size(AOTCompContext *comp_ctx,
  314. AOTTableInitData **table_init_data_list,
  315. uint32 table_init_data_count)
  316. {
  317. /*
  318. * ------------------------------
  319. * | table_init_data_count
  320. * ------------------------------
  321. * | | U32 mode
  322. * | AOTTableInitData[N] | U32 elem_type
  323. * | | U32 table_index
  324. * | | U32 offset.init_expr_type
  325. * | | U64 offset.u.i64
  326. * | | U32 func_index_count / elem_count
  327. * | | UINTPTR [func_index_count] / [elem_count]
  328. * ------------------------------
  329. */
  330. AOTTableInitData **table_init_data = table_init_data_list;
  331. uint32 size = 0, i;
  332. /* table_init_data_count(4 bytes) */
  333. size = (uint32)sizeof(uint32);
  334. for (i = 0; i < table_init_data_count; i++, table_init_data++) {
  335. size = align_uint(size, 4);
  336. size += get_table_init_data_size(comp_ctx, *table_init_data);
  337. }
  338. return size;
  339. }
  340. static uint32
  341. get_import_table_size(const AOTCompContext *comp_ctx,
  342. const AOTCompData *comp_data)
  343. {
  344. /*
  345. * ------------------------------
  346. * | import_table_count
  347. * ------------------------------
  348. * | | U8 elem_type
  349. * | | U8 flags
  350. * | | U8 possible_grow
  351. * | AOTImportTable[N] | U8 elem_ref_type.nullable (for GC only)
  352. * | | U32 init_size
  353. * | | U32 max_size
  354. * | | U32 elem_ref_type.heap_type (for GC only)
  355. * ------------------------------
  356. */
  357. uint32 size = 0, i;
  358. size = (uint32)sizeof(uint32);
  359. for (i = 0; i < comp_data->import_table_count; i++) {
  360. size += sizeof(uint32) * 3;
  361. #if WASM_ENABLE_GC != 0
  362. if (comp_ctx->enable_gc
  363. && comp_data->import_tables[i].table_type.elem_ref_type)
  364. size += sizeof(uint32);
  365. #endif
  366. }
  367. return size;
  368. }
  369. static uint32
  370. get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
  371. {
  372. /*
  373. * ------------------------------
  374. * | table_count
  375. * ------------------------------
  376. * | | U8 elem_type
  377. * | | U8 flags
  378. * | | U8 possible_grow
  379. * | AOTTable[N] | U8 elem_ref_type.nullable (for GC only)
  380. * | | U32 init_size
  381. * | | U32 max_size
  382. * | | U32 elem_ref_type.heap_type (for GC only)
  383. * | | N init_expr (for GC only)
  384. * ------------------------------
  385. */
  386. uint32 size = 0, i;
  387. size = (uint32)sizeof(uint32);
  388. for (i = 0; i < comp_data->table_count; i++) {
  389. size += sizeof(uint32) * 3;
  390. #if WASM_ENABLE_GC != 0
  391. if (comp_ctx->enable_gc) {
  392. if (comp_data->tables[i].table_type.elem_ref_type) {
  393. size += sizeof(uint32);
  394. }
  395. size += get_init_expr_size(comp_ctx, comp_data,
  396. &comp_data->tables[i].init_expr);
  397. }
  398. #endif
  399. }
  400. return size;
  401. }
  402. static uint32
  403. get_table_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  404. {
  405. /*
  406. * ------------------------------
  407. * | import_table_count
  408. * ------------------------------
  409. * |
  410. * | AOTImportTable[import_table_count]
  411. * |
  412. * ------------------------------
  413. * | table_count
  414. * ------------------------------
  415. * |
  416. * | AOTTable[table_count]
  417. * |
  418. * ------------------------------
  419. * | table_init_data_count
  420. * ------------------------------
  421. * |
  422. * | AOTTableInitData*[table_init_data_count]
  423. * |
  424. * ------------------------------
  425. */
  426. return get_import_table_size(comp_ctx, comp_data)
  427. + get_table_size(comp_ctx, comp_data)
  428. + get_table_init_data_list_size(comp_ctx,
  429. comp_data->table_init_data_list,
  430. comp_data->table_init_data_count);
  431. }
  432. static uint32
  433. get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
  434. {
  435. #if WASM_ENABLE_GC != 0
  436. /* type flag + equivalence type flag + is_sub_final + parent_type_idx
  437. + rec_count + rec_idx + param count + result count
  438. + ref_type_map_count + types + context of ref_type_map */
  439. if (comp_ctx->enable_gc) {
  440. uint32 size = 0;
  441. /* type flag */
  442. size += sizeof(func_type->base_type.type_flag);
  443. /* equivalence type flag + is_sub_final */
  444. size += sizeof(uint16);
  445. /* parent_type_idx */
  446. size += sizeof(func_type->base_type.parent_type_idx);
  447. /* rec_count */
  448. size += sizeof(func_type->base_type.rec_count);
  449. /* rec_idx */
  450. size += sizeof(func_type->base_type.rec_idx);
  451. /* param count */
  452. size += sizeof(func_type->param_count);
  453. /* result count */
  454. size += sizeof(func_type->result_count);
  455. /* ref_type_map_count */
  456. size += sizeof(func_type->ref_type_map_count);
  457. /* param and result types */
  458. size += func_type->param_count + func_type->result_count;
  459. /* align size */
  460. size = align_uint(size, 4);
  461. /* ref_type_map */
  462. size += func_type->ref_type_map_count * 8;
  463. return size;
  464. }
  465. else
  466. #endif
  467. {
  468. /* type flag + param count + result count + types */
  469. return (uint32)sizeof(uint16) * 3 + func_type->param_count
  470. + func_type->result_count;
  471. }
  472. }
  473. #if WASM_ENABLE_GC != 0
  474. static uint32
  475. get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
  476. {
  477. uint32 size = 0;
  478. /* type flag + equivalence type flag + is_sub_final + parent_type_idx
  479. + rec_count + rec_idx + field count + fields */
  480. /* type flag */
  481. size += sizeof(struct_type->base_type.type_flag);
  482. /* equivalence type flag + is_sub_final */
  483. size += sizeof(uint16);
  484. /* parent_type_idx */
  485. size += sizeof(struct_type->base_type.parent_type_idx);
  486. /* rec_count */
  487. size += sizeof(struct_type->base_type.rec_count);
  488. /* rec_idx */
  489. size += sizeof(struct_type->base_type.rec_idx);
  490. /* field count */
  491. size += sizeof(struct_type->field_count);
  492. /* field types */
  493. size += struct_type->field_count * 2;
  494. /* ref_type_map_count */
  495. size += sizeof(struct_type->ref_type_map_count);
  496. size = align_uint(size, 4);
  497. /* ref_type_map */
  498. size += struct_type->ref_type_map_count * 8;
  499. return size;
  500. }
  501. static uint32
  502. get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
  503. {
  504. uint32 size = 0;
  505. /* type flag + equivalence type flag + is_sub_final + parent_type_idx
  506. + rec_count + rec_idx + elem_flags + elem_type + elem_ref_type */
  507. /* type flag */
  508. size += sizeof(array_type->base_type.type_flag);
  509. /* equivalence type flag + is_sub_final */
  510. size += sizeof(uint16);
  511. /* parent_type_idx (u32) */
  512. size += sizeof(array_type->base_type.parent_type_idx);
  513. /* rec_count */
  514. size += sizeof(array_type->base_type.rec_count);
  515. /* rec_idx */
  516. size += sizeof(array_type->base_type.rec_idx);
  517. /* elem_flags (u16) */
  518. size += sizeof(array_type->elem_flags);
  519. /* elem_type (u8) */
  520. size += sizeof(array_type->elem_type);
  521. /* elem_ref_type */
  522. if (array_type->elem_ref_type) {
  523. /* nullable (u8) */
  524. size += sizeof(uint8);
  525. /* heap type (u32) */
  526. size += sizeof(uint32);
  527. }
  528. return size;
  529. }
  530. #endif
  531. static uint32
  532. get_type_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  533. {
  534. /* Initial size with size of type count */
  535. uint32 size = 4;
  536. uint32 i;
  537. #if WASM_ENABLE_GC != 0
  538. if (comp_ctx->enable_gc) {
  539. for (i = 0; i < comp_data->type_count; i++) {
  540. uint32 j;
  541. size = align_uint(size, 4);
  542. /* Emit simple info if there is an equivalence type */
  543. for (j = 0; j < i; j++) {
  544. if (comp_data->types[j] == comp_data->types[i]) {
  545. /* type_flag (2 bytes) + equivalence type flag (1 byte)
  546. + padding (1 byte) + equivalence type index */
  547. size += 8;
  548. break;
  549. }
  550. }
  551. if (j < i)
  552. continue;
  553. if (comp_data->types[i]->type_flag == WASM_TYPE_FUNC)
  554. size += get_func_type_size(comp_ctx,
  555. (AOTFuncType *)comp_data->types[i]);
  556. else if (comp_data->types[i]->type_flag == WASM_TYPE_STRUCT)
  557. size += get_struct_type_size(
  558. comp_ctx, (AOTStructType *)comp_data->types[i]);
  559. else if (comp_data->types[i]->type_flag == WASM_TYPE_ARRAY)
  560. size += get_array_type_size(
  561. comp_ctx, (AOTArrayType *)comp_data->types[i]);
  562. else
  563. bh_assert(0);
  564. }
  565. }
  566. else
  567. #endif
  568. {
  569. for (i = 0; i < comp_data->type_count; i++) {
  570. size = align_uint(size, 4);
  571. size += get_func_type_size(comp_ctx,
  572. (AOTFuncType *)comp_data->types[i]);
  573. }
  574. }
  575. return size;
  576. }
  577. static uint32
  578. get_import_global_size(AOTCompContext *comp_ctx, AOTImportGlobal *import_global)
  579. {
  580. /* type (1 byte) + is_mutable (1 byte) + module_name + global_name */
  581. uint32 size = (uint32)sizeof(uint8) * 2
  582. + get_string_size(comp_ctx, import_global->module_name);
  583. size = align_uint(size, 2);
  584. size += get_string_size(comp_ctx, import_global->global_name);
  585. return size;
  586. }
  587. static uint32
  588. get_import_globals_size(AOTCompContext *comp_ctx,
  589. AOTImportGlobal *import_globals,
  590. uint32 import_global_count)
  591. {
  592. AOTImportGlobal *import_global = import_globals;
  593. uint32 size = 0, i;
  594. for (i = 0; i < import_global_count; i++, import_global++) {
  595. size = align_uint(size, 2);
  596. size += get_import_global_size(comp_ctx, import_global);
  597. }
  598. return size;
  599. }
  600. static uint32
  601. get_import_global_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  602. {
  603. /* import global count + import globals */
  604. return (uint32)sizeof(uint32)
  605. + get_import_globals_size(comp_ctx, comp_data->import_globals,
  606. comp_data->import_global_count);
  607. }
  608. static uint32
  609. get_global_size(AOTCompContext *comp_ctx, AOTGlobal *global)
  610. {
  611. /* type (1 byte) + is_mutable (1 byte) + padding (2 bytes)
  612. + init expr value (include init expr type) */
  613. return sizeof(uint8) * 2 + sizeof(uint8) * 2
  614. + get_init_expr_size(comp_ctx, comp_ctx->comp_data,
  615. &global->init_expr);
  616. }
  617. static uint32
  618. get_globals_size(AOTCompContext *comp_ctx, AOTGlobal *globals,
  619. uint32 global_count)
  620. {
  621. AOTGlobal *global = globals;
  622. uint32 size = 0, i;
  623. for (i = 0; i < global_count; i++, global++) {
  624. size = align_uint(size, 4);
  625. size += get_global_size(comp_ctx, global);
  626. }
  627. return size;
  628. }
  629. static uint32
  630. get_global_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  631. {
  632. /* global count + globals */
  633. return (uint32)sizeof(uint32)
  634. + get_globals_size(comp_ctx, comp_data->globals,
  635. comp_data->global_count);
  636. }
  637. static uint32
  638. get_import_func_size(AOTCompContext *comp_ctx, AOTImportFunc *import_func)
  639. {
  640. /* type index (2 bytes) + module_name + func_name */
  641. uint32 size = (uint32)sizeof(uint16)
  642. + get_string_size(comp_ctx, import_func->module_name);
  643. size = align_uint(size, 2);
  644. size += get_string_size(comp_ctx, import_func->func_name);
  645. return size;
  646. }
  647. static uint32
  648. get_import_funcs_size(AOTCompContext *comp_ctx, AOTImportFunc *import_funcs,
  649. uint32 import_func_count)
  650. {
  651. AOTImportFunc *import_func = import_funcs;
  652. uint32 size = 0, i;
  653. for (i = 0; i < import_func_count; i++, import_func++) {
  654. size = align_uint(size, 2);
  655. size += get_import_func_size(comp_ctx, import_func);
  656. }
  657. return size;
  658. }
  659. static uint32
  660. get_import_func_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  661. {
  662. /* import func count + import funcs */
  663. return (uint32)sizeof(uint32)
  664. + get_import_funcs_size(comp_ctx, comp_data->import_funcs,
  665. comp_data->import_func_count);
  666. }
  667. static uint32
  668. get_object_data_sections_size(AOTCompContext *comp_ctx,
  669. AOTObjectDataSection *data_sections,
  670. uint32 data_sections_count)
  671. {
  672. AOTObjectDataSection *data_section = data_sections;
  673. uint32 size = 0, i;
  674. for (i = 0; i < data_sections_count; i++, data_section++) {
  675. /* name + size + data */
  676. size = align_uint(size, 2);
  677. size += get_string_size(comp_ctx, data_section->name);
  678. size = align_uint(size, 4);
  679. size += (uint32)sizeof(uint32);
  680. size += data_section->size;
  681. }
  682. return size;
  683. }
  684. static uint32
  685. get_object_data_section_info_size(AOTCompContext *comp_ctx,
  686. AOTObjectData *obj_data)
  687. {
  688. /* data sections count + data sections */
  689. return (uint32)sizeof(uint32)
  690. + get_object_data_sections_size(comp_ctx, obj_data->data_sections,
  691. obj_data->data_sections_count);
  692. }
  693. static uint32
  694. get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  695. AOTObjectData *obj_data)
  696. {
  697. uint32 size = 0;
  698. size += get_mem_info_size(comp_ctx, comp_data);
  699. size = align_uint(size, 4);
  700. size += get_table_info_size(comp_ctx, comp_data);
  701. size = align_uint(size, 4);
  702. size += get_type_info_size(comp_ctx, comp_data);
  703. size = align_uint(size, 4);
  704. size += get_import_global_info_size(comp_ctx, comp_data);
  705. size = align_uint(size, 4);
  706. size += get_global_info_size(comp_ctx, comp_data);
  707. size = align_uint(size, 4);
  708. size += get_import_func_info_size(comp_ctx, comp_data);
  709. /* func count + start func index */
  710. size = align_uint(size, 4);
  711. size += (uint32)sizeof(uint32) * 2;
  712. /* aux data/heap/stack data */
  713. size += sizeof(uint32) * 10;
  714. size += get_object_data_section_info_size(comp_ctx, obj_data);
  715. return size;
  716. }
  717. static uint32
  718. get_text_section_size(AOTObjectData *obj_data)
  719. {
  720. return sizeof(uint32) + align_uint(obj_data->literal_size, 4)
  721. + align_uint(obj_data->text_size, 4)
  722. + align_uint(obj_data->text_unlikely_size, 4)
  723. + align_uint(obj_data->text_hot_size, 4);
  724. }
  725. static uint32
  726. get_func_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  727. AOTObjectData *obj_data)
  728. {
  729. uint32 size = 0;
  730. /* text offsets */
  731. if (is_32bit_binary(obj_data))
  732. size = (uint32)sizeof(uint32) * comp_data->func_count;
  733. else
  734. size = (uint32)sizeof(uint64) * comp_data->func_count;
  735. /* function type indexes */
  736. size += (uint32)sizeof(uint32) * comp_data->func_count;
  737. /* max_local_cell_nums */
  738. size += (uint32)sizeof(uint32) * comp_data->func_count;
  739. /* max_stack_cell_nums */
  740. size += (uint32)sizeof(uint32) * comp_data->func_count;
  741. #if WASM_ENABLE_GC != 0
  742. /* func_local_ref_flags */
  743. if (comp_ctx->enable_gc) {
  744. AOTFuncType *func_type;
  745. uint32 i, j, local_ref_flags_cell_num;
  746. for (i = 0; i < comp_data->import_func_count; i++) {
  747. func_type = comp_data->import_funcs[i].func_type;
  748. /* recalculate cell_num based on target pointer size */
  749. local_ref_flags_cell_num = 0;
  750. for (j = 0; j < func_type->param_count; j++) {
  751. local_ref_flags_cell_num += wasm_value_type_cell_num_internal(
  752. func_type->types[j], comp_ctx->pointer_size);
  753. }
  754. local_ref_flags_cell_num =
  755. local_ref_flags_cell_num > 2 ? local_ref_flags_cell_num : 2;
  756. size = align_uint(size, 4);
  757. size += (uint32)sizeof(uint32);
  758. size += (uint32)sizeof(uint8) * local_ref_flags_cell_num;
  759. }
  760. for (i = 0; i < comp_data->func_count; i++) {
  761. func_type = comp_data->funcs[i]->func_type;
  762. local_ref_flags_cell_num = comp_data->funcs[i]->param_cell_num
  763. + comp_data->funcs[i]->local_cell_num;
  764. size = align_uint(size, 4);
  765. size += (uint32)sizeof(uint32);
  766. size += (uint32)sizeof(uint8) * local_ref_flags_cell_num;
  767. }
  768. }
  769. #endif
  770. return size;
  771. }
  772. static uint32
  773. get_export_size(AOTCompContext *comp_ctx, AOTExport *export)
  774. {
  775. /* export index + export kind + 1 byte padding + export name */
  776. return (uint32)sizeof(uint32) + sizeof(uint8) + 1
  777. + get_string_size(comp_ctx, export->name);
  778. }
  779. static uint32
  780. get_exports_size(AOTCompContext *comp_ctx, AOTExport *exports,
  781. uint32 export_count)
  782. {
  783. AOTExport *export = exports;
  784. uint32 size = 0, i;
  785. for (i = 0; i < export_count; i++, export ++) {
  786. size = align_uint(size, 4);
  787. size += get_export_size(comp_ctx, export);
  788. }
  789. return size;
  790. }
  791. static uint32
  792. get_export_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  793. {
  794. /* export count + exports */
  795. return (uint32)sizeof(uint32)
  796. + get_exports_size(comp_ctx, comp_data->wasm_module->exports,
  797. comp_data->wasm_module->export_count);
  798. }
  799. static uint32
  800. get_relocation_size(AOTRelocation *relocation, bool is_32bin)
  801. {
  802. /* offset + addend + relocation type + symbol name */
  803. uint32 size = 0;
  804. if (is_32bin)
  805. size = sizeof(uint32) * 2; /* offset and addend */
  806. else
  807. size = sizeof(uint64) * 2; /* offset and addend */
  808. size += (uint32)sizeof(uint32); /* relocation type */
  809. size += (uint32)sizeof(uint32); /* symbol name index */
  810. return size;
  811. }
  812. static uint32
  813. get_relocations_size(AOTObjectData *obj_data,
  814. AOTRelocationGroup *relocation_group,
  815. AOTRelocation *relocations, uint32 relocation_count,
  816. bool is_32bin)
  817. {
  818. AOTRelocation *relocation = relocations;
  819. uint32 size = 0, i;
  820. for (i = 0; i < relocation_count; i++, relocation++) {
  821. /* ignore the relocations to aot_func_internal#n in text section
  822. for windows platform since they will be applied in
  823. aot_emit_text_section */
  824. const char *name = relocation->symbol_name;
  825. if ((!strcmp(relocation_group->section_name, ".text")
  826. || !strcmp(relocation_group->section_name, ".ltext"))
  827. && !strncmp(name, AOT_FUNC_INTERNAL_PREFIX,
  828. strlen(AOT_FUNC_INTERNAL_PREFIX))
  829. && ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6)
  830. /* Windows AOT_COFF64_BIN_TYPE */
  831. && obj_data->target_info.bin_type == 6
  832. /* IMAGE_REL_AMD64_REL32 in windows x86_64 */
  833. && relocation->relocation_type == 4)
  834. || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4)
  835. /* Windows AOT_COFF32_BIN_TYPE */
  836. && obj_data->target_info.bin_type == 4
  837. /* IMAGE_REL_I386_REL32 in windows x86_32 */
  838. && relocation->relocation_type == 20))) {
  839. continue;
  840. }
  841. size = align_uint(size, 4);
  842. size += get_relocation_size(relocation, is_32bin);
  843. }
  844. return size;
  845. }
  846. static uint32
  847. get_relocation_group_size(AOTObjectData *obj_data,
  848. AOTRelocationGroup *relocation_group, bool is_32bin)
  849. {
  850. uint32 size = 0;
  851. /* section name index + relocation count + relocations */
  852. size += (uint32)sizeof(uint32);
  853. size += (uint32)sizeof(uint32);
  854. size += get_relocations_size(obj_data, relocation_group,
  855. relocation_group->relocations,
  856. relocation_group->relocation_count, is_32bin);
  857. return size;
  858. }
  859. static uint32
  860. get_relocation_groups_size(AOTObjectData *obj_data,
  861. AOTRelocationGroup *relocation_groups,
  862. uint32 relocation_group_count, bool is_32bin)
  863. {
  864. AOTRelocationGroup *relocation_group = relocation_groups;
  865. uint32 size = 0, i;
  866. for (i = 0; i < relocation_group_count; i++, relocation_group++) {
  867. size = align_uint(size, 4);
  868. size += get_relocation_group_size(obj_data, relocation_group, is_32bin);
  869. }
  870. return size;
  871. }
  872. /* return the index (in order of insertion) of the symbol,
  873. create if not exits, -1 if failed */
  874. static uint32
  875. get_relocation_symbol_index(const char *symbol_name, bool *is_new,
  876. AOTSymbolList *symbol_list)
  877. {
  878. AOTSymbolNode *sym;
  879. uint32 index = 0;
  880. sym = symbol_list->head;
  881. while (sym) {
  882. if (!strcmp(sym->symbol, symbol_name)) {
  883. if (is_new)
  884. *is_new = false;
  885. return index;
  886. }
  887. sym = sym->next;
  888. index++;
  889. }
  890. /* Not found in symbol_list, add it */
  891. sym = wasm_runtime_malloc(sizeof(AOTSymbolNode));
  892. if (!sym) {
  893. return (uint32)-1;
  894. }
  895. memset(sym, 0, sizeof(AOTSymbolNode));
  896. sym->symbol = (char *)symbol_name;
  897. sym->str_len = (uint32)strlen(symbol_name);
  898. if (!symbol_list->head) {
  899. symbol_list->head = symbol_list->end = sym;
  900. }
  901. else {
  902. symbol_list->end->next = sym;
  903. symbol_list->end = sym;
  904. }
  905. symbol_list->len++;
  906. if (is_new)
  907. *is_new = true;
  908. return index;
  909. }
  910. static uint32
  911. get_relocation_symbol_size(AOTCompContext *comp_ctx, AOTRelocation *relocation,
  912. AOTSymbolList *symbol_list)
  913. {
  914. uint32 size = 0, index = 0;
  915. bool is_new = false;
  916. index = get_relocation_symbol_index(relocation->symbol_name, &is_new,
  917. symbol_list);
  918. CHECK_SIZE(index);
  919. if (is_new) {
  920. size += get_string_size(comp_ctx, relocation->symbol_name);
  921. size = align_uint(size, 2);
  922. }
  923. relocation->symbol_index = index;
  924. return size;
  925. }
  926. static uint32
  927. get_relocations_symbol_size(AOTCompContext *comp_ctx,
  928. AOTRelocation *relocations, uint32 relocation_count,
  929. AOTSymbolList *symbol_list)
  930. {
  931. AOTRelocation *relocation = relocations;
  932. uint32 size = 0, curr_size, i;
  933. for (i = 0; i < relocation_count; i++, relocation++) {
  934. curr_size =
  935. get_relocation_symbol_size(comp_ctx, relocation, symbol_list);
  936. CHECK_SIZE(curr_size);
  937. size += curr_size;
  938. }
  939. return size;
  940. }
  941. static uint32
  942. get_relocation_group_symbol_size(AOTCompContext *comp_ctx,
  943. AOTRelocationGroup *relocation_group,
  944. AOTSymbolList *symbol_list)
  945. {
  946. uint32 size = 0, index = 0, curr_size;
  947. bool is_new = false;
  948. index = get_relocation_symbol_index(relocation_group->section_name, &is_new,
  949. symbol_list);
  950. CHECK_SIZE(index);
  951. if (is_new) {
  952. size += get_string_size(comp_ctx, relocation_group->section_name);
  953. size = align_uint(size, 2);
  954. }
  955. relocation_group->name_index = index;
  956. curr_size = get_relocations_symbol_size(
  957. comp_ctx, relocation_group->relocations,
  958. relocation_group->relocation_count, symbol_list);
  959. CHECK_SIZE(curr_size);
  960. size += curr_size;
  961. return size;
  962. }
  963. static uint32
  964. get_relocation_groups_symbol_size(AOTCompContext *comp_ctx,
  965. AOTRelocationGroup *relocation_groups,
  966. uint32 relocation_group_count,
  967. AOTSymbolList *symbol_list)
  968. {
  969. AOTRelocationGroup *relocation_group = relocation_groups;
  970. uint32 size = 0, curr_size, i;
  971. for (i = 0; i < relocation_group_count; i++, relocation_group++) {
  972. curr_size = get_relocation_group_symbol_size(comp_ctx, relocation_group,
  973. symbol_list);
  974. CHECK_SIZE(curr_size);
  975. size += curr_size;
  976. }
  977. return size;
  978. }
  979. static uint32
  980. get_symbol_size_from_symbol_list(AOTCompContext *comp_ctx,
  981. AOTSymbolList *symbol_list)
  982. {
  983. AOTSymbolNode *sym;
  984. uint32 size = 0;
  985. sym = symbol_list->head;
  986. while (sym) {
  987. /* (uint16)str_len + str */
  988. size += get_string_size(comp_ctx, sym->symbol);
  989. size = align_uint(size, 2);
  990. sym = sym->next;
  991. }
  992. return size;
  993. }
  994. static uint32
  995. get_relocation_section_symbol_size(AOTCompContext *comp_ctx,
  996. AOTObjectData *obj_data)
  997. {
  998. AOTRelocationGroup *relocation_groups = obj_data->relocation_groups;
  999. uint32 relocation_group_count = obj_data->relocation_group_count;
  1000. uint32 string_count = 0, symbol_table_size = 0;
  1001. /* section size will be calculated twice,
  1002. get symbol size from symbol list directly in the second calculation */
  1003. if (obj_data->symbol_list.len > 0) {
  1004. symbol_table_size =
  1005. get_symbol_size_from_symbol_list(comp_ctx, &obj_data->symbol_list);
  1006. }
  1007. else {
  1008. symbol_table_size = get_relocation_groups_symbol_size(
  1009. comp_ctx, relocation_groups, relocation_group_count,
  1010. &obj_data->symbol_list);
  1011. }
  1012. CHECK_SIZE(symbol_table_size);
  1013. string_count = obj_data->symbol_list.len;
  1014. /* string_count + string_offsets + total_string_len
  1015. + [str (string_len + str)] */
  1016. return (uint32)(sizeof(uint32) + sizeof(uint32) * string_count
  1017. + sizeof(uint32) + symbol_table_size);
  1018. }
  1019. static uint32
  1020. get_relocation_section_size(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
  1021. {
  1022. AOTRelocationGroup *relocation_groups = obj_data->relocation_groups;
  1023. uint32 relocation_group_count = obj_data->relocation_group_count;
  1024. uint32 symbol_table_size = 0;
  1025. symbol_table_size = get_relocation_section_symbol_size(comp_ctx, obj_data);
  1026. CHECK_SIZE(symbol_table_size);
  1027. symbol_table_size = align_uint(symbol_table_size, 4);
  1028. /* relocation group count + symbol_table + relocation groups */
  1029. return (uint32)sizeof(uint32) + symbol_table_size
  1030. + get_relocation_groups_size(obj_data, relocation_groups,
  1031. relocation_group_count,
  1032. is_32bit_binary(obj_data));
  1033. }
  1034. static uint32
  1035. get_native_symbol_list_size(AOTCompContext *comp_ctx)
  1036. {
  1037. uint32 len = 0;
  1038. AOTNativeSymbol *sym = NULL;
  1039. sym = bh_list_first_elem(&comp_ctx->native_symbols);
  1040. while (sym) {
  1041. len = align_uint(len, 2);
  1042. len += get_string_size(comp_ctx, sym->symbol);
  1043. sym = bh_list_elem_next(sym);
  1044. }
  1045. return len;
  1046. }
  1047. #if WASM_ENABLE_STRINGREF != 0
  1048. static uint32
  1049. get_string_literal_section_size(AOTCompContext *comp_ctx,
  1050. AOTCompData *comp_data);
  1051. #endif
  1052. static uint32
  1053. get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data);
  1054. uint32
  1055. aot_get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  1056. AOTObjectData *obj_data)
  1057. {
  1058. uint32 size = 0;
  1059. uint32 size_custom_section = 0;
  1060. #if WASM_ENABLE_STRINGREF != 0
  1061. uint32 size_string_literal_section = 0;
  1062. #endif
  1063. /* aot file header */
  1064. size += get_file_header_size();
  1065. /* target info section */
  1066. size = align_uint(size, 4);
  1067. /* section id + section size */
  1068. size += (uint32)sizeof(uint32) * 2;
  1069. size += get_target_info_section_size();
  1070. /* init data section */
  1071. size = align_uint(size, 4);
  1072. /* section id + section size */
  1073. size += (uint32)sizeof(uint32) * 2;
  1074. size += get_init_data_section_size(comp_ctx, comp_data, obj_data);
  1075. /* text section */
  1076. size = align_uint(size, 4);
  1077. /* section id + section size */
  1078. size += (uint32)sizeof(uint32) * 2;
  1079. size += get_text_section_size(obj_data);
  1080. /* function section */
  1081. size = align_uint(size, 4);
  1082. /* section id + section size */
  1083. size += (uint32)sizeof(uint32) * 2;
  1084. size += get_func_section_size(comp_ctx, comp_data, obj_data);
  1085. /* export section */
  1086. size = align_uint(size, 4);
  1087. /* section id + section size */
  1088. size += (uint32)sizeof(uint32) * 2;
  1089. size += get_export_section_size(comp_ctx, comp_data);
  1090. /* relocation section */
  1091. size = align_uint(size, 4);
  1092. /* section id + section size */
  1093. size += (uint32)sizeof(uint32) * 2;
  1094. size += get_relocation_section_size(comp_ctx, obj_data);
  1095. if (get_native_symbol_list_size(comp_ctx) > 0) {
  1096. /* emit only when there are native symbols */
  1097. size = align_uint(size, 4);
  1098. /* section id + section size + sub section id + symbol count */
  1099. size += (uint32)sizeof(uint32) * 4;
  1100. size += get_native_symbol_list_size(comp_ctx);
  1101. }
  1102. size_custom_section = get_custom_sections_size(comp_ctx, comp_data);
  1103. if (size_custom_section > 0) {
  1104. size = align_uint(size, 4);
  1105. size += size_custom_section;
  1106. }
  1107. #if WASM_ENABLE_STRINGREF != 0
  1108. /* string literal section */
  1109. size_string_literal_section =
  1110. get_string_literal_section_size(comp_ctx, comp_data);
  1111. if (size_string_literal_section > 0) {
  1112. size = align_uint(size, 4);
  1113. /* section id + section size + sub section id */
  1114. size += (uint32)sizeof(uint32) * 3;
  1115. size += size_string_literal_section;
  1116. }
  1117. #endif
  1118. return size;
  1119. }
  1120. #define exchange_uint8(p_data) (void)0
  1121. static void
  1122. exchange_uint16(uint8 *p_data)
  1123. {
  1124. uint8 value = *p_data;
  1125. *p_data = *(p_data + 1);
  1126. *(p_data + 1) = value;
  1127. }
  1128. static void
  1129. exchange_uint32(uint8 *p_data)
  1130. {
  1131. uint8 value = *p_data;
  1132. *p_data = *(p_data + 3);
  1133. *(p_data + 3) = value;
  1134. value = *(p_data + 1);
  1135. *(p_data + 1) = *(p_data + 2);
  1136. *(p_data + 2) = value;
  1137. }
  1138. static void
  1139. exchange_uint64(uint8 *p_data)
  1140. {
  1141. uint32 value;
  1142. value = *(uint32 *)p_data;
  1143. *(uint32 *)p_data = *(uint32 *)(p_data + 4);
  1144. *(uint32 *)(p_data + 4) = value;
  1145. exchange_uint32(p_data);
  1146. exchange_uint32(p_data + 4);
  1147. }
  1148. static void
  1149. exchange_uint128(uint8 *p_data)
  1150. {
  1151. /* swap high 64bit and low 64bit */
  1152. uint64 value = *(uint64 *)p_data;
  1153. *(uint64 *)p_data = *(uint64 *)(p_data + 8);
  1154. *(uint64 *)(p_data + 8) = value;
  1155. /* exchange high 64bit */
  1156. exchange_uint64(p_data);
  1157. /* exchange low 64bit */
  1158. exchange_uint64(p_data + 8);
  1159. }
  1160. static union {
  1161. int a;
  1162. char b;
  1163. } __ue = { .a = 1 };
  1164. #define is_little_endian() (__ue.b == 1)
  1165. #define CHECK_BUF(length) \
  1166. do { \
  1167. if (buf + offset + length > buf_end) { \
  1168. aot_set_last_error("buf overflow"); \
  1169. return false; \
  1170. } \
  1171. } while (0)
  1172. #define EMIT_U8(v) \
  1173. do { \
  1174. CHECK_BUF(1); \
  1175. *(uint8 *)(buf + offset) = (uint8)v; \
  1176. offset++; \
  1177. } while (0)
  1178. #define EMIT_U16(v) \
  1179. do { \
  1180. uint16 t = (uint16)v; \
  1181. CHECK_BUF(2); \
  1182. if (!is_little_endian()) \
  1183. exchange_uint16((uint8 *)&t); \
  1184. *(uint16 *)(buf + offset) = t; \
  1185. offset += (uint32)sizeof(uint16); \
  1186. } while (0)
  1187. #define EMIT_U32(v) \
  1188. do { \
  1189. uint32 t = (uint32)v; \
  1190. CHECK_BUF(4); \
  1191. if (!is_little_endian()) \
  1192. exchange_uint32((uint8 *)&t); \
  1193. *(uint32 *)(buf + offset) = t; \
  1194. offset += (uint32)sizeof(uint32); \
  1195. } while (0)
  1196. #define EMIT_U64(v) \
  1197. do { \
  1198. uint64 t = (uint64)v; \
  1199. CHECK_BUF(8); \
  1200. if (!is_little_endian()) \
  1201. exchange_uint64((uint8 *)&t); \
  1202. PUT_U64_TO_ADDR(buf + offset, t); \
  1203. offset += (uint32)sizeof(uint64); \
  1204. } while (0)
  1205. #define EMIT_V128(v) \
  1206. do { \
  1207. uint64 *t = (uint64 *)v.i64x2; \
  1208. CHECK_BUF(16); \
  1209. if (!is_little_endian()) \
  1210. exchange_uint128((uint8 *)t); \
  1211. PUT_U64_TO_ADDR(buf + offset, t[0]); \
  1212. offset += (uint32)sizeof(uint64); \
  1213. PUT_U64_TO_ADDR(buf + offset, t[1]); \
  1214. offset += (uint32)sizeof(uint64); \
  1215. } while (0)
  1216. #define EMIT_BUF(v, len) \
  1217. do { \
  1218. CHECK_BUF(len); \
  1219. memcpy(buf + offset, v, len); \
  1220. offset += len; \
  1221. } while (0)
  1222. /* Emit string with '\0'
  1223. */
  1224. #define EMIT_STR(s) \
  1225. do { \
  1226. uint32 str_len = (uint32)strlen(s) + 1; \
  1227. if (str_len > INT16_MAX) { \
  1228. aot_set_last_error("emit string failed: " \
  1229. "string too long"); \
  1230. return false; \
  1231. } \
  1232. EMIT_U16(str_len); \
  1233. EMIT_BUF(s, str_len); \
  1234. } while (0)
  1235. #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
  1236. static bool
  1237. read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
  1238. uint64 *p_result)
  1239. {
  1240. const uint8 *buf = *p_buf;
  1241. uint64 result = 0;
  1242. uint32 shift = 0;
  1243. uint32 offset = 0, bcnt = 0;
  1244. uint64 byte;
  1245. while (true) {
  1246. /* uN or SN must not exceed ceil(N/7) bytes */
  1247. if (bcnt + 1 > (maxbits + 6) / 7) {
  1248. aot_set_last_error("integer representation too long");
  1249. return false;
  1250. }
  1251. if (buf + offset + 1 > buf_end) {
  1252. aot_set_last_error("unexpected end of section or function");
  1253. return false;
  1254. }
  1255. byte = buf[offset];
  1256. offset += 1;
  1257. result |= ((byte & 0x7f) << shift);
  1258. shift += 7;
  1259. bcnt += 1;
  1260. if ((byte & 0x80) == 0) {
  1261. break;
  1262. }
  1263. }
  1264. if (!sign && maxbits == 32 && shift >= maxbits) {
  1265. /* The top bits set represent values > 32 bits */
  1266. if (((uint8)byte) & 0xf0)
  1267. goto fail_integer_too_large;
  1268. }
  1269. else if (sign && maxbits == 32) {
  1270. if (shift < maxbits) {
  1271. /* Sign extend, second highest bit is the sign bit */
  1272. if ((uint8)byte & 0x40)
  1273. result |= (~((uint64)0)) << shift;
  1274. }
  1275. else {
  1276. /* The top bits should be a sign-extension of the sign bit */
  1277. bool sign_bit_set = ((uint8)byte) & 0x8;
  1278. int top_bits = ((uint8)byte) & 0xf0;
  1279. if ((sign_bit_set && top_bits != 0x70)
  1280. || (!sign_bit_set && top_bits != 0))
  1281. goto fail_integer_too_large;
  1282. }
  1283. }
  1284. else if (sign && maxbits == 64) {
  1285. if (shift < maxbits) {
  1286. /* Sign extend, second highest bit is the sign bit */
  1287. if ((uint8)byte & 0x40)
  1288. result |= (~((uint64)0)) << shift;
  1289. }
  1290. else {
  1291. /* The top bits should be a sign-extension of the sign bit */
  1292. bool sign_bit_set = ((uint8)byte) & 0x1;
  1293. int top_bits = ((uint8)byte) & 0xfe;
  1294. if ((sign_bit_set && top_bits != 0x7e)
  1295. || (!sign_bit_set && top_bits != 0))
  1296. goto fail_integer_too_large;
  1297. }
  1298. }
  1299. *p_buf += offset;
  1300. *p_result = result;
  1301. return true;
  1302. fail_integer_too_large:
  1303. aot_set_last_error("integer too large");
  1304. return false;
  1305. }
  1306. /* NOLINTNEXTLINE */
  1307. #define read_leb_uint32(p, p_end, res) \
  1308. do { \
  1309. uint64 res64; \
  1310. if (!read_leb((uint8 **)&p, p_end, 32, false, &res64)) \
  1311. goto fail; \
  1312. res = (uint32)res64; \
  1313. } while (0)
  1314. /*
  1315. * - transfer .name section in .wasm (comp_data->name_section_buf) to
  1316. * aot buf (comp_data->aot_name_section_buf)
  1317. * - leb128 to u32
  1318. * - add `\0` at the end of every name, and adjust length(+1)
  1319. */
  1320. static uint32
  1321. get_name_section_size(AOTCompData *comp_data)
  1322. {
  1323. /* original name section content in .wasm */
  1324. const uint8 *p = comp_data->name_section_buf,
  1325. *p_end = comp_data->name_section_buf_end;
  1326. uint8 *buf, *buf_end;
  1327. uint32 name_type, subsection_size;
  1328. uint32 previous_name_type = 0;
  1329. uint32 num_func_name;
  1330. uint32 func_index;
  1331. uint32 previous_func_index = ~0U;
  1332. uint32 func_name_len;
  1333. uint32 name_index;
  1334. int i = 0;
  1335. uint32 name_len;
  1336. uint32 offset = 0;
  1337. uint32 max_aot_buf_size = 0;
  1338. if (p >= p_end) {
  1339. aot_set_last_error("unexpected end");
  1340. return 0;
  1341. }
  1342. max_aot_buf_size = 4 * (uint32)(p_end - p);
  1343. if (!(buf = comp_data->aot_name_section_buf =
  1344. wasm_runtime_malloc(max_aot_buf_size))) {
  1345. aot_set_last_error("allocate memory for custom name section failed.");
  1346. return 0;
  1347. }
  1348. memset(buf, 0, (uint32)max_aot_buf_size);
  1349. buf_end = buf + max_aot_buf_size;
  1350. /* the size of "name". it should be 4 */
  1351. read_leb_uint32(p, p_end, name_len);
  1352. offset = align_uint(offset, 4);
  1353. EMIT_U32(name_len);
  1354. if (name_len != 4 || p + name_len > p_end) {
  1355. aot_set_last_error("unexpected end");
  1356. return 0;
  1357. }
  1358. /* "name" */
  1359. if (memcmp(p, "name", 4) != 0) {
  1360. aot_set_last_error("invalid custom name section");
  1361. return 0;
  1362. }
  1363. EMIT_BUF(p, name_len);
  1364. p += name_len;
  1365. while (p < p_end) {
  1366. read_leb_uint32(p, p_end, name_type);
  1367. if (i != 0) {
  1368. if (name_type == previous_name_type) {
  1369. aot_set_last_error("duplicate sub-section");
  1370. return 0;
  1371. }
  1372. if (name_type < previous_name_type) {
  1373. aot_set_last_error("out-of-order sub-section");
  1374. return 0;
  1375. }
  1376. }
  1377. previous_name_type = name_type;
  1378. read_leb_uint32(p, p_end, subsection_size);
  1379. switch (name_type) {
  1380. case SUB_SECTION_TYPE_FUNC:
  1381. if (subsection_size) {
  1382. offset = align_uint(offset, 4);
  1383. EMIT_U32(name_type);
  1384. EMIT_U32(subsection_size);
  1385. read_leb_uint32(p, p_end, num_func_name);
  1386. EMIT_U32(num_func_name);
  1387. for (name_index = 0; name_index < num_func_name;
  1388. name_index++) {
  1389. read_leb_uint32(p, p_end, func_index);
  1390. offset = align_uint(offset, 4);
  1391. EMIT_U32(func_index);
  1392. if (func_index == previous_func_index) {
  1393. aot_set_last_error("duplicate function name");
  1394. return 0;
  1395. }
  1396. if (func_index < previous_func_index
  1397. && previous_func_index != ~0U) {
  1398. aot_set_last_error("out-of-order function index ");
  1399. return 0;
  1400. }
  1401. previous_func_index = func_index;
  1402. read_leb_uint32(p, p_end, func_name_len);
  1403. offset = align_uint(offset, 2);
  1404. /* emit a string ends with `\0` */
  1405. if (func_name_len + 1 > UINT16_MAX) {
  1406. aot_set_last_error(
  1407. "emit string failed: string too long");
  1408. goto fail;
  1409. }
  1410. /* extra 1 byte for \0 */
  1411. EMIT_U16(func_name_len + 1);
  1412. EMIT_BUF(p, func_name_len);
  1413. p += func_name_len;
  1414. EMIT_U8(0);
  1415. }
  1416. }
  1417. break;
  1418. case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection
  1419. */
  1420. case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */
  1421. default:
  1422. p = p + subsection_size;
  1423. break;
  1424. }
  1425. i++;
  1426. }
  1427. return offset;
  1428. fail:
  1429. return 0;
  1430. }
  1431. #endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
  1432. #if WASM_ENABLE_STRINGREF != 0
  1433. static uint32
  1434. get_string_literal_section_size(AOTCompContext *comp_ctx,
  1435. AOTCompData *comp_data)
  1436. {
  1437. uint32 i;
  1438. uint32 size = 0;
  1439. uint32 string_count = comp_data->string_literal_count;
  1440. if (string_count == 0) {
  1441. return 0;
  1442. }
  1443. /* reserved slot + string count + string_lengths */
  1444. size += sizeof(uint32) * (2 + string_count);
  1445. for (i = 0; i < string_count; i++) {
  1446. size += comp_data->string_literal_lengths_wp[i];
  1447. }
  1448. return size;
  1449. }
  1450. #endif /* end of WASM_ENABLE_STRINGREF != 0 */
  1451. static uint32
  1452. get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
  1453. {
  1454. #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
  1455. uint32 size = 0, i;
  1456. for (i = 0; i < comp_ctx->custom_sections_count; i++) {
  1457. const char *section_name = comp_ctx->custom_sections_wp[i];
  1458. const uint8 *content = NULL;
  1459. uint32 length = 0;
  1460. if (strcmp(section_name, "name") == 0) {
  1461. /* custom name section */
  1462. comp_data->aot_name_section_size = get_name_section_size(comp_data);
  1463. if (comp_data->aot_name_section_size == 0) {
  1464. LOG_WARNING("Can't find custom section [name], ignore it");
  1465. continue;
  1466. }
  1467. size = align_uint(size, 4);
  1468. /* section id + section size + sub section id */
  1469. size += (uint32)sizeof(uint32) * 3;
  1470. size += comp_data->aot_name_section_size;
  1471. continue;
  1472. }
  1473. content = wasm_loader_get_custom_section(comp_data->wasm_module,
  1474. section_name, &length);
  1475. if (!content) {
  1476. LOG_WARNING("Can't find custom section [%s], ignore it",
  1477. section_name);
  1478. continue;
  1479. }
  1480. size = align_uint(size, 4);
  1481. /* section id + section size + sub section id */
  1482. size += (uint32)sizeof(uint32) * 3;
  1483. /* section name and len */
  1484. size += get_string_size(comp_ctx, section_name);
  1485. /* section content */
  1486. size += length;
  1487. }
  1488. return size;
  1489. #else
  1490. return 0;
  1491. #endif
  1492. }
  1493. static bool
  1494. aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1495. AOTCompData *comp_data, AOTObjectData *obj_data)
  1496. {
  1497. uint32 offset = *p_offset;
  1498. uint32 aot_curr_version = AOT_CURRENT_VERSION;
  1499. EMIT_U8('\0');
  1500. EMIT_U8('a');
  1501. EMIT_U8('o');
  1502. EMIT_U8('t');
  1503. EMIT_U32(aot_curr_version);
  1504. *p_offset = offset;
  1505. return true;
  1506. }
  1507. static bool
  1508. aot_emit_target_info_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1509. AOTCompData *comp_data, AOTObjectData *obj_data)
  1510. {
  1511. uint32 offset = *p_offset;
  1512. uint32 section_size = get_target_info_section_size();
  1513. AOTTargetInfo *target_info = &obj_data->target_info;
  1514. *p_offset = offset = align_uint(offset, 4);
  1515. EMIT_U32(AOT_SECTION_TYPE_TARGET_INFO);
  1516. EMIT_U32(section_size);
  1517. EMIT_U16(target_info->bin_type);
  1518. EMIT_U16(target_info->abi_type);
  1519. EMIT_U16(target_info->e_type);
  1520. EMIT_U16(target_info->e_machine);
  1521. EMIT_U32(target_info->e_version);
  1522. EMIT_U32(target_info->e_flags);
  1523. EMIT_U64(target_info->feature_flags);
  1524. EMIT_U64(target_info->reserved);
  1525. EMIT_BUF(target_info->arch, sizeof(target_info->arch));
  1526. if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
  1527. aot_set_last_error("emit target info failed.");
  1528. return false;
  1529. }
  1530. *p_offset = offset;
  1531. return true;
  1532. }
  1533. static bool
  1534. aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1535. AOTCompContext *comp_ctx, InitializerExpression *expr);
  1536. static bool
  1537. aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1538. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  1539. AOTObjectData *obj_data)
  1540. {
  1541. uint32 offset = *p_offset, i;
  1542. AOTMemInitData **init_datas = comp_data->mem_init_data_list;
  1543. *p_offset = offset = align_uint(offset, 4);
  1544. /* Emit import memory count, only emit 0 currently.
  1545. TODO: emit the actual import memory count and
  1546. the full import memory info. */
  1547. EMIT_U32(0);
  1548. /* Emit memory count */
  1549. EMIT_U32(comp_data->memory_count);
  1550. /* Emit memory items */
  1551. for (i = 0; i < comp_data->memory_count; i++) {
  1552. EMIT_U32(comp_data->memories[i].flags);
  1553. EMIT_U32(comp_data->memories[i].num_bytes_per_page);
  1554. EMIT_U32(comp_data->memories[i].init_page_count);
  1555. EMIT_U32(comp_data->memories[i].max_page_count);
  1556. }
  1557. /* Emit mem init data count */
  1558. EMIT_U32(comp_data->mem_init_data_count);
  1559. /* Emit mem init data items */
  1560. for (i = 0; i < comp_data->mem_init_data_count; i++) {
  1561. offset = align_uint(offset, 4);
  1562. #if WASM_ENABLE_BULK_MEMORY != 0
  1563. if (comp_ctx->enable_bulk_memory) {
  1564. EMIT_U32(init_datas[i]->is_passive);
  1565. EMIT_U32(init_datas[i]->memory_index);
  1566. }
  1567. else
  1568. #endif
  1569. {
  1570. /* emit two placeholder to keep the same size */
  1571. EMIT_U32(0);
  1572. EMIT_U32(0);
  1573. }
  1574. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  1575. &init_datas[i]->offset))
  1576. return false;
  1577. EMIT_U32(init_datas[i]->byte_count);
  1578. if (init_datas[i]->byte_count) {
  1579. EMIT_BUF(init_datas[i]->bytes, init_datas[i]->byte_count);
  1580. }
  1581. }
  1582. if (offset - *p_offset != get_mem_info_size(comp_ctx, comp_data)) {
  1583. aot_set_last_error("emit memory info failed.");
  1584. return false;
  1585. }
  1586. *p_offset = offset;
  1587. return true;
  1588. }
  1589. static bool
  1590. aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1591. AOTCompContext *comp_ctx, InitializerExpression *expr)
  1592. {
  1593. if (expr == NULL) {
  1594. aot_set_last_error("invalid init expr.");
  1595. return false;
  1596. }
  1597. uint32 offset = *p_offset;
  1598. #if WASM_ENABLE_GC != 0
  1599. WASMModule *module = comp_ctx->comp_data->wasm_module;
  1600. #endif
  1601. *p_offset = offset = align_uint(offset, 4);
  1602. EMIT_U32(expr->init_expr_type);
  1603. switch (expr->init_expr_type) {
  1604. case INIT_EXPR_NONE:
  1605. break;
  1606. case INIT_EXPR_TYPE_I32_CONST:
  1607. case INIT_EXPR_TYPE_F32_CONST:
  1608. EMIT_U32(expr->u.unary.v.i32);
  1609. break;
  1610. case INIT_EXPR_TYPE_I64_CONST:
  1611. case INIT_EXPR_TYPE_F64_CONST:
  1612. EMIT_U64(expr->u.unary.v.i64);
  1613. break;
  1614. case INIT_EXPR_TYPE_V128_CONST:
  1615. EMIT_V128(expr->u.unary.v.v128);
  1616. break;
  1617. case INIT_EXPR_TYPE_GET_GLOBAL:
  1618. EMIT_U32(expr->u.unary.v.global_index);
  1619. break;
  1620. case INIT_EXPR_TYPE_FUNCREF_CONST:
  1621. case INIT_EXPR_TYPE_REFNULL_CONST:
  1622. EMIT_U32(expr->u.unary.v.ref_index);
  1623. break;
  1624. #if WASM_ENABLE_GC != 0
  1625. case INIT_EXPR_TYPE_I31_NEW:
  1626. EMIT_U32(expr->u.unary.v.i32);
  1627. break;
  1628. case INIT_EXPR_TYPE_STRUCT_NEW:
  1629. {
  1630. uint32 i;
  1631. WASMStructNewInitValues *init_values =
  1632. (WASMStructNewInitValues *)expr->u.unary.v.data;
  1633. WASMStructType *struct_type = NULL;
  1634. EMIT_U32(init_values->type_idx);
  1635. EMIT_U32(init_values->count);
  1636. bh_assert(init_values->type_idx < module->type_count);
  1637. struct_type =
  1638. (WASMStructType *)module->types[init_values->type_idx];
  1639. bh_assert(struct_type);
  1640. bh_assert(struct_type->field_count == init_values->count);
  1641. for (i = 0; i < init_values->count; i++) {
  1642. uint32 field_size = wasm_value_type_size_internal(
  1643. struct_type->fields[i].field_type, comp_ctx->pointer_size);
  1644. if (field_size <= sizeof(uint32))
  1645. EMIT_U32(init_values->fields[i].u32);
  1646. else if (field_size == sizeof(uint64))
  1647. EMIT_U64(init_values->fields[i].u64);
  1648. else if (field_size == sizeof(uint64) * 2)
  1649. EMIT_V128(init_values->fields[i].v128);
  1650. else {
  1651. bh_assert(0);
  1652. }
  1653. }
  1654. break;
  1655. }
  1656. case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
  1657. EMIT_U32(expr->u.unary.v.type_index);
  1658. break;
  1659. case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
  1660. {
  1661. WASMArrayType *array_type = NULL;
  1662. bh_assert(expr->u.unary.v.array_new_default.type_index
  1663. < module->type_count);
  1664. array_type =
  1665. (WASMArrayType *)
  1666. module->types[expr->u.unary.v.array_new_default.type_index];
  1667. EMIT_U32(array_type->elem_type);
  1668. EMIT_U32(expr->u.unary.v.array_new_default.type_index);
  1669. EMIT_U32(expr->u.unary.v.array_new_default.length);
  1670. break;
  1671. }
  1672. case INIT_EXPR_TYPE_ARRAY_NEW:
  1673. case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
  1674. {
  1675. uint32 value_count, i, field_size;
  1676. WASMArrayNewInitValues *init_values =
  1677. (WASMArrayNewInitValues *)expr->u.unary.v.data;
  1678. WASMArrayType *array_type = NULL;
  1679. bh_assert(init_values->type_idx < module->type_count);
  1680. array_type = (WASMArrayType *)module->types[init_values->type_idx];
  1681. EMIT_U32(array_type->elem_type);
  1682. EMIT_U32(init_values->type_idx);
  1683. EMIT_U32(init_values->length);
  1684. value_count =
  1685. (expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED)
  1686. ? init_values->length
  1687. : 1;
  1688. field_size = wasm_value_type_size_internal(array_type->elem_type,
  1689. comp_ctx->pointer_size);
  1690. for (i = 0; i < value_count; i++) {
  1691. if (field_size <= sizeof(uint32))
  1692. EMIT_U32(init_values->elem_data[i].u32);
  1693. else if (field_size == sizeof(uint64))
  1694. EMIT_U64(init_values->elem_data[i].u64);
  1695. else if (field_size == sizeof(uint64) * 2)
  1696. EMIT_V128(init_values->elem_data[i].v128);
  1697. else {
  1698. bh_assert(0);
  1699. }
  1700. }
  1701. break;
  1702. }
  1703. #endif /* end of WASM_ENABLE_GC != 0 */
  1704. #if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
  1705. case INIT_EXPR_TYPE_I32_ADD:
  1706. case INIT_EXPR_TYPE_I32_SUB:
  1707. case INIT_EXPR_TYPE_I32_MUL:
  1708. case INIT_EXPR_TYPE_I64_ADD:
  1709. case INIT_EXPR_TYPE_I64_SUB:
  1710. case INIT_EXPR_TYPE_I64_MUL:
  1711. if (comp_ctx->enable_extended_const) {
  1712. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  1713. expr->u.binary.l_expr)) {
  1714. return false;
  1715. }
  1716. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  1717. expr->u.binary.r_expr)) {
  1718. return false;
  1719. }
  1720. }
  1721. break;
  1722. #endif
  1723. default:
  1724. aot_set_last_error("invalid init expr type.");
  1725. return false;
  1726. }
  1727. *p_offset = offset;
  1728. return true;
  1729. }
  1730. static bool
  1731. aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1732. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  1733. AOTObjectData *obj_data)
  1734. {
  1735. uint32 offset = *p_offset, i, j;
  1736. AOTTableInitData **init_datas = comp_data->table_init_data_list;
  1737. *p_offset = offset = align_uint(offset, 4);
  1738. /* Emit import table count */
  1739. EMIT_U32(comp_data->import_table_count);
  1740. /* Emit table items */
  1741. for (i = 0; i < comp_data->import_table_count; i++) {
  1742. /* TODO:
  1743. * EMIT_STR(comp_data->import_tables[i].module_name );
  1744. * EMIT_STR(comp_data->import_tables[i].table_name);
  1745. */
  1746. EMIT_U8(comp_data->import_tables[i].table_type.elem_type);
  1747. EMIT_U8(comp_data->import_tables[i].table_type.flags);
  1748. EMIT_U8(comp_data->import_tables[i].table_type.possible_grow);
  1749. #if WASM_ENABLE_GC != 0
  1750. if (comp_ctx->enable_gc
  1751. && comp_data->import_tables[i].table_type.elem_ref_type) {
  1752. EMIT_U8(comp_data->import_tables[i]
  1753. .table_type.elem_ref_type->ref_ht_common.nullable);
  1754. }
  1755. else
  1756. #endif
  1757. {
  1758. /* emit one placeholder to keep the same size */
  1759. EMIT_U8(0);
  1760. }
  1761. EMIT_U32(comp_data->import_tables[i].table_type.init_size);
  1762. EMIT_U32(comp_data->import_tables[i].table_type.max_size);
  1763. #if WASM_ENABLE_GC != 0
  1764. if (comp_ctx->enable_gc
  1765. && comp_data->import_tables[i].table_type.elem_ref_type) {
  1766. bh_assert(wasm_is_type_multi_byte_type(
  1767. comp_data->import_tables[i].table_type.elem_type));
  1768. EMIT_U32(comp_data->import_tables[i]
  1769. .table_type.elem_ref_type->ref_ht_common.heap_type);
  1770. }
  1771. #endif
  1772. }
  1773. /* Emit table count */
  1774. EMIT_U32(comp_data->table_count);
  1775. /* Emit table items */
  1776. for (i = 0; i < comp_data->table_count; i++) {
  1777. EMIT_U8(comp_data->tables[i].table_type.elem_type);
  1778. EMIT_U8(comp_data->tables[i].table_type.flags);
  1779. EMIT_U8(comp_data->tables[i].table_type.possible_grow);
  1780. #if WASM_ENABLE_GC != 0
  1781. if (comp_ctx->enable_gc
  1782. && comp_data->tables[i].table_type.elem_ref_type) {
  1783. EMIT_U8(comp_data->tables[i]
  1784. .table_type.elem_ref_type->ref_ht_common.nullable);
  1785. }
  1786. else
  1787. #endif
  1788. {
  1789. /* emit one placeholder to keep the same size */
  1790. EMIT_U8(0);
  1791. }
  1792. EMIT_U32(comp_data->tables[i].table_type.init_size);
  1793. EMIT_U32(comp_data->tables[i].table_type.max_size);
  1794. #if WASM_ENABLE_GC != 0
  1795. if (comp_ctx->enable_gc) {
  1796. if (comp_data->tables[i].table_type.elem_ref_type) {
  1797. bh_assert(wasm_is_type_multi_byte_type(
  1798. comp_data->tables[i].table_type.elem_type));
  1799. EMIT_U32(
  1800. comp_data->tables[i]
  1801. .table_type.elem_ref_type->ref_ht_common.heap_type);
  1802. }
  1803. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  1804. &comp_data->tables[i].init_expr)) {
  1805. return false;
  1806. }
  1807. }
  1808. #endif
  1809. }
  1810. /* Emit table init data count */
  1811. EMIT_U32(comp_data->table_init_data_count);
  1812. /* Emit table init data items */
  1813. for (i = 0; i < comp_data->table_init_data_count; i++) {
  1814. offset = align_uint(offset, 4);
  1815. EMIT_U32(init_datas[i]->mode);
  1816. EMIT_U32(init_datas[i]->elem_type);
  1817. EMIT_U32(init_datas[i]->table_index);
  1818. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  1819. &init_datas[i]->offset))
  1820. return false;
  1821. #if WASM_ENABLE_GC != 0
  1822. if (comp_ctx->enable_gc && init_datas[i]->elem_ref_type) {
  1823. EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.ref_type);
  1824. EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.nullable);
  1825. EMIT_U32(init_datas[i]->elem_ref_type->ref_ht_common.heap_type);
  1826. }
  1827. else
  1828. #endif
  1829. {
  1830. EMIT_U16(init_datas[i]->elem_type);
  1831. EMIT_U16(0);
  1832. EMIT_U32(0);
  1833. }
  1834. EMIT_U32(init_datas[i]->value_count);
  1835. for (j = 0; j < init_datas[i]->value_count; j++) {
  1836. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  1837. &init_datas[i]->init_values[j]))
  1838. return false;
  1839. }
  1840. }
  1841. if (offset - *p_offset != get_table_info_size(comp_ctx, comp_data)) {
  1842. aot_set_last_error("emit table info failed.");
  1843. return false;
  1844. }
  1845. *p_offset = offset;
  1846. return true;
  1847. }
  1848. #if WASM_ENABLE_GC != 0
  1849. static bool
  1850. aot_emit_reftype_map(uint8 *buf, uint8 *buf_end, uint32 *p_offset, uint32 count,
  1851. WASMRefTypeMap *refmap)
  1852. {
  1853. uint32 offset = *p_offset, i;
  1854. for (i = 0; i < count; i++) {
  1855. EMIT_U16(refmap->index);
  1856. WASMRefType *ref_type = refmap->ref_type;
  1857. /* Note: WASMRefType is a union type */
  1858. EMIT_U8(ref_type->ref_ht_common.ref_type);
  1859. EMIT_U8(ref_type->ref_ht_common.nullable);
  1860. EMIT_U32(ref_type->ref_ht_common.heap_type);
  1861. refmap++;
  1862. }
  1863. *p_offset = offset;
  1864. return true;
  1865. }
  1866. #endif
  1867. static bool
  1868. aot_emit_type_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1869. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  1870. AOTObjectData *obj_data)
  1871. {
  1872. uint32 offset = *p_offset, i;
  1873. *p_offset = offset = align_uint(offset, 4);
  1874. EMIT_U32(comp_data->type_count);
  1875. #if WASM_ENABLE_GC != 0
  1876. if (comp_ctx->enable_gc) {
  1877. AOTType **types = comp_data->types;
  1878. int32 idx;
  1879. uint32 j;
  1880. for (i = 0; i < comp_data->type_count; i++) {
  1881. offset = align_uint(offset, 4);
  1882. /* Emit simple info if there is an equivalence type */
  1883. for (j = 0; j < i; j++) {
  1884. if (types[j] == types[i]) {
  1885. EMIT_U16(types[i]->type_flag);
  1886. /* equivalence type flag is true */
  1887. EMIT_U8(1);
  1888. EMIT_U8(0);
  1889. /* equivalence type index */
  1890. EMIT_U32(j);
  1891. break;
  1892. }
  1893. }
  1894. if (j < i)
  1895. continue;
  1896. EMIT_U16(types[i]->type_flag);
  1897. /* equivalence type flag is false */
  1898. EMIT_U8(0);
  1899. EMIT_U8(types[i]->is_sub_final);
  1900. EMIT_U32(types[i]->parent_type_idx);
  1901. EMIT_U16(types[i]->rec_count);
  1902. EMIT_U16(types[i]->rec_idx);
  1903. /* Emit WASM_TYPE_FUNC */
  1904. if (types[i]->type_flag == WASM_TYPE_FUNC) {
  1905. AOTFuncType *func_type = (AOTFuncType *)types[i];
  1906. EMIT_U16(func_type->param_count);
  1907. EMIT_U16(func_type->result_count);
  1908. EMIT_U16(func_type->ref_type_map_count);
  1909. EMIT_BUF(func_type->types,
  1910. func_type->param_count + func_type->result_count);
  1911. offset = align_uint(offset, 4);
  1912. aot_emit_reftype_map(buf, buf_end, &offset,
  1913. func_type->ref_type_map_count,
  1914. func_type->ref_type_maps);
  1915. }
  1916. /* Emit WASM_TYPE_STRUCT */
  1917. else if (types[i]->type_flag == WASM_TYPE_STRUCT) {
  1918. AOTStructType *struct_type = (AOTStructType *)types[i];
  1919. EMIT_U16(struct_type->field_count);
  1920. EMIT_U16(struct_type->ref_type_map_count);
  1921. for (idx = 0; idx < struct_type->field_count; idx++) {
  1922. EMIT_U8(struct_type->fields[idx].field_flags);
  1923. EMIT_U8(struct_type->fields[idx].field_type);
  1924. }
  1925. offset = align_uint(offset, 4);
  1926. aot_emit_reftype_map(buf, buf_end, &offset,
  1927. struct_type->ref_type_map_count,
  1928. struct_type->ref_type_maps);
  1929. }
  1930. /* Emit WASM_TYPE_ARRAY */
  1931. else if (types[i]->type_flag == WASM_TYPE_ARRAY) {
  1932. AOTArrayType *array_type = (AOTArrayType *)types[i];
  1933. EMIT_U16(array_type->elem_flags);
  1934. EMIT_U8(array_type->elem_type);
  1935. if (array_type->elem_ref_type) {
  1936. bh_assert(
  1937. wasm_is_type_multi_byte_type(array_type->elem_type));
  1938. EMIT_U8(array_type->elem_ref_type->ref_ht_common.nullable);
  1939. EMIT_U32(
  1940. array_type->elem_ref_type->ref_ht_common.heap_type);
  1941. }
  1942. }
  1943. else {
  1944. aot_set_last_error("invalid type flag.");
  1945. return false;
  1946. }
  1947. }
  1948. if (offset - *p_offset != get_type_info_size(comp_ctx, comp_data)) {
  1949. aot_set_last_error("emit function type info failed.");
  1950. return false;
  1951. }
  1952. *p_offset = offset;
  1953. }
  1954. else
  1955. #endif
  1956. {
  1957. AOTFuncType **func_types = (AOTFuncType **)comp_data->types;
  1958. for (i = 0; i < comp_data->type_count; i++) {
  1959. offset = align_uint(offset, 4);
  1960. /* If GC is disabled, only emit function type info */
  1961. EMIT_U16(WASM_TYPE_FUNC);
  1962. /* Omit to emit dummy padding for is_sub_final,
  1963. * parent_type_index, rec_count, rec_idx, 10 bytes in total */
  1964. EMIT_U16(func_types[i]->param_count);
  1965. EMIT_U16(func_types[i]->result_count);
  1966. /* Omit to emit dummy padding for ref_type_map_count, 2 bytes in
  1967. * total */
  1968. EMIT_BUF(func_types[i]->types,
  1969. func_types[i]->param_count + func_types[i]->result_count);
  1970. }
  1971. if (offset - *p_offset != get_type_info_size(comp_ctx, comp_data)) {
  1972. aot_set_last_error("emit function type info failed.");
  1973. return false;
  1974. }
  1975. *p_offset = offset;
  1976. }
  1977. return true;
  1978. }
  1979. static bool
  1980. aot_emit_import_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  1981. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  1982. AOTObjectData *obj_data)
  1983. {
  1984. uint32 offset = *p_offset, i;
  1985. AOTImportGlobal *import_global = comp_data->import_globals;
  1986. *p_offset = offset = align_uint(offset, 4);
  1987. EMIT_U32(comp_data->import_global_count);
  1988. for (i = 0; i < comp_data->import_global_count; i++, import_global++) {
  1989. offset = align_uint(offset, 2);
  1990. EMIT_U8(import_global->type.val_type);
  1991. EMIT_U8(import_global->type.is_mutable);
  1992. EMIT_STR(import_global->module_name);
  1993. offset = align_uint(offset, 2);
  1994. EMIT_STR(import_global->global_name);
  1995. }
  1996. if (offset - *p_offset
  1997. != get_import_global_info_size(comp_ctx, comp_data)) {
  1998. aot_set_last_error("emit import global info failed.");
  1999. return false;
  2000. }
  2001. *p_offset = offset;
  2002. return true;
  2003. }
  2004. static bool
  2005. aot_emit_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2006. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  2007. AOTObjectData *obj_data)
  2008. {
  2009. uint32 offset = *p_offset, i;
  2010. AOTGlobal *global = comp_data->globals;
  2011. *p_offset = offset = align_uint(offset, 4);
  2012. EMIT_U32(comp_data->global_count);
  2013. for (i = 0; i < comp_data->global_count; i++, global++) {
  2014. offset = align_uint(offset, 4);
  2015. EMIT_U8(global->type.val_type);
  2016. EMIT_U8(global->type.is_mutable);
  2017. offset = align_uint(offset, 4);
  2018. if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
  2019. &global->init_expr))
  2020. return false;
  2021. }
  2022. if (offset - *p_offset != get_global_info_size(comp_ctx, comp_data)) {
  2023. aot_set_last_error("emit global info failed.");
  2024. return false;
  2025. }
  2026. *p_offset = offset;
  2027. return true;
  2028. }
  2029. static bool
  2030. aot_emit_import_func_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2031. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  2032. AOTObjectData *obj_data)
  2033. {
  2034. uint32 offset = *p_offset, i;
  2035. AOTImportFunc *import_func = comp_data->import_funcs;
  2036. *p_offset = offset = align_uint(offset, 4);
  2037. EMIT_U32(comp_data->import_func_count);
  2038. for (i = 0; i < comp_data->import_func_count; i++, import_func++) {
  2039. offset = align_uint(offset, 2);
  2040. EMIT_U16(import_func->func_type_index);
  2041. EMIT_STR(import_func->module_name);
  2042. offset = align_uint(offset, 2);
  2043. EMIT_STR(import_func->func_name);
  2044. }
  2045. if (offset - *p_offset != get_import_func_info_size(comp_ctx, comp_data)) {
  2046. aot_set_last_error("emit import function info failed.");
  2047. return false;
  2048. }
  2049. *p_offset = offset;
  2050. return true;
  2051. }
  2052. static bool
  2053. aot_emit_object_data_section_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2054. AOTCompContext *comp_ctx,
  2055. AOTObjectData *obj_data)
  2056. {
  2057. uint32 offset = *p_offset, i;
  2058. AOTObjectDataSection *data_section = obj_data->data_sections;
  2059. *p_offset = offset = align_uint(offset, 4);
  2060. EMIT_U32(obj_data->data_sections_count);
  2061. for (i = 0; i < obj_data->data_sections_count; i++, data_section++) {
  2062. offset = align_uint(offset, 2);
  2063. EMIT_STR(data_section->name);
  2064. offset = align_uint(offset, 4);
  2065. EMIT_U32(data_section->size);
  2066. if (obj_data->stack_sizes_section_name != NULL
  2067. && !strcmp(obj_data->stack_sizes_section_name,
  2068. data_section->name)) {
  2069. uint32 ss_offset = obj_data->stack_sizes_offset;
  2070. uint32 ss_size =
  2071. obj_data->func_count * sizeof(*obj_data->stack_sizes);
  2072. LOG_VERBOSE("Replacing stack_sizes in %s section, offset %" PRIu32
  2073. ", size %" PRIu32,
  2074. obj_data->stack_sizes_section_name, ss_offset, ss_size);
  2075. bh_assert(ss_offset + ss_size <= data_section->size);
  2076. /* 0 .. ss_offset */
  2077. if (ss_offset > 0) {
  2078. EMIT_BUF(data_section->data, ss_offset);
  2079. }
  2080. /* ss_offset .. ss_offset+ss_size */
  2081. EMIT_BUF(obj_data->stack_sizes, ss_size);
  2082. /* ss_offset+ss_size .. data_section->size */
  2083. if (data_section->size > ss_offset + ss_size) {
  2084. EMIT_BUF(data_section->data + ss_offset + ss_size,
  2085. data_section->size - (ss_offset + ss_size));
  2086. }
  2087. }
  2088. else {
  2089. EMIT_BUF(data_section->data, data_section->size);
  2090. }
  2091. }
  2092. if (offset - *p_offset
  2093. != get_object_data_section_info_size(comp_ctx, obj_data)) {
  2094. aot_set_last_error("emit object data section info failed.");
  2095. return false;
  2096. }
  2097. *p_offset = offset;
  2098. return true;
  2099. }
  2100. static bool
  2101. aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2102. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  2103. AOTObjectData *obj_data)
  2104. {
  2105. uint32 section_size =
  2106. get_init_data_section_size(comp_ctx, comp_data, obj_data);
  2107. uint32 offset = *p_offset;
  2108. *p_offset = offset = align_uint(offset, 4);
  2109. EMIT_U32(AOT_SECTION_TYPE_INIT_DATA);
  2110. EMIT_U32(section_size);
  2111. if (!aot_emit_mem_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data)
  2112. || !aot_emit_table_info(buf, buf_end, &offset, comp_ctx, comp_data,
  2113. obj_data)
  2114. || !aot_emit_type_info(buf, buf_end, &offset, comp_ctx, comp_data,
  2115. obj_data)
  2116. || !aot_emit_import_global_info(buf, buf_end, &offset, comp_ctx,
  2117. comp_data, obj_data)
  2118. || !aot_emit_global_info(buf, buf_end, &offset, comp_ctx, comp_data,
  2119. obj_data)
  2120. || !aot_emit_import_func_info(buf, buf_end, &offset, comp_ctx,
  2121. comp_data, obj_data))
  2122. return false;
  2123. offset = align_uint(offset, 4);
  2124. EMIT_U32(comp_data->func_count);
  2125. EMIT_U32(comp_data->start_func_index);
  2126. EMIT_U32(comp_data->aux_data_end_global_index);
  2127. EMIT_U64(comp_data->aux_data_end);
  2128. EMIT_U32(comp_data->aux_heap_base_global_index);
  2129. EMIT_U64(comp_data->aux_heap_base);
  2130. EMIT_U32(comp_data->aux_stack_top_global_index);
  2131. EMIT_U64(comp_data->aux_stack_bottom);
  2132. EMIT_U32(comp_data->aux_stack_size);
  2133. if (!aot_emit_object_data_section_info(buf, buf_end, &offset, comp_ctx,
  2134. obj_data))
  2135. return false;
  2136. if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
  2137. aot_set_last_error("emit init data section failed.");
  2138. return false;
  2139. }
  2140. *p_offset = offset;
  2141. return true;
  2142. }
  2143. static bool
  2144. aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2145. AOTCompData *comp_data, AOTObjectData *obj_data)
  2146. {
  2147. uint32 section_size = get_text_section_size(obj_data);
  2148. uint32 offset = *p_offset;
  2149. uint8 placeholder = 0;
  2150. AOTRelocationGroup *relocation_group;
  2151. AOTRelocation *relocation;
  2152. uint32 i, j, relocation_count;
  2153. uint8 *text;
  2154. *p_offset = offset = align_uint(offset, 4);
  2155. EMIT_U32(AOT_SECTION_TYPE_TEXT);
  2156. EMIT_U32(section_size);
  2157. EMIT_U32(obj_data->literal_size);
  2158. if (obj_data->literal_size > 0) {
  2159. EMIT_BUF(obj_data->literal, obj_data->literal_size);
  2160. while (offset & 3)
  2161. EMIT_BUF(&placeholder, 1);
  2162. }
  2163. text = buf + offset;
  2164. if (obj_data->text_size > 0) {
  2165. EMIT_BUF(obj_data->text, obj_data->text_size);
  2166. while (offset & 3)
  2167. EMIT_BUF(&placeholder, 1);
  2168. }
  2169. if (obj_data->text_unlikely_size > 0) {
  2170. EMIT_BUF(obj_data->text_unlikely, obj_data->text_unlikely_size);
  2171. while (offset & 3)
  2172. EMIT_BUF(&placeholder, 1);
  2173. }
  2174. if (obj_data->text_hot_size > 0) {
  2175. EMIT_BUF(obj_data->text_hot, obj_data->text_hot_size);
  2176. while (offset & 3)
  2177. EMIT_BUF(&placeholder, 1);
  2178. }
  2179. if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
  2180. aot_set_last_error("emit text section failed.");
  2181. return false;
  2182. }
  2183. /* apply relocations to aot_func_internal#n in text section for
  2184. windows platform */
  2185. if ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6)
  2186. /* Windows AOT_COFF64_BIN_TYPE */
  2187. && obj_data->target_info.bin_type == 6)
  2188. || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4)
  2189. /* Windows AOT_COFF32_BIN_TYPE */
  2190. && obj_data->target_info.bin_type == 4)) {
  2191. relocation_group = obj_data->relocation_groups;
  2192. for (i = 0; i < obj_data->relocation_group_count;
  2193. i++, relocation_group++) {
  2194. /* relocation in text section */
  2195. if ((!strcmp(relocation_group->section_name, ".text")
  2196. || !strcmp(relocation_group->section_name, ".ltext"))) {
  2197. relocation = relocation_group->relocations;
  2198. relocation_count = relocation_group->relocation_count;
  2199. for (j = 0; j < relocation_count; j++) {
  2200. /* relocation to aot_func_internal#n */
  2201. const char *name = relocation->symbol_name;
  2202. if (str_starts_with(name, AOT_FUNC_INTERNAL_PREFIX)
  2203. && ((obj_data->target_info.bin_type
  2204. == 6 /* AOT_COFF64_BIN_TYPE */
  2205. && relocation->relocation_type
  2206. == 4 /* IMAGE_REL_AMD64_REL32 */)
  2207. || (obj_data->target_info.bin_type
  2208. == 4 /* AOT_COFF32_BIN_TYPE */
  2209. && relocation->relocation_type
  2210. == 20 /* IMAGE_REL_I386_REL32 */))) {
  2211. uint32 func_idx =
  2212. atoi(name + strlen(AOT_FUNC_INTERNAL_PREFIX));
  2213. uint64 text_offset, reloc_offset, reloc_addend;
  2214. bh_assert(func_idx < obj_data->func_count);
  2215. text_offset = obj_data->funcs[func_idx]
  2216. .text_offset_of_aot_func_internal;
  2217. reloc_offset = relocation->relocation_offset;
  2218. reloc_addend = relocation->relocation_addend;
  2219. /* S + A - P */
  2220. *(uint32 *)(text + reloc_offset) =
  2221. (uint32)(text_offset + reloc_addend - reloc_offset
  2222. - 4);
  2223. /* remove current relocation as it has been applied */
  2224. if (j < relocation_count - 1) {
  2225. uint32 move_size =
  2226. (uint32)(sizeof(AOTRelocation)
  2227. * (relocation_count - 1 - j));
  2228. bh_memmove_s(relocation, move_size, relocation + 1,
  2229. move_size);
  2230. }
  2231. relocation_group->relocation_count--;
  2232. }
  2233. else {
  2234. relocation++;
  2235. }
  2236. }
  2237. }
  2238. }
  2239. }
  2240. *p_offset = offset;
  2241. return true;
  2242. }
  2243. #if WASM_ENABLE_GC != 0
  2244. static bool
  2245. aot_emit_ref_flag(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2246. uint8 pointer_size, int8 type)
  2247. {
  2248. uint32 j, offset = *p_offset;
  2249. uint16 value_type_cell_num;
  2250. if (wasm_is_type_reftype(type) && !wasm_is_reftype_i31ref(type)) {
  2251. EMIT_U8(1);
  2252. if (pointer_size == sizeof(uint64))
  2253. EMIT_U8(1);
  2254. }
  2255. else {
  2256. value_type_cell_num = wasm_value_type_cell_num(type);
  2257. for (j = 0; j < value_type_cell_num; j++)
  2258. EMIT_U8(0);
  2259. }
  2260. *p_offset = offset;
  2261. return true;
  2262. }
  2263. #endif
  2264. static bool
  2265. aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2266. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  2267. AOTObjectData *obj_data)
  2268. {
  2269. uint32 section_size = get_func_section_size(comp_ctx, comp_data, obj_data);
  2270. uint32 i, offset = *p_offset;
  2271. AOTObjectFunc *func = obj_data->funcs;
  2272. AOTFunc **funcs = comp_data->funcs;
  2273. *p_offset = offset = align_uint(offset, 4);
  2274. EMIT_U32(AOT_SECTION_TYPE_FUNCTION);
  2275. EMIT_U32(section_size);
  2276. for (i = 0; i < obj_data->func_count; i++, func++) {
  2277. if (is_32bit_binary(obj_data))
  2278. EMIT_U32(func->text_offset);
  2279. else
  2280. EMIT_U64(func->text_offset);
  2281. }
  2282. for (i = 0; i < comp_data->func_count; i++)
  2283. EMIT_U32(funcs[i]->func_type_index);
  2284. for (i = 0; i < comp_data->func_count; i++) {
  2285. uint32 max_local_cell_num =
  2286. funcs[i]->param_cell_num + funcs[i]->local_cell_num;
  2287. EMIT_U32(max_local_cell_num);
  2288. }
  2289. for (i = 0; i < comp_data->func_count; i++)
  2290. EMIT_U32(funcs[i]->max_stack_cell_num);
  2291. #if WASM_ENABLE_GC != 0
  2292. if (comp_ctx->enable_gc) {
  2293. /* emit func_local_ref_flag arrays for both import and AOTed funcs */
  2294. AOTFuncType *func_type;
  2295. uint32 j, local_ref_flags_cell_num, paddings;
  2296. for (i = 0; i < comp_data->import_func_count; i++) {
  2297. func_type = comp_data->import_funcs[i].func_type;
  2298. /* recalculate cell_num based on target pointer size */
  2299. local_ref_flags_cell_num = 0;
  2300. for (j = 0; j < func_type->param_count; j++) {
  2301. local_ref_flags_cell_num += wasm_value_type_cell_num_internal(
  2302. func_type->types[j], comp_ctx->pointer_size);
  2303. }
  2304. paddings =
  2305. local_ref_flags_cell_num < 2 ? 2 - local_ref_flags_cell_num : 0;
  2306. local_ref_flags_cell_num =
  2307. local_ref_flags_cell_num > 2 ? local_ref_flags_cell_num : 2;
  2308. offset = align_uint(offset, 4);
  2309. EMIT_U32(local_ref_flags_cell_num);
  2310. for (j = 0; j < func_type->param_count; j++) {
  2311. if (!aot_emit_ref_flag(buf, buf_end, &offset,
  2312. comp_ctx->pointer_size,
  2313. func_type->types[j]))
  2314. return false;
  2315. }
  2316. for (j = 0; j < paddings; j++)
  2317. EMIT_U8(0);
  2318. }
  2319. for (i = 0; i < comp_data->func_count; i++) {
  2320. func_type = funcs[i]->func_type;
  2321. local_ref_flags_cell_num =
  2322. funcs[i]->param_cell_num + funcs[i]->local_cell_num;
  2323. offset = align_uint(offset, 4);
  2324. EMIT_U32(local_ref_flags_cell_num);
  2325. /* emit local_ref_flag for param variables */
  2326. for (j = 0; j < func_type->param_count; j++) {
  2327. if (!aot_emit_ref_flag(buf, buf_end, &offset,
  2328. comp_ctx->pointer_size,
  2329. func_type->types[j]))
  2330. return false;
  2331. }
  2332. /* emit local_ref_flag for local variables */
  2333. for (j = 0; j < funcs[i]->local_count; j++) {
  2334. if (!aot_emit_ref_flag(buf, buf_end, &offset,
  2335. comp_ctx->pointer_size,
  2336. funcs[i]->local_types_wp[j]))
  2337. return false;
  2338. }
  2339. }
  2340. }
  2341. #endif /* end of WASM_ENABLE_GC != 0 */
  2342. if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
  2343. aot_set_last_error("emit function section failed.");
  2344. return false;
  2345. }
  2346. *p_offset = offset;
  2347. return true;
  2348. }
  2349. static bool
  2350. aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2351. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  2352. AOTObjectData *obj_data)
  2353. {
  2354. uint32 section_size = get_export_section_size(comp_ctx, comp_data);
  2355. AOTExport *export = comp_data->wasm_module->exports;
  2356. uint32 export_count = comp_data->wasm_module->export_count;
  2357. uint32 i, offset = *p_offset;
  2358. *p_offset = offset = align_uint(offset, 4);
  2359. EMIT_U32(AOT_SECTION_TYPE_EXPORT);
  2360. EMIT_U32(section_size);
  2361. EMIT_U32(export_count);
  2362. for (i = 0; i < export_count; i++, export ++) {
  2363. offset = align_uint(offset, 4);
  2364. EMIT_U32(export->index);
  2365. EMIT_U8(export->kind);
  2366. EMIT_U8(0);
  2367. EMIT_STR(export->name);
  2368. }
  2369. if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
  2370. aot_set_last_error("emit export section failed.");
  2371. return false;
  2372. }
  2373. *p_offset = offset;
  2374. return true;
  2375. }
  2376. static bool
  2377. aot_emit_relocation_symbol_table(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2378. AOTCompContext *comp_ctx,
  2379. AOTCompData *comp_data,
  2380. AOTObjectData *obj_data)
  2381. {
  2382. uint32 symbol_offset = 0, total_string_len = 0;
  2383. uint32 offset = *p_offset;
  2384. AOTSymbolNode *sym;
  2385. EMIT_U32(obj_data->symbol_list.len);
  2386. /* emit symbol offsets */
  2387. sym = (AOTSymbolNode *)(obj_data->symbol_list.head);
  2388. while (sym) {
  2389. EMIT_U32(symbol_offset);
  2390. /* string_len + str[0 .. string_len - 1] */
  2391. symbol_offset += get_string_size(comp_ctx, sym->symbol);
  2392. symbol_offset = align_uint(symbol_offset, 2);
  2393. sym = sym->next;
  2394. }
  2395. /* emit total string len */
  2396. total_string_len = symbol_offset;
  2397. EMIT_U32(total_string_len);
  2398. /* emit symbols */
  2399. sym = (AOTSymbolNode *)(obj_data->symbol_list.head);
  2400. while (sym) {
  2401. EMIT_STR(sym->symbol);
  2402. offset = align_uint(offset, 2);
  2403. sym = sym->next;
  2404. }
  2405. *p_offset = offset;
  2406. return true;
  2407. }
  2408. static bool
  2409. aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2410. AOTCompContext *comp_ctx, AOTCompData *comp_data,
  2411. AOTObjectData *obj_data)
  2412. {
  2413. uint32 section_size = get_relocation_section_size(comp_ctx, obj_data);
  2414. uint32 i, offset = *p_offset;
  2415. AOTRelocationGroup *relocation_group = obj_data->relocation_groups;
  2416. if (section_size == (uint32)-1)
  2417. return false;
  2418. *p_offset = offset = align_uint(offset, 4);
  2419. EMIT_U32(AOT_SECTION_TYPE_RELOCATION);
  2420. EMIT_U32(section_size);
  2421. aot_emit_relocation_symbol_table(buf, buf_end, &offset, comp_ctx, comp_data,
  2422. obj_data);
  2423. offset = align_uint(offset, 4);
  2424. EMIT_U32(obj_data->relocation_group_count);
  2425. /* emit each relocation group */
  2426. for (i = 0; i < obj_data->relocation_group_count; i++, relocation_group++) {
  2427. AOTRelocation *relocation = relocation_group->relocations;
  2428. uint32 j;
  2429. offset = align_uint(offset, 4);
  2430. EMIT_U32(relocation_group->name_index);
  2431. offset = align_uint(offset, 4);
  2432. EMIT_U32(relocation_group->relocation_count);
  2433. /* emit each relocation */
  2434. for (j = 0; j < relocation_group->relocation_count; j++, relocation++) {
  2435. offset = align_uint(offset, 4);
  2436. if (is_32bit_binary(obj_data)) {
  2437. EMIT_U32(relocation->relocation_offset);
  2438. EMIT_U32(relocation->relocation_addend);
  2439. }
  2440. else {
  2441. EMIT_U64(relocation->relocation_offset);
  2442. EMIT_U64(relocation->relocation_addend);
  2443. }
  2444. EMIT_U32(relocation->relocation_type);
  2445. EMIT_U32(relocation->symbol_index);
  2446. }
  2447. }
  2448. if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
  2449. aot_set_last_error("emit relocation section failed.");
  2450. return false;
  2451. }
  2452. *p_offset = offset;
  2453. return true;
  2454. }
  2455. static bool
  2456. aot_emit_native_symbol(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2457. AOTCompContext *comp_ctx)
  2458. {
  2459. uint32 offset = *p_offset;
  2460. AOTNativeSymbol *sym = NULL;
  2461. if (bh_list_length(&comp_ctx->native_symbols) == 0)
  2462. /* emit only when there are native symbols */
  2463. return true;
  2464. *p_offset = offset = align_uint(offset, 4);
  2465. EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
  2466. /* sub section id + symbol count + symbol list */
  2467. EMIT_U32(sizeof(uint32) * 2 + get_native_symbol_list_size(comp_ctx));
  2468. EMIT_U32(AOT_CUSTOM_SECTION_NATIVE_SYMBOL);
  2469. EMIT_U32(bh_list_length(&comp_ctx->native_symbols));
  2470. sym = bh_list_first_elem(&comp_ctx->native_symbols);
  2471. while (sym) {
  2472. offset = align_uint(offset, 2);
  2473. EMIT_STR(sym->symbol);
  2474. sym = bh_list_elem_next(sym);
  2475. }
  2476. *p_offset = offset;
  2477. return true;
  2478. }
  2479. #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
  2480. static bool
  2481. aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2482. AOTCompData *comp_data, AOTCompContext *comp_ctx)
  2483. {
  2484. uint32 offset = *p_offset;
  2485. if (comp_data->aot_name_section_size == 0)
  2486. return true;
  2487. offset = align_uint(offset, 4);
  2488. EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
  2489. /* sub section id + name section size */
  2490. EMIT_U32(sizeof(uint32) * 1 + comp_data->aot_name_section_size);
  2491. EMIT_U32(AOT_CUSTOM_SECTION_NAME);
  2492. bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf),
  2493. comp_data->aot_name_section_buf,
  2494. (uint32)comp_data->aot_name_section_size);
  2495. offset += comp_data->aot_name_section_size;
  2496. *p_offset = offset;
  2497. LOG_DEBUG("emit name section");
  2498. return true;
  2499. }
  2500. #endif
  2501. #if WASM_ENABLE_STRINGREF != 0
  2502. static bool
  2503. aot_emit_string_literal_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2504. AOTCompData *comp_data,
  2505. AOTCompContext *comp_ctx)
  2506. {
  2507. uint32 string_count = comp_data->string_literal_count;
  2508. if (string_count > 0) {
  2509. uint32 offset = *p_offset;
  2510. uint32 i;
  2511. *p_offset = offset = align_uint(offset, 4);
  2512. EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
  2513. /* sub section id + string literal section size */
  2514. EMIT_U32(sizeof(uint32) * 1
  2515. + get_string_literal_section_size(comp_ctx, comp_data));
  2516. EMIT_U32(AOT_CUSTOM_SECTION_STRING_LITERAL);
  2517. /* reserved */
  2518. EMIT_U32(0);
  2519. /* string literal count */
  2520. EMIT_U32(string_count);
  2521. for (i = 0; i < string_count; i++) {
  2522. EMIT_U32(comp_data->string_literal_lengths_wp[i]);
  2523. }
  2524. for (i = 0; i < string_count; i++) {
  2525. uint32 string_length = comp_data->string_literal_lengths_wp[i];
  2526. bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf),
  2527. comp_data->string_literal_ptrs_wp[i], string_length);
  2528. offset += string_length;
  2529. }
  2530. *p_offset = offset;
  2531. }
  2532. return true;
  2533. }
  2534. #endif /* end of WASM_ENABLE_STRINGREF != 0 */
  2535. static bool
  2536. aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
  2537. AOTCompData *comp_data, AOTCompContext *comp_ctx)
  2538. {
  2539. #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
  2540. uint32 offset = *p_offset, i;
  2541. for (i = 0; i < comp_ctx->custom_sections_count; i++) {
  2542. const char *section_name = comp_ctx->custom_sections_wp[i];
  2543. const uint8 *content = NULL;
  2544. uint32 length = 0;
  2545. if (strcmp(section_name, "name") == 0) {
  2546. *p_offset = offset;
  2547. if (!aot_emit_name_section(buf, buf_end, p_offset, comp_data,
  2548. comp_ctx))
  2549. return false;
  2550. offset = *p_offset;
  2551. continue;
  2552. }
  2553. content = wasm_loader_get_custom_section(comp_data->wasm_module,
  2554. section_name, &length);
  2555. if (!content) {
  2556. /* Warning has been reported during calculating size */
  2557. continue;
  2558. }
  2559. offset = align_uint(offset, 4);
  2560. EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
  2561. /* sub section id + content */
  2562. EMIT_U32(sizeof(uint32) * 1 + get_string_size(comp_ctx, section_name)
  2563. + length);
  2564. EMIT_U32(AOT_CUSTOM_SECTION_RAW);
  2565. EMIT_STR(section_name);
  2566. bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf), content,
  2567. length);
  2568. offset += length;
  2569. }
  2570. *p_offset = offset;
  2571. #endif
  2572. return true;
  2573. }
  2574. typedef uint32 U32;
  2575. typedef int32 I32;
  2576. typedef uint16 U16;
  2577. typedef uint8 U8;
  2578. struct coff_hdr {
  2579. U16 u16Machine;
  2580. U16 u16NumSections;
  2581. U32 u32DateTimeStamp;
  2582. U32 u32SymTblPtr;
  2583. U32 u32NumSymbols;
  2584. U16 u16PeHdrSize;
  2585. U16 u16Characs;
  2586. };
  2587. #define E_TYPE_REL 1
  2588. #define E_TYPE_XIP 4
  2589. #define IMAGE_FILE_MACHINE_AMD64 0x8664
  2590. #define IMAGE_FILE_MACHINE_I386 0x014c
  2591. #define IMAGE_FILE_MACHINE_IA64 0x0200
  2592. #define AOT_COFF32_BIN_TYPE 4 /* 32-bit little endian */
  2593. #define AOT_COFF64_BIN_TYPE 6 /* 64-bit little endian */
  2594. #define EI_NIDENT 16
  2595. typedef uint32 elf32_word;
  2596. typedef int32 elf32_sword;
  2597. typedef uint16 elf32_half;
  2598. typedef uint32 elf32_off;
  2599. typedef uint32 elf32_addr;
  2600. struct elf32_ehdr {
  2601. unsigned char e_ident[EI_NIDENT]; /* ident bytes */
  2602. elf32_half e_type; /* file type */
  2603. elf32_half e_machine; /* target machine */
  2604. elf32_word e_version; /* file version */
  2605. elf32_addr e_entry; /* start address */
  2606. elf32_off e_phoff; /* phdr file offset */
  2607. elf32_off e_shoff; /* shdr file offset */
  2608. elf32_word e_flags; /* file flags */
  2609. elf32_half e_ehsize; /* sizeof ehdr */
  2610. elf32_half e_phentsize; /* sizeof phdr */
  2611. elf32_half e_phnum; /* number phdrs */
  2612. elf32_half e_shentsize; /* sizeof shdr */
  2613. elf32_half e_shnum; /* number shdrs */
  2614. elf32_half e_shstrndx; /* shdr string index */
  2615. };
  2616. struct elf32_rel {
  2617. elf32_addr r_offset;
  2618. elf32_word r_info;
  2619. } elf32_rel;
  2620. struct elf32_rela {
  2621. elf32_addr r_offset;
  2622. elf32_word r_info;
  2623. elf32_sword r_addend;
  2624. } elf32_rela;
  2625. typedef uint32 elf64_word;
  2626. typedef int32 elf64_sword;
  2627. typedef uint64 elf64_xword;
  2628. typedef int64 elf64_sxword;
  2629. typedef uint16 elf64_half;
  2630. typedef uint64 elf64_off;
  2631. typedef uint64 elf64_addr;
  2632. struct elf64_ehdr {
  2633. unsigned char e_ident[EI_NIDENT]; /* ident bytes */
  2634. elf64_half e_type; /* file type */
  2635. elf64_half e_machine; /* target machine */
  2636. elf64_word e_version; /* file version */
  2637. elf64_addr e_entry; /* start address */
  2638. elf64_off e_phoff; /* phdr file offset */
  2639. elf64_off e_shoff; /* shdr file offset */
  2640. elf64_word e_flags; /* file flags */
  2641. elf64_half e_ehsize; /* sizeof ehdr */
  2642. elf64_half e_phentsize; /* sizeof phdr */
  2643. elf64_half e_phnum; /* number phdrs */
  2644. elf64_half e_shentsize; /* sizeof shdr */
  2645. elf64_half e_shnum; /* number shdrs */
  2646. elf64_half e_shstrndx; /* shdr string index */
  2647. };
  2648. typedef struct elf64_rel {
  2649. elf64_addr r_offset;
  2650. elf64_xword r_info;
  2651. } elf64_rel;
  2652. typedef struct elf64_rela {
  2653. elf64_addr r_offset;
  2654. elf64_xword r_info;
  2655. elf64_sxword r_addend;
  2656. } elf64_rela;
  2657. #define SET_TARGET_INFO_VALUE(f, val, type, little) \
  2658. do { \
  2659. type tmp = val; \
  2660. if ((little && !is_little_endian()) \
  2661. || (!little && is_little_endian())) \
  2662. exchange_##type((uint8 *)&tmp); \
  2663. obj_data->target_info.f = tmp; \
  2664. } while (0)
  2665. #define SET_TARGET_INFO_FIELD(f, v, type, little) \
  2666. SET_TARGET_INFO_VALUE(f, elf_header->v, type, little)
  2667. /* in windows 32, the symbol name may start with '_' */
  2668. static char *
  2669. LLVMGetSymbolNameAndUnDecorate(LLVMSymbolIteratorRef si,
  2670. AOTTargetInfo target_info)
  2671. {
  2672. char *original_name = (char *)LLVMGetSymbolName(si);
  2673. if (!original_name) {
  2674. return NULL;
  2675. }
  2676. if (target_info.bin_type != AOT_COFF32_BIN_TYPE) {
  2677. return original_name;
  2678. }
  2679. if (*original_name == '_') {
  2680. return ++original_name;
  2681. }
  2682. return original_name;
  2683. }
  2684. static bool
  2685. aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
  2686. {
  2687. LLVMBinaryType bin_type = LLVMBinaryGetType(obj_data->binary);
  2688. const uint8 *elf_buf = (uint8 *)LLVMGetBufferStart(obj_data->mem_buf);
  2689. uint32 elf_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
  2690. if (bin_type != LLVMBinaryTypeCOFF && bin_type != LLVMBinaryTypeELF32L
  2691. && bin_type != LLVMBinaryTypeELF32B && bin_type != LLVMBinaryTypeELF64L
  2692. && bin_type != LLVMBinaryTypeELF64B
  2693. && bin_type != LLVMBinaryTypeMachO32L
  2694. && bin_type != LLVMBinaryTypeMachO32B
  2695. && bin_type != LLVMBinaryTypeMachO64L
  2696. && bin_type != LLVMBinaryTypeMachO64B) {
  2697. aot_set_last_error("invalid llvm binary bin_type.");
  2698. return false;
  2699. }
  2700. obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L;
  2701. if (bin_type == LLVMBinaryTypeCOFF) {
  2702. struct coff_hdr *coff_header;
  2703. if (!elf_buf || elf_size < sizeof(struct coff_hdr)) {
  2704. aot_set_last_error("invalid coff_hdr buffer.");
  2705. return false;
  2706. }
  2707. coff_header = (struct coff_hdr *)elf_buf;
  2708. /* Emit eXecute In Place file type while in indirect mode */
  2709. if (comp_ctx->is_indirect_mode)
  2710. obj_data->target_info.e_type = E_TYPE_XIP;
  2711. else
  2712. obj_data->target_info.e_type = E_TYPE_REL;
  2713. obj_data->target_info.e_machine = coff_header->u16Machine;
  2714. obj_data->target_info.e_version = 1;
  2715. obj_data->target_info.e_flags = 0;
  2716. if (coff_header->u16Machine == IMAGE_FILE_MACHINE_AMD64
  2717. || coff_header->u16Machine == IMAGE_FILE_MACHINE_IA64)
  2718. obj_data->target_info.bin_type = AOT_COFF64_BIN_TYPE;
  2719. else if (coff_header->u16Machine == IMAGE_FILE_MACHINE_I386)
  2720. obj_data->target_info.bin_type = AOT_COFF32_BIN_TYPE;
  2721. }
  2722. else if (bin_type == LLVMBinaryTypeELF32L
  2723. || bin_type == LLVMBinaryTypeELF32B) {
  2724. struct elf32_ehdr *elf_header;
  2725. bool is_little_bin = bin_type == LLVMBinaryTypeELF32L;
  2726. uint16 e_type;
  2727. if (!elf_buf || elf_size < sizeof(struct elf32_ehdr)) {
  2728. aot_set_last_error("invalid elf32 buffer.");
  2729. return false;
  2730. }
  2731. elf_header = (struct elf32_ehdr *)elf_buf;
  2732. e_type = elf_header->e_type;
  2733. /* Emit eXecute In Place file type while in indirect mode */
  2734. if (comp_ctx->is_indirect_mode)
  2735. e_type = E_TYPE_XIP;
  2736. SET_TARGET_INFO_VALUE(e_type, e_type, uint16, is_little_bin);
  2737. SET_TARGET_INFO_FIELD(e_machine, e_machine, uint16, is_little_bin);
  2738. SET_TARGET_INFO_FIELD(e_version, e_version, uint32, is_little_bin);
  2739. SET_TARGET_INFO_FIELD(e_flags, e_flags, uint32, is_little_bin);
  2740. }
  2741. else if (bin_type == LLVMBinaryTypeELF64L
  2742. || bin_type == LLVMBinaryTypeELF64B) {
  2743. struct elf64_ehdr *elf_header;
  2744. bool is_little_bin = bin_type == LLVMBinaryTypeELF64L;
  2745. uint16 e_type;
  2746. if (!elf_buf || elf_size < sizeof(struct elf64_ehdr)) {
  2747. aot_set_last_error("invalid elf64 buffer.");
  2748. return false;
  2749. }
  2750. elf_header = (struct elf64_ehdr *)elf_buf;
  2751. e_type = elf_header->e_type;
  2752. /* Emit eXecute In Place file type while in indirect mode */
  2753. if (comp_ctx->is_indirect_mode)
  2754. e_type = E_TYPE_XIP;
  2755. SET_TARGET_INFO_VALUE(e_type, e_type, uint16, is_little_bin);
  2756. SET_TARGET_INFO_FIELD(e_machine, e_machine, uint16, is_little_bin);
  2757. SET_TARGET_INFO_FIELD(e_version, e_version, uint32, is_little_bin);
  2758. SET_TARGET_INFO_FIELD(e_flags, e_flags, uint32, is_little_bin);
  2759. }
  2760. else if (bin_type == LLVMBinaryTypeMachO32L
  2761. || bin_type == LLVMBinaryTypeMachO32B) {
  2762. /* TODO: parse file type of Mach-O 32 */
  2763. aot_set_last_error("invalid llvm binary bin_type.");
  2764. return false;
  2765. }
  2766. else if (bin_type == LLVMBinaryTypeMachO64L
  2767. || bin_type == LLVMBinaryTypeMachO64B) {
  2768. /* TODO: parse file type of Mach-O 64 */
  2769. aot_set_last_error("invalid llvm binary bin_type.");
  2770. return false;
  2771. }
  2772. bh_assert(sizeof(obj_data->target_info.arch)
  2773. == sizeof(comp_ctx->target_arch));
  2774. bh_memcpy_s(obj_data->target_info.arch, sizeof(obj_data->target_info.arch),
  2775. comp_ctx->target_arch, sizeof(comp_ctx->target_arch));
  2776. return true;
  2777. }
  2778. static bool
  2779. aot_resolve_text(AOTObjectData *obj_data)
  2780. {
  2781. #if WASM_ENABLE_DEBUG_AOT != 0
  2782. LLVMBinaryType bin_type = LLVMBinaryGetType(obj_data->binary);
  2783. if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF64L) {
  2784. obj_data->text = (char *)LLVMGetBufferStart(obj_data->mem_buf);
  2785. obj_data->text_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
  2786. }
  2787. else
  2788. #endif
  2789. {
  2790. LLVMSectionIteratorRef sec_itr;
  2791. char *name;
  2792. if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  2793. aot_set_last_error("llvm get section iterator failed.");
  2794. return false;
  2795. }
  2796. while (
  2797. !LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
  2798. if ((name = (char *)LLVMGetSectionName(sec_itr))) {
  2799. if (!strcmp(name, ".text") || !strcmp(name, ".ltext")) {
  2800. obj_data->text = (char *)LLVMGetSectionContents(sec_itr);
  2801. obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr);
  2802. }
  2803. else if (!strcmp(name, ".text.unlikely.")
  2804. || !strcmp(name, ".ltext.unlikely.")) {
  2805. obj_data->text_unlikely =
  2806. (char *)LLVMGetSectionContents(sec_itr);
  2807. obj_data->text_unlikely_size =
  2808. (uint32)LLVMGetSectionSize(sec_itr);
  2809. }
  2810. else if (!strcmp(name, ".text.hot.")
  2811. || !strcmp(name, ".ltext.hot.")) {
  2812. obj_data->text_hot =
  2813. (char *)LLVMGetSectionContents(sec_itr);
  2814. obj_data->text_hot_size =
  2815. (uint32)LLVMGetSectionSize(sec_itr);
  2816. }
  2817. }
  2818. LLVMMoveToNextSection(sec_itr);
  2819. }
  2820. LLVMDisposeSectionIterator(sec_itr);
  2821. }
  2822. return true;
  2823. }
  2824. static bool
  2825. aot_resolve_literal(AOTObjectData *obj_data)
  2826. {
  2827. LLVMSectionIteratorRef sec_itr;
  2828. char *name;
  2829. if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  2830. aot_set_last_error("llvm get section iterator failed.");
  2831. return false;
  2832. }
  2833. while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
  2834. if ((name = (char *)LLVMGetSectionName(sec_itr))
  2835. && !strcmp(name, ".literal")) {
  2836. obj_data->literal = (char *)LLVMGetSectionContents(sec_itr);
  2837. obj_data->literal_size = (uint32)LLVMGetSectionSize(sec_itr);
  2838. break;
  2839. }
  2840. LLVMMoveToNextSection(sec_itr);
  2841. }
  2842. LLVMDisposeSectionIterator(sec_itr);
  2843. return true;
  2844. }
  2845. static bool
  2846. get_relocations_count(LLVMSectionIteratorRef sec_itr, uint32 *p_count);
  2847. static bool
  2848. is_data_section(AOTObjectData *obj_data, LLVMSectionIteratorRef sec_itr,
  2849. char *section_name)
  2850. {
  2851. uint32 relocation_count = 0;
  2852. return (!strcmp(section_name, ".data") || !strcmp(section_name, ".sdata")
  2853. || !strcmp(section_name, ".rodata")
  2854. #if LLVM_VERSION_MAJOR >= 19
  2855. /* https://github.com/llvm/llvm-project/pull/82214 */
  2856. || !strcmp(section_name, ".srodata")
  2857. #endif
  2858. /* ".rodata.cst4/8/16/.." */
  2859. || !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst"))
  2860. #if LLVM_VERSION_MAJOR >= 19
  2861. /* https://github.com/llvm/llvm-project/pull/82214
  2862. * ".srodata.cst4/8/16/.." */
  2863. || !strncmp(section_name, ".srodata.cst", strlen(".srodata.cst"))
  2864. #endif
  2865. /* ".rodata.strn.m" */
  2866. || !strncmp(section_name, ".rodata.str", strlen(".rodata.str"))
  2867. || (!strcmp(section_name, ".rdata")
  2868. && get_relocations_count(sec_itr, &relocation_count)
  2869. && relocation_count > 0)
  2870. || !strcmp(section_name, aot_stack_sizes_section_name)
  2871. || (obj_data->comp_ctx->enable_llvm_pgo
  2872. && (!strncmp(section_name, "__llvm_prf_cnts", 15)
  2873. || !strncmp(section_name, "__llvm_prf_data", 15)
  2874. || !strncmp(section_name, "__llvm_prf_names", 16))));
  2875. }
  2876. static bool
  2877. get_object_data_sections_count(AOTObjectData *obj_data, uint32 *p_count)
  2878. {
  2879. LLVMSectionIteratorRef sec_itr;
  2880. char *name;
  2881. uint32 count = 0;
  2882. if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  2883. aot_set_last_error("llvm get section iterator failed.");
  2884. return false;
  2885. }
  2886. while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
  2887. if ((name = (char *)LLVMGetSectionName(sec_itr))
  2888. && (is_data_section(obj_data, sec_itr, name))) {
  2889. count++;
  2890. }
  2891. LLVMMoveToNextSection(sec_itr);
  2892. }
  2893. LLVMDisposeSectionIterator(sec_itr);
  2894. *p_count = count;
  2895. return true;
  2896. }
  2897. static bool
  2898. aot_resolve_object_data_sections(AOTObjectData *obj_data)
  2899. {
  2900. LLVMSectionIteratorRef sec_itr;
  2901. char *name;
  2902. AOTObjectDataSection *data_section;
  2903. uint32 sections_count;
  2904. uint32 size;
  2905. if (!get_object_data_sections_count(obj_data, &sections_count)) {
  2906. return false;
  2907. }
  2908. if (sections_count > 0) {
  2909. uint32 llvm_prf_cnts_idx = 0, llvm_prf_data_idx = 0;
  2910. char buf[32];
  2911. size = (uint32)sizeof(AOTObjectDataSection) * sections_count;
  2912. if (!(data_section = obj_data->data_sections =
  2913. wasm_runtime_malloc(size))) {
  2914. aot_set_last_error("allocate memory for data sections failed.");
  2915. return false;
  2916. }
  2917. memset(obj_data->data_sections, 0, size);
  2918. obj_data->data_sections_count = sections_count;
  2919. if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  2920. aot_set_last_error("llvm get section iterator failed.");
  2921. return false;
  2922. }
  2923. while (
  2924. !LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
  2925. if ((name = (char *)LLVMGetSectionName(sec_itr))
  2926. && (is_data_section(obj_data, sec_itr, name))) {
  2927. data_section->name = name;
  2928. if (obj_data->comp_ctx->enable_llvm_pgo
  2929. && !strcmp(name, "__llvm_prf_cnts")) {
  2930. snprintf(buf, sizeof(buf), "%s%u", name,
  2931. llvm_prf_cnts_idx++);
  2932. size = (uint32)(strlen(buf) + 1);
  2933. if (!(data_section->name = wasm_runtime_malloc(size))) {
  2934. aot_set_last_error(
  2935. "allocate memory for data section name failed.");
  2936. return false;
  2937. }
  2938. bh_memcpy_s(data_section->name, size, buf, size);
  2939. data_section->is_name_allocated = true;
  2940. }
  2941. else if (obj_data->comp_ctx->enable_llvm_pgo
  2942. && !strcmp(name, "__llvm_prf_data")) {
  2943. snprintf(buf, sizeof(buf), "%s%u", name,
  2944. llvm_prf_data_idx++);
  2945. size = (uint32)(strlen(buf) + 1);
  2946. if (!(data_section->name = wasm_runtime_malloc(size))) {
  2947. aot_set_last_error(
  2948. "allocate memory for data section name failed.");
  2949. return false;
  2950. }
  2951. bh_memcpy_s(data_section->name, size, buf, size);
  2952. data_section->is_name_allocated = true;
  2953. }
  2954. else if (obj_data->comp_ctx->enable_llvm_pgo
  2955. && !strcmp(name, "__llvm_prf_bits")) {
  2956. LOG_WARNING("__llvm_prf_bits section is not supported and "
  2957. "shouldn't be used in PGO.");
  2958. return false;
  2959. }
  2960. if (obj_data->comp_ctx->enable_llvm_pgo
  2961. && !strcmp(name, "__llvm_prf_names")) {
  2962. data_section->data = (uint8 *)aot_compress_aot_func_names(
  2963. obj_data->comp_ctx, &data_section->size);
  2964. data_section->is_data_allocated = true;
  2965. }
  2966. else {
  2967. data_section->data =
  2968. (uint8 *)LLVMGetSectionContents(sec_itr);
  2969. data_section->size = (uint32)LLVMGetSectionSize(sec_itr);
  2970. }
  2971. data_section++;
  2972. }
  2973. LLVMMoveToNextSection(sec_itr);
  2974. }
  2975. LLVMDisposeSectionIterator(sec_itr);
  2976. }
  2977. return true;
  2978. }
  2979. static bool
  2980. read_stack_usage_file(const AOTCompContext *comp_ctx, const char *filename,
  2981. uint32 *sizes, uint32 count)
  2982. {
  2983. FILE *fp = NULL;
  2984. if (filename == NULL) {
  2985. aot_set_last_error("no stack usage file is specified.");
  2986. return false;
  2987. }
  2988. fp = fopen(filename, "r");
  2989. if (fp == NULL) {
  2990. LOG_ERROR("failed to open stack usage file: %s", filename);
  2991. goto fail;
  2992. }
  2993. /*
  2994. * the file consists of lines like:
  2995. *
  2996. * WASM Module:aot_func#9 72 static
  2997. */
  2998. const char *aot_func_prefix = AOT_FUNC_PREFIX;
  2999. const char *aot_func_internal_prefix = AOT_FUNC_INTERNAL_PREFIX;
  3000. uint32 precheck_found = 0;
  3001. uint32 precheck_stack_size_max = 0;
  3002. uint32 precheck_stack_size_min = UINT32_MAX;
  3003. uint32 found = 0;
  3004. while (true) {
  3005. const char *prefix;
  3006. char line[100];
  3007. char *cp = fgets(line, sizeof(line), fp);
  3008. char *fn;
  3009. char *colon;
  3010. uintmax_t func_idx;
  3011. uintmax_t sz;
  3012. int ret;
  3013. if (cp == NULL) {
  3014. break;
  3015. }
  3016. /*
  3017. * Note: strrchr (not strchr) because a module name can contain
  3018. * colons.
  3019. */
  3020. colon = strrchr(cp, ':');
  3021. if (colon == NULL) {
  3022. goto fail;
  3023. }
  3024. fn = strstr(colon, aot_func_prefix);
  3025. if (fn != NULL) {
  3026. prefix = aot_func_prefix;
  3027. }
  3028. else {
  3029. fn = strstr(colon, aot_func_internal_prefix);
  3030. if (fn == NULL) {
  3031. LOG_ERROR("failed to parse stack usage line: %s", cp);
  3032. goto fail;
  3033. }
  3034. prefix = aot_func_internal_prefix;
  3035. }
  3036. ret = sscanf(fn + strlen(prefix), "%ju %ju static", &func_idx, &sz);
  3037. if (ret != 2) {
  3038. goto fail;
  3039. }
  3040. if (sz > UINT32_MAX) {
  3041. goto fail;
  3042. }
  3043. if (func_idx > UINT32_MAX) {
  3044. goto fail;
  3045. }
  3046. if (func_idx >= count) {
  3047. goto fail;
  3048. }
  3049. if (prefix == aot_func_prefix) {
  3050. if (sz < precheck_stack_size_min) {
  3051. precheck_stack_size_min = (uint32)sz;
  3052. }
  3053. if (sz > precheck_stack_size_max) {
  3054. precheck_stack_size_max = (uint32)sz;
  3055. }
  3056. precheck_found++;
  3057. continue;
  3058. }
  3059. sizes[func_idx] = (uint32)sz;
  3060. found++;
  3061. }
  3062. fclose(fp);
  3063. if (precheck_found != count) {
  3064. LOG_ERROR("%" PRIu32 " precheck entries found while %" PRIu32
  3065. " entries are expected",
  3066. precheck_found, count);
  3067. return false;
  3068. }
  3069. if (found != count) {
  3070. /*
  3071. * LLVM seems to eliminate calls to an empty function
  3072. * (and eliminate the function) even if it's marked noinline.
  3073. */
  3074. LOG_VERBOSE("%" PRIu32 " entries found while %" PRIu32
  3075. " entries are expected. Maybe LLVM optimization eliminated "
  3076. "some functions.",
  3077. found, count);
  3078. }
  3079. if (precheck_stack_size_min != precheck_stack_size_max) {
  3080. /*
  3081. * Note: this is too strict.
  3082. *
  3083. * actually, the stack consumption of the precheck functions
  3084. * can depend on the type of them.
  3085. * that is, depending on various factors including
  3086. * calling conventions and compilers, a function with many
  3087. * parameters can consume more stack, even if it merely does
  3088. * a tail-call to another function.
  3089. */
  3090. bool musttail = aot_target_precheck_can_use_musttail(comp_ctx);
  3091. if (musttail) {
  3092. LOG_WARNING(
  3093. "precheck functions use variable amount of stack. (%" PRIu32
  3094. " - %" PRIu32 ")",
  3095. precheck_stack_size_min, precheck_stack_size_max);
  3096. }
  3097. else {
  3098. LOG_VERBOSE("precheck functions use %" PRIu32 " - %" PRIu32
  3099. " bytes of stack.",
  3100. precheck_stack_size_min, precheck_stack_size_max);
  3101. }
  3102. }
  3103. else {
  3104. LOG_VERBOSE("precheck functions use %" PRIu32 " bytes of stack.",
  3105. precheck_stack_size_max);
  3106. }
  3107. if (precheck_stack_size_max >= 1024) {
  3108. LOG_WARNING("precheck functions themselves consume relatively large "
  3109. "amount of stack (%" PRIu32
  3110. "). Please ensure the runtime has large enough "
  3111. "WASM_STACK_GUARD_SIZE.",
  3112. precheck_stack_size_max);
  3113. }
  3114. return true;
  3115. fail:
  3116. if (fp != NULL)
  3117. fclose(fp);
  3118. aot_set_last_error("failed to read stack usage file.");
  3119. return false;
  3120. }
  3121. static bool
  3122. aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
  3123. {
  3124. LLVMSectionIteratorRef sec_itr = NULL;
  3125. LLVMSymbolIteratorRef sym_itr;
  3126. const char *name;
  3127. if (!(sym_itr = LLVMObjectFileCopySymbolIterator(obj_data->binary))) {
  3128. aot_set_last_error("llvm get symbol iterator failed.");
  3129. return false;
  3130. }
  3131. while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) {
  3132. if ((name =
  3133. LLVMGetSymbolNameAndUnDecorate(sym_itr, obj_data->target_info))
  3134. && (!strcmp(name, aot_stack_sizes_alias_name))) {
  3135. #if 0 /* cf. https://github.com/llvm/llvm-project/issues/67765 */
  3136. uint64 sz = LLVMGetSymbolSize(sym_itr);
  3137. if (sz != sizeof(uint32) * obj_data->func_count
  3138. /* sz of COFF64/COFF32 is 0, ignore the check */
  3139. && obj_data->target_info.bin_type != AOT_COFF64_BIN_TYPE
  3140. && obj_data->target_info.bin_type != AOT_COFF32_BIN_TYPE) {
  3141. aot_set_last_error("stack_sizes had unexpected size.");
  3142. goto fail;
  3143. }
  3144. #endif
  3145. uint64 addr = LLVMGetSymbolAddress(sym_itr);
  3146. if (!(sec_itr =
  3147. LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  3148. aot_set_last_error("llvm get section iterator failed.");
  3149. goto fail;
  3150. }
  3151. LLVMMoveToContainingSection(sec_itr, sym_itr);
  3152. const char *sec_name = LLVMGetSectionName(sec_itr);
  3153. LOG_VERBOSE("stack_sizes found in section %s offset %" PRIu64 ".",
  3154. sec_name, addr);
  3155. if (strcmp(sec_name, aot_stack_sizes_section_name) || addr != 0) {
  3156. aot_set_last_error(
  3157. "stack_sizes found at an unexpected location.");
  3158. goto fail;
  3159. }
  3160. /*
  3161. * Note: We can't always modify stack_sizes in-place.
  3162. * E.g. When WAMRC_LLC_COMPILER is used, LLVM sometimes uses
  3163. * read-only mmap of the temporary file to back
  3164. * LLVMGetSectionContents.
  3165. */
  3166. const uint32 *ro_stack_sizes =
  3167. (const uint32 *)(LLVMGetSectionContents(sec_itr) + addr);
  3168. uint32 i;
  3169. for (i = 0; i < obj_data->func_count; i++) {
  3170. /* Note: -1 == AOT_NEG_ONE from aot_create_stack_sizes */
  3171. if (ro_stack_sizes[i] != (uint32)-1) {
  3172. aot_set_last_error("unexpected data in stack_sizes.");
  3173. goto fail;
  3174. }
  3175. }
  3176. /*
  3177. * Record section/offset and construct a copy of stack_sizes.
  3178. * aot_emit_object_data_section_info will emit this copy.
  3179. */
  3180. obj_data->stack_sizes_section_name = sec_name;
  3181. obj_data->stack_sizes_offset = (uint32)addr;
  3182. obj_data->stack_sizes = wasm_runtime_malloc(
  3183. obj_data->func_count * sizeof(*obj_data->stack_sizes));
  3184. if (obj_data->stack_sizes == NULL) {
  3185. aot_set_last_error("failed to allocate memory.");
  3186. goto fail;
  3187. }
  3188. uint32 *stack_sizes = obj_data->stack_sizes;
  3189. for (i = 0; i < obj_data->func_count; i++) {
  3190. stack_sizes[i] = (uint32)-1;
  3191. }
  3192. if (!read_stack_usage_file(comp_ctx, comp_ctx->stack_usage_file,
  3193. stack_sizes, obj_data->func_count)) {
  3194. goto fail;
  3195. }
  3196. for (i = 0; i < obj_data->func_count; i++) {
  3197. const AOTFuncContext *func_ctx = comp_ctx->func_ctxes[i];
  3198. bool musttail = aot_target_precheck_can_use_musttail(comp_ctx);
  3199. unsigned int stack_consumption_to_call_wrapped_func =
  3200. musttail ? 0
  3201. : aot_estimate_stack_usage_for_function_call(
  3202. comp_ctx, func_ctx->aot_func->func_type);
  3203. /*
  3204. * LLVM seems to eliminate calls to an empty function
  3205. * (and eliminate the function) even if it's marked noinline.
  3206. *
  3207. * Note: -1 == AOT_NEG_ONE from aot_create_stack_sizes
  3208. */
  3209. if (stack_sizes[i] == (uint32)-1) {
  3210. if (func_ctx->stack_consumption_for_func_call != 0) {
  3211. /*
  3212. * This happens if a function calling another
  3213. * function has been optimized out.
  3214. *
  3215. * for example,
  3216. *
  3217. * (func $func
  3218. * (local i32)
  3219. * local.get 0
  3220. * if
  3221. * call $another
  3222. * end
  3223. * )
  3224. */
  3225. LOG_VERBOSE("AOT func#%" PRIu32
  3226. " had call(s) but eliminated?",
  3227. i);
  3228. }
  3229. else {
  3230. LOG_VERBOSE("AOT func#%" PRIu32 " eliminated?", i);
  3231. }
  3232. stack_sizes[i] = 0;
  3233. }
  3234. else {
  3235. LOG_VERBOSE("AOT func#%" PRIu32 " stack_size %u + %" PRIu32
  3236. " + %u",
  3237. i, stack_consumption_to_call_wrapped_func,
  3238. stack_sizes[i],
  3239. func_ctx->stack_consumption_for_func_call);
  3240. if (UINT32_MAX - stack_sizes[i]
  3241. < func_ctx->stack_consumption_for_func_call) {
  3242. aot_set_last_error("stack size overflow.");
  3243. goto fail;
  3244. }
  3245. stack_sizes[i] += func_ctx->stack_consumption_for_func_call;
  3246. if (UINT32_MAX - stack_sizes[i]
  3247. < stack_consumption_to_call_wrapped_func) {
  3248. aot_set_last_error("stack size overflow.");
  3249. goto fail;
  3250. }
  3251. stack_sizes[i] += stack_consumption_to_call_wrapped_func;
  3252. }
  3253. }
  3254. LLVMDisposeSectionIterator(sec_itr);
  3255. LLVMDisposeSymbolIterator(sym_itr);
  3256. return true;
  3257. }
  3258. LLVMMoveToNextSymbol(sym_itr);
  3259. }
  3260. aot_set_last_error("stack_sizes not found.");
  3261. fail:
  3262. if (sec_itr)
  3263. LLVMDisposeSectionIterator(sec_itr);
  3264. LLVMDisposeSymbolIterator(sym_itr);
  3265. return false;
  3266. }
  3267. static bool
  3268. aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
  3269. {
  3270. AOTObjectFunc *func;
  3271. LLVMSymbolIteratorRef sym_itr;
  3272. char *name, *prefix = AOT_FUNC_PREFIX;
  3273. uint32 func_index, total_size;
  3274. /* allocate memory for aot function */
  3275. obj_data->func_count = comp_ctx->comp_data->func_count;
  3276. if (obj_data->func_count) {
  3277. if ((comp_ctx->enable_stack_bound_check
  3278. || comp_ctx->enable_stack_estimation)
  3279. && !aot_resolve_stack_sizes(comp_ctx, obj_data))
  3280. return false;
  3281. total_size = (uint32)sizeof(AOTObjectFunc) * obj_data->func_count;
  3282. if (!(obj_data->funcs = wasm_runtime_malloc(total_size))) {
  3283. aot_set_last_error("allocate memory for functions failed.");
  3284. return false;
  3285. }
  3286. memset(obj_data->funcs, 0, total_size);
  3287. }
  3288. if (!(sym_itr = LLVMObjectFileCopySymbolIterator(obj_data->binary))) {
  3289. aot_set_last_error("llvm get symbol iterator failed.");
  3290. return false;
  3291. }
  3292. while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) {
  3293. name = LLVMGetSymbolNameAndUnDecorate(sym_itr, obj_data->target_info);
  3294. if (name && str_starts_with(name, prefix)) {
  3295. /* symbol aot_func#n */
  3296. func_index = (uint32)atoi(name + strlen(prefix));
  3297. if (func_index < obj_data->func_count) {
  3298. LLVMSectionIteratorRef contain_section;
  3299. char *contain_section_name;
  3300. func = obj_data->funcs + func_index;
  3301. func->func_name = name;
  3302. if (!(contain_section = LLVMObjectFileCopySectionIterator(
  3303. obj_data->binary))) {
  3304. aot_set_last_error("llvm get section iterator failed.");
  3305. LLVMDisposeSymbolIterator(sym_itr);
  3306. return false;
  3307. }
  3308. LLVMMoveToContainingSection(contain_section, sym_itr);
  3309. contain_section_name =
  3310. (char *)LLVMGetSectionName(contain_section);
  3311. LLVMDisposeSectionIterator(contain_section);
  3312. if (!strcmp(contain_section_name, ".text.unlikely.")
  3313. || !strcmp(contain_section_name, ".ltext.unlikely.")) {
  3314. func->text_offset = align_uint(obj_data->text_size, 4)
  3315. + LLVMGetSymbolAddress(sym_itr);
  3316. }
  3317. else if (!strcmp(contain_section_name, ".text.hot.")
  3318. || !strcmp(contain_section_name, ".ltext.hot.")) {
  3319. func->text_offset =
  3320. align_uint(obj_data->text_size, 4)
  3321. + align_uint(obj_data->text_unlikely_size, 4)
  3322. + LLVMGetSymbolAddress(sym_itr);
  3323. }
  3324. else {
  3325. func->text_offset = LLVMGetSymbolAddress(sym_itr);
  3326. }
  3327. }
  3328. }
  3329. else if (name && str_starts_with(name, AOT_FUNC_INTERNAL_PREFIX)) {
  3330. /* symbol aot_func_internal#n */
  3331. func_index = (uint32)atoi(name + strlen(AOT_FUNC_INTERNAL_PREFIX));
  3332. if (func_index < obj_data->func_count) {
  3333. LLVMSectionIteratorRef contain_section;
  3334. char *contain_section_name;
  3335. func = obj_data->funcs + func_index;
  3336. if (!(contain_section = LLVMObjectFileCopySectionIterator(
  3337. obj_data->binary))) {
  3338. aot_set_last_error("llvm get section iterator failed.");
  3339. LLVMDisposeSymbolIterator(sym_itr);
  3340. return false;
  3341. }
  3342. LLVMMoveToContainingSection(contain_section, sym_itr);
  3343. contain_section_name =
  3344. (char *)LLVMGetSectionName(contain_section);
  3345. LLVMDisposeSectionIterator(contain_section);
  3346. if (!strcmp(contain_section_name, ".text.unlikely.")
  3347. || !strcmp(contain_section_name, ".ltext.unlikely.")) {
  3348. func->text_offset_of_aot_func_internal =
  3349. align_uint(obj_data->text_size, 4)
  3350. + LLVMGetSymbolAddress(sym_itr);
  3351. }
  3352. else if (!strcmp(contain_section_name, ".text.hot.")
  3353. || !strcmp(contain_section_name, ".ltext.hot.")) {
  3354. func->text_offset_of_aot_func_internal =
  3355. align_uint(obj_data->text_size, 4)
  3356. + align_uint(obj_data->text_unlikely_size, 4)
  3357. + LLVMGetSymbolAddress(sym_itr);
  3358. }
  3359. else {
  3360. func->text_offset_of_aot_func_internal =
  3361. LLVMGetSymbolAddress(sym_itr);
  3362. }
  3363. }
  3364. }
  3365. LLVMMoveToNextSymbol(sym_itr);
  3366. }
  3367. LLVMDisposeSymbolIterator(sym_itr);
  3368. return true;
  3369. }
  3370. static bool
  3371. get_relocations_count(LLVMSectionIteratorRef sec_itr, uint32 *p_count)
  3372. {
  3373. uint32 relocation_count = 0;
  3374. LLVMRelocationIteratorRef rel_itr;
  3375. if (!(rel_itr = LLVMGetRelocations(sec_itr))) {
  3376. aot_set_last_error("llvm get relocations failed.");
  3377. LLVMDisposeSectionIterator(sec_itr);
  3378. return false;
  3379. }
  3380. while (!LLVMIsRelocationIteratorAtEnd(sec_itr, rel_itr)) {
  3381. relocation_count++;
  3382. LLVMMoveToNextRelocation(rel_itr);
  3383. }
  3384. LLVMDisposeRelocationIterator(rel_itr);
  3385. *p_count = relocation_count;
  3386. return true;
  3387. }
  3388. static bool
  3389. aot_resolve_object_relocation_group(AOTObjectData *obj_data,
  3390. AOTRelocationGroup *group,
  3391. LLVMSectionIteratorRef rel_sec)
  3392. {
  3393. LLVMRelocationIteratorRef rel_itr;
  3394. AOTRelocation *relocation = group->relocations;
  3395. uint32 size;
  3396. bool is_binary_32bit = is_32bit_binary(obj_data);
  3397. bool is_binary_little_endian = is_little_endian_binary(obj_data);
  3398. bool has_addend = str_starts_with(group->section_name, ".rela");
  3399. uint8 *rela_content = NULL;
  3400. /* calculate relocations count and allocate memory */
  3401. if (!get_relocations_count(rel_sec, &group->relocation_count))
  3402. return false;
  3403. if (group->relocation_count == 0) {
  3404. aot_set_last_error("invalid relocations count");
  3405. return false;
  3406. }
  3407. size = (uint32)sizeof(AOTRelocation) * group->relocation_count;
  3408. if (!(relocation = group->relocations = wasm_runtime_malloc(size))) {
  3409. aot_set_last_error("allocate memory for relocations failed.");
  3410. return false;
  3411. }
  3412. memset(group->relocations, 0, size);
  3413. if (has_addend) {
  3414. uint64 rela_content_size;
  3415. /* LLVM doesn't provide C API to get relocation addend. So we have to
  3416. * parse it manually. */
  3417. rela_content = (uint8 *)LLVMGetSectionContents(rel_sec);
  3418. rela_content_size = LLVMGetSectionSize(rel_sec);
  3419. if (is_binary_32bit)
  3420. size = (uint32)sizeof(struct elf32_rela) * group->relocation_count;
  3421. else
  3422. size = (uint32)sizeof(struct elf64_rela) * group->relocation_count;
  3423. if (rela_content_size != (uint64)size) {
  3424. aot_set_last_error("invalid relocation section content.");
  3425. return false;
  3426. }
  3427. }
  3428. /* parse each relocation */
  3429. if (!(rel_itr = LLVMGetRelocations(rel_sec))) {
  3430. aot_set_last_error("llvm get relocations failed.");
  3431. return false;
  3432. }
  3433. while (!LLVMIsRelocationIteratorAtEnd(rel_sec, rel_itr)) {
  3434. uint64 offset = LLVMGetRelocationOffset(rel_itr);
  3435. uint64 type = LLVMGetRelocationType(rel_itr);
  3436. LLVMSymbolIteratorRef rel_sym = LLVMGetRelocationSymbol(rel_itr);
  3437. if (!rel_sym) {
  3438. aot_set_last_error("llvm get relocation symbol failed.");
  3439. goto fail;
  3440. }
  3441. /* parse relocation addend from relocation content */
  3442. if (has_addend) {
  3443. if (is_binary_32bit) {
  3444. int32 addend =
  3445. (int32)(((struct elf32_rela *)rela_content)->r_addend);
  3446. if (is_binary_little_endian != is_little_endian())
  3447. exchange_uint32((uint8 *)&addend);
  3448. relocation->relocation_addend = (int64)addend;
  3449. rela_content += sizeof(struct elf32_rela);
  3450. }
  3451. else {
  3452. int64 addend =
  3453. (int64)(((struct elf64_rela *)rela_content)->r_addend);
  3454. if (is_binary_little_endian != is_little_endian())
  3455. exchange_uint64((uint8 *)&addend);
  3456. relocation->relocation_addend = addend;
  3457. rela_content += sizeof(struct elf64_rela);
  3458. }
  3459. }
  3460. /* set relocation fields */
  3461. relocation->relocation_type = (uint32)type;
  3462. relocation->symbol_name =
  3463. LLVMGetSymbolNameAndUnDecorate(rel_sym, obj_data->target_info);
  3464. relocation->relocation_offset = offset;
  3465. if (!strcmp(group->section_name, ".rela.text.unlikely.")
  3466. || !strcmp(group->section_name, ".rel.text.unlikely.")) {
  3467. relocation->relocation_offset += align_uint(obj_data->text_size, 4);
  3468. }
  3469. else if (!strcmp(group->section_name, ".rela.text.hot.")
  3470. || !strcmp(group->section_name, ".rel.text.hot.")) {
  3471. relocation->relocation_offset +=
  3472. align_uint(obj_data->text_size, 4)
  3473. + align_uint(obj_data->text_unlikely_size, 4);
  3474. }
  3475. if (!strcmp(relocation->symbol_name, ".text.unlikely.")) {
  3476. relocation->symbol_name = ".text";
  3477. relocation->relocation_addend += align_uint(obj_data->text_size, 4);
  3478. }
  3479. if (!strcmp(relocation->symbol_name, ".text.hot.")) {
  3480. relocation->symbol_name = ".text";
  3481. relocation->relocation_addend +=
  3482. align_uint(obj_data->text_size, 4)
  3483. + align_uint(obj_data->text_unlikely_size, 4);
  3484. }
  3485. /*
  3486. * Note: aot_stack_sizes_section_name section only contains
  3487. * stack_sizes table.
  3488. */
  3489. if (!strcmp(relocation->symbol_name, aot_stack_sizes_name)) {
  3490. /* discard const */
  3491. relocation->symbol_name = (char *)aot_stack_sizes_section_name;
  3492. }
  3493. if (obj_data->comp_ctx->enable_llvm_pgo
  3494. && (!strcmp(relocation->symbol_name, "__llvm_prf_cnts")
  3495. || !strcmp(relocation->symbol_name, "__llvm_prf_data"))) {
  3496. LLVMSectionIteratorRef sec_itr;
  3497. char buf[32], *section_name;
  3498. uint32 prof_section_idx = 0;
  3499. if (!(sec_itr =
  3500. LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  3501. aot_set_last_error("llvm get section iterator failed.");
  3502. LLVMDisposeSymbolIterator(rel_sym);
  3503. goto fail;
  3504. }
  3505. while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary,
  3506. sec_itr)) {
  3507. section_name = (char *)LLVMGetSectionName(sec_itr);
  3508. if (section_name
  3509. && !strcmp(section_name, relocation->symbol_name)) {
  3510. if (LLVMGetSectionContainsSymbol(sec_itr, rel_sym))
  3511. break;
  3512. prof_section_idx++;
  3513. }
  3514. LLVMMoveToNextSection(sec_itr);
  3515. }
  3516. LLVMDisposeSectionIterator(sec_itr);
  3517. if (!strcmp(group->section_name, ".rela.text")
  3518. || !strcmp(group->section_name, ".rel.text")) {
  3519. snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name,
  3520. prof_section_idx);
  3521. size = (uint32)(strlen(buf) + 1);
  3522. if (!(relocation->symbol_name = wasm_runtime_malloc(size))) {
  3523. aot_set_last_error(
  3524. "allocate memory for relocation symbol name failed.");
  3525. LLVMDisposeSymbolIterator(rel_sym);
  3526. goto fail;
  3527. }
  3528. bh_memcpy_s(relocation->symbol_name, size, buf, size);
  3529. relocation->is_symbol_name_allocated = true;
  3530. }
  3531. else if (!strncmp(group->section_name, ".rela__llvm_prf_data", 20)
  3532. || !strncmp(group->section_name, ".rel__llvm_prf_data",
  3533. 19)) {
  3534. snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name,
  3535. prof_section_idx);
  3536. size = (uint32)(strlen(buf) + 1);
  3537. if (!(relocation->symbol_name = wasm_runtime_malloc(size))) {
  3538. aot_set_last_error(
  3539. "allocate memory for relocation symbol name failed.");
  3540. LLVMDisposeSymbolIterator(rel_sym);
  3541. goto fail;
  3542. }
  3543. bh_memcpy_s(relocation->symbol_name, size, buf, size);
  3544. relocation->is_symbol_name_allocated = true;
  3545. }
  3546. }
  3547. /* for ".LCPIxxx", ".LJTIxxx", ".LBBxxx" and switch lookup table
  3548. * relocation, transform the symbol name to real section name and set
  3549. * addend to the offset of the symbol in the real section */
  3550. if (relocation->symbol_name
  3551. && (str_starts_with(relocation->symbol_name, ".LCPI")
  3552. || str_starts_with(relocation->symbol_name, ".LJTI")
  3553. || str_starts_with(relocation->symbol_name, ".LBB")
  3554. || str_starts_with(relocation->symbol_name, ".Lswitch.table.")
  3555. #if LLVM_VERSION_MAJOR >= 16
  3556. /* cf. https://reviews.llvm.org/D123264 */
  3557. || str_starts_with(relocation->symbol_name, ".Lpcrel_hi")
  3558. #endif
  3559. #if LLVM_VERSION_MAJOR >= 19
  3560. /* cf.
  3561. * https://github.com/llvm/llvm-project/pull/95031
  3562. * https://github.com/llvm/llvm-project/pull/89693
  3563. *
  3564. * note: the trailing space in ".L0 " is intentional. */
  3565. || !strcmp(relocation->symbol_name, "")
  3566. || !strcmp(relocation->symbol_name, ".L0 ")
  3567. #endif
  3568. )) {
  3569. /* change relocation->relocation_addend and
  3570. relocation->symbol_name */
  3571. LLVMSectionIteratorRef contain_section;
  3572. if (!(contain_section =
  3573. LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  3574. aot_set_last_error("llvm get section iterator failed.");
  3575. goto fail;
  3576. }
  3577. LLVMMoveToContainingSection(contain_section, rel_sym);
  3578. if (LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary,
  3579. contain_section)) {
  3580. LLVMDisposeSectionIterator(contain_section);
  3581. aot_set_last_error("llvm get containing section failed.");
  3582. goto fail;
  3583. }
  3584. relocation->relocation_addend += LLVMGetSymbolAddress(rel_sym);
  3585. relocation->symbol_name =
  3586. (char *)LLVMGetSectionName(contain_section);
  3587. LLVMDisposeSectionIterator(contain_section);
  3588. }
  3589. LLVMDisposeSymbolIterator(rel_sym);
  3590. LLVMMoveToNextRelocation(rel_itr);
  3591. relocation++;
  3592. }
  3593. LLVMDisposeRelocationIterator(rel_itr);
  3594. return true;
  3595. fail:
  3596. LLVMDisposeRelocationIterator(rel_itr);
  3597. return false;
  3598. }
  3599. static bool
  3600. is_relocation_section_name(AOTObjectData *obj_data, char *section_name)
  3601. {
  3602. return (!strcmp(section_name, ".rela.text")
  3603. || !strcmp(section_name, ".rel.text")
  3604. || !strcmp(section_name, ".rela.text.unlikely.")
  3605. || !strcmp(section_name, ".rel.text.unlikely.")
  3606. || !strcmp(section_name, ".rela.text.hot.")
  3607. || !strcmp(section_name, ".rel.text.hot.")
  3608. || !strcmp(section_name, ".rela.ltext")
  3609. || !strcmp(section_name, ".rel.ltext")
  3610. || !strcmp(section_name, ".rela.ltext.unlikely.")
  3611. || !strcmp(section_name, ".rel.ltext.unlikely.")
  3612. || !strcmp(section_name, ".rela.ltext.hot.")
  3613. || !strcmp(section_name, ".rel.ltext.hot.")
  3614. || !strcmp(section_name, ".rela.literal")
  3615. || !strcmp(section_name, ".rela.data")
  3616. || !strcmp(section_name, ".rel.data")
  3617. || !strcmp(section_name, ".rela.sdata")
  3618. || !strcmp(section_name, ".rel.sdata")
  3619. || !strcmp(section_name, ".rela.rodata")
  3620. || !strcmp(section_name, ".rel.rodata")
  3621. || (obj_data->comp_ctx->enable_llvm_pgo
  3622. && (!strcmp(section_name, ".rela__llvm_prf_data")
  3623. || !strcmp(section_name, ".rel__llvm_prf_data")))
  3624. /* ".rela.rodata.cst4/8/16/.." */
  3625. || !strncmp(section_name, ".rela.rodata.cst",
  3626. strlen(".rela.rodata.cst"))
  3627. /* ".rel.rodata.cst4/8/16/.." */
  3628. || !strncmp(section_name, ".rel.rodata.cst",
  3629. strlen(".rel.rodata.cst")));
  3630. }
  3631. static bool
  3632. is_relocation_section(AOTObjectData *obj_data, LLVMSectionIteratorRef sec_itr)
  3633. {
  3634. uint32 count = 0;
  3635. char *name = (char *)LLVMGetSectionName(sec_itr);
  3636. if (name) {
  3637. if (is_relocation_section_name(obj_data, name))
  3638. return true;
  3639. else if ((!strcmp(name, ".text") || !strcmp(name, ".text.unlikely.")
  3640. || !strcmp(name, ".text.hot.") || !strcmp(name, ".rdata"))
  3641. && get_relocations_count(sec_itr, &count) && count > 0)
  3642. return true;
  3643. }
  3644. return false;
  3645. }
  3646. static bool
  3647. is_readonly_section(const char *name)
  3648. {
  3649. return !strcmp(name, ".rel.text") || !strcmp(name, ".rela.text")
  3650. || !strcmp(name, ".rel.ltext") || !strcmp(name, ".rela.ltext")
  3651. || !strcmp(name, ".rela.literal") || !strcmp(name, ".text")
  3652. || !strcmp(name, ".ltext");
  3653. }
  3654. static bool
  3655. get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count)
  3656. {
  3657. uint32 count = 0;
  3658. LLVMSectionIteratorRef sec_itr;
  3659. if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  3660. aot_set_last_error("llvm get section iterator failed.");
  3661. return false;
  3662. }
  3663. while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
  3664. if (is_relocation_section(obj_data, sec_itr)) {
  3665. count++;
  3666. }
  3667. LLVMMoveToNextSection(sec_itr);
  3668. }
  3669. LLVMDisposeSectionIterator(sec_itr);
  3670. *p_count = count;
  3671. return true;
  3672. }
  3673. static bool
  3674. aot_resolve_object_relocation_groups(AOTObjectData *obj_data)
  3675. {
  3676. LLVMSectionIteratorRef sec_itr;
  3677. AOTRelocationGroup *relocation_group;
  3678. uint32 group_count, llvm_prf_data_idx = 0;
  3679. char *name;
  3680. uint32 size;
  3681. /* calculate relocation groups count and allocate memory */
  3682. if (!get_relocation_groups_count(obj_data, &group_count))
  3683. return false;
  3684. if (0 == (obj_data->relocation_group_count = group_count))
  3685. return true;
  3686. size = (uint32)sizeof(AOTRelocationGroup) * group_count;
  3687. if (!(relocation_group = obj_data->relocation_groups =
  3688. wasm_runtime_malloc(size))) {
  3689. aot_set_last_error("allocate memory for relocation groups failed.");
  3690. return false;
  3691. }
  3692. memset(obj_data->relocation_groups, 0, size);
  3693. /* resolve each relocation group */
  3694. if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
  3695. aot_set_last_error("llvm get section iterator failed.");
  3696. return false;
  3697. }
  3698. while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
  3699. if (is_relocation_section(obj_data, sec_itr)) {
  3700. name = (char *)LLVMGetSectionName(sec_itr);
  3701. relocation_group->section_name = name;
  3702. if (obj_data->comp_ctx->enable_llvm_pgo
  3703. && (!strcmp(name, ".rela__llvm_prf_data")
  3704. || !strcmp(name, ".rel__llvm_prf_data"))) {
  3705. char buf[32];
  3706. snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_data_idx);
  3707. size = (uint32)(strlen(buf) + 1);
  3708. if (!(relocation_group->section_name =
  3709. wasm_runtime_malloc(size))) {
  3710. aot_set_last_error(
  3711. "allocate memory for section name failed.");
  3712. LLVMDisposeSectionIterator(sec_itr);
  3713. return false;
  3714. }
  3715. bh_memcpy_s(relocation_group->section_name, size, buf, size);
  3716. relocation_group->is_section_name_allocated = true;
  3717. }
  3718. if (!aot_resolve_object_relocation_group(obj_data, relocation_group,
  3719. sec_itr)) {
  3720. LLVMDisposeSectionIterator(sec_itr);
  3721. return false;
  3722. }
  3723. if (obj_data->comp_ctx->enable_llvm_pgo
  3724. && (!strcmp(name, ".rela__llvm_prf_data")
  3725. || !strcmp(name, ".rel__llvm_prf_data"))) {
  3726. llvm_prf_data_idx++;
  3727. }
  3728. if (!strcmp(relocation_group->section_name, ".rela.text.unlikely.")
  3729. || !strcmp(relocation_group->section_name, ".rela.text.hot.")) {
  3730. relocation_group->section_name = ".rela.text";
  3731. }
  3732. else if (!strcmp(relocation_group->section_name,
  3733. ".rela.ltext.unlikely.")
  3734. || !strcmp(relocation_group->section_name,
  3735. ".rela.ltext.hot.")) {
  3736. relocation_group->section_name = ".rela.ltext";
  3737. }
  3738. else if (!strcmp(relocation_group->section_name,
  3739. ".rel.text.unlikely.")
  3740. || !strcmp(relocation_group->section_name,
  3741. ".rel.text.hot.")) {
  3742. relocation_group->section_name = ".rel.text";
  3743. }
  3744. else if (!strcmp(relocation_group->section_name,
  3745. ".rel.ltext.unlikely.")
  3746. || !strcmp(relocation_group->section_name,
  3747. ".rel.ltext.hot.")) {
  3748. relocation_group->section_name = ".rel.ltext";
  3749. }
  3750. /*
  3751. * Relocations in read-only sections are problematic,
  3752. * especially for XIP on platforms which don't have
  3753. * copy-on-write mappings.
  3754. */
  3755. if (obj_data->comp_ctx->is_indirect_mode
  3756. && is_readonly_section(relocation_group->section_name)) {
  3757. LOG_WARNING("%" PRIu32
  3758. " text relocations in %s section for indirect mode",
  3759. relocation_group->relocation_count,
  3760. relocation_group->section_name);
  3761. }
  3762. relocation_group++;
  3763. }
  3764. LLVMMoveToNextSection(sec_itr);
  3765. }
  3766. LLVMDisposeSectionIterator(sec_itr);
  3767. return true;
  3768. }
  3769. static void
  3770. destroy_relocation_groups(AOTRelocationGroup *relocation_groups,
  3771. uint32 relocation_group_count)
  3772. {
  3773. uint32 i, j;
  3774. AOTRelocationGroup *relocation_group = relocation_groups;
  3775. for (i = 0; i < relocation_group_count; i++, relocation_group++) {
  3776. if (relocation_group->relocations) {
  3777. for (j = 0; j < relocation_group->relocation_count; j++) {
  3778. if (relocation_group->relocations[j].is_symbol_name_allocated)
  3779. wasm_runtime_free(
  3780. relocation_group->relocations[j].symbol_name);
  3781. }
  3782. wasm_runtime_free(relocation_group->relocations);
  3783. }
  3784. if (relocation_group->is_section_name_allocated)
  3785. wasm_runtime_free(relocation_group->section_name);
  3786. }
  3787. wasm_runtime_free(relocation_groups);
  3788. }
  3789. static void
  3790. destroy_relocation_symbol_list(AOTSymbolList *symbol_list)
  3791. {
  3792. AOTSymbolNode *elem;
  3793. elem = symbol_list->head;
  3794. while (elem) {
  3795. AOTSymbolNode *next = elem->next;
  3796. wasm_runtime_free(elem);
  3797. elem = next;
  3798. }
  3799. }
  3800. void
  3801. aot_obj_data_destroy(AOTObjectData *obj_data)
  3802. {
  3803. if (obj_data->binary)
  3804. LLVMDisposeBinary(obj_data->binary);
  3805. if (obj_data->mem_buf)
  3806. LLVMDisposeMemoryBuffer(obj_data->mem_buf);
  3807. if (obj_data->funcs)
  3808. wasm_runtime_free(obj_data->funcs);
  3809. if (obj_data->data_sections) {
  3810. uint32 i;
  3811. for (i = 0; i < obj_data->data_sections_count; i++) {
  3812. if (obj_data->data_sections[i].name
  3813. && obj_data->data_sections[i].is_name_allocated) {
  3814. wasm_runtime_free(obj_data->data_sections[i].name);
  3815. }
  3816. if (obj_data->data_sections[i].data
  3817. && obj_data->data_sections[i].is_data_allocated) {
  3818. wasm_runtime_free(obj_data->data_sections[i].data);
  3819. }
  3820. }
  3821. wasm_runtime_free(obj_data->data_sections);
  3822. }
  3823. if (obj_data->relocation_groups)
  3824. destroy_relocation_groups(obj_data->relocation_groups,
  3825. obj_data->relocation_group_count);
  3826. if (obj_data->symbol_list.len)
  3827. destroy_relocation_symbol_list(&obj_data->symbol_list);
  3828. if (obj_data->stack_sizes)
  3829. wasm_runtime_free(obj_data->stack_sizes);
  3830. wasm_runtime_free(obj_data);
  3831. }
  3832. AOTObjectData *
  3833. aot_obj_data_create(AOTCompContext *comp_ctx)
  3834. {
  3835. char *err = NULL;
  3836. AOTObjectData *obj_data;
  3837. LLVMTargetRef target = LLVMGetTargetMachineTarget(comp_ctx->target_machine);
  3838. bh_print_time("Begin to emit object file to buffer");
  3839. if (!(obj_data = wasm_runtime_malloc(sizeof(AOTObjectData)))) {
  3840. aot_set_last_error("allocate memory failed.");
  3841. return false;
  3842. }
  3843. memset(obj_data, 0, sizeof(AOTObjectData));
  3844. obj_data->comp_ctx = comp_ctx;
  3845. bh_print_time("Begin to emit object file");
  3846. if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
  3847. /* Generate a temp file name */
  3848. int ret;
  3849. char obj_file_name[64];
  3850. if (!aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name,
  3851. sizeof(obj_file_name))) {
  3852. goto fail;
  3853. }
  3854. if (!aot_emit_object_file(comp_ctx, obj_file_name)) {
  3855. goto fail;
  3856. }
  3857. /* create memory buffer from object file */
  3858. ret = LLVMCreateMemoryBufferWithContentsOfFile(
  3859. obj_file_name, &obj_data->mem_buf, &err);
  3860. /* remove temp object file */
  3861. unlink(obj_file_name);
  3862. if (ret != 0) {
  3863. if (err) {
  3864. LLVMDisposeMessage(err);
  3865. err = NULL;
  3866. }
  3867. aot_set_last_error("create mem buffer with file failed.");
  3868. goto fail;
  3869. }
  3870. }
  3871. else if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
  3872. /* Emit to assembly file instead for arc target
  3873. as it cannot emit to object file */
  3874. char file_name[] = "wasm-XXXXXX", buf[128];
  3875. int ret;
  3876. if (!bh_mkstemp(file_name, sizeof(file_name))) {
  3877. aot_set_last_error("make temp file failed.");
  3878. goto fail;
  3879. }
  3880. snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
  3881. if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
  3882. comp_ctx->module, buf, LLVMAssemblyFile,
  3883. &err)
  3884. != 0) {
  3885. if (err) {
  3886. LLVMDisposeMessage(err);
  3887. err = NULL;
  3888. }
  3889. aot_set_last_error("emit elf to object file failed.");
  3890. goto fail;
  3891. }
  3892. /* call arc gcc to compile assembly file to object file */
  3893. /* TODO: get arc gcc from environment variable firstly
  3894. and check whether the toolchain exists actually */
  3895. snprintf(buf, sizeof(buf), "%s%s%s%s%s%s",
  3896. "/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ",
  3897. "-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s");
  3898. /* TODO: use try..catch to handle possible exceptions */
  3899. ret = bh_system(buf);
  3900. /* remove temp assembly file */
  3901. snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
  3902. unlink(buf);
  3903. if (ret != 0) {
  3904. aot_set_last_error("failed to compile asm file to obj file "
  3905. "with arc gcc toolchain.");
  3906. goto fail;
  3907. }
  3908. /* create memory buffer from object file */
  3909. snprintf(buf, sizeof(buf), "%s%s", file_name, ".o");
  3910. ret = LLVMCreateMemoryBufferWithContentsOfFile(buf, &obj_data->mem_buf,
  3911. &err);
  3912. /* remove temp object file */
  3913. snprintf(buf, sizeof(buf), "%s%s", file_name, ".o");
  3914. unlink(buf);
  3915. if (ret != 0) {
  3916. if (err) {
  3917. LLVMDisposeMessage(err);
  3918. err = NULL;
  3919. }
  3920. aot_set_last_error("create mem buffer with file failed.");
  3921. goto fail;
  3922. }
  3923. }
  3924. else {
  3925. if (LLVMTargetMachineEmitToMemoryBuffer(
  3926. comp_ctx->target_machine, comp_ctx->module, LLVMObjectFile,
  3927. &err, &obj_data->mem_buf)
  3928. != 0) {
  3929. if (err) {
  3930. LLVMDisposeMessage(err);
  3931. err = NULL;
  3932. }
  3933. aot_set_last_error("llvm emit to memory buffer failed.");
  3934. goto fail;
  3935. }
  3936. }
  3937. if (!(obj_data->binary = LLVMCreateBinary(obj_data->mem_buf, NULL, &err))) {
  3938. if (err) {
  3939. LLVMDisposeMessage(err);
  3940. err = NULL;
  3941. }
  3942. aot_set_last_error("llvm create binary failed.");
  3943. goto fail;
  3944. }
  3945. /* Create wasm feature flags form compile options */
  3946. obj_data->target_info.feature_flags = 0;
  3947. if (comp_ctx->enable_simd) {
  3948. obj_data->target_info.feature_flags |= WASM_FEATURE_SIMD_128BIT;
  3949. }
  3950. if (comp_ctx->enable_bulk_memory) {
  3951. obj_data->target_info.feature_flags |= WASM_FEATURE_BULK_MEMORY;
  3952. }
  3953. if (comp_ctx->enable_thread_mgr) {
  3954. obj_data->target_info.feature_flags |= WASM_FEATURE_MULTI_THREAD;
  3955. }
  3956. if (comp_ctx->enable_ref_types) {
  3957. obj_data->target_info.feature_flags |= WASM_FEATURE_REF_TYPES;
  3958. }
  3959. if (comp_ctx->enable_gc) {
  3960. obj_data->target_info.feature_flags |= WASM_FEATURE_GARBAGE_COLLECTION;
  3961. }
  3962. if (comp_ctx->aux_stack_frame_type == AOT_STACK_FRAME_TYPE_TINY) {
  3963. obj_data->target_info.feature_flags |= WASM_FEATURE_TINY_STACK_FRAME;
  3964. }
  3965. if (comp_ctx->call_stack_features.frame_per_function) {
  3966. obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_PER_FUNCTION;
  3967. }
  3968. if (!comp_ctx->call_stack_features.func_idx) {
  3969. obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_NO_FUNC_IDX;
  3970. }
  3971. bh_print_time("Begin to resolve object file info");
  3972. /* resolve target info/text/relocations/functions */
  3973. if (!aot_resolve_target_info(comp_ctx, obj_data)
  3974. || !aot_resolve_text(obj_data) || !aot_resolve_literal(obj_data)
  3975. || !aot_resolve_object_data_sections(obj_data)
  3976. || !aot_resolve_functions(comp_ctx, obj_data)
  3977. || !aot_resolve_object_relocation_groups(obj_data))
  3978. goto fail;
  3979. return obj_data;
  3980. fail:
  3981. aot_obj_data_destroy(obj_data);
  3982. return NULL;
  3983. }
  3984. uint8 *
  3985. aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  3986. uint32 *p_aot_file_size)
  3987. {
  3988. AOTObjectData *obj_data = aot_obj_data_create(comp_ctx);
  3989. uint8 *aot_file_buf;
  3990. uint32 aot_file_size;
  3991. if (!obj_data)
  3992. return NULL;
  3993. aot_file_size = aot_get_aot_file_size(comp_ctx, comp_data, obj_data);
  3994. if (aot_file_size == 0) {
  3995. aot_set_last_error("get aot file size failed");
  3996. goto fail1;
  3997. }
  3998. if (!(aot_file_buf = wasm_runtime_malloc(aot_file_size))) {
  3999. aot_set_last_error("allocate memory failed.");
  4000. goto fail1;
  4001. }
  4002. memset(aot_file_buf, 0, aot_file_size);
  4003. if (!aot_emit_aot_file_buf_ex(comp_ctx, comp_data, obj_data, aot_file_buf,
  4004. aot_file_size))
  4005. goto fail2;
  4006. *p_aot_file_size = aot_file_size;
  4007. aot_obj_data_destroy(obj_data);
  4008. return aot_file_buf;
  4009. fail2:
  4010. wasm_runtime_free(aot_file_buf);
  4011. fail1:
  4012. aot_obj_data_destroy(obj_data);
  4013. return NULL;
  4014. }
  4015. bool
  4016. aot_emit_aot_file_buf_ex(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  4017. AOTObjectData *obj_data, uint8 *buf,
  4018. uint32 aot_file_size)
  4019. {
  4020. uint8 *buf_end = buf + aot_file_size;
  4021. uint32 offset = 0;
  4022. if (!aot_emit_file_header(buf, buf_end, &offset, comp_data, obj_data)
  4023. || !aot_emit_target_info_section(buf, buf_end, &offset, comp_data,
  4024. obj_data)
  4025. || !aot_emit_init_data_section(buf, buf_end, &offset, comp_ctx,
  4026. comp_data, obj_data)
  4027. || !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data)
  4028. || !aot_emit_func_section(buf, buf_end, &offset, comp_ctx, comp_data,
  4029. obj_data)
  4030. || !aot_emit_export_section(buf, buf_end, &offset, comp_ctx, comp_data,
  4031. obj_data)
  4032. || !aot_emit_relocation_section(buf, buf_end, &offset, comp_ctx,
  4033. comp_data, obj_data)
  4034. || !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx)
  4035. || !aot_emit_custom_sections(buf, buf_end, &offset, comp_data, comp_ctx)
  4036. #if WASM_ENABLE_STRINGREF != 0
  4037. || !aot_emit_string_literal_section(buf, buf_end, &offset, comp_data,
  4038. comp_ctx)
  4039. #endif
  4040. )
  4041. return false;
  4042. #if 0
  4043. dump_buf(buf, offset, "sections");
  4044. #endif
  4045. if (offset != aot_file_size) {
  4046. aot_set_last_error("emit aot file failed.");
  4047. return false;
  4048. }
  4049. return true;
  4050. }
  4051. bool
  4052. aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
  4053. const char *file_name)
  4054. {
  4055. uint8 *aot_file_buf;
  4056. uint32 aot_file_size;
  4057. bool ret = false;
  4058. FILE *file;
  4059. bh_print_time("Begin to emit AOT file");
  4060. if (!(aot_file_buf =
  4061. aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size))) {
  4062. return false;
  4063. }
  4064. /* write buffer to file */
  4065. if (!(file = fopen(file_name, "wb"))) {
  4066. aot_set_last_error("open or create aot file failed.");
  4067. goto fail1;
  4068. }
  4069. if (!fwrite(aot_file_buf, aot_file_size, 1, file)) {
  4070. aot_set_last_error("write to aot file failed.");
  4071. goto fail2;
  4072. }
  4073. ret = true;
  4074. fail2:
  4075. fclose(file);
  4076. fail1:
  4077. wasm_runtime_free(aot_file_buf);
  4078. return ret;
  4079. }