ogbase.pas 114 KB

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