ogbase.pas 129 KB

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