ogbase.pas 76 KB

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