ogbase.pas 77 KB

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