ogbase.pas 137 KB

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