ogbase.pas 109 KB

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