ogbase.pas 112 KB

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