ogbase.pas 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623
  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. TObjRelocationType = (
  36. { Relocation to absolute address }
  37. RELOC_ABSOLUTE,
  38. {$ifdef x86_64}
  39. { 32bit Relocation to absolute address }
  40. RELOC_ABSOLUTE32,
  41. { 64 bit coff only }
  42. RELOC_RELATIVE_1,
  43. RELOC_RELATIVE_2,
  44. RELOC_RELATIVE_3,
  45. RELOC_RELATIVE_4,
  46. RELOC_RELATIVE_5,
  47. { PIC }
  48. RELOC_GOTPCREL,
  49. RELOC_PLT32,
  50. {$endif x86_64}
  51. {$ifdef arm}
  52. RELOC_RELATIVE_24,
  53. {$endif arm}
  54. { Relative relocation }
  55. RELOC_RELATIVE,
  56. { PECoff (Windows) RVA relocation }
  57. RELOC_RVA,
  58. { PECoff (Windows) section relocation, required by DWARF2 debug info }
  59. RELOC_SECREL32,
  60. { Generate a 0 value at the place of the relocation,
  61. this is used to remove unused vtable entries }
  62. RELOC_ZERO,
  63. { No relocation is needed. It is used in ARM object files.
  64. Also internal linker use this reloc to make virtual (not real)
  65. links to some sections }
  66. RELOC_NONE
  67. );
  68. {$ifndef x86_64}
  69. const
  70. RELOC_ABSOLUTE32 = RELOC_ABSOLUTE;
  71. {$endif x86_64}
  72. const
  73. { stab types }
  74. N_GSYM = $20;
  75. N_STSYM = 38; { initialized const }
  76. N_LCSYM = 40; { non initialized variable}
  77. N_Function = $24; { function or const }
  78. N_TextLine = $44;
  79. N_DataLine = $46;
  80. N_BssLine = $48;
  81. N_RSYM = $40; { register variable }
  82. N_LSYM = $80;
  83. N_tsym = 160;
  84. N_SourceFile = $64;
  85. N_IncludeFile = $84;
  86. N_BINCL = $82;
  87. N_EINCL = $A2;
  88. N_LBRAC = $C0;
  89. N_EXCL = $C2;
  90. N_RBRAC = $E0;
  91. { GNU extensions }
  92. debuglinkname='.gnu_debuglink';
  93. type
  94. TObjSectionOption = (
  95. { Has Data available in the file }
  96. oso_Data,
  97. { Is loaded into memory }
  98. oso_load,
  99. { Not loaded into memory }
  100. oso_noload,
  101. { Read only }
  102. oso_readonly,
  103. { Read/Write }
  104. oso_write,
  105. { Contains executable instructions }
  106. oso_executable,
  107. { Never discard section }
  108. oso_keep,
  109. { Special common symbols }
  110. oso_common,
  111. { Contains debug info and can be stripped }
  112. oso_debug,
  113. { Contains only strings }
  114. oso_strings
  115. );
  116. TObjSectionOptions = set of TObjSectionOption;
  117. TObjSymbol = class(TFPHashObject)
  118. public
  119. bind : TAsmsymbind;
  120. typ : TAsmsymtype;
  121. { Current assemble pass, used to detect duplicate labels }
  122. pass : byte;
  123. objsection : TObjSection;
  124. symidx : longint;
  125. offset,
  126. size : aint;
  127. { Used for external and common solving during linking }
  128. exesymbol : TExeSymbol;
  129. constructor create(AList:TFPHashObjectList;const AName:string);
  130. function address:aint;
  131. procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  132. end;
  133. { Stabs is common for all targets }
  134. TObjStabEntry=packed record
  135. strpos : longint;
  136. ntype : byte;
  137. nother : byte;
  138. ndesc : word;
  139. nvalue : longint;
  140. end;
  141. PObjStabEntry=^TObjStabEntry;
  142. TObjRelocation = class
  143. DataOffset,
  144. orgsize : aint; { original size of the symbol to Relocate, required for COFF }
  145. symbol : TObjSymbol;
  146. objsection : TObjSection; { only used if symbol=nil }
  147. typ : TObjRelocationType;
  148. constructor CreateSymbol(ADataOffset:aint;s:TObjSymbol;Atyp:TObjRelocationType);
  149. constructor CreateSymbolSize(ADataOffset:aint;s:TObjSymbol;Aorgsize:aint;Atyp:TObjRelocationType);
  150. constructor CreateSection(ADataOffset:aint;aobjsec:TObjSection;Atyp:TObjRelocationType);
  151. end;
  152. TObjSection = class(TFPHashObject)
  153. private
  154. FData : TDynamicArray;
  155. FSecOptions : TObjSectionOptions;
  156. FCachedFullName : pshortstring;
  157. procedure SetSecOptions(Aoptions:TObjSectionOptions);
  158. public
  159. ObjData : TObjData;
  160. SecSymIdx : longint; { index for the section in symtab }
  161. SecAlign : shortint; { alignment of the section }
  162. { section Data }
  163. Size,
  164. DataPos,
  165. MemPos : aint;
  166. DataAlignBytes : shortint;
  167. { Relocations (=references) to other sections }
  168. ObjRelocations : TFPObjectList;
  169. { Symbols this defines }
  170. ObjSymbolDefines : TFPObjectList;
  171. { executable linking }
  172. ExeSection : TExeSection;
  173. USed : Boolean;
  174. VTRefList : TFPObjectList;
  175. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual;
  176. destructor destroy;override;
  177. function write(const d;l:aint):aint;
  178. function writestr(const s:string):aint;
  179. function WriteZeros(l:longint):aint;
  180. procedure setmempos(var mpos:aint);
  181. procedure setDatapos(var dpos:aint);
  182. procedure alloc(l:aint);
  183. procedure addsymReloc(ofs:aint;p:TObjSymbol;Reloctype:TObjRelocationType);
  184. procedure addsectionReloc(ofs:aint;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  185. procedure AddSymbolDefine(p:TObjSymbol);
  186. procedure FixupRelocs;virtual;
  187. procedure ReleaseData;
  188. function FullName:string;
  189. property Data:TDynamicArray read FData;
  190. property SecOptions:TObjSectionOptions read FSecOptions write SetSecOptions;
  191. end;
  192. TObjSectionClass = class of TObjSection;
  193. TString80 = string[80];
  194. TObjData = class(TLinkedListItem)
  195. private
  196. FName : TString80;
  197. FCurrObjSec : TObjSection;
  198. FObjSectionList : TFPHashObjectList;
  199. FCObjSection : TObjSectionClass;
  200. { Symbols that will be defined in this object file }
  201. FObjSymbolList : TFPHashObjectList;
  202. FCachedAsmSymbolList : TFPObjectList;
  203. { Special info sections that are written to during object generation }
  204. FStabsObjSec,
  205. FStabStrObjSec : TObjSection;
  206. procedure section_reset(p:TObject;arg:pointer);
  207. procedure section_afteralloc(p:TObject;arg:pointer);
  208. procedure section_afterwrite(p:TObject;arg:pointer);
  209. protected
  210. property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
  211. public
  212. CurrPass : byte;
  213. ImageBase : aint;
  214. constructor create(const n:string);virtual;
  215. destructor destroy;override;
  216. { Sections }
  217. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;
  218. function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;virtual;
  219. function sectiontype2align(atype:TAsmSectiontype):shortint;virtual;
  220. function createsection(atype:TAsmSectionType;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;
  221. function createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean=true):TObjSection;virtual;
  222. procedure CreateDebugSections;virtual;
  223. function findsection(const aname:string):TObjSection;
  224. procedure setsection(asec:TObjSection);
  225. { Symbols }
  226. function createsymbol(const aname:string):TObjSymbol;
  227. function symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  228. function symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  229. function symbolref(asmsym:TAsmSymbol):TObjSymbol;
  230. function symbolref(const aname:string):TObjSymbol;
  231. procedure ResetCachedAsmSymbols;
  232. { Allocation }
  233. procedure alloc(len:aint);
  234. procedure allocalign(len:shortint);
  235. procedure writebytes(const Data;len:aint);
  236. procedure writeReloc(Data,len:aint;p:TObjSymbol;Reloctype:TObjRelocationType);virtual;abstract;
  237. procedure beforealloc;virtual;
  238. procedure beforewrite;virtual;
  239. procedure afteralloc;virtual;
  240. procedure afterwrite;virtual;
  241. procedure resetsections;
  242. property Name:TString80 read FName;
  243. property CurrObjSec:TObjSection read FCurrObjSec;
  244. property ObjSymbolList:TFPHashObjectList read FObjSymbolList;
  245. property ObjSectionList:TFPHashObjectList read FObjSectionList;
  246. property StabsSec:TObjSection read FStabsObjSec write FStabsObjSec;
  247. property StabStrSec:TObjSection read FStabStrObjSec write FStabStrObjSec;
  248. end;
  249. TObjDataClass = class of TObjData;
  250. TObjOutput = class
  251. private
  252. FCObjData : TObjDataClass;
  253. protected
  254. { writer }
  255. FWriter : TObjectwriter;
  256. function writeData(Data:TObjData):boolean;virtual;abstract;
  257. property CObjData : TObjDataClass read FCObjData write FCObjData;
  258. public
  259. constructor create(AWriter:TObjectWriter);virtual;
  260. destructor destroy;override;
  261. function newObjData(const n:string):TObjData;
  262. function startObjectfile(const fn:string):boolean;
  263. function writeobjectfile(Data:TObjData):boolean;
  264. procedure exportsymbol(p:TObjSymbol);
  265. property Writer:TObjectWriter read FWriter;
  266. end;
  267. TObjOutputClass=class of TObjOutput;
  268. TObjInput = class
  269. private
  270. FCObjData : TObjDataClass;
  271. protected
  272. { reader }
  273. FReader : TObjectReader;
  274. InputFileName : string;
  275. property CObjData : TObjDataClass read FCObjData write FCObjData;
  276. public
  277. constructor create;virtual;
  278. destructor destroy;override;
  279. function newObjData(const n:string):TObjData;
  280. function ReadObjData(AReader:TObjectreader;Data:TObjData):boolean;virtual;abstract;
  281. procedure inputerror(const s : string);
  282. end;
  283. TObjInputClass=class of TObjInput;
  284. TVTableEntry=record
  285. ObjRelocation : TObjRelocation;
  286. orgreloctype : TObjRelocationType;
  287. Enabled,
  288. Used : Boolean;
  289. end;
  290. PVTableEntry=^TVTableEntry;
  291. TExeVTable = class
  292. private
  293. procedure CheckIdx(VTableIdx:longint);
  294. public
  295. ExeSymbol : TExeSymbol;
  296. EntryCnt : Longint;
  297. EntryArray : PVTableEntry;
  298. Consolidated : Boolean;
  299. ChildList : TFPObjectList;
  300. constructor Create(AExeSymbol:TExeSymbol);
  301. destructor Destroy;override;
  302. procedure AddChild(vt:TExeVTable);
  303. procedure AddEntry(VTableIdx:Longint);
  304. procedure SetVTableSize(ASize:longint);
  305. function VTableRef(VTableIdx:Longint):TObjRelocation;
  306. end;
  307. TSymbolState = (symstate_undefined,symstate_defined,symstate_common);
  308. TExeSymbol = class(TFPHashObject)
  309. ObjSymbol : TObjSymbol;
  310. ExeSection : TExeSection;
  311. State : TSymbolState;
  312. { Used for vmt references optimization }
  313. VTable : TExeVTable;
  314. end;
  315. TExeSection = class(TFPHashObject)
  316. private
  317. FSecSymIdx : longint;
  318. FObjSectionList : TFPObjectList;
  319. public
  320. Size,
  321. DataPos,
  322. MemPos : aint;
  323. SecAlign : shortint;
  324. SecOptions : TObjSectionOptions;
  325. constructor create(AList:TFPHashObjectList;const AName:string);virtual;
  326. destructor destroy;override;
  327. procedure AddObjSection(objsec:TObjSection);
  328. property ObjSectionList:TFPObjectList read FObjSectionList;
  329. property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
  330. end;
  331. TExeSectionClass=class of TExeSection;
  332. TStaticLibrary = class(TFPHashObject)
  333. private
  334. FArReader : TObjectReader;
  335. FObjInputClass : TObjInputClass;
  336. public
  337. constructor create(AList:TFPHashObjectList;const AName:string;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  338. destructor destroy;override;
  339. property ArReader:TObjectReader read FArReader;
  340. property ObjInputClass:TObjInputClass read FObjInputClass;
  341. end;
  342. TImportLibrary = class(TFPHashObject)
  343. private
  344. FImportSymbolList : TFPHashObjectList;
  345. public
  346. constructor create(AList:TFPHashObjectList;const AName:string);
  347. destructor destroy;override;
  348. property ImportSymbolList:TFPHashObjectList read FImportSymbolList;
  349. end;
  350. TImportSymbol = class(TFPHashObject)
  351. private
  352. FOrdNr : longint;
  353. FIsVar : boolean;
  354. FMangledName : string;
  355. public
  356. constructor create(AList:TFPHashObjectList;const AName:string;AOrdNr:longint;AIsVar:boolean);
  357. property OrdNr: longint read FOrdNr;
  358. property MangledName: string read FMangledName;
  359. property IsVar: boolean read FIsVar;
  360. end;
  361. TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);
  362. TExeOutput = class
  363. private
  364. { ExeSectionList }
  365. FCObjData : TObjDataClass;
  366. FCExeSection : TExeSectionClass;
  367. FCurrExeSec : TExeSection;
  368. FExeSectionList : TFPHashObjectList;
  369. Fzeronr : longint;
  370. { Symbols }
  371. FExeSymbolList : TFPHashObjectList;
  372. FUnresolvedExeSymbols : TFPObjectList;
  373. FExternalObjSymbols,
  374. FCommonObjSymbols : TFPObjectList;
  375. FEntryName : string;
  376. FExeVTableList : TFPObjectList;
  377. { Objects }
  378. FObjDataList : TFPObjectList;
  379. { Position calculation }
  380. FImageBase : aint;
  381. protected
  382. { writer }
  383. FExeWriteMode : TExeWriteMode;
  384. FWriter : TObjectwriter;
  385. commonObjSection : TObjSection;
  386. internalObjData : TObjData;
  387. EntrySym : TObjSymbol;
  388. SectionDataAlign,
  389. SectionMemAlign : aint;
  390. function writeData:boolean;virtual;abstract;
  391. property CExeSection:TExeSectionClass read FCExeSection write FCExeSection;
  392. property CObjData:TObjDataClass read FCObjData write FCObjData;
  393. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList);virtual;
  394. public
  395. CurrDataPos,
  396. CurrMemPos : aint;
  397. IsSharedLibrary : boolean;
  398. constructor create;virtual;
  399. destructor destroy;override;
  400. function FindExeSection(const aname:string):TExeSection;
  401. procedure AddObjData(ObjData:TObjData);
  402. procedure Load_Start;virtual;
  403. procedure Load_EntryName(const aname:string);virtual;
  404. procedure Load_Symbol(const aname:string);virtual;
  405. procedure Load_IsSharedLibrary;
  406. procedure Load_ImageBase(const avalue:string);
  407. procedure Order_Start;virtual;
  408. procedure Order_End;virtual;
  409. procedure Order_ExeSection(const aname:string);virtual;
  410. procedure Order_Align(const avalue:string);virtual;
  411. procedure Order_Zeros(const avalue:string);virtual;
  412. procedure Order_Symbol(const aname:string);virtual;
  413. procedure Order_EndExeSection;virtual;
  414. procedure Order_ObjSection(const aname:string);virtual;
  415. procedure MemPos_Start;virtual;
  416. procedure MemPos_Header;virtual;
  417. procedure MemPos_ExeSection(const aname:string);virtual;
  418. procedure MemPos_EndExeSection;virtual;
  419. procedure DataPos_Start;virtual;
  420. procedure DataPos_Header;virtual;
  421. procedure DataPos_ExeSection(const aname:string);virtual;
  422. procedure DataPos_EndExeSection;virtual;
  423. procedure DataPos_Symbols;virtual;
  424. procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  425. procedure PackUnresolvedExeSymbols(const s:string);
  426. procedure ResolveSymbols(StaticLibraryList:TFPHashObjectList);
  427. procedure PrintMemoryMap;
  428. procedure FixupSymbols;
  429. procedure FixupRelocations;
  430. procedure MergeStabs;
  431. procedure RemoveUnreferencedSections;
  432. procedure RemoveEmptySections;
  433. procedure RemoveDebugInfo;
  434. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual;
  435. procedure GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  436. function WriteExeFile(const fn:string):boolean;
  437. property Writer:TObjectWriter read FWriter;
  438. property ExeSectionList:TFPHashObjectList read FExeSectionList;
  439. property ObjDataList:TFPObjectList read FObjDataList;
  440. property ExeSymbolList:TFPHashObjectList read FExeSymbolList;
  441. property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
  442. property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols;
  443. property CommonObjSymbols:TFPObjectList read FCommonObjSymbols;
  444. property ExeVTableList:TFPObjectList read FExeVTableList;
  445. property EntryName:string read FEntryName write FEntryName;
  446. property ImageBase:aint read FImageBase write FImageBase;
  447. property CurrExeSec:TExeSection read FCurrExeSec;
  448. property ExeWriteMode:TExeWriteMode read FExeWriteMode write FExeWriteMode;
  449. end;
  450. TExeOutputClass=class of TExeOutput;
  451. var
  452. exeoutput : TExeOutput;
  453. implementation
  454. uses
  455. SysUtils,
  456. globals,verbose,fmodule,ogmap;
  457. const
  458. SectionDataMaxGrow = 4096;
  459. {$ifdef MEMDEBUG}
  460. var
  461. memobjsymbols,
  462. memobjsections : TMemDebug;
  463. {$endif MEMDEBUG}
  464. {*****************************************************************************
  465. TObjSymbol
  466. *****************************************************************************}
  467. constructor TObjSymbol.create(AList:TFPHashObjectList;const AName:string);
  468. begin;
  469. inherited create(AList,AName);
  470. bind:=AB_EXTERNAL;
  471. typ:=AT_NONE;
  472. symidx:=-1;
  473. size:=0;
  474. offset:=0;
  475. objsection:=nil;
  476. end;
  477. function TObjSymbol.address:aint;
  478. begin
  479. if assigned(objsection) then
  480. result:=offset+objsection.mempos
  481. else
  482. result:=0;
  483. end;
  484. procedure TObjSymbol.SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  485. begin
  486. if not(abind in [AB_GLOBAL,AB_LOCAL,AB_COMMON]) then
  487. internalerror(200603016);
  488. if not assigned(aobjsec) then
  489. internalerror(200603017);
  490. if (bind=AB_EXTERNAL) then
  491. begin
  492. bind:=abind;
  493. typ:=atyp;
  494. end
  495. else
  496. begin
  497. if pass=apass then
  498. begin
  499. Message1(asmw_e_duplicate_label,name);
  500. exit;
  501. end;
  502. end;
  503. pass:=apass;
  504. { Code can never grow after a pass }
  505. if assigned(objsection) and
  506. (objsection=aobjsec) and
  507. (aobjsec.size>offset) then
  508. internalerror(200603014);
  509. objsection:=aobjsec;
  510. offset:=aobjsec.size;
  511. end;
  512. {****************************************************************************
  513. TObjRelocation
  514. ****************************************************************************}
  515. constructor TObjRelocation.CreateSymbol(ADataOffset:aint;s:TObjSymbol;Atyp:TObjRelocationType);
  516. begin
  517. if not assigned(s) then
  518. internalerror(200603034);
  519. DataOffset:=ADataOffset;
  520. Symbol:=s;
  521. OrgSize:=0;
  522. ObjSection:=nil;
  523. Typ:=Atyp;
  524. end;
  525. constructor TObjRelocation.CreateSymbolSize(ADataOffset:aint;s:TObjSymbol;Aorgsize:aint;Atyp:TObjRelocationType);
  526. begin
  527. if not assigned(s) then
  528. internalerror(200603035);
  529. DataOffset:=ADataOffset;
  530. Symbol:=s;
  531. OrgSize:=Aorgsize;
  532. ObjSection:=nil;
  533. Typ:=Atyp;
  534. end;
  535. constructor TObjRelocation.CreateSection(ADataOffset:aint;aobjsec:TObjSection;Atyp:TObjRelocationType);
  536. begin
  537. if not assigned(aobjsec) then
  538. internalerror(200603036);
  539. DataOffset:=ADataOffset;
  540. Symbol:=nil;
  541. OrgSize:=0;
  542. ObjSection:=aobjsec;
  543. Typ:=Atyp;
  544. end;
  545. {****************************************************************************
  546. TObjSection
  547. ****************************************************************************}
  548. constructor TObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
  549. begin
  550. inherited Create(AList,Aname);
  551. { Data }
  552. Size:=0;
  553. Datapos:=0;
  554. mempos:=0;
  555. FData:=Nil;
  556. { Setting the secoptions allocates Data if needed }
  557. secoptions:=Aoptions;
  558. secalign:=Aalign;
  559. secsymidx:=0;
  560. { relocation }
  561. ObjRelocations:=TFPObjectList.Create(true);
  562. ObjSymbolDefines:=TFPObjectList.Create(false);
  563. VTRefList:=TFPObjectList.Create(false);
  564. end;
  565. destructor TObjSection.destroy;
  566. begin
  567. if assigned(Data) then
  568. Data.Free;
  569. stringdispose(FCachedFullName);
  570. ObjRelocations.Free;
  571. ObjSymbolDefines.Free;
  572. VTRefList.Free;
  573. inherited destroy;
  574. end;
  575. procedure TObjSection.SetSecOptions(Aoptions:TObjSectionOptions);
  576. begin
  577. FSecOptions:=FSecOptions+AOptions;
  578. if (oso_Data in secoptions) and
  579. not assigned(FData) then
  580. FData:=TDynamicArray.Create(SectionDataMaxGrow);
  581. end;
  582. function TObjSection.write(const d;l:aint):aint;
  583. begin
  584. result:=size;
  585. if assigned(Data) then
  586. begin
  587. if Size<>Data.size then
  588. internalerror(200602281);
  589. Data.write(d,l);
  590. inc(Size,l);
  591. end
  592. else
  593. internalerror(200602289);
  594. end;
  595. function TObjSection.writestr(const s:string):aint;
  596. begin
  597. result:=Write(s[1],length(s));
  598. end;
  599. function TObjSection.WriteZeros(l:longint):aint;
  600. var
  601. empty : array[0..1023] of byte;
  602. begin
  603. if l>sizeof(empty) then
  604. internalerror(200404082);
  605. if l>0 then
  606. begin
  607. fillchar(empty,l,0);
  608. result:=Write(empty,l);
  609. end
  610. else
  611. result:=Size;
  612. end;
  613. procedure TObjSection.setDatapos(var dpos:aint);
  614. begin
  615. if oso_Data in secoptions then
  616. begin
  617. { get aligned Datapos }
  618. Datapos:=align(dpos,secalign);
  619. Dataalignbytes:=Datapos-dpos;
  620. { return updated Datapos }
  621. dpos:=Datapos+size;
  622. end
  623. else
  624. Datapos:=dpos;
  625. end;
  626. procedure TObjSection.setmempos(var mpos:aint);
  627. begin
  628. mempos:=align(mpos,secalign);
  629. { return updated mempos }
  630. mpos:=mempos+size;
  631. end;
  632. procedure TObjSection.alloc(l:aint);
  633. begin
  634. inc(size,l);
  635. end;
  636. procedure TObjSection.addsymReloc(ofs:aint;p:TObjSymbol;Reloctype:TObjRelocationType);
  637. begin
  638. ObjRelocations.Add(TObjRelocation.CreateSymbol(ofs,p,reloctype));
  639. end;
  640. procedure TObjSection.addsectionReloc(ofs:aint;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  641. begin
  642. ObjRelocations.Add(TObjRelocation.CreateSection(ofs,aobjsec,reloctype));
  643. end;
  644. procedure TObjSection.AddSymbolDefine(p:TObjSymbol);
  645. begin
  646. if p.bind<>AB_GLOBAL then
  647. exit;
  648. ObjSymbolDefines.Add(p);
  649. end;
  650. procedure TObjSection.FixupRelocs;
  651. begin
  652. end;
  653. procedure TObjSection.ReleaseData;
  654. begin
  655. if assigned(FData) then
  656. begin
  657. FData.free;
  658. FData:=nil;
  659. end;
  660. ObjRelocations.free;
  661. ObjRelocations:=nil;
  662. ObjSymbolDefines.Free;
  663. ObjSymbolDefines:=nil;
  664. if assigned(FCachedFullName) then
  665. begin
  666. stringdispose(FCachedFullName);
  667. FCachedFullName:=nil;
  668. end;
  669. end;
  670. function TObjSection.FullName:string;
  671. begin
  672. if not assigned(FCachedFullName) then
  673. begin
  674. if assigned(ObjData) then
  675. FCachedFullName:=stringdup(ObjData.Name+'('+Name+')')
  676. else
  677. FCachedFullName:=stringdup(Name);
  678. end;
  679. result:=FCachedFullName^;
  680. end;
  681. {****************************************************************************
  682. TObjData
  683. ****************************************************************************}
  684. constructor TObjData.create(const n:string);
  685. begin
  686. inherited create;
  687. FName:=ExtractFileName(n);
  688. FObjSectionList:=TFPHashObjectList.Create(true);
  689. FStabsObjSec:=nil;
  690. FStabStrObjSec:=nil;
  691. { symbols }
  692. FObjSymbolList:=TFPHashObjectList.Create(true);
  693. FCachedAsmSymbolList:=TFPObjectList.Create(false);
  694. { section class type for creating of new sections }
  695. FCObjSection:=TObjSection;
  696. end;
  697. destructor TObjData.destroy;
  698. begin
  699. { Symbols }
  700. {$ifdef MEMDEBUG}
  701. MemObjSymbols.Start;
  702. {$endif}
  703. ResetCachedAsmSymbols;
  704. FCachedAsmSymbolList.free;
  705. FObjSymbolList.free;
  706. {$ifdef MEMDEBUG}
  707. MemObjSymbols.Stop;
  708. {$endif}
  709. { Sections }
  710. {$ifdef MEMDEBUG}
  711. MemObjSections.Start;
  712. {$endif}
  713. FObjSectionList.free;
  714. {$ifdef MEMDEBUG}
  715. MemObjSections.Stop;
  716. {$endif}
  717. inherited destroy;
  718. end;
  719. function TObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  720. const
  721. secnames : array[TAsmSectiontype] of string[16] = ('',
  722. 'code',
  723. 'Data',
  724. 'Data',
  725. 'roData',
  726. 'bss',
  727. 'threadvar',
  728. 'pdata',
  729. 'stub',
  730. 'stab','stabstr',
  731. 'iData2','iData4','iData5','iData6','iData7','eData',
  732. 'eh_frame',
  733. 'debug_frame','debug_info','debug_line','debug_abbrev',
  734. 'fpc',
  735. 'toc',
  736. 'init',
  737. 'fini'
  738. );
  739. var
  740. sep : string[3];
  741. begin
  742. if aname<>'' then
  743. begin
  744. case aorder of
  745. secorder_begin :
  746. sep:='.b_';
  747. secorder_end :
  748. sep:='.z_';
  749. else
  750. sep:='.n_';
  751. end;
  752. result:=secnames[atype]+sep+aname
  753. end
  754. else
  755. result:=secnames[atype];
  756. end;
  757. function TObjData.sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
  758. const
  759. secoptions : array[TAsmSectiontype] of TObjSectionOptions = ([],
  760. {code} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
  761. {Data} [oso_Data,oso_load,oso_write,oso_keep],
  762. {$warning TODO Fix sec_rodata be read-only-with-relocs}
  763. {roData} [oso_Data,oso_load,oso_write,oso_keep],
  764. {$warning TODO Fix sec_rodata_norel be read-only/constant}
  765. {roData_norel} [oso_Data,oso_load,oso_write,oso_keep],
  766. {bss} [oso_load,oso_write,oso_keep],
  767. {threadvar} [oso_load,oso_write],
  768. {pdata} [oso_load,oso_readonly,oso_keep],
  769. {stub} [oso_Data,oso_load,oso_readonly,oso_executable],
  770. {stab} [oso_Data,oso_noload,oso_debug],
  771. {stabstr} [oso_Data,oso_noload,oso_strings,oso_debug],
  772. {iData2} [oso_Data,oso_load,oso_write],
  773. {iData4} [oso_Data,oso_load,oso_write],
  774. {iData5} [oso_Data,oso_load,oso_write],
  775. {iData6} [oso_Data,oso_load,oso_write],
  776. {iData7} [oso_Data,oso_load,oso_write],
  777. {eData} [oso_Data,oso_load,oso_readonly],
  778. {eh_frame} [oso_Data,oso_load,oso_readonly],
  779. {debug_frame} [oso_Data,oso_noload,oso_debug],
  780. {debug_info} [oso_Data,oso_noload,oso_debug],
  781. {debug_line} [oso_Data,oso_noload,oso_debug],
  782. {debug_abbrev} [oso_Data,oso_noload,oso_debug],
  783. {fpc} [oso_Data,oso_load,oso_write,oso_keep],
  784. {toc} [oso_Data,oso_load,oso_readonly],
  785. {init} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
  786. {fini} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep]
  787. );
  788. begin
  789. result:=secoptions[atype];
  790. end;
  791. function TObjData.sectiontype2align(atype:TAsmSectiontype):shortint;
  792. begin
  793. case atype of
  794. sec_stabstr,sec_debug_info,sec_debug_line,sec_debug_abbrev:
  795. result:=1;
  796. sec_code,
  797. sec_bss,
  798. sec_data:
  799. result:=16;
  800. { For idata (at least idata2) it must be 4 bytes, because
  801. an entry is always (also in win64) 20 bytes and aligning
  802. on 8 bytes will insert 4 bytes between the entries resulting
  803. in a corrupt idata section }
  804. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7:
  805. result:=4;
  806. else
  807. result:=sizeof(aint);
  808. end;
  809. end;
  810. function TObjData.createsection(atype:TAsmSectionType;const aname:string;aorder:TAsmSectionOrder):TObjSection;
  811. begin
  812. result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),sectiontype2options(atype));
  813. end;
  814. function TObjData.createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean):TObjSection;
  815. begin
  816. if DiscardDuplicate then
  817. result:=TObjSection(FObjSectionList.Find(aname))
  818. else
  819. result:=nil;
  820. if not assigned(result) then
  821. begin
  822. result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
  823. result.ObjData:=self;
  824. end;
  825. FCurrObjSec:=result;
  826. end;
  827. procedure TObjData.CreateDebugSections;
  828. begin
  829. end;
  830. function TObjData.FindSection(const aname:string):TObjSection;
  831. begin
  832. result:=TObjSection(FObjSectionList.Find(aname));
  833. end;
  834. procedure TObjData.setsection(asec:TObjSection);
  835. begin
  836. if asec.ObjData<>self then
  837. internalerror(200403041);
  838. FCurrObjSec:=asec;
  839. end;
  840. function TObjData.createsymbol(const aname:string):TObjSymbol;
  841. begin
  842. result:=TObjSymbol(FObjSymbolList.Find(aname));
  843. if not assigned(result) then
  844. result:=TObjSymbol.Create(FObjSymbolList,aname);
  845. end;
  846. function TObjData.symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  847. begin
  848. if assigned(asmsym) then
  849. begin
  850. if not assigned(asmsym.cachedObjSymbol) then
  851. begin
  852. result:=symboldefine(asmsym.name,asmsym.bind,asmsym.typ);
  853. asmsym.cachedObjSymbol:=result;
  854. FCachedAsmSymbolList.add(asmsym);
  855. end
  856. else
  857. begin
  858. result:=TObjSymbol(asmsym.cachedObjSymbol);
  859. result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
  860. { Register also in TObjSection }
  861. CurrObjSec.AddSymbolDefine(result);
  862. end;
  863. end
  864. else
  865. result:=nil;
  866. end;
  867. function TObjData.symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  868. begin
  869. if not assigned(CurrObjSec) then
  870. internalerror(200603051);
  871. result:=CreateSymbol(aname);
  872. { Register also in TObjSection }
  873. CurrObjSec.AddSymbolDefine(result);
  874. result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
  875. end;
  876. function TObjData.symbolref(asmsym:TAsmSymbol):TObjSymbol;
  877. begin
  878. if assigned(asmsym) then
  879. begin
  880. if not assigned(asmsym.cachedObjSymbol) then
  881. begin
  882. result:=symbolref(asmsym.name);
  883. asmsym.cachedObjSymbol:=result;
  884. FCachedAsmSymbolList.add(asmsym);
  885. end
  886. else
  887. result:=TObjSymbol(asmsym.cachedObjSymbol);
  888. end
  889. else
  890. result:=nil;
  891. end;
  892. function TObjData.symbolref(const aname:string):TObjSymbol;
  893. begin
  894. if not assigned(CurrObjSec) then
  895. internalerror(200603052);
  896. result:=CreateSymbol(aname);
  897. end;
  898. procedure TObjData.ResetCachedAsmSymbols;
  899. var
  900. i : longint;
  901. begin
  902. for i:=0 to FCachedAsmSymbolList.Count-1 do
  903. tasmsymbol(FCachedAsmSymbolList[i]).cachedObjSymbol:=nil;
  904. FCachedAsmSymbolList.Clear;
  905. end;
  906. procedure TObjData.writebytes(const Data;len:aint);
  907. begin
  908. if not assigned(CurrObjSec) then
  909. internalerror(200402251);
  910. CurrObjSec.write(Data,len);
  911. end;
  912. procedure TObjData.alloc(len:aint);
  913. begin
  914. if not assigned(CurrObjSec) then
  915. internalerror(200402252);
  916. CurrObjSec.alloc(len);
  917. end;
  918. procedure TObjData.allocalign(len:shortint);
  919. begin
  920. if not assigned(CurrObjSec) then
  921. internalerror(200402253);
  922. CurrObjSec.alloc(align(CurrObjSec.size,len)-CurrObjSec.size);
  923. end;
  924. procedure TObjData.section_afteralloc(p:TObject;arg:pointer);
  925. begin
  926. with TObjSection(p) do
  927. alloc(align(size,secalign)-size);
  928. end;
  929. procedure TObjData.section_afterwrite(p:TObject;arg:pointer);
  930. begin
  931. with TObjSection(p) do
  932. begin
  933. if assigned(Data) then
  934. writezeros(align(size,secalign)-size);
  935. end;
  936. end;
  937. procedure TObjData.section_reset(p:TObject;arg:pointer);
  938. begin
  939. with TObjSection(p) do
  940. begin
  941. Size:=0;
  942. Datapos:=0;
  943. mempos:=0;
  944. end;
  945. end;
  946. procedure TObjData.beforealloc;
  947. begin
  948. { create stabs sections if debugging }
  949. if assigned(StabsSec) then
  950. begin
  951. StabsSec.Alloc(sizeof(TObjStabEntry));
  952. StabStrSec.Alloc(1);
  953. end;
  954. end;
  955. procedure TObjData.beforewrite;
  956. var
  957. s : string[1];
  958. hstab : TObjStabEntry;
  959. begin
  960. { create stabs sections if debugging }
  961. if assigned(StabsSec) then
  962. begin
  963. { Create dummy HdrSym stab, it will be overwritten in AfterWrite }
  964. fillchar(hstab,sizeof(hstab),0);
  965. StabsSec.Write(hstab,sizeof(hstab));
  966. { start of stabstr }
  967. s:=#0;
  968. StabStrSec.write(s[1],length(s));
  969. end;
  970. end;
  971. procedure TObjData.afteralloc;
  972. begin
  973. FObjSectionList.ForEachCall(@section_afteralloc,nil);
  974. end;
  975. procedure TObjData.afterwrite;
  976. var
  977. s : string[1];
  978. hstab : TObjStabEntry;
  979. begin
  980. FObjSectionList.ForEachCall(@section_afterwrite,nil);
  981. { For the stab section we need an HdrSym which can now be
  982. calculated more easily }
  983. if assigned(StabsSec) then
  984. begin
  985. { end of stabstr }
  986. s:=#0;
  987. StabStrSec.write(s[1],length(s));
  988. { header stab }
  989. hstab.strpos:=1;
  990. hstab.ntype:=0;
  991. hstab.nother:=0;
  992. hstab.ndesc:=(StabsSec.Size div sizeof(TObjStabEntry))-1;
  993. hstab.nvalue:=StabStrSec.Size;
  994. StabsSec.Data.seek(0);
  995. StabsSec.Data.write(hstab,sizeof(hstab));
  996. end;
  997. end;
  998. procedure TObjData.resetsections;
  999. begin
  1000. FObjSectionList.ForEachCall(@section_reset,nil);
  1001. end;
  1002. {****************************************************************************
  1003. TObjOutput
  1004. ****************************************************************************}
  1005. constructor TObjOutput.create(AWriter:TObjectWriter);
  1006. begin
  1007. FWriter:=AWriter;
  1008. CObjData:=TObjData;
  1009. end;
  1010. destructor TObjOutput.destroy;
  1011. begin
  1012. inherited destroy;
  1013. end;
  1014. function TObjOutput.newObjData(const n:string):TObjData;
  1015. begin
  1016. result:=CObjData.create(n);
  1017. if (cs_use_lineinfo in current_settings.globalswitches) or
  1018. (cs_debuginfo in current_settings.moduleswitches) then
  1019. result.CreateDebugSections;
  1020. end;
  1021. function TObjOutput.startObjectfile(const fn:string):boolean;
  1022. begin
  1023. result:=false;
  1024. { start the writer already, so the .a generation can initialize
  1025. the position of the current objectfile }
  1026. if not FWriter.createfile(fn) then
  1027. Comment(V_Fatal,'Can''t create object '+fn);
  1028. result:=true;
  1029. end;
  1030. function TObjOutput.writeobjectfile(Data:TObjData):boolean;
  1031. begin
  1032. if errorcount=0 then
  1033. result:=writeData(Data)
  1034. else
  1035. result:=true;
  1036. { close the writer }
  1037. FWriter.closefile;
  1038. end;
  1039. procedure TObjOutput.exportsymbol(p:TObjSymbol);
  1040. begin
  1041. { export globals and common symbols, this is needed
  1042. for .a files }
  1043. if p.bind in [AB_GLOBAL,AB_COMMON] then
  1044. FWriter.writesym(p.name);
  1045. end;
  1046. {****************************************************************************
  1047. TExeVTable
  1048. ****************************************************************************}
  1049. constructor TExeVTable.Create(AExeSymbol:TExeSymbol);
  1050. begin
  1051. ExeSymbol:=AExeSymbol;
  1052. if ExeSymbol.State=symstate_undefined then
  1053. internalerror(200604012);
  1054. ChildList:=TFPObjectList.Create(false);
  1055. end;
  1056. destructor TExeVTable.Destroy;
  1057. begin
  1058. ChildList.Free;
  1059. if assigned(EntryArray) then
  1060. Freemem(EntryArray);
  1061. end;
  1062. procedure TExeVTable.CheckIdx(VTableIdx:longint);
  1063. var
  1064. OldEntryCnt : longint;
  1065. begin
  1066. if VTableIdx>=EntryCnt then
  1067. begin
  1068. OldEntryCnt:=EntryCnt;
  1069. EntryCnt:=VTableIdx+1;
  1070. ReAllocMem(EntryArray,EntryCnt*sizeof(TVTableEntry));
  1071. FillChar(EntryArray[OldEntryCnt],(EntryCnt-OldEntryCnt)*sizeof(TVTableEntry),0);
  1072. end;
  1073. end;
  1074. procedure TExeVTable.AddChild(vt:TExeVTable);
  1075. begin
  1076. ChildList.Add(vt);
  1077. end;
  1078. procedure TExeVTable.AddEntry(VTableIdx:Longint);
  1079. var
  1080. i : longint;
  1081. objreloc : TObjRelocation;
  1082. vtblentryoffset : aint;
  1083. begin
  1084. CheckIdx(VTableIdx);
  1085. vtblentryoffset:=ExeSymbol.ObjSymbol.Offset+VTableIdx*sizeof(aint);
  1086. { Find and disable relocation }
  1087. for i:=0 to ExeSymbol.ObjSymbol.ObjSection.ObjRelocations.Count-1 do
  1088. begin
  1089. objreloc:=TObjRelocation(ExeSymbol.ObjSymbol.ObjSection.ObjRelocations[i]);
  1090. if objreloc.dataoffset=vtblentryoffset then
  1091. begin
  1092. EntryArray[VTableIdx].ObjRelocation:=objreloc;
  1093. EntryArray[VTableIdx].OrgRelocType:=objreloc.typ;
  1094. objreloc.typ:=RELOC_ZERO;
  1095. break;
  1096. end;
  1097. end;
  1098. if not assigned(EntryArray[VTableIdx].ObjRelocation) then
  1099. internalerror(200604011);
  1100. end;
  1101. procedure TExeVTable.SetVTableSize(ASize:longint);
  1102. begin
  1103. if EntryCnt<>0 then
  1104. internalerror(200603313);
  1105. EntryCnt:=ASize div sizeof(aint);
  1106. EntryArray:=AllocMem(EntryCnt*sizeof(TVTableEntry));
  1107. end;
  1108. function TExeVTable.VTableRef(VTableIdx:Longint):TObjRelocation;
  1109. begin
  1110. result:=nil;
  1111. CheckIdx(VTableIdx);
  1112. if EntryArray[VTableIdx].Used then
  1113. exit;
  1114. { Restore relocation if available }
  1115. if assigned(EntryArray[VTableIdx].ObjRelocation) then
  1116. begin
  1117. EntryArray[VTableIdx].ObjRelocation.typ:=EntryArray[VTableIdx].OrgRelocType;
  1118. result:=EntryArray[VTableIdx].ObjRelocation;
  1119. end;
  1120. EntryArray[VTableIdx].Used:=true;
  1121. end;
  1122. {****************************************************************************
  1123. TExeSection
  1124. ****************************************************************************}
  1125. constructor TExeSection.create(AList:TFPHashObjectList;const AName:string);
  1126. begin
  1127. inherited create(AList,AName);
  1128. Size:=0;
  1129. MemPos:=0;
  1130. DataPos:=0;
  1131. FSecSymIdx:=0;
  1132. FObjSectionList:=TFPObjectList.Create(false);
  1133. end;
  1134. destructor TExeSection.destroy;
  1135. begin
  1136. ObjSectionList.Free;
  1137. inherited destroy;
  1138. end;
  1139. procedure TExeSection.AddObjSection(objsec:TObjSection);
  1140. begin
  1141. ObjSectionList.Add(objsec);
  1142. if (SecOptions<>[]) then
  1143. begin
  1144. { Only if the section contains (un)initialized data the
  1145. data flag must match. This check is not needed if the
  1146. section is empty for a symbol allocation }
  1147. if (objsec.size>0) and
  1148. ((oso_Data in SecOptions)<>(oso_Data in objsec.SecOptions)) then
  1149. Comment(V_Error,'Incompatible section options');
  1150. end
  1151. else
  1152. begin
  1153. { inherit section options }
  1154. SecAlign:=objsec.SecAlign;
  1155. SecOptions:=SecOptions+objsec.SecOptions;
  1156. end;
  1157. { relate ObjSection to ExeSection, and mark it Used by default }
  1158. objsec.ExeSection:=self;
  1159. objsec.Used:=true;
  1160. end;
  1161. {****************************************************************************
  1162. TStaticLibrary
  1163. ****************************************************************************}
  1164. constructor TStaticLibrary.create(AList:TFPHashObjectList;const AName:string;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  1165. begin
  1166. inherited create(AList,AName);
  1167. FArReader:=AReader;
  1168. FObjInputClass:=AObjInputClass;
  1169. end;
  1170. destructor TStaticLibrary.destroy;
  1171. begin
  1172. ArReader.Free;
  1173. inherited destroy;
  1174. end;
  1175. {****************************************************************************
  1176. TImportLibrary
  1177. ****************************************************************************}
  1178. constructor TImportLibrary.create(AList:TFPHashObjectList;const AName:string);
  1179. begin
  1180. inherited create(AList,AName);
  1181. FImportSymbolList:=TFPHashObjectList.Create(true);
  1182. end;
  1183. destructor TImportLibrary.destroy;
  1184. begin
  1185. ImportSymbolList.Free;
  1186. inherited destroy;
  1187. end;
  1188. {****************************************************************************
  1189. TImportSymbol
  1190. ****************************************************************************}
  1191. constructor TImportSymbol.create(AList:TFPHashObjectList;const AName:string;AOrdNr:longint;AIsVar:boolean);
  1192. begin
  1193. inherited Create(AList, AName);
  1194. FOrdNr:=AOrdNr;
  1195. FIsVar:=AIsVar;
  1196. FMangledName:=AName;
  1197. { Replace ? and @ in import name }
  1198. { these replaces broke existing code on i386-win32 at least, while fixed
  1199. bug 8391 on arm-wince so limit this to arm-wince (KB) }
  1200. if (target_info.system in [system_arm_wince]) then
  1201. begin
  1202. Replace(FMangledName,'?','__q$$');
  1203. Replace(FMangledName,'@','__a$$');
  1204. end;
  1205. end;
  1206. {****************************************************************************
  1207. TExeOutput
  1208. ****************************************************************************}
  1209. constructor TExeOutput.create;
  1210. begin
  1211. { init writer }
  1212. FWriter:=TObjectwriter.create;
  1213. FExeWriteMode:=ewm_exefull;
  1214. { object files }
  1215. FObjDataList:=TFPObjectList.Create(true);
  1216. { symbols }
  1217. FExeSymbolList:=TFPHashObjectList.Create(true);
  1218. FUnresolvedExeSymbols:=TFPObjectList.Create(false);
  1219. FExternalObjSymbols:=TFPObjectList.Create(false);
  1220. FCommonObjSymbols:=TFPObjectList.Create(false);
  1221. FExeVTableList:=TFPObjectList.Create(false);
  1222. FEntryName:='start';
  1223. { sections }
  1224. FExeSectionList:=TFPHashObjectList.Create(true);
  1225. FImageBase:=0;
  1226. SectionMemAlign:=$1000;
  1227. SectionDataAlign:=$200;
  1228. FCExeSection:=TExeSection;
  1229. FCObjData:=TObjData;
  1230. end;
  1231. destructor TExeOutput.destroy;
  1232. begin
  1233. FExeSymbolList.free;
  1234. UnresolvedExeSymbols.free;
  1235. ExternalObjSymbols.free;
  1236. CommonObjSymbols.free;
  1237. ExeVTableList.free;
  1238. FExeSectionList.free;
  1239. ObjDatalist.free;
  1240. FWriter.free;
  1241. inherited destroy;
  1242. end;
  1243. function TExeOutput.WriteExeFile(const fn:string):boolean;
  1244. begin
  1245. result:=false;
  1246. if FWriter.createfile(fn) then
  1247. begin
  1248. { Only write the .o if there are no errors }
  1249. if errorcount=0 then
  1250. result:=writedata
  1251. else
  1252. result:=true;
  1253. { close the writer }
  1254. FWriter.closefile;
  1255. end
  1256. else
  1257. Comment(V_Fatal,'Can''t create executable '+fn);
  1258. end;
  1259. function TExeOutput.FindExeSection(const aname:string):TExeSection;
  1260. begin
  1261. result:=TExeSection(ExeSectionList.Find(aname));
  1262. end;
  1263. procedure TExeOutput.AddObjData(ObjData:TObjData);
  1264. begin
  1265. if ObjData.classtype<>FCObjData then
  1266. Comment(V_Error,'Invalid input object format for '+ObjData.name+' got '+ObjData.classname+' expected '+FCObjData.classname);
  1267. ObjDataList.Add(ObjData);
  1268. end;
  1269. procedure TExeOutput.Load_Start;
  1270. begin
  1271. ObjDataList.Clear;
  1272. { Globals defined in the linker script }
  1273. if not assigned(internalObjData) then
  1274. internalObjData:=CObjData.create('*Internal*');
  1275. AddObjData(internalObjData);
  1276. { Common Data section }
  1277. commonObjSection:=internalObjData.createsection(sec_bss,'');
  1278. end;
  1279. procedure TExeOutput.Load_EntryName(const aname:string);
  1280. begin
  1281. EntryName:=aname;
  1282. end;
  1283. procedure TExeOutput.Load_IsSharedLibrary;
  1284. begin
  1285. IsSharedLibrary:=true;
  1286. end;
  1287. procedure TExeOutput.Load_ImageBase(const avalue:string);
  1288. var
  1289. code : integer;
  1290. objsec : TObjSection;
  1291. objsym : TObjSymbol;
  1292. exesym : TExeSymbol;
  1293. begin
  1294. val(avalue,ImageBase,code);
  1295. if code<>0 then
  1296. Comment(V_Error,'Invalid number '+avalue);
  1297. { Create __image_base__ symbol, create the symbol
  1298. in a section with adress 0 and at offset 0 }
  1299. objsec:=internalObjData.createsection('*__image_base__',0,[]);
  1300. internalObjData.setsection(objsec);
  1301. objsym:=internalObjData.SymbolDefine('__image_base__',AB_GLOBAL,AT_FUNCTION);
  1302. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  1303. exesym.ObjSymbol:=objsym;
  1304. end;
  1305. procedure TExeOutput.Load_Symbol(const aname:string);
  1306. begin
  1307. internalObjData.createsection('*'+aname,0,[]);
  1308. internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION);
  1309. end;
  1310. procedure TExeOutput.Order_Start;
  1311. begin
  1312. end;
  1313. procedure TExeOutput.Order_End;
  1314. begin
  1315. internalObjData.afterwrite;
  1316. end;
  1317. procedure TExeOutput.Order_ExeSection(const aname:string);
  1318. var
  1319. sec : TExeSection;
  1320. begin
  1321. sec:=FindExeSection(aname);
  1322. if not assigned(sec) then
  1323. sec:=CExeSection.create(ExeSectionList,aname);
  1324. { Clear ExeSection contents }
  1325. FCurrExeSec:=sec;
  1326. end;
  1327. procedure TExeOutput.Order_EndExeSection;
  1328. begin
  1329. if not assigned(CurrExeSec) then
  1330. internalerror(200602184);
  1331. FCurrExeSec:=nil;
  1332. end;
  1333. procedure TExeOutput.Order_ObjSection(const aname:string);
  1334. var
  1335. i,j : longint;
  1336. ObjData : TObjData;
  1337. objsec : TObjSection;
  1338. TmpObjSectionList : TFPObjectList;
  1339. begin
  1340. if not assigned(CurrExeSec) then
  1341. internalerror(200602181);
  1342. TmpObjSectionList:=TFPObjectList.Create(false);
  1343. for i:=0 to ObjDataList.Count-1 do
  1344. begin
  1345. ObjData:=TObjData(ObjDataList[i]);
  1346. for j:=0 to ObjData.ObjSectionList.Count-1 do
  1347. begin
  1348. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  1349. if (not objsec.Used) and
  1350. MatchPattern(aname,objsec.name) then
  1351. TmpObjSectionList.Add(objsec);
  1352. end;
  1353. end;
  1354. { Order list if needed }
  1355. Order_ObjSectionList(TmpObjSectionList);
  1356. { Add the (ordered) list to the current ExeSection }
  1357. for i:=0 to TmpObjSectionList.Count-1 do
  1358. begin
  1359. objsec:=TObjSection(TmpObjSectionList[i]);
  1360. CurrExeSec.AddObjSection(objsec);
  1361. end;
  1362. TmpObjSectionList.Free;
  1363. end;
  1364. procedure TExeOutput.Order_ObjSectionList(ObjSectionList : TFPObjectList);
  1365. begin
  1366. end;
  1367. procedure TExeOutput.Order_Symbol(const aname:string);
  1368. var
  1369. ObjSection : TObjSection;
  1370. begin
  1371. ObjSection:=internalObjData.findsection('*'+aname);
  1372. if not assigned(ObjSection) then
  1373. internalerror(200603041);
  1374. CurrExeSec.AddObjSection(ObjSection);
  1375. end;
  1376. procedure TExeOutput.Order_Align(const avalue:string);
  1377. var
  1378. code : integer;
  1379. alignval : shortint;
  1380. objsec : TObjSection;
  1381. begin
  1382. val(avalue,alignval,code);
  1383. if code<>0 then
  1384. Comment(V_Error,'Invalid number '+avalue);
  1385. if alignval<=0 then
  1386. exit;
  1387. { Create an empty section with the required aligning }
  1388. inc(Fzeronr);
  1389. objsec:=internalObjData.createsection('*align'+tostr(Fzeronr),alignval,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1390. CurrExeSec.AddObjSection(objsec);
  1391. end;
  1392. procedure TExeOutput.Order_Zeros(const avalue:string);
  1393. var
  1394. zeros : array[0..1023] of byte;
  1395. code : integer;
  1396. len : longint;
  1397. objsec : TObjSection;
  1398. begin
  1399. val(avalue,len,code);
  1400. if code<>0 then
  1401. Comment(V_Error,'Invalid number '+avalue);
  1402. if len<=0 then
  1403. exit;
  1404. if len>sizeof(zeros) then
  1405. internalerror(200602254);
  1406. fillchar(zeros,len,0);
  1407. inc(Fzeronr);
  1408. objsec:=internalObjData.createsection('*zeros'+tostr(Fzeronr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1409. internalObjData.writebytes(zeros,len);
  1410. CurrExeSec.AddObjSection(objsec);
  1411. end;
  1412. procedure TExeOutput.MemPos_Start;
  1413. begin
  1414. CurrMemPos:=0;
  1415. end;
  1416. procedure TExeOutput.MemPos_Header;
  1417. begin
  1418. end;
  1419. procedure TExeOutput.MemPos_ExeSection(const aname:string);
  1420. var
  1421. i : longint;
  1422. objsec : TObjSection;
  1423. begin
  1424. { Section can be removed }
  1425. FCurrExeSec:=FindExeSection(aname);
  1426. if not assigned(CurrExeSec) then
  1427. exit;
  1428. { Alignment of ExeSection }
  1429. CurrMemPos:=align(CurrMemPos,SectionMemAlign);
  1430. CurrExeSec.MemPos:=CurrMemPos;
  1431. { set position of object ObjSections }
  1432. for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
  1433. begin
  1434. objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
  1435. objsec.setmempos(CurrMemPos);
  1436. end;
  1437. { calculate size of the section }
  1438. CurrExeSec.Size:=CurrMemPos-CurrExeSec.MemPos;
  1439. end;
  1440. procedure TExeOutput.MemPos_EndExeSection;
  1441. begin
  1442. if not assigned(CurrExeSec) then
  1443. exit;
  1444. FCurrExeSec:=nil;
  1445. end;
  1446. procedure TExeOutput.DataPos_Start;
  1447. begin
  1448. end;
  1449. procedure TExeOutput.DataPos_Header;
  1450. begin
  1451. end;
  1452. procedure TExeOutput.DataPos_ExeSection(const aname:string);
  1453. var
  1454. i : longint;
  1455. objsec : TObjSection;
  1456. begin
  1457. { Section can be removed }
  1458. FCurrExeSec:=FindExeSection(aname);
  1459. if not assigned(CurrExeSec) then
  1460. exit;
  1461. { don't write normal section if writing only debug info }
  1462. if (ExeWriteMode=ewm_dbgonly) and
  1463. not(oso_debug in CurrExeSec.SecOptions) then
  1464. exit;
  1465. if (oso_Data in currexesec.SecOptions) then
  1466. begin
  1467. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  1468. CurrExeSec.DataPos:=CurrDataPos;
  1469. end;
  1470. { set position of object ObjSections }
  1471. for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
  1472. begin
  1473. objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
  1474. if (oso_Data in objsec.SecOptions) then
  1475. begin
  1476. if not(oso_Data in currexesec.SecOptions) then
  1477. internalerror(200603043);
  1478. if not assigned(objsec.Data) then
  1479. internalerror(200603044);
  1480. objsec.setDatapos(CurrDataPos);
  1481. end;
  1482. end;
  1483. end;
  1484. procedure TExeOutput.DataPos_EndExeSection;
  1485. begin
  1486. if not assigned(CurrExeSec) then
  1487. exit;
  1488. FCurrExeSec:=nil;
  1489. end;
  1490. procedure TExeOutput.DataPos_Symbols;
  1491. var
  1492. i : longint;
  1493. sym : TExeSymbol;
  1494. begin
  1495. { Removing unused symbols }
  1496. for i:=0 to ExeSymbolList.Count-1 do
  1497. begin
  1498. sym:=TExeSymbol(ExeSymbolList[i]);
  1499. if not sym.ObjSymbol.objsection.Used then
  1500. ExeSymbolList[i]:=nil;
  1501. end;
  1502. ExeSymbolList.Pack;
  1503. end;
  1504. procedure TExeOutput.BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  1505. var
  1506. hs : string;
  1507. code : integer;
  1508. i,k,
  1509. vtableidx : longint;
  1510. vtableexesym,
  1511. childexesym,
  1512. parentexesym : TExeSymbol;
  1513. objsym : TObjSymbol;
  1514. begin
  1515. { Build inheritance tree from VTINHERIT }
  1516. for i:=0 to VTInheritList.Count-1 do
  1517. begin
  1518. objsym:=TObjSymbol(VTInheritList[i]);
  1519. hs:=objsym.name;
  1520. { VTINHERIT_<ChildVMTName>$$<ParentVMTName> }
  1521. Delete(hs,1,Pos('_',hs));
  1522. k:=Pos('$$',hs);
  1523. if k=0 then
  1524. internalerror(200603311);
  1525. childexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  1526. parentexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,k+2,length(hs)-k-1)));
  1527. if not assigned(childexesym) or
  1528. not assigned(parentexesym)then
  1529. internalerror(200603312);
  1530. if not assigned(childexesym.vtable) then
  1531. begin
  1532. childexesym.vtable:=TExeVTable.Create(childexesym);
  1533. ExeVTableList.Add(childexesym.vtable);
  1534. end;
  1535. if not assigned(parentexesym.vtable) then
  1536. begin
  1537. parentexesym.vtable:=TExeVTable.Create(parentexesym);
  1538. ExeVTableList.Add(parentexesym.vtable);
  1539. end;
  1540. childexesym.vtable.SetVTableSize(childexesym.ObjSymbol.Size);
  1541. if parentexesym<>childexesym then
  1542. parentexesym.vtable.AddChild(childexesym.vtable);
  1543. end;
  1544. { Find VTable entries from VTENTRY }
  1545. for i:=0 to VTEntryList.Count-1 do
  1546. begin
  1547. objsym:=TObjSymbol(VTEntryList[i]);
  1548. hs:=objsym.name;
  1549. { VTENTRY_<VTableName>$$<Index> }
  1550. Delete(hs,1,Pos('_',hs));
  1551. k:=Pos('$$',hs);
  1552. if k=0 then
  1553. internalerror(200603319);
  1554. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  1555. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  1556. if (code<>0) then
  1557. internalerror(200603318);
  1558. if not assigned(vtableexesym) then
  1559. internalerror(2006033110);
  1560. vtableexesym.vtable.AddEntry(vtableidx);
  1561. end;
  1562. end;
  1563. procedure TExeOutput.PackUnresolvedExeSymbols(const s:string);
  1564. var
  1565. i : longint;
  1566. exesym : TExeSymbol;
  1567. begin
  1568. { Generate a list of Unresolved External symbols }
  1569. for i:=0 to UnresolvedExeSymbols.count-1 do
  1570. begin
  1571. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  1572. if exesym.State<>symstate_undefined then
  1573. UnresolvedExeSymbols[i]:=nil;
  1574. end;
  1575. UnresolvedExeSymbols.Pack;
  1576. Comment(V_Debug,'Number of unresolved externals '+s+' '+tostr(UnresolvedExeSymbols.Count));
  1577. end;
  1578. procedure TExeOutput.ResolveSymbols(StaticLibraryList:TFPHashObjectList);
  1579. var
  1580. ObjData : TObjData;
  1581. exesym : TExeSymbol;
  1582. objsym,
  1583. commonsym : TObjSymbol;
  1584. objinput : TObjInput;
  1585. StaticLibrary : TStaticLibrary;
  1586. firstarchive,
  1587. firstcommon : boolean;
  1588. i,j : longint;
  1589. VTEntryList,
  1590. VTInheritList : TFPObjectList;
  1591. procedure LoadObjDataSymbols(ObjData:TObjData);
  1592. var
  1593. j : longint;
  1594. hs : string;
  1595. exesym : TExeSymbol;
  1596. objsym : TObjSymbol;
  1597. begin
  1598. for j:=0 to ObjData.ObjSymbolList.Count-1 do
  1599. begin
  1600. objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
  1601. { From the local symbols we are only interressed in the
  1602. VTENTRY and VTINHERIT symbols }
  1603. if objsym.bind=AB_LOCAL then
  1604. begin
  1605. if cs_link_opt_vtable in current_settings.globalswitches then
  1606. begin
  1607. hs:=objsym.name;
  1608. if (hs[1]='V') then
  1609. begin
  1610. if Copy(hs,1,5)='VTREF' then
  1611. begin
  1612. if not assigned(objsym.ObjSection.VTRefList) then
  1613. objsym.ObjSection.VTRefList:=TFPObjectList.Create(false);
  1614. objsym.ObjSection.VTRefList.Add(objsym);
  1615. end
  1616. else if Copy(hs,1,7)='VTENTRY' then
  1617. VTEntryList.Add(objsym)
  1618. else if Copy(hs,1,9)='VTINHERIT' then
  1619. VTInheritList.Add(objsym);
  1620. end;
  1621. end;
  1622. continue;
  1623. end;
  1624. { Search for existing exesymbol }
  1625. exesym:=texesymbol(FExeSymbolList.Find(objsym.name));
  1626. if not assigned(exesym) then
  1627. begin
  1628. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  1629. exesym.ObjSymbol:=objsym;
  1630. end;
  1631. objsym.ExeSymbol:=exesym;
  1632. case objsym.bind of
  1633. AB_GLOBAL :
  1634. begin
  1635. if exesym.State<>symstate_defined then
  1636. begin
  1637. exesym.ObjSymbol:=objsym;
  1638. exesym.State:=symstate_defined;
  1639. end
  1640. else
  1641. Comment(V_Error,'Multiple defined symbol '+objsym.name);
  1642. end;
  1643. AB_EXTERNAL :
  1644. begin
  1645. ExternalObjSymbols.add(objsym);
  1646. { Register unresolved symbols only the first time they
  1647. are registered }
  1648. if exesym.ObjSymbol=objsym then
  1649. UnresolvedExeSymbols.Add(exesym);
  1650. end;
  1651. AB_COMMON :
  1652. begin
  1653. if exesym.State=symstate_undefined then
  1654. begin
  1655. exesym.ObjSymbol:=objsym;
  1656. exesym.State:=symstate_common;
  1657. end;
  1658. CommonObjSymbols.add(objsym);
  1659. end;
  1660. end;
  1661. end;
  1662. end;
  1663. begin
  1664. VTEntryList:=TFPObjectList.Create(false);
  1665. VTInheritList:=TFPObjectList.Create(false);
  1666. {
  1667. The symbol resolving is done in 3 steps:
  1668. 1. Register symbols from objects
  1669. 2. Find symbols in static libraries
  1670. 3. Define stil undefined common symbols
  1671. }
  1672. { Step 1, Register symbols from objects }
  1673. for i:=0 to ObjDataList.Count-1 do
  1674. begin
  1675. ObjData:=TObjData(ObjDataList[i]);
  1676. LoadObjDataSymbols(ObjData);
  1677. end;
  1678. PackUnresolvedExeSymbols('in objects');
  1679. { Step 2, Find unresolved symbols in the libraries }
  1680. firstarchive:=true;
  1681. for i:=0 to StaticLibraryList.Count-1 do
  1682. begin
  1683. StaticLibrary:=TStaticLibrary(StaticLibraryList[i]);
  1684. { Process list of Unresolved External symbols, we need
  1685. to use a while loop because the list can be extended when
  1686. we load members from the library. }
  1687. j:=0;
  1688. while (j<UnresolvedExeSymbols.count) do
  1689. begin
  1690. exesym:=TExeSymbol(UnresolvedExeSymbols[j]);
  1691. { Check first if the symbol is still undefined }
  1692. if exesym.State=symstate_undefined then
  1693. begin
  1694. if StaticLibrary.ArReader.OpenFile(exesym.name) then
  1695. begin
  1696. if assigned(exemap) then
  1697. begin
  1698. if firstarchive then
  1699. begin
  1700. exemap.Add('');
  1701. exemap.Add('Archive member included because of file (symbol)');
  1702. exemap.Add('');
  1703. firstarchive:=false;
  1704. end;
  1705. exemap.Add(StaticLibrary.ArReader.FileName+' - '+
  1706. {exesym.ObjSymbol.ObjSection.FullName+}
  1707. '('+exesym.Name+')');
  1708. end;
  1709. objinput:=StaticLibrary.ObjInputClass.Create;
  1710. objdata:=objinput.newObjData(StaticLibrary.ArReader.FileName);
  1711. objinput.ReadObjData(StaticLibrary.ArReader,objdata);
  1712. objinput.free;
  1713. AddObjData(objdata);
  1714. LoadObjDataSymbols(objdata);
  1715. StaticLibrary.ArReader.CloseFile;
  1716. end;
  1717. end;
  1718. inc(j);
  1719. end;
  1720. end;
  1721. PackUnresolvedExeSymbols('after static libraries');
  1722. { Step 3, Match common symbols or add to the globals }
  1723. firstcommon:=true;
  1724. for i:=0 to CommonObjSymbols.count-1 do
  1725. begin
  1726. objsym:=TObjSymbol(CommonObjSymbols[i]);
  1727. if objsym.exesymbol.State=symstate_defined then
  1728. begin
  1729. if objsym.exesymbol.ObjSymbol.size<>objsym.size then
  1730. Comment(V_Debug,'Size of common symbol '+objsym.name+' is different, expected '+tostr(objsym.size)+' got '+tostr(objsym.exesymbol.ObjSymbol.size));
  1731. end
  1732. else
  1733. begin
  1734. { allocate new objsymbol in .bss of *COMMON* and assign
  1735. it to the exesymbol }
  1736. if firstcommon then
  1737. begin
  1738. if assigned(exemap) then
  1739. exemap.AddCommonSymbolsHeader;
  1740. firstcommon:=false;
  1741. end;
  1742. internalObjData.setsection(commonObjSection);
  1743. internalObjData.allocalign(var_align(objsym.size));
  1744. commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_FUNCTION);
  1745. commonsym.size:=objsym.size;
  1746. internalObjData.alloc(objsym.size);
  1747. if assigned(exemap) then
  1748. exemap.AddCommonSymbol(commonsym);
  1749. { Assign to the exesymbol }
  1750. objsym.exesymbol.objsymbol:=commonsym;
  1751. objsym.exesymbol.state:=symstate_defined;
  1752. end;
  1753. end;
  1754. PackUnresolvedExeSymbols('after defining COMMON symbols');
  1755. { Find entry symbol and print in map }
  1756. exesym:=texesymbol(ExeSymbolList.Find(EntryName));
  1757. if assigned(exesym) then
  1758. begin
  1759. EntrySym:=exesym.ObjSymbol;
  1760. if assigned(exemap) then
  1761. begin
  1762. exemap.Add('');
  1763. exemap.Add('Entry symbol '+EntryName);
  1764. end;
  1765. end
  1766. else
  1767. Comment(V_Error,'Entrypoint '+EntryName+' not defined');
  1768. { Generate VTable tree }
  1769. if cs_link_opt_vtable in current_settings.globalswitches then
  1770. BuildVTableTree(VTInheritList,VTEntryList);
  1771. VTInheritList.Free;
  1772. VTEntryList.Free;
  1773. end;
  1774. procedure TExeOutput.GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  1775. var
  1776. debuglink : array[0..1023] of byte;
  1777. len : longint;
  1778. objsec : TObjSection;
  1779. exesec : TExeSection;
  1780. begin
  1781. { From the gdb manual chapter 15. GDB Files:
  1782. * A filename, with any leading directory components removed, followed by a zero byte,
  1783. * zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and
  1784. * a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed
  1785. on the debugging information file's full contents by the function given below, passing zero as the crc argument.
  1786. }
  1787. fillchar(debuglink,sizeof(debuglink),0);
  1788. len:=0;
  1789. move(dbgname[1],debuglink[len],length(dbgname));
  1790. inc(len,length(dbgname)+1);
  1791. len:=align(len,4);
  1792. if source_info.endian<>target_info.endian then
  1793. SwapEndian(dbgcrc);
  1794. move(dbgcrc,debuglink[len],sizeof(cardinal));
  1795. inc(len,4);
  1796. { Add section }
  1797. exesec:=FindExeSection(debuglinkname);
  1798. if not assigned(exesec) then
  1799. exesec:=CExeSection.create(ExeSectionList,debuglinkname);
  1800. exesec.SecOptions:=[oso_data,oso_keep];
  1801. exesec.SecAlign:=4;
  1802. objsec:=internalObjData.createsection(exesec.name,0,exesec.SecOptions);
  1803. internalObjData.writebytes(debuglink,len);
  1804. exesec.AddObjSection(objsec);
  1805. end;
  1806. procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  1807. begin
  1808. end;
  1809. procedure TExeOutput.PrintMemoryMap;
  1810. var
  1811. exesec : TExeSection;
  1812. objsec : TObjSection;
  1813. objsym : TObjSymbol;
  1814. i,j,k : longint;
  1815. begin
  1816. if not assigned(exemap) then
  1817. exit;
  1818. exemap.AddMemoryMapHeader(ImageBase);
  1819. for i:=0 to ExeSectionList.Count-1 do
  1820. begin
  1821. exesec:=TExeSection(ExeSectionList[i]);
  1822. exemap.AddMemoryMapExeSection(exesec);
  1823. for j:=0 to exesec.ObjSectionList.count-1 do
  1824. begin
  1825. objsec:=TObjSection(exesec.ObjSectionList[j]);
  1826. exemap.AddMemoryMapObjectSection(objsec);
  1827. for k:=0 to objsec.ObjSymbolDefines.Count-1 do
  1828. begin
  1829. objsym:=TObjSymbol(objsec.ObjSymbolDefines[k]);
  1830. exemap.AddMemoryMapSymbol(objsym);
  1831. end;
  1832. end;
  1833. end;
  1834. end;
  1835. procedure TExeOutput.FixupSymbols;
  1836. procedure UpdateSymbol(objsym:TObjSymbol);
  1837. begin
  1838. objsym.bind:=objsym.ExeSymbol.ObjSymbol.bind;
  1839. objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
  1840. objsym.size:=objsym.ExeSymbol.ObjSymbol.size;
  1841. objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
  1842. objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
  1843. end;
  1844. var
  1845. i : longint;
  1846. objsym : TObjSymbol;
  1847. exesym : TExeSymbol;
  1848. begin
  1849. { Print list of Unresolved External symbols }
  1850. for i:=0 to UnresolvedExeSymbols.count-1 do
  1851. begin
  1852. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  1853. if exesym.State<>symstate_defined then
  1854. Comment(V_Error,'Undefined symbol: '+exesym.name);
  1855. end;
  1856. { Update ImageBase to ObjData so it can access from ObjSymbols }
  1857. for i:=0 to ObjDataList.Count-1 do
  1858. TObjData(ObjDataList[i]).imagebase:=imagebase;
  1859. {
  1860. Fixing up symbols is done in the following steps:
  1861. 1. Update common references
  1862. 2. Update external references
  1863. }
  1864. { Step 1, Update commons }
  1865. for i:=0 to CommonObjSymbols.count-1 do
  1866. begin
  1867. objsym:=TObjSymbol(CommonObjSymbols[i]);
  1868. if objsym.bind<>AB_COMMON then
  1869. internalerror(200606241);
  1870. UpdateSymbol(objsym);
  1871. end;
  1872. { Step 2, Update externals }
  1873. for i:=0 to ExternalObjSymbols.count-1 do
  1874. begin
  1875. objsym:=TObjSymbol(ExternalObjSymbols[i]);
  1876. if objsym.bind<>AB_EXTERNAL then
  1877. internalerror(200606242);
  1878. UpdateSymbol(objsym);
  1879. end;
  1880. end;
  1881. procedure TExeOutput.MergeStabs;
  1882. var
  1883. stabexesec,
  1884. stabstrexesec : TExeSection;
  1885. relocsec,
  1886. currstabsec,
  1887. currstabstrsec,
  1888. mergedstabsec,
  1889. mergedstabstrsec : TObjSection;
  1890. hstabreloc,
  1891. currstabreloc : TObjRelocation;
  1892. currstabrelocidx,
  1893. i,j,
  1894. mergestabcnt,
  1895. stabcnt : longint;
  1896. skipstab : boolean;
  1897. skipfun : boolean;
  1898. hstab : TObjStabEntry;
  1899. stabrelocofs : longint;
  1900. buf : array[0..1023] of byte;
  1901. bufend,
  1902. bufsize : longint;
  1903. begin
  1904. stabexesec:=FindExeSection('.stab');
  1905. stabstrexesec:=FindExeSection('.stabstr');
  1906. if (stabexesec=nil) or
  1907. (stabstrexesec=nil) or
  1908. (stabexesec.ObjSectionlist.count=0) then
  1909. exit;
  1910. { Create new stabsection }
  1911. stabRelocofs:=pbyte(@hstab.nvalue)-pbyte(@hstab);
  1912. mergedstabsec:=internalObjData.CreateSection(sec_stab,'');
  1913. mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,'');
  1914. { write stab for hdrsym }
  1915. fillchar(hstab,sizeof(TObjStabEntry),0);
  1916. mergedstabsec.write(hstab,sizeof(TObjStabEntry));
  1917. mergestabcnt:=1;
  1918. { .stabstr starts with a #0 }
  1919. buf[0]:=0;
  1920. mergedstabstrsec.write(buf[0],1);
  1921. skipfun:=false;
  1922. { Copy stabs and corresponding Relocations }
  1923. for i:=0 to stabexesec.ObjSectionList.Count-1 do
  1924. begin
  1925. currstabsec:=TObjSection(stabexesec.ObjSectionList[i]);
  1926. currstabstrsec:=currstabsec.ObjData.findsection('.stabstr');
  1927. if assigned(currstabstrsec) then
  1928. begin
  1929. stabcnt:=currstabsec.Data.size div sizeof(TObjStabEntry);
  1930. currstabsec.Data.seek(0);
  1931. currstabrelocidx:=0;
  1932. for j:=0 to stabcnt-1 do
  1933. begin
  1934. hstabreloc:=nil;
  1935. skipstab:=false;
  1936. currstabsec.Data.read(hstab,sizeof(TObjStabEntry));
  1937. { Only include first hdrsym stab }
  1938. if hstab.ntype=0 then
  1939. skipstab:=true;
  1940. if skipfun then
  1941. begin
  1942. { Skip all stabs for function body until N_RBRAC }
  1943. skipfun:=hstab.ntype<>N_RBRAC;
  1944. skipstab:=true;
  1945. end;
  1946. if not skipstab then
  1947. begin
  1948. { Find corresponding Relocation }
  1949. currstabreloc:=nil;
  1950. while (currstabrelocidx<currstabsec.ObjRelocations.Count) do
  1951. begin
  1952. currstabreloc:=TObjRelocation(currstabsec.ObjRelocations[currstabrelocidx]);
  1953. if assigned(currstabreloc) and
  1954. (currstabreloc.dataoffset>=j*sizeof(TObjStabEntry)+stabrelocofs) then
  1955. break;
  1956. inc(currstabrelocidx);
  1957. end;
  1958. if assigned(currstabreloc) and
  1959. (currstabreloc.dataoffset=j*sizeof(TObjStabEntry)+stabrelocofs) then
  1960. begin
  1961. hstabReloc:=currstabReloc;
  1962. inc(currstabrelocidx);
  1963. end;
  1964. { Check if the stab is refering to a removed section }
  1965. if assigned(hstabreloc) then
  1966. begin
  1967. if assigned(hstabreloc.Symbol) then
  1968. relocsec:=hstabreloc.Symbol.ObjSection
  1969. else
  1970. relocsec:=hstabreloc.ObjSection;
  1971. if not assigned(relocsec) then
  1972. internalerror(200603302);
  1973. if not relocsec.Used then
  1974. begin
  1975. skipstab:=true;
  1976. if (hstab.ntype=N_Function) and (hstab.strpos<>0) then
  1977. begin
  1978. currstabstrsec.Data.seek(hstab.strpos);
  1979. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  1980. bufend:=indexbyte(buf,bufsize,Ord(':'));
  1981. if (bufend<>-1) and (bufend<bufsize-1) and (buf[bufend+1]=Ord('F')) then
  1982. skipfun:=true;
  1983. end;
  1984. end;
  1985. end;
  1986. end;
  1987. if not skipstab then
  1988. begin
  1989. { Copy string in stabstr }
  1990. if hstab.strpos<>0 then
  1991. begin
  1992. currstabstrsec.Data.seek(hstab.strpos);
  1993. hstab.strpos:=mergedstabstrsec.Size;
  1994. repeat
  1995. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  1996. bufend:=indexbyte(buf,bufsize,0);
  1997. if bufend=-1 then
  1998. bufend:=bufsize
  1999. else
  2000. begin
  2001. { include the #0 }
  2002. inc(bufend);
  2003. end;
  2004. mergedstabstrsec.write(buf,bufend);
  2005. until (buf[bufend-1]=0) or (bufsize<sizeof(buf));
  2006. end;
  2007. { Copy and Update the relocation }
  2008. if assigned(hstabreloc) then
  2009. begin
  2010. hstabreloc.Dataoffset:=mergestabcnt*sizeof(TObjStabEntry)+stabRelocofs;
  2011. { Remove from List without freeing the object }
  2012. currstabsec.ObjRelocations.List[currstabrelocidx-1]:=nil;
  2013. mergedstabsec.ObjRelocations.Add(hstabreloc);
  2014. end;
  2015. { Write updated stab }
  2016. mergedstabsec.write(hstab,sizeof(hstab));
  2017. inc(mergestabcnt);
  2018. end;
  2019. end;
  2020. end;
  2021. { Unload stabs }
  2022. if assigned(currstabstrsec) then
  2023. begin
  2024. currstabstrsec.Used:=False;
  2025. currstabstrsec.ReleaseData;
  2026. end;
  2027. currstabsec.Used:=false;
  2028. currstabsec.ReleaseData;
  2029. end;
  2030. { Generate new HdrSym }
  2031. if mergedstabsec.Size>0 then
  2032. begin
  2033. hstab.strpos:=1;
  2034. hstab.ntype:=0;
  2035. hstab.nother:=0;
  2036. hstab.ndesc:=word(mergestabcnt-1);
  2037. hstab.nvalue:=mergedstabstrsec.Size;
  2038. mergedstabsec.Data.seek(0);
  2039. mergedstabsec.Data.write(hstab,sizeof(hstab));
  2040. end;
  2041. { Replace all sections with our combined stabsec }
  2042. stabexesec.ObjSectionList.Clear;
  2043. stabstrexesec.ObjSectionList.Clear;
  2044. stabexesec.AddObjSection(mergedstabsec);
  2045. stabstrexesec.AddObjSection(mergedstabstrsec);
  2046. end;
  2047. procedure TExeOutput.RemoveEmptySections;
  2048. var
  2049. i, j : longint;
  2050. exesec : TExeSection;
  2051. doremove : boolean;
  2052. begin
  2053. for i:=0 to ExeSectionList.Count-1 do
  2054. begin
  2055. exesec:=TExeSection(ExeSectionList[i]);
  2056. doremove:=not(oso_keep in exesec.SecOptions) and
  2057. (
  2058. (exesec.ObjSectionlist.count=0) or
  2059. (
  2060. (cs_link_strip in current_settings.globalswitches) and
  2061. not(cs_link_separate_dbg_file in current_settings.globalswitches) and
  2062. (oso_debug in exesec.SecOptions)
  2063. )
  2064. );
  2065. if not doremove then
  2066. begin
  2067. { Check if section has no actual data }
  2068. doremove:=true;
  2069. for j:=0 to exesec.ObjSectionList.Count-1 do
  2070. if TObjSection(exesec.ObjSectionList[j]).Size<>0 then
  2071. begin
  2072. doremove:=false;
  2073. break;
  2074. end;
  2075. end;
  2076. if doremove and not (RelocSection and (exesec.Name='.reloc')) then
  2077. begin
  2078. Comment(V_Debug,'Deleting empty section '+exesec.name);
  2079. ExeSectionList[i]:=nil;
  2080. end;
  2081. end;
  2082. ExeSectionList.Pack;
  2083. end;
  2084. procedure TExeOutput.RemoveDebugInfo;
  2085. var
  2086. i : longint;
  2087. exesec : TExeSection;
  2088. begin
  2089. for i:=0 to ExeSectionList.Count-1 do
  2090. begin
  2091. exesec:=TExeSection(ExeSectionList[i]);
  2092. if (oso_debug in exesec.SecOptions) then
  2093. ExeSectionList[i]:=nil;
  2094. end;
  2095. ExeSectionList.Pack;
  2096. end;
  2097. procedure TExeOutput.RemoveUnreferencedSections;
  2098. var
  2099. ObjSectionWorkList : TFPObjectList;
  2100. procedure AddToObjSectionWorkList(aobjsec:TObjSection);
  2101. begin
  2102. if not aobjsec.Used then
  2103. begin
  2104. aobjsec.Used:=true;
  2105. ObjSectionWorkList.Add(aobjsec);
  2106. end;
  2107. end;
  2108. procedure DoReloc(objreloc:TObjRelocation);
  2109. var
  2110. objsym : TObjSymbol;
  2111. refobjsec : TObjSection;
  2112. begin
  2113. { Disabled Relocation to 0 }
  2114. if objreloc.typ=RELOC_ZERO then
  2115. exit;
  2116. if assigned(objreloc.symbol) then
  2117. begin
  2118. objsym:=objreloc.symbol;
  2119. if objsym.bind<>AB_LOCAL then
  2120. begin
  2121. if not(assigned(objsym.exesymbol) and
  2122. (objsym.exesymbol.State=symstate_defined)) then
  2123. internalerror(200603063);
  2124. objsym:=objsym.exesymbol.objsymbol;
  2125. end;
  2126. if not assigned(objsym.objsection) then
  2127. internalerror(200603062);
  2128. refobjsec:=objsym.objsection;
  2129. end
  2130. else
  2131. if assigned(objreloc.objsection) then
  2132. refobjsec:=objreloc.objsection
  2133. else
  2134. internalerror(200603316);
  2135. if assigned(exemap) then
  2136. begin
  2137. objsym:=objreloc.symbol;
  2138. if assigned(objsym) then
  2139. exemap.Add(' References '+objsym.name+' in '
  2140. +refobjsec.fullname)
  2141. else
  2142. exemap.Add(' References '+refobjsec.fullname);
  2143. end;
  2144. AddToObjSectionWorkList(refobjsec);
  2145. end;
  2146. procedure DoVTableRef(vtable:TExeVTable;VTableIdx:longint);
  2147. var
  2148. i : longint;
  2149. objreloc : TObjRelocation;
  2150. begin
  2151. objreloc:=vtable.VTableRef(VTableIdx);
  2152. if assigned(objreloc) then
  2153. begin
  2154. { Process the relocation now if the ObjSection is
  2155. already processed and marked as used. Otherwise we leave it
  2156. unprocessed. It'll then be resolved when the ObjSection is
  2157. changed to Used }
  2158. if vtable.ExeSymbol.ObjSymbol.ObjSection.Used then
  2159. DoReloc(objreloc);
  2160. end;
  2161. { This recursive walking is done here instead of
  2162. in TExeVTable.VTableRef because we can now process
  2163. all needed relocations }
  2164. for i:=0 to vtable.ChildList.Count-1 do
  2165. DoVTableRef(TExeVTable(vtable.ChildList[i]),VTableIdx);
  2166. end;
  2167. var
  2168. hs : string;
  2169. i,j,k : longint;
  2170. exesec : TExeSection;
  2171. objdata : TObjData;
  2172. objsec : TObjSection;
  2173. objsym : TObjSymbol;
  2174. code : integer;
  2175. vtableidx : longint;
  2176. vtableexesym : TExeSymbol;
  2177. begin
  2178. ObjSectionWorkList:=TFPObjectList.Create(false);
  2179. if assigned(exemap) then
  2180. exemap.AddHeader('Removing unreferenced sections');
  2181. { Initialize by marking all sections unused and
  2182. adding the sections with oso_keep flags to the ObjSectionWorkList }
  2183. for i:=0 to ObjDataList.Count-1 do
  2184. begin
  2185. ObjData:=TObjData(ObjDataList[i]);
  2186. for j:=0 to ObjData.ObjSectionList.Count-1 do
  2187. begin
  2188. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  2189. objsec.Used:=false;
  2190. {$warning TODO remove debug section always keep}
  2191. if oso_debug in objsec.secoptions then
  2192. objsec.Used:=true;
  2193. if (oso_keep in objsec.secoptions) then
  2194. begin
  2195. AddToObjSectionWorkList(objsec);
  2196. if objsec.name='.fpc.n_links' then
  2197. objsec.Used:=false;
  2198. end;
  2199. end;
  2200. end;
  2201. AddToObjSectionWorkList(entrysym.exesymbol.objsymbol.objsection);
  2202. { Process all sections, add new sections to process based
  2203. on the symbol references }
  2204. while ObjSectionWorkList.Count>0 do
  2205. begin
  2206. objsec:=TObjSection(ObjSectionWorkList.Last);
  2207. if assigned(exemap) then
  2208. exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjRelocations.Count)+' references');
  2209. ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1);
  2210. { Process Relocations }
  2211. for i:=0 to objsec.ObjRelocations.count-1 do
  2212. DoReloc(TObjRelocation(objsec.ObjRelocations[i]));
  2213. { Process Virtual Entry calls }
  2214. if cs_link_opt_vtable in current_settings.globalswitches then
  2215. begin
  2216. for i:=0 to objsec.VTRefList.count-1 do
  2217. begin
  2218. objsym:=TObjSymbol(objsec.VTRefList[i]);
  2219. hs:=objsym.name;
  2220. Delete(hs,1,Pos('_',hs));
  2221. k:=Pos('$$',hs);
  2222. if k=0 then
  2223. internalerror(200603314);
  2224. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  2225. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  2226. if (code<>0) then
  2227. internalerror(200603317);
  2228. if not assigned(vtableexesym) then
  2229. internalerror(200603315);
  2230. if not assigned(vtableexesym.vtable) then
  2231. internalerror(200603316);
  2232. DoVTableRef(vtableexesym.vtable,vtableidx);
  2233. end;
  2234. end;
  2235. end;
  2236. ObjSectionWorkList.Free;
  2237. ObjSectionWorkList:=nil;
  2238. { Remove unused objsections from ExeSectionList }
  2239. for i:=0 to ExeSectionList.Count-1 do
  2240. begin
  2241. exesec:=TExeSection(ExeSectionList[i]);
  2242. for j:=0 to exesec.ObjSectionlist.count-1 do
  2243. begin
  2244. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  2245. if not objsec.used then
  2246. begin
  2247. if assigned(exemap) then
  2248. exemap.Add('Removing '+objsec.FullName);
  2249. exesec.ObjSectionlist[j]:=nil;
  2250. objsec.ReleaseData;
  2251. end;
  2252. end;
  2253. exesec.ObjSectionlist.Pack;
  2254. end;
  2255. end;
  2256. procedure TExeOutput.FixupRelocations;
  2257. var
  2258. i,j : longint;
  2259. exesec : TExeSection;
  2260. objsec : TObjSection;
  2261. begin
  2262. for i:=0 to ExeSectionList.Count-1 do
  2263. begin
  2264. exesec:=TExeSection(ExeSectionList[i]);
  2265. if not assigned(exesec) then
  2266. continue;
  2267. for j:=0 to exesec.ObjSectionlist.count-1 do
  2268. begin
  2269. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  2270. if not objsec.Used then
  2271. internalerror(200603301);
  2272. objsec.FixupRelocs;
  2273. end;
  2274. end;
  2275. end;
  2276. {****************************************************************************
  2277. TObjInput
  2278. ****************************************************************************}
  2279. constructor TObjInput.create;
  2280. begin
  2281. end;
  2282. destructor TObjInput.destroy;
  2283. begin
  2284. inherited destroy;
  2285. end;
  2286. function TObjInput.newObjData(const n:string):TObjData;
  2287. begin
  2288. result:=CObjData.create(n);
  2289. end;
  2290. procedure TObjInput.inputerror(const s : string);
  2291. begin
  2292. Comment(V_Error,s+' while reading '+InputFileName);
  2293. end;
  2294. {$ifdef MEMDEBUG}
  2295. initialization
  2296. memobjsymbols:=TMemDebug.create('ObjSymbols');
  2297. memobjsymbols.stop;
  2298. memobjsections:=TMemDebug.create('ObjSections');
  2299. memobjsections.stop;
  2300. finalization
  2301. memobjsymbols.free;
  2302. memobjsections.free;
  2303. {$endif MEMDEBUG}
  2304. end.