ogbase.pas 138 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188
  1. {
  2. Copyright (c) 1998-2006 by Peter Vreman
  3. Contains the base stuff for binary object file writers
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogbase;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cutils,
  23. cclasses,
  24. { targets }
  25. systems,globtype,
  26. { outputwriters }
  27. owbase,
  28. { assembler }
  29. aasmbase,
  30. cpuinfo;
  31. type
  32. TObjSection = class;
  33. TObjData = class;
  34. TExeSection = class;
  35. TExeSymbol = class;
  36. TExeOutput = class;
  37. TObjRelocationType = (
  38. { Relocation to absolute address }
  39. RELOC_ABSOLUTE,
  40. {$ifdef x86_64}
  41. { 32bit Relocation to absolute address }
  42. RELOC_ABSOLUTE32,
  43. { 64 bit coff only }
  44. RELOC_RELATIVE_1,
  45. RELOC_RELATIVE_2,
  46. RELOC_RELATIVE_3,
  47. RELOC_RELATIVE_4,
  48. RELOC_RELATIVE_5,
  49. { PIC }
  50. RELOC_GOTPCREL,
  51. RELOC_GOTPCRELX,
  52. RELOC_REX_GOTPCRELX,
  53. RELOC_PLT32,
  54. RELOC_TLSGD,
  55. RELOC_TPOFF,
  56. {$endif x86_64}
  57. {$ifdef i386}
  58. { PIC }
  59. RELOC_GOTPC,
  60. RELOC_GOT32,
  61. RELOC_PLT32,
  62. RELOC_TLSGD,
  63. RELOC_NTPOFF,
  64. {$endif i386}
  65. {$ifdef i8086}
  66. RELOC_ABSOLUTE32,
  67. RELOC_RELATIVE32,
  68. RELOC_FARPTR,
  69. RELOC_FARPTR_RELATIVEOFFSET,
  70. RELOC_FARPTR48,
  71. RELOC_FARPTR48_RELATIVEOFFSET,
  72. RELOC_SEG,
  73. RELOC_SEGREL,
  74. RELOC_DGROUP,
  75. RELOC_DGROUPREL,
  76. RELOC_FARDATASEG,
  77. RELOC_FARDATASEGREL,
  78. {$endif i8086}
  79. {$ifdef arm}
  80. RELOC_RELATIVE_24,
  81. RELOC_RELATIVE_CALL,
  82. RELOC_RELATIVE_24_THUMB,
  83. RELOC_RELATIVE_CALL_THUMB,
  84. RELOC_GOT32,
  85. RELOC_TPOFF,
  86. RELOC_TLSGD,
  87. RELOC_TLSDESC,
  88. RELOC_TLS_CALL,
  89. RELOC_ARM_CALL,
  90. {$endif arm}
  91. {$ifdef aarch64}
  92. RELOC_ABSOLUTE32,
  93. RELOC_RELATIVE_26,
  94. RELOC_RELATIVE_19,
  95. RELOC_ADR_PREL_LO21,
  96. RELOC_ADR_PREL_PG_HI21,
  97. RELOC_ADD_ABS_LO12,
  98. RELOC_LDST8_ABS_LO12,
  99. {$endif aarch64}
  100. {$ifdef z80}
  101. RELOC_ABSOLUTE_HI8,
  102. RELOC_ABSOLUTE_LO8,
  103. {$endif z80}
  104. {$ifdef WASM32}
  105. RELOC_FUNCTION_INDEX_LEB,
  106. RELOC_MEMORY_ADDR_LEB,
  107. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB,
  108. RELOC_TYPE_INDEX_LEB,
  109. RELOC_GLOBAL_INDEX_LEB,
  110. RELOC_TAG_INDEX_LEB,
  111. {$endif WASM32}
  112. { Relative relocation }
  113. RELOC_RELATIVE,
  114. { PECoff (Windows) RVA relocation }
  115. RELOC_RVA,
  116. { PECoff (Windows) section relocation, required by DWARF2 debug info }
  117. RELOC_SECREL32,
  118. { Generate a 0 value at the place of the relocation,
  119. this is used to remove unused vtable entries }
  120. RELOC_ZERO,
  121. { No relocation is needed. It is used in ARM object files.
  122. Also internal linker use this reloc to make virtual (not real)
  123. links to some sections }
  124. RELOC_NONE,
  125. { Darwin relocation, using PAIR }
  126. RELOC_PIC_PAIR,
  127. { Relative to GOT/gp }
  128. RELOC_GOTOFF,
  129. { Untranslated target-specific value }
  130. RELOC_RAW,
  131. { offset in TLS block }
  132. RELOC_DTPOFF
  133. );
  134. {$if defined(x86_64) or defined(aarch64)}
  135. { no special aliases for x86_64 }
  136. {$elseif defined(i8086)}
  137. const
  138. RELOC_ABSOLUTE16 = RELOC_ABSOLUTE;
  139. RELOC_RELATIVE16 = RELOC_RELATIVE;
  140. {$else}
  141. const
  142. RELOC_ABSOLUTE32 = RELOC_ABSOLUTE;
  143. {$endif}
  144. const
  145. { stab types }
  146. N_GSYM = $20;
  147. N_STSYM = 38; { initialized const }
  148. N_LCSYM = 40; { non initialized variable}
  149. N_Function = $24; { function or const }
  150. N_TextLine = $44;
  151. N_DataLine = $46;
  152. N_BssLine = $48;
  153. N_RSYM = $40; { register variable }
  154. N_LSYM = $80;
  155. N_tsym = 160;
  156. N_SourceFile = $64;
  157. N_IncludeFile = $84;
  158. N_BINCL = $82;
  159. N_EINCL = $A2;
  160. N_LBRAC = $C0;
  161. N_EXCL = $C2;
  162. N_RBRAC = $E0;
  163. { GNU extensions }
  164. debuglinkname='.gnu_debuglink';
  165. { TObjRelocation.flags }
  166. { 'ftype' field contains platform-specific value }
  167. rf_raw = 1;
  168. { relocation must be added to dynamic list }
  169. rf_dynamic = 2;
  170. { relocation target is absent/irrelevant (e.g. R_ARM_V4BX) }
  171. rf_nosymbol = 4;
  172. type
  173. TObjSectionOption = (
  174. { Has Data available in the file }
  175. oso_Data,
  176. { Is loaded into memory }
  177. oso_load,
  178. { Writable }
  179. oso_write,
  180. { Contains executable instructions }
  181. oso_executable,
  182. { Never discard section }
  183. oso_keep,
  184. { Procedure Linkage Table specific treatment }
  185. oso_plt,
  186. { Contains debug info and can be stripped }
  187. oso_debug,
  188. { Contains only strings }
  189. oso_strings,
  190. { Must be cloned when writing separate debug file }
  191. oso_debug_copy,
  192. { Has relocations with explicit addends (ELF-specific) }
  193. oso_rela_relocs,
  194. { Supports bss-like allocation of data, even though it is written in file (i.e. also has oso_Data) }
  195. oso_sparse_data,
  196. { Section to support the resolution of multiple symbols with the same name }
  197. oso_comdat,
  198. { section containing thread variables }
  199. oso_threadvar,
  200. { being a notes section }
  201. oso_note,
  202. { arm attributes section }
  203. oso_arm_attributes
  204. );
  205. TObjSectionOptions = set of TObjSectionOption;
  206. TObjSectionComdatSelection = (
  207. { Section is not a COMDAT section }
  208. oscs_none,
  209. { Select any of the symbols }
  210. oscs_any,
  211. { Select any symbol, but abort if they differ in size }
  212. oscs_same_size,
  213. { Select any symbol, but abort if they differ in size or content }
  214. oscs_exact_match,
  215. { Select the symbol only if the associated symbol is linked as well }
  216. oscs_associative,
  217. { Select the largest symbol }
  218. oscs_largest
  219. );
  220. {$ifdef i8086}
  221. { allow 32-bit sections on i8086. Useful for the dwarf debug info, as well
  222. as to allow linking 32-bit obj modules. }
  223. TObjSectionOfs = LongWord;
  224. {$else i8086}
  225. TObjSectionOfs = PUInt;
  226. {$endif i8086}
  227. TObjSectionGroup = class;
  228. TObjSymbol = class(TFPHashObject)
  229. public
  230. bind : TAsmsymbind;
  231. typ : TAsmsymtype;
  232. { Current assemble pass, used to detect duplicate labels }
  233. pass : byte;
  234. { how the symbol is referenced (target-specific bitfield) }
  235. refs : byte;
  236. symidx : longint;
  237. objsection : TObjSection;
  238. offset,
  239. size : TObjSectionOfs;
  240. { Used for external and common solving during linking }
  241. exesymbol : TExeSymbol;
  242. { Darwin asm is using indirect symbols resolving }
  243. indsymbol : TObjSymbol;
  244. { Used by the OMF object format and its complicated relocation records }
  245. group: TObjSectionGroup;
  246. {$ifdef ARM}
  247. ThumbFunc : boolean;
  248. {$endif ARM}
  249. constructor create(AList:TFPHashObjectList;const AName:string);virtual;
  250. function ToString:ansistring;override;
  251. function address:qword;
  252. procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  253. function ObjData: TObjData;
  254. { string representation for the linker map file }
  255. function AddressStr(AImageBase: qword): string;virtual;
  256. end;
  257. TObjSymbolClass = class of TObjSymbol;
  258. { Stabs is common for all targets }
  259. TObjStabEntry=packed record
  260. strpos : longint;
  261. ntype : byte;
  262. nother : byte;
  263. ndesc : word;
  264. nvalue : longint;
  265. end;
  266. PObjStabEntry=^TObjStabEntry;
  267. TObjRelocation = class
  268. private
  269. function GetType:TObjRelocationType;
  270. procedure SetType(v:TObjRelocationType);
  271. public
  272. DataOffset,
  273. orgsize : TObjSectionOfs; { COFF: original size of the symbol to relocate }
  274. { ELF: explicit addend }
  275. symbol : TObjSymbol;
  276. objsection : TObjSection; { only used if symbol=nil }
  277. group : TObjSectionGroup; { only used if symbol=nil and objsection=nil }
  278. ftype : byte;
  279. size : byte;
  280. flags : byte;
  281. constructor CreateSymbol(ADataOffset:TObjSectionOfs;s:TObjSymbol;Atyp:TObjRelocationType);
  282. constructor CreateSection(ADataOffset:TObjSectionOfs;aobjsec:TObjSection;Atyp:TObjRelocationType);
  283. constructor CreateGroup(ADataOffset:TObjSectionOfs;grp:TObjSectionGroup;Atyp:TObjRelocationType);
  284. constructor CreateRaw(ADataOffset:TObjSectionOfs;s:TObjSymbol;ARawType:byte);
  285. function TargetName:TSymStr;
  286. function ToString: ansistring; override;
  287. property typ: TObjRelocationType read GetType write SetType;
  288. end;
  289. TObjSection = class(TFPHashObject)
  290. private
  291. FData : TDynamicArray;
  292. FSecOptions : TObjSectionOptions;
  293. FCachedFullName : pshortstring;
  294. FSizeLimit : TObjSectionOfs;
  295. procedure SetSecOptions(Aoptions:TObjSectionOptions);
  296. procedure SectionTooLargeError;
  297. protected
  298. function GetAltName: string; virtual;
  299. public
  300. ObjData : TObjData;
  301. index : longword; { index of section in section headers }
  302. SecSymIdx : longint; { index for the section in symtab }
  303. SecAlign : longint; { alignment of the section }
  304. { section Data }
  305. Size,
  306. DataPos : TObjSectionOfs;
  307. MemPos : qword;
  308. Group : TObjSectionGroup;
  309. AssociativeSection : TObjSection;
  310. ComdatSelection : TObjSectionComdatSelection;
  311. DataAlignBytes : shortint;
  312. { Relocations (=references) to other sections }
  313. ObjRelocations : TFPObjectList;
  314. { executable linking }
  315. ExeSection : TExeSection;
  316. USed : Boolean;
  317. VTRefList : TFPObjectList;
  318. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);virtual;
  319. destructor destroy;override;
  320. function ToString:ansistring;override;
  321. function write(const d;l:TObjSectionOfs):TObjSectionOfs;
  322. procedure writeInt8(v: int8);
  323. procedure writeInt16LE(v: int16);
  324. procedure writeInt16BE(v: int16);
  325. procedure writeInt32LE(v: int32);
  326. procedure writeInt32BE(v: int32);
  327. procedure writeInt64LE(v: int64);
  328. procedure writeInt64BE(v: int64);
  329. procedure writeUInt8(v: uint8);
  330. procedure writeUInt16LE(v: uint16);
  331. procedure writeUInt16BE(v: uint16);
  332. procedure writeUInt32LE(v: uint32);
  333. procedure writeUInt32BE(v: uint32);
  334. procedure writeUInt64LE(v: uint64);
  335. procedure writeUInt64BE(v: uint64);
  336. { writes string plus zero byte }
  337. function writestr(const s:string):TObjSectionOfs;
  338. function WriteZeros(l:longword):TObjSectionOfs;
  339. { writes content of s without null termination }
  340. function WriteBytes(const s:string):TObjSectionOfs;
  341. procedure writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);virtual;
  342. function setmempos(mpos:qword):qword;
  343. procedure setDatapos(var dpos:TObjSectionOfs);
  344. procedure alloc(l:TObjSectionOfs);
  345. procedure addsymReloc(ofs:TObjSectionOfs;p:TObjSymbol;Reloctype:TObjRelocationType);
  346. procedure addsectionReloc(ofs:TObjSectionOfs;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  347. procedure addrawReloc(ofs:TObjSectionOfs;p:TObjSymbol;RawReloctype:byte);
  348. procedure ReleaseData;
  349. function FullName:string;
  350. { string representation for the linker map file }
  351. function MemPosStr(AImageBase: qword): string;virtual;
  352. property Data:TDynamicArray read FData;
  353. property SecOptions:TObjSectionOptions read FSecOptions write SetSecOptions;
  354. property SizeLimit:TObjSectionOfs read FSizeLimit write FSizeLimit;
  355. end;
  356. TObjSectionClass = class of TObjSection;
  357. TObjSectionGroup = class(TFPHashObject)
  358. public
  359. index: longword; { index of group in group headers }
  360. members: array of TObjSection;
  361. iscomdat: boolean;
  362. end;
  363. TObjSectionGroupClass = class of TObjSectionGroup;
  364. TString80 = string[80];
  365. TObjSymbolList = class(TFPHashObjectList)
  366. public
  367. Owner: TObjData;
  368. end;
  369. {$if defined(i8086)}
  370. { on i8086 we use a longint, to support 32-bit relocations as well (e.g.
  371. for allowing 386+ instructions with 32-bit addresses in inline asm code) }
  372. TRelocDataInt = longint;
  373. {$elseif defined(cpu16bitaddr)}
  374. TRelocDataInt = asizeint;
  375. {$else}
  376. TRelocDataInt = aint;
  377. {$endif}
  378. TObjData = class(TLinkedListItem)
  379. private
  380. FCurrObjSec : TObjSection;
  381. FObjSectionList : TFPHashObjectList;
  382. FCObjSymbol : TObjSymbolClass;
  383. FCObjSection : TObjSectionClass;
  384. FCObjSectionGroup: TObjSectionGroupClass;
  385. { Symbols that will be defined in this object file }
  386. FObjSymbolList : TObjSymbolList;
  387. FCachedAsmSymbolList : TFPObjectList;
  388. { Special info sections that are written to during object generation }
  389. FStabsObjSec,
  390. FStabStrObjSec : TObjSection;
  391. FGroupsList : TFPHashObjectList;
  392. FCPUType : tcputype;
  393. procedure section_reset(p:TObject;arg:pointer);
  394. procedure section_afteralloc(p:TObject;arg:pointer);
  395. procedure section_afterwrite(p:TObject;arg:pointer);
  396. protected
  397. FName : TString80;
  398. property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
  399. property CObjSectionGroup: TObjSectionGroupClass read FCObjSectionGroup write FCObjSectionGroup;
  400. public
  401. CurrPass : byte;
  402. ExecStack : boolean;
  403. {$ifdef ARM}
  404. ThumbFunc : boolean;
  405. {$endif ARM}
  406. constructor create(const n:string);virtual;
  407. destructor destroy;override;
  408. { Sections }
  409. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;abstract;
  410. class function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
  411. function sectiontype2align(atype:TAsmSectiontype):longint;virtual;
  412. class procedure sectiontype2progbitsandflags(atype:TAsmSectiontype;out progbits:TSectionProgbits;out flags:TSectionFlags);virtual;
  413. function createsection(atype:TAsmSectionType;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;virtual;
  414. function createsection(atype:TAsmSectionType;secflags:TSectionFlags;aprogbits:TSectionProgbits;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;virtual;
  415. function createsection(const aname:string;aalign:longint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean=true):TObjSection;virtual;
  416. function createsectiongroup(const aname:string):TObjSectionGroup;
  417. procedure CreateDebugSections;virtual;
  418. function findsection(const aname:string):TObjSection;
  419. procedure setsection(asec:TObjSection);
  420. { Symbols }
  421. function createsymbol(const aname:string):TObjSymbol;
  422. function symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  423. function symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  424. function symbolref(asmsym:TAsmSymbol):TObjSymbol;
  425. function symbolref(const aname:string):TObjSymbol;
  426. procedure symbolpairdefine(akind: TSymbolPairKind;const asym, avalue: string);virtual;
  427. procedure ResetCachedAsmSymbols;
  428. { Allocation }
  429. procedure alloc(len:TObjSectionOfs);
  430. procedure allocalign(len:longint);
  431. procedure writebytes(const Data;len:TObjSectionOfs);
  432. procedure writebytes(const Data : TByteDynArray;len:TObjSectionOfs);
  433. procedure writebytes(const Data : TAnsiCharDynArray;len:TObjSectionOfs);
  434. procedure writeInt8(v: int8);
  435. procedure writeInt16LE(v: int16);
  436. procedure writeInt16BE(v: int16);
  437. procedure writeInt32LE(v: int32);
  438. procedure writeInt32BE(v: int32);
  439. procedure writeInt64LE(v: int64);
  440. procedure writeInt64BE(v: int64);
  441. procedure writeUInt8(v: uint8);
  442. procedure writeUInt16LE(v: uint16);
  443. procedure writeUInt16BE(v: uint16);
  444. procedure writeUInt32LE(v: uint32);
  445. procedure writeUInt32BE(v: uint32);
  446. procedure writeUInt64LE(v: uint64);
  447. procedure writeUInt64BE(v: uint64);
  448. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);virtual;abstract;
  449. procedure beforealloc;virtual;
  450. procedure beforewrite;virtual;
  451. procedure afteralloc;virtual;
  452. procedure afterwrite;virtual;
  453. procedure resetsections;
  454. procedure layoutsections(var datapos:TObjSectionOfs);
  455. property Name:TString80 read FName;
  456. property CurrObjSec:TObjSection read FCurrObjSec;
  457. property ObjSymbolList:TObjSymbolList read FObjSymbolList;
  458. property ObjSectionList:TFPHashObjectList read FObjSectionList;
  459. property GroupsList:TFPHashObjectList read FGroupsList;
  460. property StabsSec:TObjSection read FStabsObjSec write FStabsObjSec;
  461. property StabStrSec:TObjSection read FStabStrObjSec write FStabStrObjSec;
  462. property CObjSymbol: TObjSymbolClass read FCObjSymbol write FCObjSymbol;
  463. { Current CPU type for the internal asm writer.
  464. Instructions, not supported by the given CPU should produce an error.
  465. A value of 'cpu_none' means no restrictions (all instructions should be accepted) }
  466. property CPUType : tcputype read FCPUType write FCPUType;
  467. end;
  468. TObjDataClass = class of TObjData;
  469. TObjOutput = class
  470. private
  471. FCObjData : TObjDataClass;
  472. protected
  473. { writer }
  474. FWriter : TObjectwriter;
  475. function writeData(Data:TObjData):boolean;virtual;abstract;
  476. property CObjData : TObjDataClass read FCObjData write FCObjData;
  477. procedure WriteSectionContent(Data:TObjData);
  478. public
  479. constructor create(AWriter:TObjectWriter);virtual;
  480. destructor destroy;override;
  481. function newObjData(const n:string):TObjData;
  482. function startObjectfile(const fn:string):boolean;
  483. function writeobjectfile(Data:TObjData):boolean;
  484. procedure exportsymbol(p:TObjSymbol);
  485. property Writer:TObjectWriter read FWriter;
  486. end;
  487. TObjOutputClass=class of TObjOutput;
  488. TObjInput = class
  489. private
  490. FCObjData : TObjDataClass;
  491. protected
  492. { reader }
  493. FReader : TObjectReader;
  494. InputFileName : string;
  495. property CObjData : TObjDataClass read FCObjData write FCObjData;
  496. procedure ReadSectionContent(Data:TObjData);
  497. public
  498. constructor create;virtual;
  499. function ReadObjData(AReader:TObjectreader;out Data:TObjData):boolean;virtual;abstract;
  500. class function CanReadObjData(AReader:TObjectreader):boolean;virtual;
  501. procedure inputerror(const s : string);
  502. end;
  503. TObjInputClass=class of TObjInput;
  504. TVTableEntry=record
  505. ObjRelocation : TObjRelocation;
  506. orgreloctype,
  507. orgrelocflags : byte;
  508. Enabled,
  509. Used : Boolean;
  510. end;
  511. PVTableEntry=^TVTableEntry;
  512. TExeVTable = class
  513. private
  514. procedure CheckIdx(VTableIdx:longint);
  515. public
  516. ExeSymbol : TExeSymbol;
  517. EntryCnt : Longint;
  518. EntryArray : PVTableEntry;
  519. Consolidated : Boolean;
  520. ChildList : TFPObjectList;
  521. constructor Create(AExeSymbol:TExeSymbol);
  522. destructor Destroy;override;
  523. procedure AddChild(vt:TExeVTable);
  524. procedure AddEntry(VTableIdx:Longint);
  525. procedure SetVTableSize(ASize:longint);
  526. function VTableRef(VTableIdx:Longint):TObjRelocation;
  527. end;
  528. TSymbolState = (
  529. symstate_undefined,
  530. symstate_undefweak, // undefined but has only weak refs - don't complain
  531. symstate_defined,
  532. symstate_defweak,
  533. symstate_common,
  534. symstate_dynamic // a matching symbol has been seen in .so
  535. );
  536. TExeSymbol = class(TFPHashObject)
  537. ObjSymbol : TObjSymbol;
  538. State : TSymbolState;
  539. used : boolean;
  540. { Used for vmt references optimization }
  541. VTable : TExeVTable;
  542. { fields for ELF linking }
  543. gotoffset : aword;
  544. dynindex : aword;
  545. { A thunk used to redirect some references to symbol (like absolute
  546. jumps/calls to PIC code).
  547. This probably is also needed for ARM/Thumb interworking and alike.
  548. TODO: consider reusing objsymbol.indsymbol for this purpose }
  549. {$ifdef mips}
  550. stubsymbol : TObjSymbol;
  551. {$endif mips}
  552. end;
  553. TExeSection = class(TFPHashObject)
  554. private
  555. FSecSymIdx : longint;
  556. FObjSectionList : TFPObjectList;
  557. public
  558. Size,
  559. DataPos,
  560. MemPos : qword;
  561. SecAlign : longint;
  562. Disabled : boolean;
  563. SecOptions : TObjSectionOptions;
  564. constructor create(AList:TFPHashObjectList;const AName:string);virtual;
  565. destructor destroy;override;
  566. procedure AddObjSection(objsec:TObjSection;ignoreprops:boolean=false);virtual;
  567. { string representation for the linker map file }
  568. function MemPosStr(AImageBase: qword): string;virtual;
  569. property ObjSectionList:TFPObjectList read FObjSectionList;
  570. property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
  571. end;
  572. TExeSectionClass=class of TExeSection;
  573. TlibKind = (lkArchive,lkObject,lkGroup);
  574. TStaticLibrary = class(TObject)
  575. private
  576. FName : TCmdStr;
  577. FPayload : TObject; { lkArchive: TObjectReader }
  578. { lkObject: TObjData }
  579. { lkGroup: TFPObjectList }
  580. FObjInputClass : TObjInputClass;
  581. FKind: TlibKind;
  582. FAsNeeded : Boolean;
  583. function GetArReader:TObjectReader;
  584. function GetGroupMembers:TFPObjectList;
  585. function GetObjData:TObjData;
  586. public
  587. constructor create(const AName:TCmdStr;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  588. constructor create_object(AObjData:TObjData);
  589. constructor create_group;
  590. destructor destroy;override;
  591. property ArReader:TObjectReader read GetArReader;
  592. property ObjInputClass:TObjInputClass read FObjInputClass;
  593. property GroupMembers:TFPObjectList read GetGroupMembers;
  594. property ObjData:TObjData read GetObjData;
  595. property AsNeeded:Boolean read FAsNeeded write FAsNeeded;
  596. property Kind:TLibKind read FKind;
  597. end;
  598. TImportLibrary = class(TFPHashObject)
  599. private
  600. FImportSymbolList : TFPHashObjectList;
  601. public
  602. constructor create(AList:TFPHashObjectList;const AName:string);
  603. destructor destroy;override;
  604. property ImportSymbolList:TFPHashObjectList read FImportSymbolList;
  605. end;
  606. TImportSymbol = class(TFPHashObject)
  607. private
  608. FOrdNr : longint;
  609. FIsVar : boolean;
  610. FMangledName : string;
  611. FCachedExeSymbol: TExeSymbol;
  612. public
  613. constructor create(AList:TFPHashObjectList;const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
  614. property OrdNr: longint read FOrdNr;
  615. property MangledName: string read FMangledName;
  616. property IsVar: boolean read FIsVar;
  617. property CachedExeSymbol: TExeSymbol read FCachedExeSymbol write FCachedExeSymbol;
  618. end;
  619. TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);
  620. TExeOutput = class
  621. private
  622. { ExeSectionList }
  623. FCObjSymbol : TObjSymbolClass;
  624. FCObjData : TObjDataClass;
  625. FCExeSection : TExeSectionClass;
  626. FCurrExeSec : TExeSection;
  627. FExeSectionList : TFPHashObjectList;
  628. Fzeronr : longint;
  629. Fvaluesnr : longint;
  630. { Symbols }
  631. FExeSymbolList : TFPHashObjectList;
  632. FUnresolvedExeSymbols : TFPObjectList;
  633. FExternalObjSymbols,
  634. FCommonObjSymbols : TFPObjectList;
  635. FProvidedObjSymbols : TFPObjectList;
  636. FIndirectObjSymbols : TFPObjectList;
  637. FEntryName : string;
  638. FExeVTableList : TFPObjectList;
  639. { Objects }
  640. FObjDataList : TFPObjectList;
  641. { Position calculation }
  642. FImageBase : qword;
  643. FCurrMemPos : qword;
  644. procedure SetCurrMemPos(const AValue: qword);
  645. protected
  646. { writer }
  647. FExeWriteMode : TExeWriteMode;
  648. FWriter : TObjectwriter;
  649. commonObjSection : TObjSection;
  650. internalObjData : TObjData;
  651. EntrySym : TObjSymbol;
  652. SectionDataAlign,
  653. SectionMemAlign : aword;
  654. ComdatGroups : TFPHashList;
  655. FixedSectionAlign : boolean;
  656. AllowUndefinedSymbols : boolean;
  657. function writeData:boolean;virtual;abstract;
  658. property CExeSection:TExeSectionClass read FCExeSection write FCExeSection;
  659. property CObjData:TObjDataClass read FCObjData write FCObjData;
  660. property CObjSymbol:TObjSymbolClass read FCObjSymbol write FCObjSymbol;
  661. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);virtual;
  662. procedure WriteExeSectionContent;
  663. procedure DoRelocationFixup(objsec:TObjSection);virtual;abstract;
  664. function MemAlign(exesec: TExeSection): longword;
  665. function DataAlign(exesec: TExeSection): longword;
  666. procedure ReplaceExeSectionList(newlist: TFPList);
  667. public
  668. CurrDataPos : aword;
  669. MaxMemPos : qword;
  670. IsSharedLibrary : boolean;
  671. ExecStack : boolean;
  672. constructor create;virtual;
  673. destructor destroy;override;
  674. function FindExeSection(const aname:string):TExeSection;
  675. procedure AddObjData(ObjData:TObjData);
  676. procedure Load_Start;virtual;
  677. procedure Load_EntryName(const aname:string);virtual;
  678. procedure Load_Symbol(const aname:string);virtual;
  679. procedure Load_ProvideSymbol(const aname:string);virtual;
  680. procedure Load_IsSharedLibrary;
  681. procedure Load_ImageBase(const avalue:string);
  682. procedure Load_DynamicObject(ObjData:TObjData;asneeded:boolean);virtual;
  683. procedure Order_Start;virtual;
  684. procedure Order_End;virtual;
  685. procedure Order_ExeSection(const aname:string);virtual;
  686. procedure Order_Align(const avalue:string);virtual;
  687. procedure Order_Zeros(const avalue:string);virtual;
  688. procedure Order_Values(bytesize : aword; const avalue:string);virtual;
  689. procedure Order_Symbol(const aname:string);virtual;
  690. procedure Order_ProvideSymbol(const aname:string);virtual;
  691. procedure Order_EndExeSection;virtual;
  692. procedure Order_ObjSection(const aname:string);virtual;
  693. procedure MemPos_Start;virtual;
  694. procedure MemPos_Header;virtual;
  695. procedure MemPos_ExeSection(exesec:TExeSection);
  696. procedure MemPos_ExeSection(const aname:string);virtual;
  697. procedure MemPos_EndExeSection;virtual;
  698. procedure DataPos_Start;virtual;
  699. procedure DataPos_Header;virtual;
  700. procedure DataPos_ExeSection(exesec:TExeSection);
  701. procedure DataPos_ExeSection(const aname:string);virtual;
  702. procedure DataPos_EndExeSection;virtual;
  703. procedure DataPos_Symbols;virtual;
  704. procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  705. procedure PackUnresolvedExeSymbols(const s:string);
  706. procedure ResolveSymbols(StaticLibraryList:TFPObjectList);
  707. procedure PrintMemoryMap;
  708. procedure FixupSymbols;
  709. procedure FixupRelocations;virtual;
  710. procedure RemoveUnusedExeSymbols;
  711. procedure MergeStabs;
  712. procedure MarkEmptySections;
  713. procedure RemoveUnreferencedSections;
  714. procedure RemoveDisabledSections;
  715. procedure RemoveDebugInfo;
  716. procedure MarkTargetSpecificSections(WorkList:TFPObjectList);virtual;
  717. procedure AfterUnusedSectionRemoval;virtual;
  718. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual;
  719. procedure GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  720. function WriteExeFile(const fn:string):boolean;
  721. procedure ParseScript (linkscript:TCmdStrList); virtual;
  722. property Writer:TObjectWriter read FWriter;
  723. property ExeSectionList:TFPHashObjectList read FExeSectionList;
  724. property ObjDataList:TFPObjectList read FObjDataList;
  725. property ExeSymbolList:TFPHashObjectList read FExeSymbolList;
  726. property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
  727. property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols;
  728. property CommonObjSymbols:TFPObjectList read FCommonObjSymbols;
  729. property IndirectObjSymbols:TFPObjectList read FIndirectObjSymbols;
  730. property ExeVTableList:TFPObjectList read FExeVTableList;
  731. property EntryName:string read FEntryName write FEntryName;
  732. property ImageBase:qword read FImageBase write FImageBase;
  733. property CurrExeSec:TExeSection read FCurrExeSec;
  734. property ExeWriteMode:TExeWriteMode read FExeWriteMode write FExeWriteMode;
  735. property CurrMemPos:qword read FCurrMemPos write SetCurrMemPos;
  736. end;
  737. TExeOutputClass=class of TExeOutput;
  738. const
  739. SectionDataMaxGrow = 4096;
  740. var
  741. exeoutput : TExeOutput;
  742. function align_aword(v:aword;a:longword):aword;
  743. function align_qword(v:qword;a:longword):qword;
  744. function align_objsecofs(v:TObjSectionOfs;a:longword):TObjSectionOfs;
  745. procedure MaybeSwapStab(var v:TObjStabEntry);
  746. implementation
  747. uses
  748. SysUtils,
  749. globals,verbose,
  750. {$ifdef OMFOBJSUPPORT}
  751. omfbase,
  752. {$endif OMFOBJSUPPORT}
  753. ogmap;
  754. {$ifdef MEMDEBUG}
  755. var
  756. memobjsymbols,
  757. memobjsections : TMemDebug;
  758. {$endif MEMDEBUG}
  759. {*****************************************************************************
  760. Helpers
  761. *****************************************************************************}
  762. function align_aword(v:aword;a:longword):aword;
  763. begin
  764. if a>0 then
  765. a:=a-1;
  766. result:=(v+a) and aword(not aword(a));
  767. end;
  768. function align_qword(v:qword;a:longword):qword;
  769. begin
  770. if a>0 then
  771. a:=a-1;
  772. result:=(v+a) and qword(not qword(a));
  773. end;
  774. function align_objsecofs(v:TObjSectionOfs;a:longword):TObjSectionOfs;
  775. begin
  776. if a>0 then
  777. a:=a-1;
  778. result:=(v+a) and TObjSectionOfs(not TObjSectionOfs(a));
  779. end;
  780. procedure MaybeSwapStab(var v:TObjStabEntry);
  781. begin
  782. if source_info.endian<>target_info.endian then
  783. begin
  784. v.strpos:=SwapEndian(v.strpos);
  785. v.nvalue:=SwapEndian(v.nvalue);
  786. v.ndesc:=SwapEndian(v.ndesc);
  787. end;
  788. end;
  789. {*****************************************************************************
  790. TObjSymbol
  791. *****************************************************************************}
  792. constructor TObjSymbol.create(AList:TFPHashObjectList;const AName:string);
  793. begin
  794. inherited create(AList,AName);
  795. bind:=AB_EXTERNAL;
  796. typ:=AT_NONE;
  797. symidx:=-1;
  798. size:=0;
  799. offset:=0;
  800. objsection:=nil;
  801. end;
  802. function TObjSymbol.ToString: ansistring;
  803. var
  804. objsectionstr: ansistring;
  805. begin
  806. if Assigned(objsection) then
  807. objsectionstr:=objsection.ToString
  808. else
  809. objsectionstr:='nil';
  810. WriteStr(Result,'(Name:',Name,';bind:',bind,';typ:',typ,';pass:',pass,
  811. ';refs:',refs,';symidx:',symidx,';objsection:',objsectionstr,';offset:',
  812. offset,';size:',size,')');
  813. end;
  814. function TObjSymbol.address:qword;
  815. begin
  816. if assigned(objsection) then
  817. result:=offset+objsection.mempos
  818. else
  819. result:=0;
  820. end;
  821. procedure TObjSymbol.SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  822. begin
  823. if not(abind in [AB_GLOBAL,AB_PRIVATE_EXTERN,AB_LOCAL,AB_COMMON,AB_IMPORT,AB_WEAK]) then
  824. internalerror(200603016);
  825. if not assigned(aobjsec) then
  826. internalerror(200603017);
  827. if (bind in [AB_EXTERNAL,AB_LAZY]) or
  828. { Put all COMMON to GLOBAL in step 3 of
  829. TExeOutput.ResolveSymbols }
  830. ((abind=AB_GLOBAL) and (bind=AB_COMMON)) then
  831. begin
  832. { Do not change the AB_TYPE of common symbols yet }
  833. { This will be done in FixupSymbols }
  834. if (pass<>0) or (bind<>AB_COMMON) then
  835. bind:=abind;
  836. typ:=atyp;
  837. end
  838. else
  839. begin
  840. if pass=apass then
  841. begin
  842. Message1(asmw_e_duplicate_label,name);
  843. exit;
  844. end;
  845. end;
  846. pass:=apass;
  847. { Code can never grow after a pass }
  848. if assigned(objsection) and
  849. (objsection=aobjsec) and
  850. (aobjsec.size>offset) then
  851. internalerror(200603014);
  852. objsection:=aobjsec;
  853. offset:=aobjsec.size;
  854. end;
  855. function TObjSymbol.ObjData: TObjData;
  856. begin
  857. result:=(OwnerList as TObjSymbolList).Owner;
  858. end;
  859. function TObjSymbol.AddressStr(AImageBase: qword): string;
  860. begin
  861. Result:='0x'+HexStr(address+Aimagebase,sizeof(pint)*2);
  862. end;
  863. {****************************************************************************
  864. TObjRelocation
  865. ****************************************************************************}
  866. constructor TObjRelocation.CreateSymbol(ADataOffset:TObjSectionOfs;s:TObjSymbol;Atyp:TObjRelocationType);
  867. begin
  868. if not assigned(s) then
  869. internalerror(200603034);
  870. DataOffset:=ADataOffset;
  871. Symbol:=s;
  872. OrgSize:=0;
  873. Group:=nil;
  874. ObjSection:=nil;
  875. ftype:=ord(Atyp);
  876. end;
  877. constructor TObjRelocation.CreateSection(ADataOffset:TObjSectionOfs;aobjsec:TObjSection;Atyp:TObjRelocationType);
  878. begin
  879. if not assigned(aobjsec) then
  880. internalerror(200603036);
  881. DataOffset:=ADataOffset;
  882. Symbol:=nil;
  883. OrgSize:=0;
  884. Group:=nil;
  885. ObjSection:=aobjsec;
  886. ftype:=ord(Atyp);
  887. end;
  888. constructor TObjRelocation.CreateGroup(ADataOffset:TObjSectionOfs;grp:TObjSectionGroup;Atyp:TObjRelocationType);
  889. begin
  890. if not assigned(grp) then
  891. internalerror(2015111201);
  892. DataOffset:=ADataOffset;
  893. Symbol:=nil;
  894. ObjSection:=nil;
  895. OrgSize:=0;
  896. Group:=grp;
  897. ftype:=ord(Atyp);
  898. end;
  899. constructor TObjRelocation.CreateRaw(ADataOffset:TObjSectionOfs;s:TObjSymbol;ARawType:byte);
  900. begin
  901. { nil symbol is allowed here }
  902. DataOffset:=ADataOffset;
  903. Symbol:=s;
  904. ObjSection:=nil;
  905. Group:=nil;
  906. orgsize:=0;
  907. ftype:=ARawType;
  908. flags:=rf_raw;
  909. end;
  910. function TObjRelocation.GetType:TObjRelocationType;
  911. begin
  912. if (flags and rf_raw)=0 then
  913. result:=TObjRelocationType(ftype)
  914. else
  915. result:=RELOC_RAW;
  916. end;
  917. procedure TObjRelocation.SetType(v:TObjRelocationType);
  918. begin
  919. ftype:=ord(v);
  920. flags:=flags and (not rf_raw);
  921. end;
  922. function TObjRelocation.TargetName:TSymStr;
  923. begin
  924. if assigned(symbol) then
  925. if symbol.typ=AT_SECTION then
  926. result:=symbol.objsection.name
  927. else
  928. result:=symbol.Name
  929. else
  930. result:=objsection.Name;
  931. end;
  932. function TObjRelocation.ToString: ansistring;
  933. var
  934. typstr,
  935. symbolstr,
  936. objsectionstr,
  937. groupstr: ansistring;
  938. begin
  939. Str(typ,typstr);
  940. if Assigned(symbol) then
  941. symbolstr:=symbol.ToString
  942. else
  943. symbolstr:='nil';
  944. if Assigned(objsection) then
  945. objsectionstr:=objsection.ToString
  946. else
  947. objsectionstr:='nil';
  948. if Assigned(group) then
  949. groupstr:=group.ToString
  950. else
  951. groupstr:='nil';
  952. Result:='(typ:'+typstr+';DataOffset:'+tostr(DataOffset)+
  953. ';orgsize:'+tostr(orgsize)+';symbol:'+symbolstr+
  954. ';objsection:'+objsectionstr+';group:'+groupstr+
  955. ';ftype:'+tostr(ftype)+';size:'+tostr(size)+
  956. ';flags:'+tostr(flags)+')';
  957. end;
  958. {****************************************************************************
  959. TObjSection
  960. ****************************************************************************}
  961. constructor TObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);
  962. begin
  963. inherited Create(AList,Aname);
  964. { Data }
  965. Size:=0;
  966. Datapos:=0;
  967. mempos:=0;
  968. FData:=Nil;
  969. {$ifdef i8086}
  970. FSizeLimit:=high(word);
  971. {$else i8086}
  972. FSizeLimit:=high(TObjSectionOfs);
  973. {$endif i8086}
  974. { Setting the secoptions allocates Data if needed }
  975. secoptions:=Aoptions;
  976. if (Aalign and (Aalign-1))<>0 then
  977. internalerror(2022010401); { alignment is not a power of two }
  978. secalign:=Aalign;
  979. secsymidx:=0;
  980. { relocation }
  981. ObjRelocations:=TFPObjectList.Create(true);
  982. VTRefList:=TFPObjectList.Create(false);
  983. end;
  984. destructor TObjSection.destroy;
  985. begin
  986. if assigned(Data) then
  987. begin
  988. FData.Free;
  989. FData := nil;
  990. end;
  991. stringdispose(FCachedFullName);
  992. ObjRelocations.Free;
  993. ObjRelocations := nil;
  994. VTRefList.Free;
  995. VTRefList := nil;
  996. inherited destroy;
  997. end;
  998. function TObjSection.ToString: ansistring;
  999. begin
  1000. System.WriteStr(Result,'(Name:',Name,';index',index,';SecSymIdx:',SecSymIdx,
  1001. ';SecAlign:',SecAlign,';Size:',Size,';DataPos:',DataPos,';MemPos:',
  1002. MemPos,';DataAlignBytes:',DataAlignBytes,';Used:',Used,')');
  1003. end;
  1004. procedure TObjSection.SetSecOptions(Aoptions:TObjSectionOptions);
  1005. begin
  1006. FSecOptions:=FSecOptions+AOptions;
  1007. if (oso_Data in secoptions) and
  1008. not assigned(FData) then
  1009. FData:=TDynamicArray.Create(SectionDataMaxGrow);
  1010. end;
  1011. procedure TObjSection.SectionTooLargeError;
  1012. begin
  1013. if oso_executable in SecOptions then
  1014. Message(asmw_f_code_segment_too_large)
  1015. else
  1016. Message(asmw_f_data_segment_too_large);
  1017. end;
  1018. function TObjSection.GetAltName: string;
  1019. begin
  1020. result:='';
  1021. end;
  1022. function TObjSection.write(const d;l:TObjSectionOfs):TObjSectionOfs;
  1023. begin
  1024. result:=size;
  1025. if assigned(Data) then
  1026. begin
  1027. if Size<>Data.size then
  1028. internalerror(200602281);
  1029. {$ifndef cpu64bitaddr}
  1030. if (qword(size)+l)>SizeLimit then
  1031. SectionTooLargeError;
  1032. {$endif}
  1033. Data.write(d,l);
  1034. inc(Size,l);
  1035. end
  1036. else
  1037. internalerror(200602289);
  1038. end;
  1039. procedure TObjSection.writeInt8(v: int8);
  1040. begin
  1041. write(v,1);
  1042. end;
  1043. procedure TObjSection.writeInt16LE(v: int16);
  1044. begin
  1045. {$ifdef FPC_BIG_ENDIAN}
  1046. v:=SwapEndian(v);
  1047. {$endif FPC_BIG_ENDIAN}
  1048. write(v,2);
  1049. end;
  1050. procedure TObjSection.writeInt16BE(v: int16);
  1051. begin
  1052. {$ifdef FPC_LITTLE_ENDIAN}
  1053. v:=SwapEndian(v);
  1054. {$endif FPC_LITTLE_ENDIAN}
  1055. write(v,2);
  1056. end;
  1057. procedure TObjSection.writeInt32LE(v: int32);
  1058. begin
  1059. {$ifdef FPC_BIG_ENDIAN}
  1060. v:=SwapEndian(v);
  1061. {$endif FPC_BIG_ENDIAN}
  1062. write(v,4);
  1063. end;
  1064. procedure TObjSection.writeInt32BE(v: int32);
  1065. begin
  1066. {$ifdef FPC_LITTLE_ENDIAN}
  1067. v:=SwapEndian(v);
  1068. {$endif FPC_LITTLE_ENDIAN}
  1069. write(v,4);
  1070. end;
  1071. procedure TObjSection.writeInt64LE(v: int64);
  1072. begin
  1073. {$ifdef FPC_BIG_ENDIAN}
  1074. v:=SwapEndian(v);
  1075. {$endif FPC_BIG_ENDIAN}
  1076. write(v,8);
  1077. end;
  1078. procedure TObjSection.writeInt64BE(v: int64);
  1079. begin
  1080. {$ifdef FPC_LITTLE_ENDIAN}
  1081. v:=SwapEndian(v);
  1082. {$endif FPC_LITTLE_ENDIAN}
  1083. write(v,8);
  1084. end;
  1085. procedure TObjSection.writeUInt8(v: uint8);
  1086. begin
  1087. write(v,1);
  1088. end;
  1089. procedure TObjSection.writeUInt16LE(v: uint16);
  1090. begin
  1091. {$ifdef FPC_BIG_ENDIAN}
  1092. v:=SwapEndian(v);
  1093. {$endif FPC_BIG_ENDIAN}
  1094. write(v,2);
  1095. end;
  1096. procedure TObjSection.writeUInt16BE(v: uint16);
  1097. begin
  1098. {$ifdef FPC_LITTLE_ENDIAN}
  1099. v:=SwapEndian(v);
  1100. {$endif FPC_LITTLE_ENDIAN}
  1101. write(v,2);
  1102. end;
  1103. procedure TObjSection.writeUInt32LE(v: uint32);
  1104. begin
  1105. {$ifdef FPC_BIG_ENDIAN}
  1106. v:=SwapEndian(v);
  1107. {$endif FPC_BIG_ENDIAN}
  1108. write(v,4);
  1109. end;
  1110. procedure TObjSection.writeUInt32BE(v: uint32);
  1111. begin
  1112. {$ifdef FPC_LITTLE_ENDIAN}
  1113. v:=SwapEndian(v);
  1114. {$endif FPC_LITTLE_ENDIAN}
  1115. write(v,4);
  1116. end;
  1117. procedure TObjSection.writeUInt64LE(v: uint64);
  1118. begin
  1119. {$ifdef FPC_BIG_ENDIAN}
  1120. v:=SwapEndian(v);
  1121. {$endif FPC_BIG_ENDIAN}
  1122. write(v,8);
  1123. end;
  1124. procedure TObjSection.writeUInt64BE(v: uint64);
  1125. begin
  1126. {$ifdef FPC_LITTLE_ENDIAN}
  1127. v:=SwapEndian(v);
  1128. {$endif FPC_LITTLE_ENDIAN}
  1129. write(v,8);
  1130. end;
  1131. function TObjSection.writestr(const s:string):TObjSectionOfs;
  1132. var
  1133. b: byte;
  1134. begin
  1135. result:=Write(s[1],length(s));
  1136. b:=0;
  1137. Write(b,1);
  1138. end;
  1139. function TObjSection.WriteBytes(const s:string):TObjSectionOfs;
  1140. begin
  1141. result:=Write(s[1],length(s));
  1142. end;
  1143. function TObjSection.WriteZeros(l:longword):TObjSectionOfs;
  1144. var
  1145. empty : array[0..1023] of byte;
  1146. begin
  1147. result:=Size;
  1148. if l>sizeof(empty) then
  1149. begin
  1150. fillchar(empty,sizeof(empty),0);
  1151. while l>sizeof(empty) do
  1152. begin
  1153. Write(empty,sizeof(empty));
  1154. Dec(l,sizeof(empty));
  1155. end;
  1156. if l>0 then
  1157. Write(empty,l);
  1158. end
  1159. else if l>0 then
  1160. begin
  1161. fillchar(empty,l,0);
  1162. Write(empty,l);
  1163. end;
  1164. end;
  1165. { Writes relocation to (section+offset) without need to have a symbol at that location.
  1166. Not an abstract method because not every backend needs this functionality. }
  1167. procedure TObjSection.writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);
  1168. begin
  1169. InternalError(2012081501);
  1170. end;
  1171. procedure TObjSection.setDatapos(var dpos:TObjSectionOfs);
  1172. begin
  1173. if oso_Data in secoptions then
  1174. begin
  1175. { get aligned Datapos }
  1176. Datapos:=align_aword(dpos,secalign);
  1177. Dataalignbytes:=Datapos-dpos;
  1178. { return updated Datapos }
  1179. dpos:=Datapos+size;
  1180. end
  1181. else
  1182. Datapos:=dpos;
  1183. end;
  1184. function TObjSection.setmempos(mpos:qword):qword;
  1185. begin
  1186. mempos:=align_qword(mpos,secalign);
  1187. { return updated mempos }
  1188. result:=mempos+size;
  1189. end;
  1190. procedure TObjSection.alloc(l:TObjSectionOfs);
  1191. begin
  1192. {$ifndef cpu64bitaddr}
  1193. if (qword(size)+l)>SizeLimit then
  1194. SectionTooLargeError;
  1195. {$endif}
  1196. if oso_sparse_data in SecOptions then
  1197. WriteZeros(l)
  1198. else
  1199. inc(size,l);
  1200. end;
  1201. procedure TObjSection.addsymReloc(ofs:TObjSectionOfs;p:TObjSymbol;Reloctype:TObjRelocationType);
  1202. begin
  1203. ObjRelocations.Add(TObjRelocation.CreateSymbol(ofs,p,reloctype));
  1204. end;
  1205. procedure TObjSection.addsectionReloc(ofs:TObjSectionOfs;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  1206. begin
  1207. ObjRelocations.Add(TObjRelocation.CreateSection(ofs,aobjsec,reloctype));
  1208. end;
  1209. procedure TObjSection.addrawReloc(ofs:TObjSectionOfs;p:TObjSymbol;RawReloctype:byte);
  1210. begin
  1211. ObjRelocations.Add(TObjRelocation.CreateRaw(ofs,p,RawReloctype));
  1212. end;
  1213. procedure TObjSection.ReleaseData;
  1214. begin
  1215. if assigned(FData) then
  1216. begin
  1217. FData.free;
  1218. FData:=nil;
  1219. end;
  1220. ObjRelocations.free;
  1221. ObjRelocations:=nil;
  1222. if assigned(FCachedFullName) then
  1223. begin
  1224. stringdispose(FCachedFullName);
  1225. FCachedFullName:=nil;
  1226. end;
  1227. end;
  1228. function TObjSection.FullName:string;
  1229. var
  1230. s: string;
  1231. begin
  1232. if not assigned(FCachedFullName) then
  1233. begin
  1234. s:=GetAltName;
  1235. if s<>'' then
  1236. s:=Name+s
  1237. else
  1238. s:=Name;
  1239. if assigned(ObjData) then
  1240. FCachedFullName:=stringdup(ObjData.Name+'('+s+')')
  1241. else
  1242. FCachedFullName:=stringdup(s);
  1243. end;
  1244. result:=FCachedFullName^;
  1245. end;
  1246. function TObjSection.MemPosStr(AImageBase: qword): string;
  1247. begin
  1248. result:='0x'+HexStr(mempos+AImageBase,sizeof(pint)*2);
  1249. end;
  1250. {****************************************************************************
  1251. TObjData
  1252. ****************************************************************************}
  1253. constructor TObjData.create(const n:string);
  1254. begin
  1255. inherited create;
  1256. FName:=ExtractFileName(n);
  1257. FObjSectionList:=TFPHashObjectList.Create(true);
  1258. FStabsObjSec:=nil;
  1259. FStabStrObjSec:=nil;
  1260. { symbols }
  1261. FCObjSymbol:=TObjSymbol;
  1262. FObjSymbolList:=TObjSymbolList.Create(true);
  1263. FObjSymbolList.Owner:=Self;
  1264. FCachedAsmSymbolList:=TFPObjectList.Create(false);
  1265. { section class type for creating of new sections }
  1266. FCObjSection:=TObjSection;
  1267. FCObjSectionGroup:=TObjSectionGroup;
  1268. {$ifdef ARM}
  1269. ThumbFunc:=false;
  1270. {$endif ARM}
  1271. end;
  1272. destructor TObjData.destroy;
  1273. begin
  1274. { Symbols }
  1275. {$ifdef MEMDEBUG}
  1276. MemObjSymbols.Start;
  1277. {$endif}
  1278. ResetCachedAsmSymbols;
  1279. FCachedAsmSymbolList.free;
  1280. FCachedAsmSymbolList := nil;
  1281. FObjSymbolList.free;
  1282. FObjSymbolList := nil;
  1283. {$ifdef MEMDEBUG}
  1284. MemObjSymbols.Stop;
  1285. {$endif}
  1286. FGroupsList.free;
  1287. FGroupsList := nil;
  1288. { Sections }
  1289. {$ifdef MEMDEBUG}
  1290. MemObjSections.Start;
  1291. {$endif}
  1292. FObjSectionList.free;
  1293. FObjSectionList := nil;
  1294. {$ifdef MEMDEBUG}
  1295. MemObjSections.Stop;
  1296. {$endif}
  1297. inherited destroy;
  1298. end;
  1299. class function TObjData.sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
  1300. const
  1301. secoptions : array[TAsmSectiontype] of TObjSectionOptions = ([],
  1302. {user} [oso_Data,oso_load,oso_write],
  1303. {code} [oso_Data,oso_load,oso_executable],
  1304. {Data} [oso_Data,oso_load,oso_write],
  1305. { Readonly data with relocations must be initially writable for some targets.
  1306. Moreover, e.g. for ELF it depends on whether the executable is linked statically or
  1307. dynamically. }
  1308. {$if defined(support_rodata)}
  1309. {roData} [oso_Data,oso_load],
  1310. {$else defined(support_rodata)}
  1311. {roData} [oso_Data,oso_load,oso_write],
  1312. {$endif defined(support_rodata)}
  1313. {roData_norel} [oso_Data,oso_load],
  1314. {bss} [oso_load,oso_write],
  1315. {threadvar} [oso_load,oso_write,oso_threadvar],
  1316. {pdata} [oso_data,oso_load],
  1317. {stub} [oso_Data,oso_load,oso_executable],
  1318. {data_nonlazy} [oso_Data,oso_load,oso_write],
  1319. {data_lazy} [oso_Data,oso_load,oso_write],
  1320. {init_func} [oso_Data,oso_load],
  1321. {term_func} [oso_Data,oso_load],
  1322. {stab} [oso_Data,oso_debug],
  1323. {stabstr} [oso_Data,oso_strings,oso_debug],
  1324. {iData2} [oso_Data,oso_load,oso_write],
  1325. {iData4} [oso_Data,oso_load,oso_write],
  1326. {iData5} [oso_Data,oso_load,oso_write],
  1327. {iData6} [oso_Data,oso_load,oso_write],
  1328. {iData7} [oso_Data,oso_load,oso_write],
  1329. {eData} [oso_Data,oso_load],
  1330. {eh_frame} [oso_Data,oso_load],
  1331. {debug_frame} [oso_Data,oso_debug],
  1332. {debug_info} [oso_Data,oso_debug],
  1333. {debug_line} [oso_Data,oso_debug],
  1334. {debug_abbrev} [oso_Data,oso_debug],
  1335. {debug_aranges} [oso_Data,oso_debug],
  1336. {debug_ranges} [oso_Data,oso_debug],
  1337. {debug_loc} [oso_Data,oso_debug],
  1338. {debug_loclists} [oso_Data,oso_debug],
  1339. {fpc} [oso_Data,oso_load,oso_write],
  1340. {toc} [oso_Data,oso_load],
  1341. {init} [oso_Data,oso_load,oso_executable],
  1342. {fini} [oso_Data,oso_load,oso_executable],
  1343. {objc_class} [oso_data,oso_load],
  1344. {objc_meta_class} [oso_data,oso_load],
  1345. {objc_cat_cls_meth} [oso_data,oso_load],
  1346. {objc_cat_inst_meth} [oso_data,oso_load],
  1347. {objc_protocol} [oso_data,oso_load],
  1348. {objc_string_object} [oso_data,oso_load],
  1349. {objc_cls_meth} [oso_data,oso_load],
  1350. {objc_inst_meth} [oso_data,oso_load],
  1351. {objc_cls_refs} [oso_data,oso_load],
  1352. {objc_message_refs} [oso_data,oso_load],
  1353. {objc_symbols} [oso_data,oso_load],
  1354. {objc_category} [oso_data,oso_load],
  1355. {objc_class_vars} [oso_data,oso_load],
  1356. {objc_instance_vars} [oso_data,oso_load],
  1357. {objc_module_info} [oso_data,oso_load],
  1358. {objc_class_names} [oso_data,oso_load],
  1359. {objc_meth_var_types} [oso_data,oso_load],
  1360. {objc_meth_var_names} [oso_data,oso_load],
  1361. {objc_selector_strs} [oso_data,oso_load],
  1362. {objc_protocol_ext} [oso_data,oso_load],
  1363. {objc_class_ext} [oso_data,oso_load],
  1364. {objc_property} [oso_data,oso_load],
  1365. {objc_image_info} [oso_data,oso_load],
  1366. {objc_cstring_object} [oso_data,oso_load],
  1367. {objc_sel_fixup} [oso_data,oso_load],
  1368. {sec_objc_data} [oso_data,oso_load],
  1369. {sec_objc_const} [oso_data,oso_load],
  1370. {sec_objc_sup_refs} [oso_data,oso_load],
  1371. {sec_data_coalesced} [oso_data,oso_load],
  1372. {sec_objc_classlist} [oso_data,oso_load],
  1373. {sec_objc_nlclasslist} [oso_data,oso_load],
  1374. {sec_objc_catlist} [oso_data,oso_load],
  1375. {sec_objc_nlcatlist} [oso_data,oso_load],
  1376. {sec_objc_protolist'} [oso_data,oso_load],
  1377. {stack} [oso_load,oso_write],
  1378. {heap} [oso_load,oso_write],
  1379. {gcc_except_table} [oso_data,oso_load],
  1380. {arm_attribute} [oso_data],
  1381. {note} [oso_Data,oso_note]
  1382. );
  1383. begin
  1384. if target_asm.id in asms_int_coff then
  1385. begin
  1386. if (aType in [sec_rodata,sec_rodata_norel]) then
  1387. begin
  1388. if (target_info.system in systems_all_windows) then
  1389. aType:=sec_rodata_norel
  1390. else
  1391. aType:=sec_data;
  1392. end;
  1393. end;
  1394. result:=secoptions[atype];
  1395. if (target_info.system in systems_wasm) and (atype=sec_bss) then
  1396. Result:=Result+[oso_data,oso_sparse_data];
  1397. {$ifdef OMFOBJSUPPORT}
  1398. { in the huge memory model, BSS data is actually written in the regular
  1399. FAR_DATA segment of the module }
  1400. if omf_segclass(atype)='FAR_DATA' then
  1401. Result:=Result+[oso_data,oso_sparse_data];
  1402. {$endif OMFOBJSUPPORT}
  1403. end;
  1404. function TObjData.sectiontype2align(atype:TAsmSectiontype):longint;
  1405. begin
  1406. case atype of
  1407. sec_stabstr,sec_debug_info,sec_debug_line,sec_debug_abbrev,sec_debug_aranges,sec_debug_ranges,
  1408. sec_arm_attribute:
  1409. result:=1;
  1410. sec_code,
  1411. sec_bss,
  1412. sec_data:
  1413. result:=16;
  1414. { For idata (at least idata2) it must be 4 bytes, because
  1415. an entry is always (also in win64) 20 bytes and aligning
  1416. on 8 bytes will insert 4 bytes between the entries resulting
  1417. in a corrupt idata section.
  1418. Same story with .pdata, it has 4-byte elements which should
  1419. be packed without gaps. }
  1420. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
  1421. result:=4;
  1422. else
  1423. result:=sizeof(pint);
  1424. end;
  1425. end;
  1426. class procedure TObjData.sectiontype2progbitsandflags(atype:TAsmSectiontype;out progbits:TSectionProgbits;out flags:TSectionFlags);
  1427. var
  1428. options : TObjSectionOptions;
  1429. begin
  1430. { this is essentially the inverse of the createsection overload that takes
  1431. both progbits and flags as parameters }
  1432. options:=sectiontype2options(atype);
  1433. flags:=[];
  1434. progbits:=SPB_None;
  1435. if oso_load in options then
  1436. include(flags,SF_A);
  1437. if oso_write in options then
  1438. include(flags,SF_W);
  1439. if oso_executable in options then
  1440. include(flags,SF_X);
  1441. if not (oso_data in options) then
  1442. progbits:=SPB_NOBITS
  1443. else if oso_note in options then
  1444. progbits:=SPB_NOTE
  1445. else if oso_arm_attributes in options then
  1446. progbits:=SPB_ARM_ATTRIBUTES;
  1447. end;
  1448. function TObjData.createsection(atype:TAsmSectionType;const aname:string;aorder:TAsmSectionOrder):TObjSection;
  1449. begin
  1450. result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),sectiontype2options(atype));
  1451. end;
  1452. function TObjData.createsection(atype: TAsmSectionType; secflags: TSectionFlags; aprogbits: TSectionProgbits; const aname: string; aorder: TAsmSectionOrder): TObjSection;
  1453. var
  1454. flags : TObjSectionOptions;
  1455. begin
  1456. flags:=[oso_data];
  1457. if SF_A in secflags then
  1458. Include(flags,oso_load);
  1459. if SF_W in secflags then
  1460. Include(flags,oso_write);
  1461. if SF_X in secflags then
  1462. Include(flags,oso_executable);
  1463. if aprogbits=SPB_NOBITS then
  1464. Exclude(flags,oso_data);
  1465. if aprogbits=SPB_NOTE then
  1466. Include(flags,oso_note);
  1467. if aprogbits=SPB_ARM_ATTRIBUTES then
  1468. Include(flags,oso_arm_attributes);
  1469. result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),flags);
  1470. end;
  1471. function TObjData.createsection(const aname:string;aalign:longint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean):TObjSection;
  1472. begin
  1473. if DiscardDuplicate then
  1474. result:=TObjSection(FObjSectionList.Find(aname))
  1475. else
  1476. result:=nil;
  1477. if not assigned(result) then
  1478. begin
  1479. result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
  1480. result.ObjData:=self;
  1481. end;
  1482. FCurrObjSec:=result;
  1483. end;
  1484. function TObjData.CreateSectionGroup(const aname:string):TObjSectionGroup;
  1485. begin
  1486. if FGroupsList=nil then
  1487. FGroupsList:=TFPHashObjectList.Create(true);
  1488. result:=CObjSectionGroup.Create(FGroupsList,aname);
  1489. end;
  1490. procedure TObjData.CreateDebugSections;
  1491. begin
  1492. end;
  1493. function TObjData.Findsection(const aname:string):TObjSection;
  1494. begin
  1495. result:=TObjSection(FObjSectionList.Find(aname));
  1496. end;
  1497. procedure TObjData.setsection(asec:TObjSection);
  1498. begin
  1499. if asec.ObjData<>self then
  1500. internalerror(200403041);
  1501. FCurrObjSec:=asec;
  1502. end;
  1503. function TObjData.createsymbol(const aname:string):TObjSymbol;
  1504. begin
  1505. result:=TObjSymbol(FObjSymbolList.Find(aname));
  1506. if not assigned(result) then
  1507. result:=CObjSymbol.Create(FObjSymbolList,aname);
  1508. {$ifdef ARM}
  1509. result.ThumbFunc:=ThumbFunc;
  1510. ThumbFunc:=false;
  1511. {$endif ARM}
  1512. end;
  1513. function TObjData.symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  1514. begin
  1515. if assigned(asmsym) then
  1516. begin
  1517. if asmsym.typ = AT_NONE then
  1518. InternalError(2018062800);
  1519. if not assigned(asmsym.cachedObjSymbol) then
  1520. begin
  1521. result:=symboldefine(asmsym.name,asmsym.bind,asmsym.typ);
  1522. asmsym.cachedObjSymbol:=result;
  1523. FCachedAsmSymbolList.add(asmsym);
  1524. end
  1525. else
  1526. begin
  1527. result:=TObjSymbol(asmsym.cachedObjSymbol);
  1528. result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
  1529. end;
  1530. end
  1531. else
  1532. result:=nil;
  1533. end;
  1534. function TObjData.symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  1535. begin
  1536. if not assigned(CurrObjSec) then
  1537. internalerror(2006030504);
  1538. result:=CreateSymbol(aname);
  1539. result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
  1540. end;
  1541. function TObjData.symbolref(asmsym:TAsmSymbol):TObjSymbol;
  1542. var
  1543. s:string;
  1544. begin
  1545. if assigned(asmsym) then
  1546. begin
  1547. if not assigned(asmsym.cachedObjSymbol) then
  1548. begin
  1549. s:=asmsym.name;
  1550. result:=TObjSymbol(FObjSymbolList.Find(s));
  1551. if result=nil then
  1552. begin
  1553. result:=CObjSymbol.Create(FObjSymbolList,s);
  1554. if asmsym.bind=AB_WEAK_EXTERNAL then
  1555. result.bind:=AB_WEAK_EXTERNAL;
  1556. end;
  1557. asmsym.cachedObjSymbol:=result;
  1558. FCachedAsmSymbolList.add(asmsym);
  1559. end
  1560. else
  1561. result:=TObjSymbol(asmsym.cachedObjSymbol);
  1562. { The weak bit could have been removed from asmsym. }
  1563. if (asmsym.bind=AB_EXTERNAL) and (result.bind=AB_WEAK_EXTERNAL) then
  1564. result.bind:=AB_EXTERNAL;
  1565. { the TLS type needs to be inherited }
  1566. if asmsym.typ=AT_TLS then
  1567. result.typ:=AT_TLS;
  1568. end
  1569. else
  1570. result:=nil;
  1571. end;
  1572. function TObjData.symbolref(const aname:string):TObjSymbol;
  1573. begin
  1574. if not assigned(CurrObjSec) then
  1575. internalerror(200603052);
  1576. result:=CreateSymbol(aname);
  1577. end;
  1578. procedure TObjData.symbolpairdefine(akind: TSymbolPairKind; const asym, avalue: string);
  1579. begin
  1580. end;
  1581. procedure TObjData.ResetCachedAsmSymbols;
  1582. var
  1583. i : longint;
  1584. begin
  1585. for i:=0 to FCachedAsmSymbolList.Count-1 do
  1586. tasmsymbol(FCachedAsmSymbolList[i]).cachedObjSymbol:=nil;
  1587. FCachedAsmSymbolList.Clear;
  1588. end;
  1589. procedure TObjData.writebytes(const Data;len:TObjSectionOfs);
  1590. begin
  1591. if not assigned(CurrObjSec) then
  1592. internalerror(200402251);
  1593. CurrObjSec.write(Data,len);
  1594. end;
  1595. procedure TObjData.writebytes(const Data: TByteDynArray; len: TObjSectionOfs);
  1596. begin
  1597. if len>0 then
  1598. WriteBytes(Data[0],len);
  1599. end;
  1600. procedure TObjData.writebytes(const Data: TAnsiCharDynArray; len: TObjSectionOfs);
  1601. begin
  1602. if len>0 then
  1603. WriteBytes(Data[0],len);
  1604. end;
  1605. procedure TObjData.writeInt8(v: int8);
  1606. begin
  1607. writebytes(v,1);
  1608. end;
  1609. procedure TObjData.writeInt16LE(v: int16);
  1610. begin
  1611. {$ifdef FPC_BIG_ENDIAN}
  1612. v:=SwapEndian(v);
  1613. {$endif FPC_BIG_ENDIAN}
  1614. writebytes(v,2);
  1615. end;
  1616. procedure TObjData.writeInt16BE(v: int16);
  1617. begin
  1618. {$ifdef FPC_LITTLE_ENDIAN}
  1619. v:=SwapEndian(v);
  1620. {$endif FPC_LITTLE_ENDIAN}
  1621. writebytes(v,2);
  1622. end;
  1623. procedure TObjData.writeInt32LE(v: int32);
  1624. begin
  1625. {$ifdef FPC_BIG_ENDIAN}
  1626. v:=SwapEndian(v);
  1627. {$endif FPC_BIG_ENDIAN}
  1628. writebytes(v,4);
  1629. end;
  1630. procedure TObjData.writeInt32BE(v: int32);
  1631. begin
  1632. {$ifdef FPC_LITTLE_ENDIAN}
  1633. v:=SwapEndian(v);
  1634. {$endif FPC_LITTLE_ENDIAN}
  1635. writebytes(v,4);
  1636. end;
  1637. procedure TObjData.writeInt64LE(v: int64);
  1638. begin
  1639. {$ifdef FPC_BIG_ENDIAN}
  1640. v:=SwapEndian(v);
  1641. {$endif FPC_BIG_ENDIAN}
  1642. writebytes(v,8);
  1643. end;
  1644. procedure TObjData.writeInt64BE(v: int64);
  1645. begin
  1646. {$ifdef FPC_LITTLE_ENDIAN}
  1647. v:=SwapEndian(v);
  1648. {$endif FPC_LITTLE_ENDIAN}
  1649. writebytes(v,8);
  1650. end;
  1651. procedure TObjData.writeUInt8(v: uint8);
  1652. begin
  1653. writebytes(v,1);
  1654. end;
  1655. procedure TObjData.writeUInt16LE(v: uint16);
  1656. begin
  1657. {$ifdef FPC_BIG_ENDIAN}
  1658. v:=SwapEndian(v);
  1659. {$endif FPC_BIG_ENDIAN}
  1660. writebytes(v,2);
  1661. end;
  1662. procedure TObjData.writeUInt16BE(v: uint16);
  1663. begin
  1664. {$ifdef FPC_LITTLE_ENDIAN}
  1665. v:=SwapEndian(v);
  1666. {$endif FPC_LITTLE_ENDIAN}
  1667. writebytes(v,2);
  1668. end;
  1669. procedure TObjData.writeUInt32LE(v: uint32);
  1670. begin
  1671. {$ifdef FPC_BIG_ENDIAN}
  1672. v:=SwapEndian(v);
  1673. {$endif FPC_BIG_ENDIAN}
  1674. writebytes(v,4);
  1675. end;
  1676. procedure TObjData.writeUInt32BE(v: uint32);
  1677. begin
  1678. {$ifdef FPC_LITTLE_ENDIAN}
  1679. v:=SwapEndian(v);
  1680. {$endif FPC_LITTLE_ENDIAN}
  1681. writebytes(v,4);
  1682. end;
  1683. procedure TObjData.writeUInt64LE(v: uint64);
  1684. begin
  1685. {$ifdef FPC_BIG_ENDIAN}
  1686. v:=SwapEndian(v);
  1687. {$endif FPC_BIG_ENDIAN}
  1688. writebytes(v,8);
  1689. end;
  1690. procedure TObjData.writeUInt64BE(v: uint64);
  1691. begin
  1692. {$ifdef FPC_LITTLE_ENDIAN}
  1693. v:=SwapEndian(v);
  1694. {$endif FPC_LITTLE_ENDIAN}
  1695. writebytes(v,8);
  1696. end;
  1697. procedure TObjData.alloc(len:TObjSectionOfs);
  1698. begin
  1699. if not assigned(CurrObjSec) then
  1700. internalerror(200402252);
  1701. CurrObjSec.alloc(len);
  1702. end;
  1703. procedure TObjData.allocalign(len:longint);
  1704. begin
  1705. if not assigned(CurrObjSec) then
  1706. internalerror(200402253);
  1707. CurrObjSec.alloc(align_objsecofs(CurrObjSec.size,len)-CurrObjSec.size);
  1708. end;
  1709. procedure TObjData.section_afteralloc(p:TObject;arg:pointer);
  1710. begin
  1711. with TObjSection(p) do
  1712. alloc(align_objsecofs(size,secalign)-size);
  1713. end;
  1714. procedure TObjData.section_afterwrite(p:TObject;arg:pointer);
  1715. begin
  1716. with TObjSection(p) do
  1717. begin
  1718. if assigned(Data) then
  1719. writezeros(align_objsecofs(size,secalign)-size);
  1720. end;
  1721. end;
  1722. procedure TObjData.section_reset(p:TObject;arg:pointer);
  1723. begin
  1724. with TObjSection(p) do
  1725. begin
  1726. Size:=0;
  1727. Datapos:=0;
  1728. mempos:=0;
  1729. if assigned(Data) then
  1730. Data.reset;
  1731. end;
  1732. end;
  1733. procedure TObjData.beforealloc;
  1734. begin
  1735. FCPUType:=current_settings.cputype;
  1736. { create stabs sections if debugging }
  1737. if assigned(StabsSec) then
  1738. begin
  1739. StabsSec.Alloc(sizeof(TObjStabEntry));
  1740. StabStrSec.Alloc(1);
  1741. end;
  1742. end;
  1743. procedure TObjData.beforewrite;
  1744. begin
  1745. FCPUType:=current_settings.cputype;
  1746. { create stabs sections if debugging }
  1747. if assigned(StabsSec) then
  1748. begin
  1749. { Create dummy HdrSym stab, it will be overwritten in AfterWrite }
  1750. StabsSec.WriteZeros(sizeof(TObjStabEntry));
  1751. { start of stabstr }
  1752. StabStrSec.writeZeros(1);
  1753. end;
  1754. end;
  1755. procedure TObjData.afteralloc;
  1756. begin
  1757. FObjSectionList.ForEachCall(@section_afteralloc,nil);
  1758. end;
  1759. procedure TObjData.afterwrite;
  1760. var
  1761. hstab : TObjStabEntry;
  1762. begin
  1763. FObjSectionList.ForEachCall(@section_afterwrite,nil);
  1764. { For the stab section we need an HdrSym which can now be
  1765. calculated more easily }
  1766. if assigned(StabsSec) then
  1767. begin
  1768. { end of stabstr }
  1769. StabStrSec.writeZeros(1);
  1770. { header stab }
  1771. hstab.strpos:=1;
  1772. hstab.ntype:=0;
  1773. hstab.nother:=0;
  1774. {$push}{$R-}
  1775. { for jwawindows.pas, this causes an range check error, it contains too much stab symbols }
  1776. hstab.ndesc:=(StabsSec.Size div sizeof(TObjStabEntry))-1;
  1777. {$pop}
  1778. hstab.nvalue:=StabStrSec.Size;
  1779. MaybeSwapStab(hstab);
  1780. StabsSec.Data.seek(0);
  1781. StabsSec.Data.write(hstab,sizeof(hstab));
  1782. end;
  1783. end;
  1784. procedure TObjData.resetsections;
  1785. begin
  1786. FObjSectionList.ForEachCall(@section_reset,nil);
  1787. end;
  1788. procedure TObjData.layoutsections(var datapos: TObjSectionOfs);
  1789. var
  1790. i: longint;
  1791. begin
  1792. for i:=0 to FObjSectionList.Count-1 do
  1793. TObjSection(FObjSectionList[i]).setDatapos(DataPos);
  1794. end;
  1795. {****************************************************************************
  1796. TObjOutput
  1797. ****************************************************************************}
  1798. constructor TObjOutput.create(AWriter:TObjectWriter);
  1799. begin
  1800. FWriter:=AWriter;
  1801. CObjData:=TObjData;
  1802. end;
  1803. destructor TObjOutput.destroy;
  1804. begin
  1805. inherited destroy;
  1806. end;
  1807. function TObjOutput.newObjData(const n:string):TObjData;
  1808. begin
  1809. result:=CObjData.create(n);
  1810. if (cs_use_lineinfo in current_settings.globalswitches) or
  1811. (cs_debuginfo in current_settings.moduleswitches) then
  1812. result.CreateDebugSections;
  1813. end;
  1814. function TObjOutput.startObjectfile(const fn:string):boolean;
  1815. begin
  1816. result:=false;
  1817. { start the writer already, so the .a generation can initialize
  1818. the position of the current objectfile }
  1819. if not FWriter.createfile(fn) then
  1820. Comment(V_Fatal,'Can''t create object '+fn);
  1821. result:=true;
  1822. end;
  1823. function TObjOutput.writeobjectfile(Data:TObjData):boolean;
  1824. begin
  1825. if errorcount=0 then
  1826. result:=writeData(Data)
  1827. else
  1828. result:=true;
  1829. { close the writer }
  1830. FWriter.closefile;
  1831. end;
  1832. procedure TObjOutput.exportsymbol(p:TObjSymbol);
  1833. begin
  1834. { export globals and common symbols, this is needed
  1835. for .a files }
  1836. if p.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN,AB_COMMON] then
  1837. FWriter.writesym(ApplyAsmSymbolRestrictions(p.name));
  1838. end;
  1839. procedure TObjOutput.WriteSectionContent(Data:TObjData);
  1840. var
  1841. i:longint;
  1842. sec:TObjSection;
  1843. begin
  1844. for i:=0 to Data.ObjSectionList.Count-1 do
  1845. begin
  1846. sec:=TObjSection(Data.ObjSectionList[i]);
  1847. if (oso_data in sec.SecOptions) then
  1848. begin
  1849. if sec.Data=nil then
  1850. internalerror(2004030707);
  1851. FWriter.writezeros(sec.dataalignbytes);
  1852. if sec.Datapos<>FWriter.ObjSize then
  1853. internalerror(200604031);
  1854. FWriter.writearray(sec.data);
  1855. end;
  1856. end;
  1857. end;
  1858. {****************************************************************************
  1859. TExeVTable
  1860. ****************************************************************************}
  1861. constructor TExeVTable.Create(AExeSymbol:TExeSymbol);
  1862. begin
  1863. ExeSymbol:=AExeSymbol;
  1864. if ExeSymbol.State=symstate_undefined then
  1865. internalerror(200604012);
  1866. ChildList:=TFPObjectList.Create(false);
  1867. end;
  1868. destructor TExeVTable.Destroy;
  1869. begin
  1870. ChildList.Free;
  1871. ChildList := nil;
  1872. if assigned(EntryArray) then
  1873. Freemem(EntryArray);
  1874. end;
  1875. procedure TExeVTable.CheckIdx(VTableIdx:longint);
  1876. var
  1877. OldEntryCnt : longint;
  1878. begin
  1879. if VTableIdx>=EntryCnt then
  1880. begin
  1881. OldEntryCnt:=EntryCnt;
  1882. EntryCnt:=VTableIdx+1;
  1883. ReAllocMem(EntryArray,EntryCnt*sizeof(TVTableEntry));
  1884. FillChar(EntryArray[OldEntryCnt],(EntryCnt-OldEntryCnt)*sizeof(TVTableEntry),0);
  1885. end;
  1886. end;
  1887. procedure TExeVTable.AddChild(vt:TExeVTable);
  1888. begin
  1889. ChildList.Add(vt);
  1890. end;
  1891. procedure TExeVTable.AddEntry(VTableIdx:Longint);
  1892. var
  1893. i : longint;
  1894. objreloc : TObjRelocation;
  1895. vtblentryoffset : aword;
  1896. begin
  1897. CheckIdx(VTableIdx);
  1898. vtblentryoffset:=ExeSymbol.ObjSymbol.Offset+longword(VTableIdx)*sizeof(pint);
  1899. { Find and disable relocation }
  1900. for i:=0 to ExeSymbol.ObjSymbol.ObjSection.ObjRelocations.Count-1 do
  1901. begin
  1902. objreloc:=TObjRelocation(ExeSymbol.ObjSymbol.ObjSection.ObjRelocations[i]);
  1903. if objreloc.dataoffset=vtblentryoffset then
  1904. begin
  1905. EntryArray[VTableIdx].ObjRelocation:=objreloc;
  1906. EntryArray[VTableIdx].OrgRelocType:=objreloc.ftype;
  1907. EntryArray[VTableIdx].OrgRelocFlags:=objreloc.flags;
  1908. objreloc.typ:=RELOC_ZERO;
  1909. objreloc.flags:=objreloc.flags or rf_nosymbol;
  1910. break;
  1911. end;
  1912. end;
  1913. if not assigned(EntryArray[VTableIdx].ObjRelocation) then
  1914. internalerror(200604011);
  1915. end;
  1916. procedure TExeVTable.SetVTableSize(ASize:longint);
  1917. begin
  1918. if EntryCnt<>0 then
  1919. internalerror(200603313);
  1920. EntryCnt:=ASize div sizeof(pint);
  1921. EntryArray:=AllocMem(EntryCnt*sizeof(TVTableEntry));
  1922. end;
  1923. function TExeVTable.VTableRef(VTableIdx:Longint):TObjRelocation;
  1924. begin
  1925. result:=nil;
  1926. CheckIdx(VTableIdx);
  1927. if EntryArray[VTableIdx].Used then
  1928. exit;
  1929. { Restore relocation if available }
  1930. if assigned(EntryArray[VTableIdx].ObjRelocation) then
  1931. begin
  1932. EntryArray[VTableIdx].ObjRelocation.ftype:=EntryArray[VTableIdx].OrgRelocType;
  1933. EntryArray[VTableIdx].ObjRelocation.flags:=EntryArray[VTableIdx].OrgRelocFlags;
  1934. result:=EntryArray[VTableIdx].ObjRelocation;
  1935. end;
  1936. EntryArray[VTableIdx].Used:=true;
  1937. end;
  1938. {****************************************************************************
  1939. TExeSection
  1940. ****************************************************************************}
  1941. constructor TExeSection.create(AList:TFPHashObjectList;const AName:string);
  1942. begin
  1943. inherited create(AList,AName);
  1944. Size:=0;
  1945. MemPos:=0;
  1946. DataPos:=0;
  1947. FSecSymIdx:=0;
  1948. FObjSectionList:=TFPObjectList.Create(false);
  1949. end;
  1950. destructor TExeSection.destroy;
  1951. begin
  1952. FObjSectionList.Free;
  1953. FObjSectionList := nil;
  1954. inherited destroy;
  1955. end;
  1956. procedure TExeSection.AddObjSection(objsec:TObjSection;ignoreprops:boolean);
  1957. begin
  1958. ObjSectionList.Add(objsec);
  1959. { relate ObjSection to ExeSection, and mark it Used by default }
  1960. objsec.ExeSection:=self;
  1961. objsec.Used:=true;
  1962. if ignoreprops then
  1963. exit;
  1964. if (SecOptions<>[]) then
  1965. begin
  1966. { Only if the section contains (un)initialized data the
  1967. data flag must match. }
  1968. if ((oso_Data in SecOptions)<>(oso_Data in objsec.SecOptions)) then
  1969. Comment(V_Error,'Incompatible section options');
  1970. end
  1971. else
  1972. begin
  1973. { inherit section options }
  1974. SecOptions:=SecOptions+objsec.SecOptions;
  1975. end;
  1976. SecAlign:=max(objsec.SecAlign,SecAlign);
  1977. end;
  1978. function TExeSection.MemPosStr(AImageBase: qword): string;
  1979. begin
  1980. result:='0x'+HexStr(mempos+AImageBase,sizeof(pint)*2);
  1981. end;
  1982. {****************************************************************************
  1983. TStaticLibrary
  1984. ****************************************************************************}
  1985. constructor TStaticLibrary.create(const AName:TCmdStr;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  1986. begin
  1987. FName:=AName;
  1988. FPayload:=AReader;
  1989. FObjInputClass:=AObjInputClass;
  1990. FKind:=lkArchive;
  1991. end;
  1992. constructor TStaticLibrary.create_object(AObjData:TObjData);
  1993. begin
  1994. FPayload:=AObjData;
  1995. FKind:=lkObject;
  1996. end;
  1997. constructor TStaticLibrary.create_group;
  1998. begin
  1999. FPayload:=TFPObjectList.Create(true);
  2000. FKind:=lkGroup;
  2001. end;
  2002. destructor TStaticLibrary.destroy;
  2003. begin
  2004. FPayload.Free;
  2005. FPayload := nil;
  2006. inherited destroy;
  2007. end;
  2008. function TStaticLibrary.GetArReader: TObjectReader;
  2009. begin
  2010. if (FKind<>lkArchive) then
  2011. InternalError(2012071501);
  2012. result:=TObjectReader(FPayload);
  2013. end;
  2014. function TStaticLibrary.GetGroupMembers: TFPObjectList;
  2015. begin
  2016. if (FKind<>lkGroup) then
  2017. InternalError(2012071502);
  2018. result:=TFPObjectList(FPayload);
  2019. end;
  2020. function TStaticLibrary.GetObjData: TObjData;
  2021. begin
  2022. if (FKind<>lkObject) then
  2023. InternalError(2012071503);
  2024. result:=TObjData(FPayload);
  2025. end;
  2026. {****************************************************************************
  2027. TImportLibrary
  2028. ****************************************************************************}
  2029. constructor TImportLibrary.create(AList:TFPHashObjectList;const AName:string);
  2030. begin
  2031. inherited create(AList,AName);
  2032. FImportSymbolList:=TFPHashObjectList.Create(true);
  2033. end;
  2034. destructor TImportLibrary.destroy;
  2035. begin
  2036. FImportSymbolList.Free;
  2037. FImportSymbolList := nil;
  2038. inherited destroy;
  2039. end;
  2040. {****************************************************************************
  2041. TImportSymbol
  2042. ****************************************************************************}
  2043. constructor TImportSymbol.create(AList:TFPHashObjectList;
  2044. const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
  2045. begin
  2046. inherited Create(AList, AName);
  2047. FOrdNr:=AOrdNr;
  2048. FIsVar:=AIsVar;
  2049. FMangledName:=AMangledName;
  2050. { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }
  2051. { This allows to import VC++ mangled names from DLLs. }
  2052. if target_info.system in systems_all_windows then
  2053. begin
  2054. Replace(FMangledName,'?','__q$$');
  2055. {$ifdef arm}
  2056. { @ symbol is not allowed in ARM assembler only }
  2057. Replace(FMangledName,'@','__a$$');
  2058. {$endif arm}
  2059. end;
  2060. end;
  2061. {****************************************************************************
  2062. TExeOutput
  2063. ****************************************************************************}
  2064. constructor TExeOutput.create;
  2065. begin
  2066. { init writer }
  2067. FWriter:=TObjectwriter.create;
  2068. FExeWriteMode:=ewm_exefull;
  2069. { object files }
  2070. FObjDataList:=TFPObjectList.Create(true);
  2071. { symbols }
  2072. FExeSymbolList:=TFPHashObjectList.Create(true);
  2073. FUnresolvedExeSymbols:=TFPObjectList.Create(false);
  2074. FExternalObjSymbols:=TFPObjectList.Create(false);
  2075. FCommonObjSymbols:=TFPObjectList.Create(false);
  2076. FProvidedObjSymbols:=TFPObjectList.Create(false);
  2077. FIndirectObjSymbols:=TFPObjectList.Create(false);
  2078. FExeVTableList:=TFPObjectList.Create(false);
  2079. ComdatGroups:=TFPHashList.Create;
  2080. { sections }
  2081. FExeSectionList:=TFPHashObjectList.Create(true);
  2082. FImageBase:=0;
  2083. {$ifdef cpu16bitaddr}
  2084. SectionMemAlign:=$10;
  2085. SectionDataAlign:=$10;
  2086. {$else cpu16bitaddr}
  2087. SectionMemAlign:=$1000;
  2088. SectionDataAlign:=$200;
  2089. {$endif cpu16bitaddr}
  2090. FixedSectionAlign:=True;
  2091. FCExeSection:=TExeSection;
  2092. FCObjData:=TObjData;
  2093. FCObjSymbol:=TObjSymbol;
  2094. end;
  2095. destructor TExeOutput.destroy;
  2096. begin
  2097. FExeSymbolList.free;
  2098. FExeSymbolList := nil;
  2099. FUnresolvedExeSymbols.free;
  2100. FUnresolvedExeSymbols := nil;
  2101. FExternalObjSymbols.free;
  2102. FExternalObjSymbols := nil;
  2103. FProvidedObjSymbols.free;
  2104. FProvidedObjSymbols := nil;
  2105. FIndirectObjSymbols.free;
  2106. FIndirectObjSymbols := nil;
  2107. FCommonObjSymbols.free;
  2108. FCommonObjSymbols := nil;
  2109. FExeVTableList.free;
  2110. FExeVTableList := nil;
  2111. FExeSectionList.free;
  2112. FExeSectionList := nil;
  2113. ComdatGroups.free;
  2114. ComdatGroups := nil;
  2115. FObjDatalist.free;
  2116. FObjDatalist := nil;
  2117. FWriter.free;
  2118. FWriter := nil;
  2119. inherited destroy;
  2120. end;
  2121. function TExeOutput.MemAlign(exesec:TExeSection):longword;
  2122. begin
  2123. if FixedSectionAlign then
  2124. result:=SectionMemAlign
  2125. else
  2126. result:=exesec.SecAlign;
  2127. end;
  2128. function TExeOutput.DataAlign(exesec:TExeSection):longword;
  2129. begin
  2130. if FixedSectionAlign then
  2131. result:=SectionDataAlign
  2132. else
  2133. result:=exesec.SecAlign;
  2134. end;
  2135. function TExeOutput.WriteExeFile(const fn:string):boolean;
  2136. begin
  2137. result:=false;
  2138. if FWriter.createfile(fn) then
  2139. begin
  2140. { Only write the .o if there are no errors }
  2141. if errorcount=0 then
  2142. result:=writedata
  2143. else
  2144. result:=true;
  2145. { close the writer }
  2146. FWriter.closefile;
  2147. end
  2148. else
  2149. Comment(V_Fatal,'Can''t create executable '+fn);
  2150. end;
  2151. procedure TExeOutput.ParseScript (linkscript:TCmdStrList);
  2152. begin
  2153. end;
  2154. function TExeOutput.FindExeSection(const aname:string):TExeSection;
  2155. begin
  2156. result:=TExeSection(ExeSectionList.Find(aname));
  2157. end;
  2158. procedure TExeOutput.AddObjData(ObjData:TObjData);
  2159. begin
  2160. if ObjData.classtype<>FCObjData then
  2161. Comment(V_Error,'Invalid input object format for '+ObjData.name+' got '+ObjData.classname+' expected '+FCObjData.classname);
  2162. ObjDataList.Add(ObjData);
  2163. ExecStack:=ExecStack or ObjData.ExecStack;
  2164. end;
  2165. procedure TExeOutput.Load_Start;
  2166. begin
  2167. ObjDataList.Clear;
  2168. { Globals defined in the linker script }
  2169. if not assigned(internalObjData) then
  2170. internalObjData:=CObjData.create('*Internal*');
  2171. AddObjData(internalObjData);
  2172. { Common Data section }
  2173. commonObjSection:=internalObjData.createsection(sec_bss,'');
  2174. end;
  2175. procedure TExeOutput.Load_EntryName(const aname:string);
  2176. begin
  2177. FEntryName:=aname;
  2178. end;
  2179. procedure TExeOutput.Load_IsSharedLibrary;
  2180. begin
  2181. IsSharedLibrary:=true;
  2182. end;
  2183. procedure TExeOutput.Load_ImageBase(const avalue:string);
  2184. var
  2185. code : integer;
  2186. objsec : TObjSection;
  2187. objsym : TObjSymbol;
  2188. exesym : TExeSymbol;
  2189. begin
  2190. val(avalue,FImageBase,code);
  2191. if code<>0 then
  2192. Comment(V_Error,'Invalid number '+avalue);
  2193. { Create __image_base__ symbol, create the symbol
  2194. in a section with adress 0 and at offset 0 }
  2195. objsec:=internalObjData.createsection('*__image_base__',0,[]);
  2196. internalObjData.setsection(objsec);
  2197. objsym:=internalObjData.SymbolDefine('__image_base__',AB_GLOBAL,AT_DATA);
  2198. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  2199. exesym.ObjSymbol:=objsym;
  2200. end;
  2201. procedure TExeOutput.Load_Symbol(const aname:string);
  2202. begin
  2203. internalObjData.createsection('*'+aname,0,[]);
  2204. internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_DATA);
  2205. end;
  2206. procedure TExeOutput.Load_ProvideSymbol(const aname:string);
  2207. begin
  2208. if assigned(ExeSymbolList.Find(aname)) then
  2209. exit;
  2210. internalObjData.createsection('*'+aname,0,[]);
  2211. // Use AB_COMMON to avoid multiple defined complaints
  2212. internalObjData.SymbolDefine(aname,AB_COMMON,AT_DATA);
  2213. end;
  2214. procedure TExeOutput.Load_DynamicObject(ObjData:TObjData;asneeded:boolean);
  2215. begin
  2216. end;
  2217. procedure TExeOutput.Order_Start;
  2218. begin
  2219. end;
  2220. procedure TExeOutput.Order_End;
  2221. begin
  2222. internalObjData.afterwrite;
  2223. end;
  2224. procedure TExeOutput.Order_ExeSection(const aname:string);
  2225. var
  2226. sec : TExeSection;
  2227. begin
  2228. sec:=FindExeSection(aname);
  2229. if not assigned(sec) then
  2230. sec:=CExeSection.create(ExeSectionList,aname);
  2231. { Clear ExeSection contents }
  2232. FCurrExeSec:=sec;
  2233. end;
  2234. procedure TExeOutput.Order_EndExeSection;
  2235. begin
  2236. if not assigned(CurrExeSec) then
  2237. internalerror(200602184);
  2238. FCurrExeSec:=nil;
  2239. end;
  2240. procedure TExeOutput.Order_ObjSection(const aname:string);
  2241. var
  2242. i,j : longint;
  2243. ObjData : TObjData;
  2244. objsec : TObjSection;
  2245. TmpObjSectionList : TFPObjectList;
  2246. begin
  2247. if not assigned(CurrExeSec) then
  2248. internalerror(200602181);
  2249. TmpObjSectionList:=TFPObjectList.Create(false);
  2250. for i:=0 to ObjDataList.Count-1 do
  2251. begin
  2252. ObjData:=TObjData(ObjDataList[i]);
  2253. for j:=0 to ObjData.ObjSectionList.Count-1 do
  2254. begin
  2255. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  2256. if (not objsec.Used) and
  2257. MatchPattern(aname,objsec.name) then
  2258. TmpObjSectionList.Add(objsec);
  2259. end;
  2260. end;
  2261. { Order list if needed }
  2262. Order_ObjSectionList(TmpObjSectionList,aname);
  2263. { Add the (ordered) list to the current ExeSection }
  2264. for i:=0 to TmpObjSectionList.Count-1 do
  2265. begin
  2266. objsec:=TObjSection(TmpObjSectionList[i]);
  2267. CurrExeSec.AddObjSection(objsec);
  2268. end;
  2269. TmpObjSectionList.Free;
  2270. TmpObjSectionList := nil;
  2271. end;
  2272. procedure TExeOutput.Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);
  2273. begin
  2274. end;
  2275. procedure TExeOutput.Order_Symbol(const aname:string);
  2276. var
  2277. objsym: TObjSymbol;
  2278. begin
  2279. objsym:=TObjSymbol(internalObjData.ObjSymbolList.Find(aname));
  2280. if (objsym=nil) or (objsym.ObjSection.ObjData<>internalObjData) then
  2281. internalerror(200603041);
  2282. CurrExeSec.AddObjSection(objsym.ObjSection,True);
  2283. end;
  2284. procedure TExeOutput.Order_ProvideSymbol(const aname:string);
  2285. var
  2286. objsym : TObjSymbol;
  2287. exesym : TExeSymbol;
  2288. begin
  2289. objsym:=TObjSymbol(internalObjData.ObjSymbolList.Find(aname));
  2290. if (objsym=nil) or (objsym.ObjSection.ObjData<>internalObjData) then
  2291. internalerror(2006030403);
  2292. exesym:=TExeSymbol(ExeSymbolList.Find(aname));
  2293. if not assigned(exesym) then
  2294. internalerror(201206301);
  2295. { Only include this section if it actually resolves
  2296. the symbol }
  2297. if exesym.objsymbol=objsym then
  2298. CurrExeSec.AddObjSection(objsym.ObjSection,True);
  2299. end;
  2300. procedure TExeOutput.Order_Align(const avalue:string);
  2301. var
  2302. code : integer;
  2303. alignval : shortint;
  2304. objsec : TObjSection;
  2305. begin
  2306. val(avalue,alignval,code);
  2307. if code<>0 then
  2308. Comment(V_Error,'Invalid number '+avalue);
  2309. if alignval<=0 then
  2310. exit;
  2311. { Create an empty section with the required aligning }
  2312. inc(Fzeronr);
  2313. objsec:=internalObjData.createsection('*align'+tostr(Fzeronr),alignval,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  2314. CurrExeSec.AddObjSection(objsec);
  2315. end;
  2316. procedure TExeOutput.Order_Zeros(const avalue:string);
  2317. var
  2318. zeros : array[0..1023] of byte;
  2319. code : integer;
  2320. len : longint;
  2321. objsec : TObjSection;
  2322. begin
  2323. val(avalue,len,code);
  2324. if code<>0 then
  2325. Comment(V_Error,'Invalid number '+avalue);
  2326. if len<=0 then
  2327. exit;
  2328. if len>sizeof(zeros) then
  2329. internalerror(200602254);
  2330. fillchar(zeros,len,0);
  2331. inc(Fzeronr);
  2332. objsec:=internalObjData.createsection('*zeros'+tostr(Fzeronr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  2333. internalObjData.writebytes(zeros,len);
  2334. CurrExeSec.AddObjSection(objsec);
  2335. end;
  2336. procedure TExeOutput.Order_Values(bytesize : aword; const avalue:string);
  2337. const
  2338. MAXVAL = 128;
  2339. var
  2340. bytevalues : array[0..MAXVAL-1] of byte;
  2341. twobytevalues : array[0..MAXVAL-1] of word;
  2342. fourbytevalues : array[0..MAXVAL-1] of dword;
  2343. eightbytevalues : array[0..MAXVAL-1] of qword;
  2344. allvals, oneval : string;
  2345. len, commapos : longint;
  2346. indexpos, code : integer;
  2347. anumval : qword;
  2348. signedval : int64;
  2349. objsec : TObjSection;
  2350. begin
  2351. indexpos:=0;
  2352. allvals:=avalue;
  2353. { avoid warnings }
  2354. bytevalues[0]:=0;
  2355. twobytevalues[0]:=0;
  2356. fourbytevalues[0]:=0;
  2357. eightbytevalues[0]:=0;
  2358. repeat
  2359. commapos:=pos(',',allvals);
  2360. if commapos>0 then
  2361. begin
  2362. oneval:=trim(copy(allvals,1,commapos-1));
  2363. allvals:=copy(allvals,commapos+1,length(allvals));
  2364. end
  2365. else
  2366. begin
  2367. oneval:=trim(allvals);
  2368. allvals:='';
  2369. end;
  2370. if oneval<>'' then
  2371. begin
  2372. if oneval[1]='-' then
  2373. begin
  2374. val(oneval,signedval,code);
  2375. anumval:=qword(signedval);
  2376. end
  2377. else
  2378. val(oneval,anumval,code);
  2379. if code<>0 then
  2380. Comment(V_Error,'Invalid number '+avalue)
  2381. else
  2382. begin
  2383. if (indexpos<MAXVAL) then
  2384. begin
  2385. if source_info.endian<>target_info.endian then
  2386. swapendian(anumval);
  2387. { No range checking here }
  2388. if bytesize=1 then
  2389. bytevalues[indexpos]:=byte(anumval)
  2390. else if bytesize=2 then
  2391. twobytevalues[indexpos]:=word(anumval)
  2392. else if bytesize=4 then
  2393. fourbytevalues[indexpos]:=dword(anumval)
  2394. else if bytesize=8 then
  2395. eightbytevalues[indexpos]:=anumval;
  2396. inc(indexpos);
  2397. end
  2398. else
  2399. Comment(V_Error,'Buffer overrun in Order_values');
  2400. end;
  2401. end;
  2402. until allvals='';
  2403. if indexpos=0 then
  2404. begin
  2405. Comment(V_Error,'Invalid number '+avalue);
  2406. exit;
  2407. end;
  2408. if indexpos=MAXVAL then
  2409. begin
  2410. Comment(V_Error,'Too many values '+avalue);
  2411. internalerror(2006022505);
  2412. end;
  2413. len:=bytesize*indexpos;
  2414. inc(Fvaluesnr);
  2415. objsec:=internalObjData.createsection('*values'+tostr(Fvaluesnr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  2416. if bytesize=1 then
  2417. internalObjData.writebytes(bytevalues,len)
  2418. else if bytesize=2 then
  2419. internalObjData.writebytes(twobytevalues,len)
  2420. else if bytesize=4 then
  2421. internalObjData.writebytes(fourbytevalues,len)
  2422. else if bytesize=8 then
  2423. internalObjData.writebytes(eightbytevalues,len);
  2424. CurrExeSec.AddObjSection(objsec);
  2425. end;
  2426. procedure TExeOutput.MemPos_Start;
  2427. begin
  2428. CurrMemPos:=0;
  2429. RemoveDisabledSections;
  2430. end;
  2431. procedure TExeOutput.MemPos_Header;
  2432. begin
  2433. end;
  2434. procedure TExeOutput.MemPos_ExeSection(exesec:TExeSection);
  2435. var
  2436. i : longint;
  2437. objsec : TObjSection;
  2438. begin
  2439. { Alignment of ExeSection }
  2440. CurrMemPos:=align_qword(CurrMemPos,MemAlign(exesec));
  2441. exesec.MemPos:=CurrMemPos;
  2442. { set position of object ObjSections }
  2443. for i:=0 to exesec.ObjSectionList.Count-1 do
  2444. begin
  2445. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2446. CurrMemPos:=objsec.setmempos(CurrMemPos);
  2447. end;
  2448. { calculate size of the section }
  2449. exesec.Size:=CurrMemPos-exesec.MemPos;
  2450. end;
  2451. procedure TExeOutput.MemPos_ExeSection(const aname:string);
  2452. begin
  2453. { Section can be removed }
  2454. FCurrExeSec:=FindExeSection(aname);
  2455. if not assigned(CurrExeSec) then
  2456. exit;
  2457. MemPos_ExeSection(CurrExeSec);
  2458. end;
  2459. procedure TExeOutput.MemPos_EndExeSection;
  2460. begin
  2461. if not assigned(CurrExeSec) then
  2462. exit;
  2463. FCurrExeSec:=nil;
  2464. end;
  2465. procedure TExeOutput.DataPos_Start;
  2466. begin
  2467. end;
  2468. procedure TExeOutput.DataPos_Header;
  2469. begin
  2470. end;
  2471. procedure TExeOutput.DataPos_ExeSection(exesec:TExeSection);
  2472. begin
  2473. { don't write normal section if writing only debug info }
  2474. if (ExeWriteMode=ewm_dbgonly) and
  2475. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[]) then
  2476. exit;
  2477. if (oso_Data in exesec.SecOptions) then
  2478. begin
  2479. CurrDataPos:=align_aword(CurrDataPos,DataAlign(exesec));
  2480. exesec.DataPos:=CurrDataPos;
  2481. CurrDataPos:=CurrDataPos+exesec.Size;
  2482. end;
  2483. end;
  2484. procedure TExeOutput.DataPos_ExeSection(const aname:string);
  2485. begin
  2486. { Section can be removed }
  2487. FCurrExeSec:=FindExeSection(aname);
  2488. if not assigned(CurrExeSec) then
  2489. exit;
  2490. DataPos_ExeSection(CurrExeSec);
  2491. end;
  2492. procedure TExeOutput.DataPos_EndExeSection;
  2493. begin
  2494. if not assigned(CurrExeSec) then
  2495. exit;
  2496. FCurrExeSec:=nil;
  2497. end;
  2498. procedure TExeOutput.DataPos_Symbols;
  2499. begin
  2500. end;
  2501. procedure TExeOutput.BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  2502. var
  2503. hs : string;
  2504. code : integer;
  2505. i,k,
  2506. vtableidx : longint;
  2507. vtableexesym,
  2508. childexesym,
  2509. parentexesym : TExeSymbol;
  2510. objsym : TObjSymbol;
  2511. begin
  2512. { Build inheritance tree from VTINHERIT }
  2513. for i:=0 to VTInheritList.Count-1 do
  2514. begin
  2515. objsym:=TObjSymbol(VTInheritList[i]);
  2516. hs:=objsym.name;
  2517. { VTINHERIT_<ChildVMTName>$$<ParentVMTName> }
  2518. Delete(hs,1,Pos('_',hs));
  2519. k:=Pos('$$',hs);
  2520. if k=0 then
  2521. internalerror(200603311);
  2522. childexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  2523. parentexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,k+2,length(hs)-k-1)));
  2524. if not assigned(childexesym) or
  2525. not assigned(parentexesym)then
  2526. internalerror(200603312);
  2527. if not assigned(childexesym.vtable) then
  2528. begin
  2529. childexesym.vtable:=TExeVTable.Create(childexesym);
  2530. ExeVTableList.Add(childexesym.vtable);
  2531. end;
  2532. if not assigned(parentexesym.vtable) then
  2533. begin
  2534. parentexesym.vtable:=TExeVTable.Create(parentexesym);
  2535. ExeVTableList.Add(parentexesym.vtable);
  2536. end;
  2537. childexesym.vtable.SetVTableSize(childexesym.ObjSymbol.Size);
  2538. if parentexesym<>childexesym then
  2539. parentexesym.vtable.AddChild(childexesym.vtable);
  2540. end;
  2541. { Find VTable entries from VTENTRY }
  2542. for i:=0 to VTEntryList.Count-1 do
  2543. begin
  2544. objsym:=TObjSymbol(VTEntryList[i]);
  2545. hs:=objsym.name;
  2546. { VTENTRY_<VTableName>$$<Index> }
  2547. Delete(hs,1,Pos('_',hs));
  2548. k:=Pos('$$',hs);
  2549. if k=0 then
  2550. internalerror(200603319);
  2551. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  2552. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  2553. if (code<>0) then
  2554. internalerror(200603318);
  2555. if not assigned(vtableexesym) then
  2556. internalerror(2006033110);
  2557. vtableexesym.vtable.AddEntry(vtableidx);
  2558. end;
  2559. end;
  2560. procedure TExeOutput.PackUnresolvedExeSymbols(const s:string);
  2561. var
  2562. i : longint;
  2563. exesym : TExeSymbol;
  2564. begin
  2565. { Generate a list of Unresolved External symbols }
  2566. for i:=0 to UnresolvedExeSymbols.count-1 do
  2567. begin
  2568. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2569. if not (exesym.State in [symstate_undefined,symstate_undefweak]) then
  2570. UnresolvedExeSymbols[i]:=nil;
  2571. end;
  2572. UnresolvedExeSymbols.Pack;
  2573. Comment(V_Debug,'Number of unresolved externals '+s+' '+tostr(UnresolvedExeSymbols.Count));
  2574. end;
  2575. procedure TExeOutput.ResolveSymbols(StaticLibraryList:TFPObjectList);
  2576. var
  2577. ObjData : TObjData;
  2578. exesym : TExeSymbol;
  2579. objsym,
  2580. commonsym : TObjSymbol;
  2581. firstarchive,
  2582. firstcommon : boolean;
  2583. i : longint;
  2584. VTEntryList,
  2585. VTInheritList : TFPObjectList;
  2586. procedure LoadObjDataSymbols(ObjData:TObjData);
  2587. var
  2588. j : longint;
  2589. hs : string;
  2590. exesym : TExeSymbol;
  2591. tmpsym,
  2592. objsym : TObjSymbol;
  2593. grp : TObjSectionGroup;
  2594. makeexternal : boolean;
  2595. begin
  2596. for j:=0 to ObjData.ObjSymbolList.Count-1 do
  2597. begin
  2598. objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
  2599. { From the local symbols we are only interested in the
  2600. VTENTRY and VTINHERIT symbols }
  2601. if objsym.bind=AB_LOCAL then
  2602. begin
  2603. if cs_link_opt_vtable in current_settings.globalswitches then
  2604. begin
  2605. hs:=objsym.name;
  2606. if (hs[1]='V') then
  2607. begin
  2608. if Copy(hs,1,5)='VTREF' then
  2609. begin
  2610. if not assigned(objsym.ObjSection.VTRefList) then
  2611. objsym.ObjSection.VTRefList:=TFPObjectList.Create(false);
  2612. objsym.ObjSection.VTRefList.Add(objsym);
  2613. end
  2614. else if Copy(hs,1,7)='VTENTRY' then
  2615. VTEntryList.Add(objsym)
  2616. else if Copy(hs,1,9)='VTINHERIT' then
  2617. VTInheritList.Add(objsym);
  2618. end;
  2619. end;
  2620. continue;
  2621. end;
  2622. { If this symbol comes from COMDAT group, see if a group with
  2623. matching signature is already included. }
  2624. if assigned(objsym.objsection) and
  2625. assigned(objsym.objsection.group) then
  2626. begin
  2627. grp:=objsym.objsection.group;
  2628. if grp.IsComdat then
  2629. begin
  2630. if ComdatGroups.Find(grp.name)=nil then
  2631. ComdatGroups.Add(grp.name,grp)
  2632. else
  2633. begin
  2634. { Undefine the symbol, causing relocations to it from same
  2635. objdata to be redirected to the symbol in the actually
  2636. linked group. }
  2637. if objsym.bind=AB_GLOBAL then
  2638. objsym.bind:=AB_EXTERNAL;
  2639. { AB_WEAK_EXTERNAL remains unchanged }
  2640. objsym.objsection:=nil;
  2641. end;
  2642. end;
  2643. end;
  2644. { Search for existing exesymbol }
  2645. exesym:=texesymbol(FExeSymbolList.Find(objsym.name));
  2646. if not assigned(exesym) then
  2647. begin
  2648. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  2649. exesym.ObjSymbol:=objsym;
  2650. end
  2651. else
  2652. begin
  2653. if assigned(objsym.objsection) and assigned(exesym.objsymbol.objsection) then
  2654. begin
  2655. if (oso_comdat in exesym.ObjSymbol.objsection.SecOptions) and
  2656. (oso_comdat in objsym.objsection.SecOptions) then
  2657. begin
  2658. if exesym.ObjSymbol.objsection.ComdatSelection=objsym.objsection.ComdatSelection then
  2659. begin
  2660. makeexternal:=true;
  2661. case objsym.objsection.ComdatSelection of
  2662. oscs_none:
  2663. makeexternal:=false;
  2664. oscs_any:
  2665. Message1(link_d_comdat_discard_any,objsym.name);
  2666. oscs_same_size:
  2667. if exesym.ObjSymbol.size<>objsym.size then
  2668. Message1(link_e_comdat_size_differs,objsym.name)
  2669. else
  2670. Message1(link_d_comdat_discard_size,objsym.name);
  2671. oscs_exact_match:
  2672. if (exesym.ObjSymbol.size<>objsym.size) and not exesym.ObjSymbol.objsection.Data.equal(objsym.objsection.Data) then
  2673. Message1(link_e_comdat_content_differs,objsym.name)
  2674. else
  2675. Message1(link_d_comdat_discard_content,objsym.name);
  2676. oscs_associative:
  2677. { this is handled in a different way }
  2678. makeexternal:=false;
  2679. oscs_largest:
  2680. if objsym.size>exesym.ObjSymbol.size then
  2681. begin
  2682. Message1(link_d_comdat_replace_size,objsym.name);
  2683. { we swap the symbols and turn the smaller one to an external
  2684. symbol }
  2685. tmpsym:=exesym.objsymbol;
  2686. exesym.objsymbol:=objsym;
  2687. objsym.exesymbol:=exesym;
  2688. objsym:=tmpsym;
  2689. end;
  2690. end;
  2691. if makeexternal then
  2692. begin
  2693. { Undefine the symbol, causing relocations to it from same
  2694. objdata to be redirected to the symbol that is actually
  2695. used }
  2696. if objsym.bind=AB_GLOBAL then
  2697. objsym.bind:=AB_EXTERNAL;
  2698. { AB_WEAK_EXTERNAL remains unchanged }
  2699. objsym.objsection:=nil;
  2700. end;
  2701. end
  2702. else
  2703. Message1(link_e_comdat_selection_differs,objsym.name);
  2704. end;
  2705. end;
  2706. end;
  2707. objsym.ExeSymbol:=exesym;
  2708. case objsym.bind of
  2709. AB_GLOBAL,
  2710. AB_PRIVATE_EXTERN:
  2711. begin
  2712. if exesym.State<>symstate_defined then
  2713. begin
  2714. exesym.ObjSymbol:=objsym;
  2715. exesym.State:=symstate_defined;
  2716. end
  2717. else
  2718. Message1(link_e_duplicate_symbol,objsym.name);
  2719. { hidden symbols must become local symbols in the executable }
  2720. if objsym.bind=AB_PRIVATE_EXTERN then
  2721. objsym.bind:=AB_LOCAL;
  2722. end;
  2723. AB_EXTERNAL :
  2724. begin
  2725. ExternalObjSymbols.add(objsym);
  2726. { Register unresolved symbols only the first time they
  2727. are registered }
  2728. if exesym.ObjSymbol=objsym then
  2729. UnresolvedExeSymbols.Add(exesym)
  2730. { Normal reference removes any existing "weakness" }
  2731. else if exesym.state=symstate_undefweak then
  2732. begin
  2733. exesym.state:=symstate_undefined;
  2734. exesym.ObjSymbol:=objsym;
  2735. end;
  2736. end;
  2737. AB_COMMON :
  2738. begin
  2739. { A COMMON definition overrides weak one.
  2740. Also select the symbol with largest size. }
  2741. if (exesym.State in [symstate_undefined,symstate_undefweak,symstate_defweak]) or
  2742. ((exesym.State=symstate_common) and (objsym.size>exesym.ObjSymbol.size)) then
  2743. begin
  2744. exesym.ObjSymbol:=objsym;
  2745. exesym.State:=symstate_common;
  2746. end;
  2747. if assigned(objsym.objsection) and
  2748. (objsym.objsection.objdata=internalObjData) then
  2749. FProvidedObjSymbols.add(objsym)
  2750. else
  2751. CommonObjSymbols.add(objsym);
  2752. end;
  2753. AB_WEAK_EXTERNAL :
  2754. begin
  2755. if objsym.objsection=nil then { a weak reference }
  2756. begin
  2757. ExternalObjSymbols.add(objsym);
  2758. if exesym.ObjSymbol=objsym then
  2759. begin
  2760. UnresolvedExeSymbols.Add(exesym);
  2761. exesym.state:=symstate_undefweak;
  2762. end;
  2763. end
  2764. else { a weak definition }
  2765. begin
  2766. if exesym.State in [symstate_undefined,symstate_undefweak] then
  2767. begin
  2768. exesym.ObjSymbol:=objsym;
  2769. exesym.state:=symstate_defweak;
  2770. end;
  2771. end;
  2772. end;
  2773. else
  2774. internalerror(2019050510);
  2775. end;
  2776. end;
  2777. end;
  2778. procedure LoadLibrary(lib:TStaticLibrary);
  2779. var
  2780. j,k,oldcount: longint;
  2781. members: TFPObjectList;
  2782. exesym: TExeSymbol;
  2783. objinput: TObjInput;
  2784. begin
  2785. case lib.Kind of
  2786. lkArchive:
  2787. begin
  2788. { Process list of Unresolved External symbols, we need
  2789. to use a while loop because the list can be extended when
  2790. we load members from the library. }
  2791. j:=0;
  2792. while (j<UnresolvedExeSymbols.count) do
  2793. begin
  2794. exesym:=TExeSymbol(UnresolvedExeSymbols[j]);
  2795. { Check first if the symbol is still undefined }
  2796. if (exesym.State=symstate_undefined) then
  2797. begin
  2798. if lib.ArReader.OpenFile(exesym.name) then
  2799. begin
  2800. if assigned(exemap) then
  2801. begin
  2802. if firstarchive then
  2803. begin
  2804. exemap.Add('');
  2805. exemap.Add('Archive member included because of file (symbol)');
  2806. exemap.Add('');
  2807. firstarchive:=false;
  2808. end;
  2809. exemap.Add(lib.ArReader.FileName+' - '+
  2810. {exesym.ObjSymbol.ObjSection.FullName+}
  2811. '('+exesym.Name+')');
  2812. end;
  2813. objinput:=lib.ObjInputClass.Create;
  2814. objinput.ReadObjData(lib.ArReader,objdata);
  2815. objinput.free;
  2816. objinput := nil;
  2817. AddObjData(objdata);
  2818. LoadObjDataSymbols(objdata);
  2819. lib.ArReader.CloseFile;
  2820. end;
  2821. end;
  2822. inc(j);
  2823. end;
  2824. end;
  2825. lkGroup:
  2826. begin
  2827. { repeatedly process members of the group until no new
  2828. unresolved symbols appear }
  2829. members:=lib.GroupMembers;
  2830. repeat
  2831. oldcount:=UnresolvedExeSymbols.count;
  2832. for k:=0 to members.Count-1 do
  2833. LoadLibrary(TStaticLibrary(members[k]));
  2834. until UnresolvedExeSymbols.count=oldcount;
  2835. end;
  2836. lkObject:
  2837. { TODO: ownership of objdata }
  2838. //if lib.objdata.is_dynamic then
  2839. Load_DynamicObject(lib.objdata,lib.AsNeeded);
  2840. {else
  2841. begin
  2842. AddObjData(lib.objdata);
  2843. LoadObjDataSymbols(lib.objdata);
  2844. end;}
  2845. end;
  2846. end;
  2847. begin
  2848. VTEntryList:=TFPObjectList.Create(false);
  2849. VTInheritList:=TFPObjectList.Create(false);
  2850. {
  2851. The symbol resolving is done in 4 steps:
  2852. 1. Register symbols from objects
  2853. 2. Find symbols in static libraries
  2854. 3. Define symbols PROVIDEd by the link script
  2855. 4. Define still undefined common symbols
  2856. }
  2857. { Step 1, Register symbols from objects }
  2858. for i:=0 to ObjDataList.Count-1 do
  2859. begin
  2860. ObjData:=TObjData(ObjDataList[i]);
  2861. LoadObjDataSymbols(ObjData);
  2862. end;
  2863. PackUnresolvedExeSymbols('in objects');
  2864. { Step 2, Find unresolved symbols in the libraries }
  2865. firstarchive:=true;
  2866. for i:=0 to StaticLibraryList.Count-1 do
  2867. LoadLibrary(TStaticLibrary(StaticLibraryList[i]));
  2868. PackUnresolvedExeSymbols('after static libraries');
  2869. { Step 3, handle symbols provided in script }
  2870. for i:=0 to FProvidedObjSymbols.count-1 do
  2871. begin
  2872. objsym:=TObjSymbol(FProvidedObjSymbols[i]);
  2873. if objsym.exesymbol.State=symstate_defined then
  2874. continue;
  2875. objsym.exesymbol.objsymbol:=objsym;
  2876. objsym.bind:=AB_GLOBAL;
  2877. objsym.exesymbol.State:=symstate_defined;
  2878. end;
  2879. PackUnresolvedExeSymbols('after defining symbols provided by link script');
  2880. { Step 4, Match common symbols or add to the globals }
  2881. firstcommon:=true;
  2882. for i:=0 to CommonObjSymbols.count-1 do
  2883. begin
  2884. objsym:=TObjSymbol(CommonObjSymbols[i]);
  2885. if objsym.exesymbol.State=symstate_defined then
  2886. begin
  2887. if objsym.exesymbol.ObjSymbol.size<>objsym.size then
  2888. Comment(V_Debug,'Size of common symbol '+objsym.name+' is different, expected '+tostr(objsym.size)+' got '+tostr(objsym.exesymbol.ObjSymbol.size));
  2889. end
  2890. else
  2891. begin
  2892. { allocate new objsymbol in .bss of *COMMON* and assign
  2893. it to the exesymbol }
  2894. if firstcommon then
  2895. begin
  2896. if assigned(exemap) then
  2897. exemap.AddCommonSymbolsHeader;
  2898. firstcommon:=false;
  2899. end;
  2900. internalObjData.setsection(commonObjSection);
  2901. { TODO: support alignment of common symbols (ELF targets at least),
  2902. increase commonObjSection.SecAlign if necessary here. }
  2903. internalObjData.allocalign(used_align(size_2_align(objsym.size),0,commonObjSection.SecAlign));
  2904. commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_DATA);
  2905. commonsym.size:=objsym.size;
  2906. internalObjData.alloc(objsym.size);
  2907. if assigned(exemap) then
  2908. exemap.AddCommonSymbol(objsym);
  2909. { Assign to the exesymbol }
  2910. objsym.exesymbol.objsymbol:=commonsym;
  2911. objsym.exesymbol.state:=symstate_defined;
  2912. end;
  2913. end;
  2914. PackUnresolvedExeSymbols('after defining COMMON symbols');
  2915. { Find entry symbol and print in map }
  2916. if (EntryName<>'') then
  2917. begin
  2918. exesym:=texesymbol(ExeSymbolList.Find(EntryName));
  2919. if assigned(exesym) then
  2920. begin
  2921. EntrySym:=exesym.ObjSymbol;
  2922. if assigned(exemap) then
  2923. begin
  2924. exemap.Add('');
  2925. exemap.Add('Entry symbol '+EntryName);
  2926. end;
  2927. end
  2928. else
  2929. Comment(V_Error,'Entrypoint '+EntryName+' not defined');
  2930. end;
  2931. { Generate VTable tree }
  2932. if cs_link_opt_vtable in current_settings.globalswitches then
  2933. BuildVTableTree(VTInheritList,VTEntryList);
  2934. VTInheritList.Free;
  2935. VTInheritList := nil;
  2936. VTEntryList.Free;
  2937. VTEntryList := nil;
  2938. end;
  2939. procedure TExeOutput.GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  2940. var
  2941. debuglink : array[0..1023] of byte;
  2942. len : longint;
  2943. objsec : TObjSection;
  2944. exesec : TExeSection;
  2945. begin
  2946. { From the gdb manual chapter 15. GDB Files:
  2947. * A filename, with any leading directory components removed, followed by a zero byte,
  2948. * zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and
  2949. * a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed
  2950. on the debugging information file's full contents by the function given below, passing zero as the crc argument.
  2951. }
  2952. fillchar(debuglink,sizeof(debuglink),0);
  2953. len:=0;
  2954. move(dbgname[1],debuglink[len],length(dbgname));
  2955. inc(len,length(dbgname)+1);
  2956. len:=align(len,4);
  2957. if source_info.endian<>target_info.endian then
  2958. SwapEndian(dbgcrc);
  2959. move(dbgcrc,debuglink[len],sizeof(cardinal));
  2960. inc(len,4);
  2961. { Add section }
  2962. exesec:=FindExeSection(debuglinkname);
  2963. if not assigned(exesec) then
  2964. exesec:=CExeSection.create(ExeSectionList,debuglinkname);
  2965. exesec.SecOptions:=[oso_data,oso_keep];
  2966. exesec.SecAlign:=4;
  2967. objsec:=internalObjData.createsection(exesec.name,1,exesec.SecOptions);
  2968. internalObjData.writebytes(debuglink,len);
  2969. exesec.AddObjSection(objsec);
  2970. end;
  2971. procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2972. begin
  2973. end;
  2974. procedure TExeOutput.MarkTargetSpecificSections(WorkList:TFPObjectList);
  2975. begin
  2976. end;
  2977. procedure TExeOutput.AfterUnusedSectionRemoval;
  2978. begin
  2979. end;
  2980. function ByAddress(item1,item2:pointer):longint;
  2981. var
  2982. sym1:TObjSymbol absolute item1;
  2983. sym2:TObjSymbol absolute item2;
  2984. begin
  2985. if sym1.address>sym2.address then
  2986. result:=1
  2987. else if sym1.address<sym2.address then
  2988. result:=-1
  2989. else
  2990. result:=0;
  2991. end;
  2992. procedure TExeOutput.PrintMemoryMap;
  2993. var
  2994. exesec : TExeSection;
  2995. objsec : TObjSection;
  2996. objsym : TObjSymbol;
  2997. i,j,k,m: longint;
  2998. list : TFPList;
  2999. flag : boolean;
  3000. begin
  3001. if not assigned(exemap) then
  3002. exit;
  3003. { create a list of symbols sorted by address }
  3004. list:=TFPList.Create;
  3005. list.Capacity:=ExeSymbolList.Count;
  3006. for i:=0 to ExeSymbolList.Count-1 do
  3007. list.Add(TExeSymbol(ExeSymbolList[i]).ObjSymbol);
  3008. list.Sort(@ByAddress);
  3009. exemap.AddMemoryMapHeader(ImageBase);
  3010. k:=0;
  3011. for i:=0 to ExeSectionList.Count-1 do
  3012. begin
  3013. exesec:=TExeSection(ExeSectionList[i]);
  3014. exemap.AddMemoryMapExeSection(exesec);
  3015. for j:=0 to exesec.ObjSectionList.count-1 do
  3016. begin
  3017. objsec:=TObjSection(exesec.ObjSectionList[j]);
  3018. exemap.AddMemoryMapObjectSection(objsec);
  3019. while (k<list.Count) and (TObjSymbol(list[k]).Address<objsec.MemPos) do
  3020. inc(k);
  3021. while (k<list.Count) do
  3022. begin
  3023. objsym:=TObjSymbol(list[k]);
  3024. if objsym.address>objsec.MemPos+objsec.Size then
  3025. break;
  3026. if objsym.objsection=objsec then
  3027. exemap.AddMemoryMapSymbol(objsym)
  3028. else
  3029. begin
  3030. { Got a symbol with address falling into current section, but
  3031. belonging to a different section. This may happen for zero-length
  3032. sections because symbol list is sorted by address but not by section.
  3033. Do some look-ahead in this case. }
  3034. m:=k+1;
  3035. flag:=false;
  3036. while (m<list.Count) and (TObjSymbol(list[m]).Address=objsym.address) do
  3037. begin
  3038. if TObjSymbol(list[m]).objsection=objsec then
  3039. begin
  3040. flag:=true;
  3041. list.Exchange(k,m);
  3042. exemap.AddMemoryMapSymbol(TObjSymbol(list[k]));
  3043. break;
  3044. end;
  3045. inc(m);
  3046. end;
  3047. if not flag then
  3048. break;
  3049. end;
  3050. inc(k);
  3051. end;
  3052. end;
  3053. end;
  3054. list.Free;
  3055. list := nil;
  3056. end;
  3057. procedure TExeOutput.FixupSymbols;
  3058. procedure UpdateSymbol(objsym:TObjSymbol);
  3059. begin
  3060. objsym.bind:=objsym.ExeSymbol.ObjSymbol.bind;
  3061. objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
  3062. objsym.size:=objsym.ExeSymbol.ObjSymbol.size;
  3063. objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
  3064. objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
  3065. objsym.group:=objsym.ExeSymbol.ObjSymbol.group;
  3066. end;
  3067. var
  3068. i : longint;
  3069. objsym : TObjSymbol;
  3070. exesym : TExeSymbol;
  3071. begin
  3072. { Print list of Unresolved External symbols }
  3073. if not AllowUndefinedSymbols then
  3074. for i:=0 to UnresolvedExeSymbols.count-1 do
  3075. begin
  3076. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  3077. if (exesym.State=symstate_undefined) then
  3078. begin
  3079. if assigned(exesym.ObjSymbol) and assigned(exesym.ObjSymbol.ObjData) then
  3080. Message2(link_e_undefined_symbol_in_obj,exesym.name,exesym.objsymbol.ObjData.Name)
  3081. else
  3082. Message1(link_e_undefined_symbol,exesym.name);
  3083. end;
  3084. end;
  3085. {
  3086. Fixing up symbols is done in the following steps:
  3087. 1. Update common references
  3088. 2. Update external references
  3089. Symbols with objsection<>nil are removed from the lists,
  3090. remaining ones can be processed later by calling this method again.
  3091. }
  3092. { Step 1, Update commons. Preserve the original symbol size and bind,
  3093. this is needed for correct relocation of DJCOFF files. }
  3094. for i:=0 to CommonObjSymbols.count-1 do
  3095. begin
  3096. objsym:=TObjSymbol(CommonObjSymbols[i]);
  3097. if objsym.bind<>AB_COMMON then
  3098. internalerror(200606241);
  3099. objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
  3100. objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
  3101. objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
  3102. end;
  3103. { Step 2, Update externals }
  3104. for i:=0 to ExternalObjSymbols.count-1 do
  3105. begin
  3106. objsym:=TObjSymbol(ExternalObjSymbols[i]);
  3107. if not (objsym.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
  3108. internalerror(200606242);
  3109. UpdateSymbol(objsym);
  3110. { Collect symbols that resolve to indirect functions,
  3111. they will need additional target-specific processing. }
  3112. if objsym.typ=AT_GNU_IFUNC then
  3113. IndirectObjSymbols.Add(objsym)
  3114. else if assigned(objsym.objsection) then
  3115. ExternalObjSymbols[i]:=nil;
  3116. end;
  3117. CommonObjSymbols.Clear;
  3118. ExternalObjSymbols.Pack;
  3119. end;
  3120. procedure TExeOutput.MergeStabs;
  3121. var
  3122. stabexesec,
  3123. stabstrexesec : TExeSection;
  3124. relocsec,
  3125. currstabsec,
  3126. currstabstrsec,
  3127. mergedstabsec,
  3128. mergedstabstrsec : TObjSection;
  3129. hstabreloc,
  3130. currstabreloc : TObjRelocation;
  3131. i,j : longint;
  3132. currstabrelocidx,
  3133. mergestabcnt,
  3134. stabcnt : longword;
  3135. skipstab : boolean;
  3136. skipfun : boolean;
  3137. hstab : TObjStabEntry;
  3138. stabrelocofs : longword;
  3139. buf : array[0..1023] of byte;
  3140. bufend,
  3141. bufsize : longint;
  3142. begin
  3143. stabexesec:=FindExeSection('.stab');
  3144. stabstrexesec:=FindExeSection('.stabstr');
  3145. if (stabexesec=nil) or
  3146. (stabstrexesec=nil) or
  3147. (stabexesec.ObjSectionlist.count=0) then
  3148. exit;
  3149. { Create new stabsection }
  3150. stabRelocofs:=pbyte(@hstab.nvalue)-pbyte(@hstab);
  3151. mergedstabsec:=internalObjData.CreateSection(sec_stab,'');
  3152. mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,'');
  3153. { write stab for hdrsym }
  3154. mergedstabsec.writeZeros(sizeof(TObjStabEntry));
  3155. mergestabcnt:=1;
  3156. { .stabstr starts with a #0 }
  3157. buf[0]:=0;
  3158. mergedstabstrsec.write(buf[0],1);
  3159. skipfun:=false;
  3160. { Copy stabs and corresponding Relocations }
  3161. for i:=0 to stabexesec.ObjSectionList.Count-1 do
  3162. begin
  3163. currstabsec:=TObjSection(stabexesec.ObjSectionList[i]);
  3164. currstabstrsec:=currstabsec.ObjData.findsection('.stabstr');
  3165. if assigned(currstabstrsec) then
  3166. begin
  3167. stabcnt:=currstabsec.Data.size div sizeof(TObjStabEntry);
  3168. currstabsec.Data.seek(0);
  3169. currstabrelocidx:=0;
  3170. for j:=0 to stabcnt-1 do
  3171. begin
  3172. hstabreloc:=nil;
  3173. skipstab:=false;
  3174. currstabsec.Data.read(hstab,sizeof(TObjStabEntry));
  3175. MaybeSwapStab(hstab);
  3176. { Only include first hdrsym stab }
  3177. if hstab.ntype=0 then
  3178. skipstab:=true;
  3179. if skipfun then
  3180. begin
  3181. { Skip all stabs for function body until N_RBRAC }
  3182. skipfun:=hstab.ntype<>N_RBRAC;
  3183. skipstab:=true;
  3184. end;
  3185. if not skipstab then
  3186. begin
  3187. { Find corresponding Relocation }
  3188. currstabreloc:=nil;
  3189. while (currstabrelocidx<longword(currstabsec.ObjRelocations.Count)) do
  3190. begin
  3191. currstabreloc:=TObjRelocation(currstabsec.ObjRelocations[currstabrelocidx]);
  3192. if assigned(currstabreloc) and
  3193. (currstabreloc.dataoffset>=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
  3194. break;
  3195. inc(currstabrelocidx);
  3196. end;
  3197. if assigned(currstabreloc) and
  3198. (currstabreloc.dataoffset=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
  3199. begin
  3200. hstabReloc:=currstabReloc;
  3201. inc(currstabrelocidx);
  3202. end;
  3203. { Check if the stab is referring to a removed section }
  3204. if assigned(hstabreloc) then
  3205. begin
  3206. if assigned(hstabreloc.Symbol) then
  3207. relocsec:=hstabreloc.Symbol.ObjSection
  3208. else
  3209. relocsec:=hstabreloc.ObjSection;
  3210. if not assigned(relocsec) then
  3211. internalerror(200603302);
  3212. if not relocsec.Used then
  3213. begin
  3214. skipstab:=true;
  3215. if (hstab.ntype=N_Function) and (hstab.strpos<>0) then
  3216. begin
  3217. currstabstrsec.Data.seek(hstab.strpos);
  3218. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  3219. bufend:=indexbyte(buf,bufsize,Ord(':'));
  3220. if (bufend<>-1) and (bufend<bufsize-1) and (buf[bufend+1]=Ord('F')) then
  3221. skipfun:=true;
  3222. end;
  3223. end;
  3224. end;
  3225. end;
  3226. if not skipstab then
  3227. begin
  3228. { Copy string in stabstr }
  3229. if hstab.strpos<>0 then
  3230. begin
  3231. currstabstrsec.Data.seek(hstab.strpos);
  3232. hstab.strpos:=mergedstabstrsec.Size;
  3233. repeat
  3234. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  3235. bufend:=indexbyte(buf,bufsize,0);
  3236. if bufend=-1 then
  3237. bufend:=bufsize
  3238. else
  3239. begin
  3240. { include the #0 }
  3241. inc(bufend);
  3242. end;
  3243. mergedstabstrsec.write(buf,bufend);
  3244. until (buf[bufend-1]=0) or (bufsize<sizeof(buf));
  3245. end;
  3246. { Copy and Update the relocation }
  3247. if assigned(hstabreloc) then
  3248. begin
  3249. hstabreloc.Dataoffset:=mergestabcnt*sizeof(TObjStabEntry)+stabRelocofs;
  3250. { Remove from List without freeing the object }
  3251. currstabsec.ObjRelocations.List[currstabrelocidx-1]:=nil;
  3252. mergedstabsec.ObjRelocations.Add(hstabreloc);
  3253. end;
  3254. { Write updated stab }
  3255. MaybeSwapStab(hstab);
  3256. mergedstabsec.write(hstab,sizeof(hstab));
  3257. inc(mergestabcnt);
  3258. end;
  3259. end;
  3260. end;
  3261. { Unload stabs }
  3262. if assigned(currstabstrsec) then
  3263. begin
  3264. currstabstrsec.Used:=False;
  3265. currstabstrsec.ReleaseData;
  3266. end;
  3267. currstabsec.Used:=false;
  3268. currstabsec.ReleaseData;
  3269. end;
  3270. { Generate new HdrSym }
  3271. if mergedstabsec.Size>0 then
  3272. begin
  3273. hstab.strpos:=1;
  3274. hstab.ntype:=0;
  3275. hstab.nother:=0;
  3276. hstab.ndesc:=word(mergestabcnt-1);
  3277. hstab.nvalue:=mergedstabstrsec.Size;
  3278. MaybeSwapStab(hstab);
  3279. mergedstabsec.Data.seek(0);
  3280. mergedstabsec.Data.write(hstab,sizeof(hstab));
  3281. end;
  3282. { Replace all sections with our combined stabsec }
  3283. stabexesec.ObjSectionList.Clear;
  3284. stabstrexesec.ObjSectionList.Clear;
  3285. stabexesec.AddObjSection(mergedstabsec);
  3286. stabstrexesec.AddObjSection(mergedstabstrsec);
  3287. end;
  3288. procedure TExeOutput.MarkEmptySections;
  3289. var
  3290. i, j : longint;
  3291. exesec : TExeSection;
  3292. doremove : boolean;
  3293. begin
  3294. for i:=0 to ExeSectionList.Count-1 do
  3295. begin
  3296. exesec:=TExeSection(ExeSectionList[i]);
  3297. doremove:=not(oso_keep in exesec.SecOptions) and
  3298. (
  3299. (exesec.ObjSectionlist.count=0) or
  3300. (
  3301. (cs_link_strip in current_settings.globalswitches) and
  3302. not(cs_link_separate_dbg_file in current_settings.globalswitches) and
  3303. (oso_debug in exesec.SecOptions)
  3304. )
  3305. );
  3306. if not doremove then
  3307. begin
  3308. { Check if section has no actual data }
  3309. doremove:=true;
  3310. for j:=0 to exesec.ObjSectionList.Count-1 do
  3311. if TObjSection(exesec.ObjSectionList[j]).Size<>0 then
  3312. begin
  3313. doremove:=false;
  3314. break;
  3315. end;
  3316. end;
  3317. if doremove then
  3318. begin
  3319. Comment(V_Debug,'Disabling empty section '+exesec.name);
  3320. exesec.Disabled:=true;
  3321. end;
  3322. end;
  3323. end;
  3324. procedure TExeOutput.RemoveDisabledSections;
  3325. var
  3326. i: longint;
  3327. exesec: TExeSection;
  3328. begin
  3329. for i:=0 to ExeSectionList.Count-1 do
  3330. begin
  3331. exesec:=TExeSection(ExeSectionList[i]);
  3332. if exesec.Disabled then
  3333. ExeSectionList[i]:=nil;
  3334. end;
  3335. ExeSectionList.Pack;
  3336. end;
  3337. procedure TExeOutput.RemoveDebugInfo;
  3338. var
  3339. i : longint;
  3340. exesec : TExeSection;
  3341. begin
  3342. for i:=0 to ExeSectionList.Count-1 do
  3343. begin
  3344. exesec:=TExeSection(ExeSectionList[i]);
  3345. if (oso_debug in exesec.SecOptions) then
  3346. ExeSectionList[i]:=nil;
  3347. end;
  3348. ExeSectionList.Pack;
  3349. end;
  3350. procedure TExeOutput.RemoveUnreferencedSections;
  3351. var
  3352. ObjSectionWorkList : TFPObjectList;
  3353. procedure AddToObjSectionWorkList(aobjsec:TObjSection);
  3354. begin
  3355. if not aobjsec.Used then
  3356. begin
  3357. aobjsec.Used:=true;
  3358. ObjSectionWorkList.Add(aobjsec);
  3359. end;
  3360. end;
  3361. procedure DoReloc(objreloc:TObjRelocation);
  3362. var
  3363. objsym : TObjSymbol;
  3364. refobjsec : TObjSection;
  3365. refgrp : TObjSectionGroup;
  3366. begin
  3367. { Disabled Relocation to 0 }
  3368. if (objreloc.flags and rf_nosymbol)<>0 then
  3369. exit;
  3370. refobjsec:=nil;
  3371. refgrp:=nil;
  3372. if assigned(objreloc.symbol) then
  3373. begin
  3374. objsym:=objreloc.symbol;
  3375. if objsym.bind<>AB_LOCAL then
  3376. begin
  3377. if not assigned(objsym.exesymbol) then
  3378. internalerror(200603063);
  3379. objsym.exesymbol.used:=true;
  3380. objsym:=objsym.exesymbol.objsymbol;
  3381. end;
  3382. if not assigned(objsym.objsection) then
  3383. exit
  3384. else
  3385. refobjsec:=objsym.objsection;
  3386. end
  3387. else if assigned(objreloc.objsection) then
  3388. refobjsec:=objreloc.objsection
  3389. else if assigned(objreloc.group) then
  3390. refgrp:=objreloc.group
  3391. {$ifdef WASM}
  3392. else if objreloc.ftype=Ord(RELOC_TYPE_INDEX_LEB) then
  3393. {nothing}
  3394. {$endif WASM}
  3395. else
  3396. internalerror(200603316);
  3397. if assigned(exemap) then
  3398. begin
  3399. objsym:=objreloc.symbol;
  3400. if assigned(objsym) and (objsym.typ<>AT_SECTION) then
  3401. exemap.Add(' References '+objsym.name+' in '
  3402. +refobjsec.fullname)
  3403. else if assigned(refobjsec) then
  3404. exemap.Add(' References '+refobjsec.fullname)
  3405. else if assigned(refgrp) then
  3406. exemap.Add(' References '+refgrp.Name)
  3407. {$ifdef WASM}
  3408. else if objreloc.ftype=Ord(RELOC_TYPE_INDEX_LEB) then
  3409. {nothing}
  3410. {$endif WASM}
  3411. else
  3412. internalerror(2006033111);
  3413. end;
  3414. if assigned(refobjsec) then
  3415. AddToObjSectionWorkList(refobjsec);
  3416. end;
  3417. procedure DoVTableRef(vtable:TExeVTable;VTableIdx:longint);
  3418. var
  3419. i : longint;
  3420. objreloc : TObjRelocation;
  3421. begin
  3422. objreloc:=vtable.VTableRef(VTableIdx);
  3423. if assigned(objreloc) then
  3424. begin
  3425. { Process the relocation now if the ObjSection is
  3426. already processed and marked as used. Otherwise we leave it
  3427. unprocessed. It'll then be resolved when the ObjSection is
  3428. changed to Used }
  3429. if vtable.ExeSymbol.ObjSymbol.ObjSection.Used then
  3430. DoReloc(objreloc);
  3431. end;
  3432. { This recursive walking is done here instead of
  3433. in TExeVTable.VTableRef because we can now process
  3434. all needed relocations }
  3435. for i:=0 to vtable.ChildList.Count-1 do
  3436. DoVTableRef(TExeVTable(vtable.ChildList[i]),VTableIdx);
  3437. end;
  3438. procedure ProcessWorkList;
  3439. var
  3440. hs : string;
  3441. i,k : longint;
  3442. objsec : TObjSection;
  3443. objsym : TObjSymbol;
  3444. code : integer;
  3445. vtableidx : longint;
  3446. vtableexesym : TExeSymbol;
  3447. begin
  3448. while ObjSectionWorkList.Count>0 do
  3449. begin
  3450. objsec:=TObjSection(ObjSectionWorkList.Last);
  3451. if not assigned(objsec.exesection) then
  3452. internalerror(202102001);
  3453. if assigned(exemap) then
  3454. exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjRelocations.Count)+' references');
  3455. ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1);
  3456. { Process Relocations }
  3457. for i:=0 to objsec.ObjRelocations.count-1 do
  3458. DoReloc(TObjRelocation(objsec.ObjRelocations[i]));
  3459. { Process Virtual Entry calls }
  3460. if cs_link_opt_vtable in current_settings.globalswitches then
  3461. begin
  3462. for i:=0 to objsec.VTRefList.count-1 do
  3463. begin
  3464. objsym:=TObjSymbol(objsec.VTRefList[i]);
  3465. hs:=objsym.name;
  3466. Delete(hs,1,Pos('_',hs));
  3467. k:=Pos('$$',hs);
  3468. if k=0 then
  3469. internalerror(200603314);
  3470. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  3471. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  3472. if (code<>0) then
  3473. internalerror(200603317);
  3474. if not assigned(vtableexesym) then
  3475. internalerror(200603315);
  3476. if not assigned(vtableexesym.vtable) then
  3477. internalerror(2006033112);
  3478. DoVTableRef(vtableexesym.vtable,vtableidx);
  3479. end;
  3480. end;
  3481. end;
  3482. end;
  3483. var
  3484. i,j : longint;
  3485. exesec : TExeSection;
  3486. objdata : TObjData;
  3487. objsec : TObjSection;
  3488. begin
  3489. ObjSectionWorkList:=TFPObjectList.Create(false);
  3490. if assigned(exemap) then
  3491. exemap.AddHeader('Removing unreferenced sections');
  3492. { Initialize by marking all sections unused and
  3493. adding the sections with oso_keep flags to the ObjSectionWorkList }
  3494. for i:=0 to ObjDataList.Count-1 do
  3495. begin
  3496. ObjData:=TObjData(ObjDataList[i]);
  3497. for j:=0 to ObjData.ObjSectionList.Count-1 do
  3498. begin
  3499. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  3500. objsec.Used:=false;
  3501. { TODO: remove debug section always keep}
  3502. if oso_debug in objsec.secoptions then
  3503. objsec.Used:=true;
  3504. if (oso_keep in objsec.secoptions) then
  3505. begin
  3506. AddToObjSectionWorkList(objsec);
  3507. if objsec.name='.fpc.n_links' then
  3508. objsec.Used:=false;
  3509. end;
  3510. end;
  3511. end;
  3512. if assigned(entrysym) then
  3513. AddToObjSectionWorkList(entrysym.exesymbol.objsymbol.objsection);
  3514. { Process all sections, add new sections to process based
  3515. on the symbol references }
  3516. ProcessWorkList;
  3517. { Handle stuff like .pdata, i.e. sections that are not referenced
  3518. but must be included if sections they reference are included.
  3519. Loop is necessary because .pdata can reference (via .xdata)
  3520. more text sections, VMTs of exception classes, etc. }
  3521. repeat
  3522. MarkTargetSpecificSections(ObjSectionWorkList);
  3523. if (ObjSectionWorkList.Count=0) then
  3524. break;
  3525. ProcessWorkList;
  3526. until False;
  3527. ObjSectionWorkList.Free;
  3528. ObjSectionWorkList:=nil;
  3529. { Remove unused objsections from ExeSectionList }
  3530. for i:=0 to ExeSectionList.Count-1 do
  3531. begin
  3532. exesec:=TExeSection(ExeSectionList[i]);
  3533. for j:=0 to exesec.ObjSectionlist.count-1 do
  3534. begin
  3535. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  3536. if not objsec.used then
  3537. begin
  3538. if assigned(exemap) then
  3539. exemap.Add('Removing '+objsec.FullName);
  3540. exesec.ObjSectionlist[j]:=nil;
  3541. objsec.ReleaseData;
  3542. end;
  3543. end;
  3544. exesec.ObjSectionlist.Pack;
  3545. end;
  3546. end;
  3547. procedure TExeOutput.FixupRelocations;
  3548. var
  3549. i,j : longint;
  3550. exesec : TExeSection;
  3551. objsec : TObjSection;
  3552. begin
  3553. for i:=0 to ExeSectionList.Count-1 do
  3554. begin
  3555. exesec:=TExeSection(ExeSectionList[i]);
  3556. if not assigned(exesec) then
  3557. continue;
  3558. for j:=0 to exesec.ObjSectionlist.count-1 do
  3559. begin
  3560. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  3561. if not objsec.Used then
  3562. internalerror(200603301);
  3563. if (objsec.ObjRelocations.Count>0) and
  3564. not assigned(objsec.data) then
  3565. internalerror(2002051801);
  3566. DoRelocationFixup(objsec);
  3567. {for size = 0 data is not valid PM }
  3568. if assigned(objsec.data) and (objsec.data.size<>objsec.size) then
  3569. internalerror(2010092801,'wrong data size for '+objsec.FullName);
  3570. end;
  3571. end;
  3572. end;
  3573. procedure TExeOutput.RemoveUnusedExeSymbols;
  3574. var
  3575. i : longint;
  3576. sym : TExeSymbol;
  3577. begin
  3578. { Removing unused symbols }
  3579. for i:=0 to ExeSymbolList.Count-1 do
  3580. begin
  3581. sym:=TExeSymbol(ExeSymbolList[i]);
  3582. { an unresolved weak symbol has objsection=nil }
  3583. if assigned(sym.ObjSymbol.objsection) and
  3584. (not sym.ObjSymbol.objsection.Used) then
  3585. ExeSymbolList[i]:=nil;
  3586. end;
  3587. ExeSymbolList.Pack;
  3588. end;
  3589. procedure TExeOutput.SetCurrMemPos(const AValue: qword);
  3590. begin
  3591. if AValue>MaxMemPos then
  3592. Message1(link_f_executable_too_big, target_os_string);
  3593. FCurrMemPos:=AValue;
  3594. end;
  3595. procedure TExeOutput.WriteExeSectionContent;
  3596. var
  3597. exesec : TExeSection;
  3598. objsec : TObjSection;
  3599. i,j : longint;
  3600. dpos,pad: aword;
  3601. begin
  3602. for j:=0 to ExeSectionList.Count-1 do
  3603. begin
  3604. exesec:=TExeSection(ExeSectionList[j]);
  3605. { don't write normal section if writing only debug info }
  3606. if (ExeWriteMode=ewm_dbgonly) and
  3607. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[]) then
  3608. continue;
  3609. if oso_data in exesec.SecOptions then
  3610. begin
  3611. if exesec.DataPos<FWriter.Size then
  3612. InternalError(2012103002);
  3613. FWriter.Writezeros(exesec.DataPos-FWriter.Size);
  3614. for i:=0 to exesec.ObjSectionList.Count-1 do
  3615. begin
  3616. objsec:=TObjSection(exesec.ObjSectionList[i]);
  3617. if oso_data in objsec.secoptions then
  3618. begin
  3619. if not assigned(objsec.data) then
  3620. internalerror(2006030404);
  3621. dpos:=objsec.MemPos-exesec.MemPos+exesec.DataPos;
  3622. pad:=dpos-FWriter.Size;
  3623. { objsection must be within SecAlign bytes from the previous one }
  3624. if (dpos<FWriter.Size) or
  3625. (pad>=max(objsec.SecAlign,1)) then
  3626. internalerror(2006022503);
  3627. FWriter.writeZeros(pad);
  3628. FWriter.writearray(objsec.data);
  3629. end;
  3630. end;
  3631. end;
  3632. end;
  3633. end;
  3634. procedure TExeOutput.ReplaceExeSectionList(newlist: TFPList);
  3635. var
  3636. tmp: TFPHashObjectList;
  3637. i: longint;
  3638. begin
  3639. tmp:=TFPHashObjectList.Create(true);
  3640. for i:=0 to newlist.count-1 do
  3641. TFPHashObject(newlist[i]).ChangeOwner(tmp);
  3642. { prevent destruction of existing sections }
  3643. for i:=0 to ExeSectionList.count-1 do
  3644. ExeSectionList.List[i]:=nil;
  3645. FExeSectionList.Free;
  3646. FExeSectionList:=tmp;
  3647. end;
  3648. {****************************************************************************
  3649. TObjInput
  3650. ****************************************************************************}
  3651. constructor TObjInput.create;
  3652. begin
  3653. end;
  3654. procedure TObjInput.inputerror(const s : string);
  3655. begin
  3656. Comment(V_Error,s+' while reading '+InputFileName);
  3657. end;
  3658. class function TObjInput.CanReadObjData(AReader:TObjectReader):boolean;
  3659. begin
  3660. result:=false;
  3661. end;
  3662. procedure TObjInput.ReadSectionContent(Data:TObjData);
  3663. var
  3664. i: longint;
  3665. sec: TObjSection;
  3666. begin
  3667. for i:=0 to Data.ObjSectionList.Count-1 do
  3668. begin
  3669. sec:=TObjSection(Data.ObjSectionList[i]);
  3670. { Skip debug sections }
  3671. if (oso_debug in sec.SecOptions) and
  3672. (cs_link_strip in current_settings.globalswitches) and
  3673. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  3674. continue;
  3675. if assigned(sec.Data) then
  3676. begin
  3677. FReader.Seek(sec.datapos);
  3678. if not FReader.ReadArray(sec.data,sec.Size) then
  3679. begin
  3680. InputError('Can''t read object data');
  3681. exit;
  3682. end;
  3683. end;
  3684. end;
  3685. end;
  3686. {$ifdef MEMDEBUG}
  3687. initialization
  3688. memobjsymbols:=TMemDebug.create('ObjSymbols');
  3689. memobjsymbols.stop;
  3690. memobjsections:=TMemDebug.create('ObjSections');
  3691. memobjsections.stop;
  3692. finalization
  3693. memobjsymbols.free;
  3694. memobjsymbols := nil;
  3695. memobjsections.free;
  3696. memobjsections := nil;
  3697. {$endif MEMDEBUG}
  3698. end.