ogbase.pas 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845
  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. cclasses,
  23. { targets }
  24. systems,globtype,
  25. { outputwriters }
  26. owbase,owar,
  27. { assembler }
  28. aasmbase;
  29. type
  30. TObjSection = class;
  31. TObjData = class;
  32. TExeSection = class;
  33. TExeSymbol = class;
  34. TObjRelocationType = (RELOC_ABSOLUTE,RELOC_RELATIVE,RELOC_RVA);
  35. TObjSectionOption = (
  36. { Has data available in the file }
  37. oso_data,
  38. { Is loaded into memory }
  39. oso_load,
  40. { Not loaded into memory }
  41. oso_noload,
  42. { Read only }
  43. oso_readonly,
  44. { Read/Write }
  45. oso_write,
  46. { Contains executable instructions }
  47. oso_executable,
  48. { Never discard section }
  49. oso_keep,
  50. { Special common symbols }
  51. oso_common,
  52. { Contains debug info and can be stripped }
  53. oso_debug,
  54. { Contains only strings }
  55. oso_strings
  56. );
  57. TObjSectionOptions = set of TObjSectionOption;
  58. TObjSymbol = class(TNamedIndexItem)
  59. public
  60. bind : TAsmsymbind;
  61. typ : TAsmsymtype;
  62. { Current assemble pass, used to detect duplicate labels }
  63. pass : byte;
  64. objsection : TObjSection;
  65. symidx : longint;
  66. offset,
  67. size : aint;
  68. { Used for external and common solving during linking }
  69. exesymbol : TExeSymbol;
  70. constructor create(const s:string);
  71. function address:aint;
  72. procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  73. end;
  74. { Stabs is common for all targets }
  75. TObjStabEntry=packed record
  76. strpos : longint;
  77. ntype : byte;
  78. nother : byte;
  79. ndesc : word;
  80. nvalue : longint;
  81. end;
  82. PObjStabEntry=^TObjStabEntry;
  83. TObjRelocation = class(TLinkedListItem)
  84. DataOffset,
  85. orgsize : aint; { original size of the symbol to relocate, required for COFF }
  86. symbol : TObjSymbol;
  87. objsection : TObjSection; { only used if symbol=nil }
  88. typ : TObjRelocationType;
  89. constructor CreateSymbol(ADataOffset:aint;s:TObjSymbol;Atyp:TObjRelocationType);
  90. constructor CreateSymbolSize(ADataOffset:aint;s:TObjSymbol;Aorgsize:aint;Atyp:TObjRelocationType);
  91. constructor CreateSection(ADataOffset:aint;aobjsec:TObjSection;Atyp:TObjRelocationType);
  92. end;
  93. TObjSection = class(TNamedIndexItem)
  94. private
  95. FData : TDynamicArray;
  96. FSecOptions : TObjSectionOptions;
  97. procedure SetSecOptions(Aoptions:TObjSectionOptions);
  98. public
  99. ObjData : TObjData;
  100. SecSymIdx : longint; { index for the section in symtab }
  101. SecAlign : shortint; { alignment of the section }
  102. { section data }
  103. Size,
  104. DataPos,
  105. MemPos : aint;
  106. DataAlignBytes : shortint;
  107. { relocation }
  108. relocations : TLinkedList;
  109. { Symbols this section references and defines }
  110. ObjSymbolRefs : TFPObjectList;
  111. ObjSymbolDefines : TFPObjectList;
  112. { executable linking }
  113. ExeSection : TExeSection;
  114. Used : boolean;
  115. constructor create(const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual;
  116. destructor destroy;override;
  117. function write(const d;l:aint):aint;
  118. function writestr(const s:string):aint;
  119. function WriteZeros(l:longint):aint;
  120. procedure setmempos(var mpos:aint);
  121. procedure setdatapos(var dpos:aint);
  122. procedure alloc(l:aint);
  123. procedure addsymreloc(ofs:aint;p:TObjSymbol;reloctype:TObjRelocationType);
  124. procedure addsectionreloc(ofs:aint;aobjsec:TObjSection;reloctype:TObjRelocationType);
  125. procedure AddSymbolDefine(p:TObjSymbol);
  126. procedure AddSymbolRef(p:TObjSymbol);
  127. procedure fixuprelocs;virtual;
  128. function FullName:string;
  129. property Data:TDynamicArray read FData;
  130. property SecOptions:TObjSectionOptions read FSecOptions write SetSecOptions;
  131. end;
  132. TObjSectionClass = class of TObjSection;
  133. TObjData = class(TLinkedListItem)
  134. private
  135. FName : string[80];
  136. FCurrObjSec : TObjSection;
  137. { ObjSections will be stored in order in SectsIndex, this is at least
  138. required for stabs debuginfo. The SectsDict is only used for lookups (PFV) }
  139. FObjSectionDict : TDictionary;
  140. FObjSectionList : TFPObjectList;
  141. FCObjSection : TObjSectionClass;
  142. { Symbols that will be defined in this object file }
  143. FObjSymbolList : TFPObjectList;
  144. FObjSymbolDict : TDictionary;
  145. FCachedAsmSymbolList : TFPObjectList;
  146. { Special info sections that are written to during object generation }
  147. FStabsObjSec,
  148. FStabStrObjSec : TObjSection;
  149. procedure section_reset(p:TObject;arg:pointer);
  150. procedure section_afteralloc(p:TObject;arg:pointer);
  151. procedure section_afterwrite(p:TObject;arg:pointer);
  152. procedure section_fixuprelocs(p:TObject;arg:pointer);
  153. protected
  154. property StabsSec:TObjSection read FStabsObjSec write FStabsObjSec;
  155. property StabStrSec:TObjSection read FStabStrObjSec write FStabStrObjSec;
  156. property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
  157. public
  158. CurrPass : byte;
  159. ImageBase : aint;
  160. constructor create(const n:string);virtual;
  161. destructor destroy;override;
  162. { Sections }
  163. function sectionname(atype:TAsmSectiontype;const aname:string):string;virtual;
  164. function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;virtual;
  165. function sectiontype2align(atype:TAsmSectiontype):shortint;virtual;
  166. function createsection(atype:TAsmSectionType;const aname:string):TObjSection;
  167. function createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions):TObjSection;virtual;
  168. procedure CreateDebugSections;virtual;
  169. function findsection(const aname:string):TObjSection;
  170. procedure removesection(asec:TObjSection);
  171. procedure setsection(asec:TObjSection);
  172. { Symbols }
  173. function createsymbol(const aname:string):TObjSymbol;
  174. function symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  175. function symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  176. function symbolref(asmsym:TAsmSymbol):TObjSymbol;
  177. function symbolref(const aname:string):TObjSymbol;
  178. procedure ResetCachedAsmSymbols;
  179. { Allocation }
  180. procedure alloc(len:aint);
  181. procedure allocalign(len:shortint);
  182. procedure allocstab(p:pchar);
  183. procedure writebytes(const data;len:aint);
  184. procedure writereloc(data,len:aint;p:TObjSymbol;reloctype:TObjRelocationType);virtual;abstract;
  185. procedure writestab(offset:aint;ps:TObjSymbol;nidx,nother:byte;ndesc:word;p:pchar);virtual;abstract;
  186. procedure beforealloc;virtual;
  187. procedure beforewrite;virtual;
  188. procedure afteralloc;virtual;
  189. procedure afterwrite;virtual;
  190. procedure resetsections;
  191. procedure fixuprelocs;
  192. property Name:string[80] read FName;
  193. property CurrObjSec:TObjSection read FCurrObjSec;
  194. property ObjSymbolList:TFPObjectList read FObjSymbolList;
  195. property ObjSectionList:TFPObjectList read FObjSectionList;
  196. end;
  197. TObjDataClass = class of TObjData;
  198. TObjOutput = class
  199. private
  200. FCObjData : TObjDataClass;
  201. protected
  202. { writer }
  203. FWriter : TObjectwriter;
  204. function writedata(data:TObjData):boolean;virtual;abstract;
  205. property CObjData : TObjDataClass read FCObjData write FCObjData;
  206. public
  207. constructor create(smart:boolean);virtual;
  208. destructor destroy;override;
  209. function newObjData(const n:string):TObjData;
  210. function startObjectfile(const fn:string):boolean;
  211. function writeobjectfile(data:TObjData):boolean;
  212. procedure exportsymbol(p:TObjSymbol);
  213. property Writer:TObjectWriter read FWriter;
  214. end;
  215. TObjOutputClass=class of TObjOutput;
  216. TObjInput = class
  217. private
  218. FCObjData : TObjDataClass;
  219. protected
  220. { reader }
  221. FReader : TObjectreader;
  222. function readObjData(data:TObjData):boolean;virtual;abstract;
  223. property CObjData : TObjDataClass read FCObjData write FCObjData;
  224. public
  225. constructor create;virtual;
  226. destructor destroy;override;
  227. function newObjData(const n:string):TObjData;
  228. function readobjectfile(const fn:string;data:TObjData):boolean;virtual;
  229. property Reader:TObjectReader read FReader;
  230. end;
  231. TObjInputClass=class of TObjInput;
  232. TExeSymbol = class(TNamedIndexItem)
  233. ObjSymbol : TObjSymbol;
  234. ExeSection : TExeSection;
  235. constructor create(sym:TObjSymbol);
  236. end;
  237. TExeSection = class(tnamedindexitem)
  238. private
  239. FSecSymIdx : longint;
  240. FObjSectionList : TFPObjectList;
  241. public
  242. Size,
  243. DataPos,
  244. MemPos : aint;
  245. SecAlign : shortint;
  246. SecOptions : TObjSectionOptions;
  247. constructor create(const n:string);virtual;
  248. destructor destroy;override;
  249. procedure AddObjSection(objsec:TObjSection);
  250. property ObjSectionList:TFPObjectList read FObjSectionList;
  251. property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
  252. end;
  253. TExeSectionClass=class of TExeSection;
  254. TExeOutput = class
  255. private
  256. { ExeSections }
  257. FCObjData : TObjDataClass;
  258. FCExeSection : TExeSectionClass;
  259. FCurrExeSec : TExeSection;
  260. FExeSectionList : TFPObjectList;
  261. FExeSectionDict : TDictionary;
  262. Fzeronr : longint;
  263. { Symbols }
  264. FExeSymbolDict : TDictionary;
  265. FExeSymbolList,
  266. FUnresolvedExeSymbols : TFPObjectList;
  267. FExternalObjSymbols,
  268. FCommonObjSymbols : TFPObjectList;
  269. FEntryName : string;
  270. { Objects }
  271. FObjDataList : TFPObjectList;
  272. { Position calculation }
  273. FImageBase : aint;
  274. FCurrDataPos,
  275. FCurrMemPos : aint;
  276. protected
  277. { writer }
  278. FWriter : TObjectwriter;
  279. commonObjSection : TObjSection;
  280. commonobjdata,
  281. internalobjdata : TObjData;
  282. EntrySym : TObjSymbol;
  283. SectionDataAlign,
  284. SectionMemAlign : aint;
  285. function writedata:boolean;virtual;abstract;
  286. property CExeSection:TExeSectionClass read FCExeSection write FCExeSection;
  287. property CObjData:TObjDataClass read FCObjData write FCObjData;
  288. public
  289. constructor create;virtual;
  290. destructor destroy;override;
  291. procedure AddObjData(objdata:TObjData);
  292. function FindExeSection(const aname:string):TExeSection;
  293. procedure Load_Start;virtual;
  294. procedure Load_EntryName(const aname:string);virtual;
  295. procedure Load_Symbol(const aname:string);virtual;
  296. procedure Order_Start;virtual;
  297. procedure Order_ExeSection(const aname:string);virtual;
  298. procedure Order_Zeros(const aname:string);virtual;
  299. procedure Order_Symbol(const aname:string);virtual;
  300. procedure Order_EndExeSection;virtual;
  301. procedure Order_Stabs;
  302. procedure Order_ObjSection(const aname:string);virtual;
  303. procedure CalcPos_ExeSection(const aname:string);virtual;
  304. procedure CalcPos_EndExeSection;virtual;
  305. procedure CalcPos_Header;virtual;
  306. procedure CalcPos_Start;virtual;
  307. procedure CalcPos_Symbols;virtual;
  308. procedure ResolveSymbols;
  309. procedure PrintMemoryMap;
  310. procedure FixUpSymbols;
  311. procedure FixUpRelocations;
  312. procedure RemoveUnreferencedSections;
  313. procedure RemoveEmptySections;
  314. procedure ResolveExternals(const libname:string);virtual;
  315. function writeexefile(const fn:string):boolean;
  316. property Writer:TObjectWriter read FWriter;
  317. property ExeSections:TFPObjectList read FExeSectionList;
  318. property ObjDataList:TFPObjectList read FObjDataList;
  319. property ExeSymbolDict:TDictionary read FExeSymbolDict;
  320. property ExeSymbolList:TFPObjectList read FExeSymbolList;
  321. property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
  322. property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols;
  323. property CommonObjSymbols:TFPObjectList read FCommonObjSymbols;
  324. property EntryName:string read FEntryName write FEntryName;
  325. property ImageBase:aint read FImageBase write FImageBase;
  326. property CurrExeSec:TExeSection read FCurrExeSec;
  327. property CurrDataPos:aint read FCurrDataPos write FCurrDataPos;
  328. property CurrMemPos:aint read FCurrMemPos write FCurrMemPos;
  329. end;
  330. TExeOutputClass=class of TExeOutput;
  331. var
  332. exeoutput : TExeOutput;
  333. implementation
  334. uses
  335. cutils,globals,verbose,fmodule,ogmap;
  336. const
  337. sectiondatagrowsize = 1024;
  338. {*****************************************************************************
  339. TObjSymbol
  340. *****************************************************************************}
  341. constructor TObjSymbol.create(const s:string);
  342. begin;
  343. inherited createname(s);
  344. bind:=AB_EXTERNAL;
  345. typ:=AT_NONE;
  346. symidx:=-1;
  347. size:=0;
  348. offset:=0;
  349. objsection:=nil;
  350. end;
  351. function TObjSymbol.address:aint;
  352. begin
  353. if assigned(objsection) then
  354. result:=offset+objsection.mempos
  355. else
  356. result:=0;
  357. end;
  358. procedure TObjSymbol.SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  359. begin
  360. if not(abind in [AB_GLOBAL,AB_LOCAL,AB_COMMON]) then
  361. internalerror(200603016);
  362. if not assigned(aobjsec) then
  363. internalerror(200603017);
  364. if (bind=AB_EXTERNAL) then
  365. begin
  366. bind:=abind;
  367. typ:=atyp;
  368. end
  369. else
  370. begin
  371. if pass=apass then
  372. Message1(asmw_e_duplicate_label,name);
  373. end;
  374. pass:=apass;
  375. { Code can never grow after a pass }
  376. if assigned(objsection) and
  377. (aobjsec.size>offset) then
  378. internalerror(200603014);
  379. objsection:=aobjsec;
  380. offset:=aobjsec.size;
  381. end;
  382. {****************************************************************************
  383. TObjRelocation
  384. ****************************************************************************}
  385. constructor TObjRelocation.CreateSymbol(ADataOffset:aint;s:TObjSymbol;Atyp:TObjRelocationType);
  386. begin
  387. if not assigned(s) then
  388. internalerror(200603034);
  389. DataOffset:=ADataOffset;
  390. Symbol:=s;
  391. OrgSize:=0;
  392. ObjSection:=nil;
  393. Typ:=Atyp;
  394. end;
  395. constructor TObjRelocation.CreateSymbolSize(ADataOffset:aint;s:TObjSymbol;Aorgsize:aint;Atyp:TObjRelocationType);
  396. begin
  397. if not assigned(s) then
  398. internalerror(200603035);
  399. DataOffset:=ADataOffset;
  400. Symbol:=s;
  401. OrgSize:=Aorgsize;
  402. ObjSection:=nil;
  403. Typ:=Atyp;
  404. end;
  405. constructor TObjRelocation.CreateSection(ADataOffset:aint;aobjsec:TObjSection;Atyp:TObjRelocationType);
  406. begin
  407. if not assigned(aobjsec) then
  408. internalerror(200603036);
  409. DataOffset:=ADataOffset;
  410. Symbol:=nil;
  411. OrgSize:=0;
  412. ObjSection:=aobjsec;
  413. Typ:=Atyp;
  414. end;
  415. {****************************************************************************
  416. TObjSection
  417. ****************************************************************************}
  418. constructor TObjSection.create(const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
  419. begin
  420. inherited createname(Aname);
  421. name:=Aname;
  422. { data }
  423. Size:=0;
  424. datapos:=0;
  425. mempos:=0;
  426. FData:=Nil;
  427. { Setting the secoptions allocates Data if needed }
  428. secoptions:=Aoptions;
  429. secalign:=Aalign;
  430. secsymidx:=0;
  431. { relocation }
  432. relocations:=TLinkedList.Create;
  433. ObjSymbolRefs:=TFPObjectList.Create(false);
  434. ObjSymbolDefines:=TFPObjectList.Create(false);
  435. end;
  436. destructor TObjSection.destroy;
  437. begin
  438. if assigned(Data) then
  439. Data.Free;
  440. relocations.free;
  441. ObjSymbolRefs.Free;
  442. ObjSymbolDefines.Free;
  443. end;
  444. procedure TObjSection.SetSecOptions(Aoptions:TObjSectionOptions);
  445. begin
  446. FSecOptions:=FSecOptions+AOptions;
  447. if (oso_data in secoptions) and
  448. not assigned(FData) then
  449. FData:=TDynamicArray.Create(sectiondatagrowsize);
  450. end;
  451. function TObjSection.write(const d;l:aint):aint;
  452. begin
  453. result:=size;
  454. if assigned(Data) then
  455. begin
  456. if Size<>data.size then
  457. internalerror(200602281);
  458. Data.write(d,l);
  459. inc(Size,l);
  460. end
  461. else
  462. internalerror(200602289);
  463. end;
  464. function TObjSection.writestr(const s:string):aint;
  465. begin
  466. result:=Write(s[1],length(s));
  467. end;
  468. function TObjSection.WriteZeros(l:longint):aint;
  469. var
  470. empty : array[0..1023] of byte;
  471. begin
  472. if l>sizeof(empty) then
  473. internalerror(200404082);
  474. if l>0 then
  475. begin
  476. fillchar(empty,l,0);
  477. result:=Write(empty,l);
  478. end
  479. else
  480. result:=Size;
  481. end;
  482. procedure TObjSection.setdatapos(var dpos:aint);
  483. begin
  484. if oso_data in secoptions then
  485. begin
  486. { get aligned datapos }
  487. datapos:=align(dpos,secalign);
  488. dataalignbytes:=datapos-dpos;
  489. { return updated datapos }
  490. dpos:=datapos+size;
  491. end
  492. else
  493. datapos:=dpos;
  494. end;
  495. procedure TObjSection.setmempos(var mpos:aint);
  496. begin
  497. mempos:=align(mpos,secalign);
  498. { return updated mempos }
  499. mpos:=mempos+size;
  500. end;
  501. procedure TObjSection.alloc(l:aint);
  502. begin
  503. inc(size,l);
  504. end;
  505. procedure TObjSection.addsymreloc(ofs:aint;p:TObjSymbol;reloctype:TObjRelocationType);
  506. begin
  507. relocations.concat(TObjRelocation.CreateSymbol(ofs,p,reloctype));
  508. end;
  509. procedure TObjSection.addsectionreloc(ofs:aint;aobjsec:TObjSection;reloctype:TObjRelocationType);
  510. begin
  511. relocations.concat(TObjRelocation.CreateSection(ofs,aobjsec,reloctype));
  512. end;
  513. procedure TObjSection.AddSymbolDefine(p:TObjSymbol);
  514. begin
  515. if p.bind<>AB_GLOBAL then
  516. exit;
  517. ObjSymbolDefines.Add(p);
  518. end;
  519. procedure TObjSection.AddSymbolRef(p:TObjSymbol);
  520. begin
  521. { Register all references, also the local references between the
  522. ObjSections in an ObjData }
  523. ObjSymbolRefs.Add(p);
  524. end;
  525. procedure TObjSection.fixuprelocs;
  526. begin
  527. end;
  528. function TObjSection.FullName:string;
  529. begin
  530. if assigned(objdata) then
  531. result:=objdata.Name+'('+Name+')'
  532. else
  533. result:=Name;
  534. end;
  535. {****************************************************************************
  536. TObjData
  537. ****************************************************************************}
  538. constructor TObjData.create(const n:string);
  539. begin
  540. inherited create;
  541. FName:=SplitFileName(n);
  542. { sections, the SectsIndex owns the items, the FObjSectionDict
  543. is only used for lookups }
  544. FObjSectionDict:=tdictionary.create;
  545. FObjSectionDict.noclear:=true;
  546. FObjSectionList:=TFPObjectList.Create(true);
  547. FStabsObjSec:=nil;
  548. FStabStrObjSec:=nil;
  549. { symbols }
  550. FObjSymbolDict:=tdictionary.create;
  551. FObjSymbolDict.noclear:=true;
  552. FObjSymbolList:=TFPObjectList.Create(true);
  553. FCachedAsmSymbolList:=TFPObjectList.Create(false);
  554. { section class type for creating of new sections }
  555. FCObjSection:=TObjSection;
  556. end;
  557. destructor TObjData.destroy;
  558. {$ifdef MEMDEBUG}
  559. var
  560. d : tmemdebug;
  561. {$endif}
  562. begin
  563. {$ifdef MEMDEBUG}
  564. d:=tmemdebug.create(name+' - objdata symbols');
  565. {$endif}
  566. ResetCachedAsmSymbols;
  567. FCachedAsmSymbolList.free;
  568. FObjSymbolDict.free;
  569. FObjSymbolList.free;
  570. {$ifdef MEMDEBUG}
  571. d.free;
  572. {$endif}
  573. {$ifdef MEMDEBUG}
  574. d:=tmemdebug.create(name+' - objdata sections');
  575. {$endif}
  576. FObjSectionDict.free;
  577. FObjSectionList.free;
  578. {$ifdef MEMDEBUG}
  579. d.free;
  580. {$endif}
  581. end;
  582. function TObjData.sectionname(atype:TAsmSectiontype;const aname:string):string;
  583. const
  584. secnames : array[TAsmSectiontype] of string[13] = ('',
  585. 'code',
  586. 'data',
  587. 'rodata',
  588. 'bss',
  589. 'threadvar',
  590. 'stub',
  591. 'stab','stabstr',
  592. 'idata2','idata4','idata5','idata6','idata7','edata',
  593. 'eh_frame',
  594. 'debug_frame','debug_info','debug_line','debug_abbrev',
  595. 'fpc',
  596. 'toc'
  597. );
  598. begin
  599. if aname<>'' then
  600. result:=secnames[atype]+'.'+aname
  601. else
  602. result:=secnames[atype];
  603. end;
  604. function TObjData.sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
  605. const
  606. secoptions : array[TAsmSectiontype] of TObjSectionOptions = ([],
  607. {code} [oso_data,oso_load,oso_readonly,oso_executable,oso_keep],
  608. {data} [oso_data,oso_load,oso_write,oso_keep],
  609. {$warning TODO Fix rodata be really read-only}
  610. {rodata} [oso_data,oso_load,oso_write,oso_keep],
  611. {bss} [oso_load,oso_write,oso_keep],
  612. {threadvar} [oso_load,oso_write],
  613. {stub} [oso_data,oso_load,oso_readonly,oso_executable],
  614. {stab} [oso_data,oso_noload,oso_debug],
  615. {stabstr} [oso_data,oso_noload,oso_strings,oso_debug],
  616. {$warning TODO idata keep can maybe replaced with grouping of text and idata}
  617. {idata2} [oso_data,oso_load,oso_write,oso_keep],
  618. {idata4} [oso_data,oso_load,oso_write,oso_keep],
  619. {idata5} [oso_data,oso_load,oso_write,oso_keep],
  620. {idata6} [oso_data,oso_load,oso_write,oso_keep],
  621. {idata7} [oso_data,oso_load,oso_write,oso_keep],
  622. {edata} [oso_data,oso_load,oso_readonly],
  623. {eh_frame} [oso_data,oso_load,oso_readonly],
  624. {debug_frame} [oso_data,oso_noload,oso_debug],
  625. {debug_info} [oso_data,oso_noload,oso_debug],
  626. {debug_line} [oso_data,oso_noload,oso_debug],
  627. {debug_abbrev} [oso_data,oso_noload,oso_debug],
  628. {fpc} [oso_data,oso_load,oso_write,oso_keep],
  629. {toc} [oso_data,oso_load,oso_readonly]
  630. );
  631. begin
  632. result:=secoptions[atype];
  633. end;
  634. function TObjData.sectiontype2align(atype:TAsmSectiontype):shortint;
  635. begin
  636. result:=sizeof(aint);
  637. end;
  638. function TObjData.createsection(atype:TAsmSectionType;const aname:string):TObjSection;
  639. begin
  640. result:=createsection(sectionname(atype,aname),sectiontype2align(atype),sectiontype2options(atype));
  641. end;
  642. function TObjData.createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions):TObjSection;
  643. begin
  644. result:=TObjSection(FObjSectionDict.search(aname));
  645. if not assigned(result) then
  646. begin
  647. result:=CObjSection.create(aname,aalign,aoptions);
  648. FObjSectionDict.Insert(result);
  649. FObjSectionList.Add(result);
  650. result.ObjData:=self;
  651. end;
  652. FCurrObjSec:=result;
  653. end;
  654. procedure TObjData.CreateDebugSections;
  655. begin
  656. end;
  657. function TObjData.FindSection(const aname:string):TObjSection;
  658. begin
  659. result:=TObjSection(FObjSectionDict.Search(aname));
  660. end;
  661. procedure TObjData.removesection(asec:TObjSection);
  662. begin
  663. FObjSectionDict.Delete(asec.name);
  664. FObjSectionList.Remove(asec);
  665. end;
  666. procedure TObjData.setsection(asec:TObjSection);
  667. begin
  668. if asec.ObjData<>self then
  669. internalerror(200403041);
  670. FCurrObjSec:=asec;
  671. end;
  672. function TObjData.createsymbol(const aname:string):TObjSymbol;
  673. begin
  674. result:=TObjSymbol(FObjSymbolDict.search(aname));
  675. if not assigned(result) then
  676. begin
  677. result:=TObjSymbol.Create(aname);
  678. FObjSymbolDict.Insert(result);
  679. FObjSymbolList.Add(result);
  680. end;
  681. end;
  682. function TObjData.symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  683. begin
  684. if assigned(asmsym) then
  685. begin
  686. if not assigned(asmsym.cachedObjSymbol) then
  687. begin
  688. result:=symboldefine(asmsym.name,asmsym.bind,asmsym.typ);
  689. asmsym.cachedObjSymbol:=result;
  690. FCachedAsmSymbolList.add(asmsym);
  691. end
  692. else
  693. begin
  694. result:=TObjSymbol(asmsym.cachedObjSymbol);
  695. result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
  696. { Register also in TObjSection }
  697. CurrObjSec.AddSymbolDefine(result);
  698. end;
  699. end
  700. else
  701. result:=nil;
  702. end;
  703. function TObjData.symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  704. begin
  705. if not assigned(CurrObjSec) then
  706. internalerror(200603051);
  707. result:=CreateSymbol(aname);
  708. { Register also in TObjSection }
  709. CurrObjSec.AddSymbolDefine(result);
  710. result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
  711. end;
  712. function TObjData.symbolref(asmsym:TAsmSymbol):TObjSymbol;
  713. begin
  714. if assigned(asmsym) then
  715. begin
  716. if not assigned(asmsym.cachedObjSymbol) then
  717. begin
  718. result:=symbolref(asmsym.name);
  719. asmsym.cachedObjSymbol:=result;
  720. FCachedAsmSymbolList.add(asmsym);
  721. end
  722. else
  723. begin
  724. result:=TObjSymbol(asmsym.cachedObjSymbol);
  725. { Register also in TObjSection }
  726. CurrObjSec.AddSymbolRef(result);
  727. end;
  728. end
  729. else
  730. result:=nil;
  731. end;
  732. function TObjData.symbolref(const aname:string):TObjSymbol;
  733. begin
  734. if not assigned(CurrObjSec) then
  735. internalerror(200603052);
  736. result:=CreateSymbol(aname);
  737. { Register also in TObjSection }
  738. CurrObjSec.AddSymbolRef(result);
  739. end;
  740. procedure TObjData.ResetCachedAsmSymbols;
  741. var
  742. i : longint;
  743. begin
  744. for i:=0 to FCachedAsmSymbolList.Count-1 do
  745. tasmsymbol(FCachedAsmSymbolList[i]).cachedObjSymbol:=nil;
  746. FCachedAsmSymbolList.Clear;
  747. end;
  748. procedure TObjData.writebytes(const data;len:aint);
  749. begin
  750. if not assigned(CurrObjSec) then
  751. internalerror(200402251);
  752. CurrObjSec.write(data,len);
  753. end;
  754. procedure TObjData.alloc(len:aint);
  755. begin
  756. if not assigned(CurrObjSec) then
  757. internalerror(200402252);
  758. CurrObjSec.alloc(len);
  759. end;
  760. procedure TObjData.allocalign(len:shortint);
  761. begin
  762. if not assigned(CurrObjSec) then
  763. internalerror(200402253);
  764. CurrObjSec.alloc(align(CurrObjSec.size,len)-CurrObjSec.size);
  765. end;
  766. procedure TObjData.allocstab(p:pchar);
  767. begin
  768. if not(assigned(FStabsObjSec) and assigned(FStabStrObjSec)) then
  769. internalerror(200402254);
  770. FStabsObjSec.alloc(sizeof(TObjStabEntry));
  771. if assigned(p) and (p[0]<>#0) then
  772. FStabStrObjSec.alloc(strlen(p)+1);
  773. end;
  774. procedure TObjData.section_afteralloc(p:TObject;arg:pointer);
  775. begin
  776. with TObjSection(p) do
  777. alloc(align(size,secalign)-size);
  778. end;
  779. procedure TObjData.section_afterwrite(p:TObject;arg:pointer);
  780. begin
  781. with TObjSection(p) do
  782. begin
  783. if assigned(data) then
  784. writezeros(align(size,secalign)-size);
  785. end;
  786. end;
  787. procedure TObjData.section_reset(p:TObject;arg:pointer);
  788. begin
  789. with TObjSection(p) do
  790. begin
  791. Size:=0;
  792. datapos:=0;
  793. mempos:=0;
  794. end;
  795. end;
  796. procedure TObjData.section_fixuprelocs(p:TObject;arg:pointer);
  797. begin
  798. if TObjSection(p).Used then
  799. TObjSection(p).fixuprelocs;
  800. end;
  801. procedure TObjData.beforealloc;
  802. begin
  803. { create stabs sections if debugging }
  804. if assigned(StabsSec) then
  805. begin
  806. StabsSec.Alloc(sizeof(TObjStabEntry));
  807. StabStrSec.Alloc(1);
  808. end;
  809. end;
  810. procedure TObjData.beforewrite;
  811. var
  812. s : string[1];
  813. begin
  814. { create stabs sections if debugging }
  815. if assigned(StabsSec) then
  816. begin
  817. writestab(0,nil,0,0,0,nil);
  818. s:=#0;
  819. stabstrsec.write(s[1],length(s));
  820. end;
  821. end;
  822. procedure TObjData.afteralloc;
  823. begin
  824. FObjSectionList.ForEachCall(@section_afteralloc,nil);
  825. end;
  826. procedure TObjData.afterwrite;
  827. var
  828. s : string[1];
  829. hstab : TObjStabEntry;
  830. begin
  831. FObjSectionList.ForEachCall(@section_afterwrite,nil);
  832. { For the stab section we need an HdrSym which can now be
  833. calculated more easily }
  834. if assigned(StabsSec) then
  835. begin
  836. { header stab }
  837. s:=#0;
  838. stabstrsec.write(s[1],length(s));
  839. hstab.strpos:=1;
  840. hstab.ntype:=0;
  841. hstab.nother:=0;
  842. hstab.ndesc:=(StabsSec.Size div sizeof(TObjStabEntry))-1;
  843. hstab.nvalue:=StabStrSec.Size;
  844. StabsSec.data.seek(0);
  845. StabsSec.data.write(hstab,sizeof(hstab));
  846. end;
  847. end;
  848. procedure TObjData.resetsections;
  849. begin
  850. FObjSectionList.ForEachCall(@section_reset,nil);
  851. end;
  852. procedure TObjData.fixuprelocs;
  853. begin
  854. FObjSectionList.ForEachCall(@section_fixuprelocs,nil);
  855. end;
  856. {****************************************************************************
  857. TObjOutput
  858. ****************************************************************************}
  859. constructor TObjOutput.create(smart:boolean);
  860. begin
  861. { init writer }
  862. if smart and
  863. not(cs_asm_leave in aktglobalswitches) then
  864. FWriter:=tarobjectwriter.create(current_module.staticlibfilename^)
  865. else
  866. FWriter:=TObjectwriter.create;
  867. CObjData:=TObjData;
  868. end;
  869. destructor TObjOutput.destroy;
  870. begin
  871. FWriter.free;
  872. end;
  873. function TObjOutput.newObjData(const n:string):TObjData;
  874. begin
  875. result:=CObjData.create(n);
  876. if (cs_use_lineinfo in aktglobalswitches) or
  877. (cs_debuginfo in aktmoduleswitches) then
  878. result.CreateDebugSections;
  879. end;
  880. function TObjOutput.startObjectfile(const fn:string):boolean;
  881. begin
  882. result:=false;
  883. { start the writer already, so the .a generation can initialize
  884. the position of the current objectfile }
  885. if not FWriter.createfile(fn) then
  886. Comment(V_Fatal,'Can''t create object '+fn);
  887. result:=true;
  888. end;
  889. function TObjOutput.writeobjectfile(data:TObjData):boolean;
  890. begin
  891. if errorcount=0 then
  892. result:=writedata(data)
  893. else
  894. result:=true;
  895. { close the writer }
  896. FWriter.closefile;
  897. end;
  898. procedure TObjOutput.exportsymbol(p:TObjSymbol);
  899. begin
  900. { export globals and common symbols, this is needed
  901. for .a files }
  902. if p.bind in [AB_GLOBAL,AB_COMMON] then
  903. FWriter.writesym(p.name);
  904. end;
  905. {****************************************************************************
  906. TExeSymbol
  907. ****************************************************************************}
  908. constructor TExeSymbol.create(sym:TObjSymbol);
  909. begin
  910. inherited createname(sym.name);
  911. ObjSymbol:=sym;
  912. end;
  913. {****************************************************************************
  914. tExeSection
  915. ****************************************************************************}
  916. constructor tExeSection.create(const n:string);
  917. begin
  918. inherited createname(n);
  919. Size:=0;
  920. MemPos:=0;
  921. DataPos:=0;
  922. FSecSymIdx:=0;
  923. FObjSectionList:=TFPObjectList.Create(false);
  924. end;
  925. destructor tExeSection.destroy;
  926. begin
  927. ObjSectionList.Free;
  928. end;
  929. procedure tExeSection.AddObjSection(objsec:TObjSection);
  930. begin
  931. ObjSectionList.Add(objsec);
  932. if (SecOptions<>[]) then
  933. begin
  934. if (oso_data in SecOptions)<>(oso_data in objsec.SecOptions) then
  935. Comment(V_Error,'Incompatible section options');
  936. end
  937. else
  938. begin
  939. { inherit section options }
  940. SecAlign:=objsec.SecAlign;
  941. SecOptions:=SecOptions+objsec.SecOptions;
  942. end;
  943. { relate ObjSection to ExeSection }
  944. objsec.ExeSection:=self;
  945. end;
  946. {****************************************************************************
  947. TExeOutput
  948. ****************************************************************************}
  949. constructor TExeOutput.create;
  950. begin
  951. { init writer }
  952. FWriter:=TObjectwriter.create;
  953. { object files }
  954. FObjDataList:=TFPObjectList.Create(true);
  955. { symbols }
  956. FExeSymbolDict:=tdictionary.create;
  957. FExeSymbolDict.noclear:=true;
  958. FExeSymbolDict.usehash;
  959. FExeSymbolList:=TFPObjectList.Create(true);
  960. FUnresolvedExeSymbols:=TFPObjectList.Create(false);
  961. FExternalObjSymbols:=TFPObjectList.Create(false);
  962. FCommonObjSymbols:=TFPObjectList.Create(false);
  963. FEntryName:='start';
  964. { sections }
  965. FExeSectionDict:=TDictionary.create;
  966. FExeSectionDict.noclear:=true;
  967. FExeSectionList:=TFPObjectList.Create(true);
  968. FImageBase:=0;
  969. SectionMemAlign:=$1000;
  970. SectionDataAlign:=$200;
  971. FCExeSection:=TExeSection;
  972. FCObjData:=TObjData;
  973. end;
  974. destructor TExeOutput.destroy;
  975. begin
  976. FExeSymbolDict.free;
  977. FExeSymbolList.free;
  978. UnresolvedExeSymbols.free;
  979. ExternalObjSymbols.free;
  980. CommonObjSymbols.free;
  981. FExeSectionDict.free;
  982. FExeSectionList.free;
  983. objdatalist.free;
  984. FWriter.free;
  985. end;
  986. function TExeOutput.writeexefile(const fn:string):boolean;
  987. begin
  988. result:=false;
  989. if FWriter.createfile(fn) then
  990. begin
  991. { Only write the .o if there are no errors }
  992. if errorcount=0 then
  993. result:=writedata
  994. else
  995. result:=true;
  996. { close the writer }
  997. FWriter.closefile;
  998. end
  999. else
  1000. Comment(V_Fatal,'Can''t create executable '+fn);
  1001. end;
  1002. procedure TExeOutput.AddObjData(objdata:TObjData);
  1003. begin
  1004. if objdata.classtype<>FCObjData then
  1005. Comment(V_Error,'Invalid input object format for '+objdata.name+' got '+objdata.classname+' expected '+FCObjData.classname);
  1006. ObjDataList.Add(objdata);
  1007. end;
  1008. function TExeOutput.FindExeSection(const aname:string):TExeSection;
  1009. begin
  1010. result:=TExeSection(FExeSectionDict.Search(aname));
  1011. end;
  1012. procedure TExeOutput.Load_Start;
  1013. begin
  1014. ObjDataList.Clear;
  1015. { Globals defined in the linker script }
  1016. if not assigned(internalobjdata) then
  1017. internalobjdata:=CObjData.create('*GLOBALS*');
  1018. AddObjData(internalobjdata);
  1019. { Common data }
  1020. if not assigned(commonobjdata) then
  1021. begin
  1022. commonobjdata:=CObjData.create('*COMMON*');
  1023. commonObjSection:=commonobjdata.createsection(sec_bss,'');
  1024. end;
  1025. AddObjData(commonobjdata);
  1026. end;
  1027. procedure TExeOutput.Load_EntryName(const aname:string);
  1028. begin
  1029. EntryName:=aname;
  1030. end;
  1031. procedure TExeOutput.Load_Symbol(const aname:string);
  1032. begin
  1033. internalobjdata.createsection('*'+aname,0,[]);
  1034. internalobjdata.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION);
  1035. end;
  1036. procedure TExeOutput.Order_Start;
  1037. begin
  1038. end;
  1039. procedure TExeOutput.Order_ExeSection(const aname:string);
  1040. var
  1041. sec : TExeSection;
  1042. begin
  1043. sec:=FindExeSection(aname);
  1044. if not assigned(sec) then
  1045. begin
  1046. sec:=CExeSection.create(aname);
  1047. FExeSectionDict.Insert(sec);
  1048. FExeSectionList.Add(sec);
  1049. end;
  1050. { Clear ExeSection contents }
  1051. FCurrExeSec:=sec;
  1052. end;
  1053. procedure TExeOutput.Order_EndExeSection;
  1054. begin
  1055. if not assigned(CurrExeSec) then
  1056. internalerror(200602184);
  1057. FCurrExeSec:=nil;
  1058. end;
  1059. procedure TExeOutput.Order_ObjSection(const aname:string);
  1060. var
  1061. i,j : longint;
  1062. objdata : TObjData;
  1063. objsec : TObjSection;
  1064. begin
  1065. if not assigned(CurrExeSec) then
  1066. internalerror(200602181);
  1067. for i:=0 to ObjDataList.Count-1 do
  1068. begin
  1069. objdata:=TObjData(ObjDataList[i]);
  1070. for j:=0 to objdata.ObjSectionList.Count-1 do
  1071. begin
  1072. objsec:=TObjSection(objdata.ObjSectionList[j]);
  1073. if MatchPattern(aname,objsec.name) then
  1074. CurrExeSec.AddObjSection(objsec);
  1075. end;
  1076. end;
  1077. end;
  1078. procedure TExeOutput.Order_Symbol(const aname:string);
  1079. var
  1080. ObjSection : TObjSection;
  1081. begin
  1082. ObjSection:=internalobjdata.findsection('*'+aname);
  1083. if not assigned(ObjSection) then
  1084. internalerror(200603041);
  1085. ObjSection.SecOptions:=CurrExeSec.SecOptions;
  1086. CurrExeSec.AddObjSection(ObjSection);
  1087. end;
  1088. procedure TExeOutput.Order_Zeros(const aname:string);
  1089. var
  1090. zeros : array[0..1023] of byte;
  1091. code : integer;
  1092. len : longint;
  1093. objsec : TObjSection;
  1094. begin
  1095. val(aname,len,code);
  1096. if len<=0 then
  1097. exit;
  1098. if len>sizeof(zeros) then
  1099. internalerror(200602254);
  1100. fillchar(zeros,len,0);
  1101. inc(Fzeronr);
  1102. objsec:=internalobjdata.createsection('*zeros'+tostr(Fzeronr),0,CurrExeSec.SecOptions+[oso_data,oso_keep]);
  1103. internalobjdata.writebytes(zeros,len);
  1104. internalobjdata.afterwrite;
  1105. CurrExeSec.AddObjSection(objsec);
  1106. end;
  1107. procedure TExeOutput.Order_Stabs;
  1108. var
  1109. stabexesec,
  1110. stabstrexesec : TExeSection;
  1111. currstabsec,
  1112. currstabstrsec,
  1113. mergedstabsec,
  1114. mergedstabstrsec : TObjSection;
  1115. nextstabreloc,
  1116. currstabreloc : TObjRelocation;
  1117. i,j,
  1118. stabcnt : longint;
  1119. skipstab : boolean;
  1120. hstab : TObjStabEntry;
  1121. stabrelocofs : longint;
  1122. buf : array[0..1023] of byte;
  1123. bufend,
  1124. bufsize : longint;
  1125. begin
  1126. stabexesec:=FindExeSection('.stab');
  1127. stabstrexesec:=FindExeSection('.stabstr');
  1128. if (stabexesec=nil) or
  1129. (stabstrexesec=nil) or
  1130. (stabexesec.ObjSectionlist.count=0) then
  1131. exit;
  1132. { Create new stabsection }
  1133. stabrelocofs:[email protected]@hstab;
  1134. mergedstabsec:=internalobjdata.CreateSection(sec_stab,'');
  1135. mergedstabstrsec:=internalobjdata.CreateSection(sec_stabstr,'');
  1136. { write stab for hdrsym }
  1137. fillchar(hstab,sizeof(TObjStabEntry),0);
  1138. mergedstabsec.write(hstab,sizeof(TObjStabEntry));
  1139. { .stabstr starts with a #0 }
  1140. buf[0]:=0;
  1141. mergedstabstrsec.write(buf[0],1);
  1142. { Copy stabs and corresponding relocations }
  1143. for i:=0 to stabexesec.ObjSectionList.Count-1 do
  1144. begin
  1145. currstabsec:=TObjSection(stabexesec.ObjSectionList[i]);
  1146. currstabstrsec:=currstabsec.objdata.findsection('.stabstr');
  1147. if assigned(currstabstrsec) then
  1148. begin
  1149. stabcnt:=currstabsec.data.size div sizeof(TObjStabEntry);
  1150. currstabsec.data.seek(0);
  1151. currstabreloc:=TObjRelocation(currstabsec.relocations.first);
  1152. for j:=0 to stabcnt-1 do
  1153. begin
  1154. skipstab:=false;
  1155. currstabsec.data.read(hstab,sizeof(TObjStabEntry));
  1156. { Only include first hdrsym stab }
  1157. if hstab.ntype=0 then
  1158. skipstab:=true;
  1159. if not skipstab then
  1160. begin
  1161. { Copy string in stabstr }
  1162. if hstab.strpos<>0 then
  1163. begin
  1164. currstabstrsec.data.seek(hstab.strpos);
  1165. hstab.strpos:=mergedstabstrsec.Size;
  1166. repeat
  1167. bufsize:=currstabstrsec.data.read(buf,sizeof(buf));
  1168. bufend:=indexbyte(buf,bufsize,0);
  1169. if bufend=-1 then
  1170. bufend:=bufsize
  1171. else
  1172. begin
  1173. { include the #0 }
  1174. inc(bufend);
  1175. end;
  1176. mergedstabstrsec.write(buf,bufend);
  1177. until (bufend<>-1) or (bufsize<sizeof(buf));
  1178. end;
  1179. { Copy relocation }
  1180. while assigned(currstabreloc) and
  1181. (currstabreloc.dataoffset<j*sizeof(TObjStabEntry)+stabrelocofs) do
  1182. currstabreloc:=TObjRelocation(currstabreloc.next);
  1183. if assigned(currstabreloc) then
  1184. begin
  1185. if (currstabreloc.dataoffset=j*sizeof(TObjStabEntry)+stabrelocofs) then
  1186. begin
  1187. currstabreloc.dataoffset:=mergedstabsec.Size+stabrelocofs;
  1188. nextstabreloc:=TObjRelocation(currstabreloc.next);
  1189. currstabsec.relocations.remove(currstabreloc);
  1190. mergedstabsec.relocations.concat(currstabreloc);
  1191. currstabreloc:=nextstabreloc;
  1192. end;
  1193. end;
  1194. mergedstabsec.write(hstab,sizeof(hstab));
  1195. end;
  1196. end;
  1197. end;
  1198. { Unload stabs }
  1199. if assigned(currstabstrsec) then
  1200. currstabsec.objdata.removesection(currstabstrsec);
  1201. currstabsec.objdata.removesection(currstabsec);
  1202. end;
  1203. { Generate new HdrSym }
  1204. if mergedstabsec.Size>0 then
  1205. begin
  1206. hstab.strpos:=1;
  1207. hstab.ntype:=0;
  1208. hstab.nother:=0;
  1209. hstab.ndesc:=word((mergedstabsec.Size div sizeof(TObjStabEntry))-1);
  1210. hstab.nvalue:=mergedstabstrsec.Size;
  1211. mergedstabsec.data.seek(0);
  1212. mergedstabsec.data.write(hstab,sizeof(hstab));
  1213. end;
  1214. { Replace all sections with our combined stabsec }
  1215. stabexesec.ObjSectionList.Clear;
  1216. stabstrexesec.ObjSectionList.Clear;
  1217. stabexesec.AddObjSection(mergedstabsec);
  1218. stabstrexesec.AddObjSection(mergedstabstrsec);
  1219. end;
  1220. procedure TExeOutput.CalcPos_ExeSection(const aname:string);
  1221. var
  1222. i : longint;
  1223. objsec : TObjSection;
  1224. begin
  1225. { Section can be removed }
  1226. FCurrExeSec:=FindExeSection(aname);
  1227. if not assigned(CurrExeSec) then
  1228. exit;
  1229. { Alignment of ExeSection }
  1230. CurrMemPos:=align(CurrMemPos,SectionMemAlign);
  1231. CurrExeSec.MemPos:=CurrMemPos;
  1232. if (oso_data in currexesec.SecOptions) then
  1233. begin
  1234. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  1235. CurrExeSec.DataPos:=CurrDataPos;
  1236. end;
  1237. { set position of object ObjSections }
  1238. for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
  1239. begin
  1240. objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
  1241. { Position in memory }
  1242. objsec.setmempos(CurrMemPos);
  1243. { Position in File }
  1244. if (oso_data in objsec.SecOptions) then
  1245. begin
  1246. if not (oso_data in currexesec.SecOptions) then
  1247. internalerror(200603043);
  1248. if not assigned(objsec.Data) then
  1249. internalerror(200603044);
  1250. objsec.setdatapos(CurrDataPos);
  1251. end;
  1252. end;
  1253. { calculate size of the section }
  1254. CurrExeSec.Size:=CurrMemPos-CurrExeSec.MemPos;
  1255. end;
  1256. procedure TExeOutput.CalcPos_EndExeSection;
  1257. begin
  1258. if not assigned(CurrExeSec) then
  1259. exit;
  1260. FCurrExeSec:=nil;
  1261. end;
  1262. procedure TExeOutput.CalcPos_Start;
  1263. begin
  1264. CurrMemPos:=0;
  1265. CurrDataPos:=0;
  1266. end;
  1267. procedure TExeOutput.CalcPos_Header;
  1268. begin
  1269. end;
  1270. procedure TExeOutput.CalcPos_Symbols;
  1271. begin
  1272. end;
  1273. procedure TExeOutput.ResolveSymbols;
  1274. var
  1275. objdata : TObjData;
  1276. exesym : TExeSymbol;
  1277. objsym,
  1278. commonsym : TObjSymbol;
  1279. firstcommon : boolean;
  1280. i,j : longint;
  1281. begin
  1282. {
  1283. The symbol calculation is done in 3 steps:
  1284. 1. register globals
  1285. register externals
  1286. register commons
  1287. 2. try to find commons, if not found then
  1288. add to the globals (so externals can be resolved)
  1289. 3. try to find externals
  1290. }
  1291. { Step 1, Register symbols }
  1292. for i:=0 to ObjDataList.Count-1 do
  1293. begin
  1294. objdata:=TObjData(ObjDataList[i]);
  1295. for j:=0 to objdata.ObjSymbolList.Count-1 do
  1296. begin
  1297. objsym:=TObjSymbol(objdata.ObjSymbolList[j]);
  1298. { Skip local symbols }
  1299. if objsym.bind=AB_LOCAL then
  1300. continue;
  1301. exesym:=texesymbol(FExeSymbolDict.search(objsym.name));
  1302. if not assigned(exesym) then
  1303. begin
  1304. exesym:=texesymbol.createname(objsym.name);
  1305. FExeSymbolDict.insert(exesym);
  1306. FExeSymbolList.Add(exesym);
  1307. end;
  1308. { Defining the symbol? }
  1309. if objsym.bind=AB_GLOBAL then
  1310. begin
  1311. if not assigned(exesym.ObjSymbol) then
  1312. exesym.ObjSymbol:=objsym
  1313. else
  1314. Comment(V_Error,'Multiple defined symbol '+objsym.name);
  1315. end;
  1316. objsym.exesymbol:=exesym;
  1317. case objsym.bind of
  1318. AB_EXTERNAL :
  1319. ExternalObjSymbols.add(objsym);
  1320. AB_COMMON :
  1321. CommonObjSymbols.add(objsym);
  1322. end;
  1323. end;
  1324. end;
  1325. { Step 2, Match common symbols or add to the globals }
  1326. firstcommon:=true;
  1327. for i:=0 to CommonObjSymbols.count-1 do
  1328. begin
  1329. objsym:=TObjSymbol(CommonObjSymbols[i]);
  1330. if assigned(objsym.exesymbol.objsymbol) then
  1331. begin
  1332. if objsym.exesymbol.ObjSymbol.size<>objsym.size then
  1333. internalerror(200206301)
  1334. else
  1335. begin
  1336. { allocate new objsymbol in .bss of *COMMON* and assign
  1337. it to the exesymbol }
  1338. if firstcommon then
  1339. begin
  1340. if assigned(exemap) then
  1341. exemap.AddCommonSymbolsHeader;
  1342. firstcommon:=false;
  1343. end;
  1344. commonobjdata.setsection(commonObjSection);
  1345. commonsym:=commonobjdata.symboldefine(objsym.name,AB_GLOBAL,AT_FUNCTION);
  1346. commonsym.size:=objsym.size;
  1347. commonobjdata.alloc(objsym.size);
  1348. if assigned(exemap) then
  1349. exemap.AddCommonSymbol(commonsym);
  1350. { Assign to the exesymbol }
  1351. objsym.exesymbol.objsymbol:=commonsym
  1352. end;
  1353. end;
  1354. end;
  1355. if not firstcommon then
  1356. commonobjdata.afterwrite;
  1357. { Generate a list of Unresolved External symbols }
  1358. for i:=0 to ExeSymbolList.count-1 do
  1359. begin
  1360. exesym:=TExeSymbol(ExeSymbolList[i]);
  1361. if exesym.objsymbol=nil then
  1362. UnresolvedExeSymbols.Add(exesym);
  1363. end;
  1364. Comment(V_Debug,'Number of unresolved externals in objects '+tostr(UnresolvedExeSymbols.Count));
  1365. { Find entry symbol and print in map }
  1366. exesym:=texesymbol(ExeSymbolDict.search(EntryName));
  1367. if assigned(exesym) then
  1368. begin
  1369. EntrySym:=exesym.ObjSymbol;
  1370. if assigned(exemap) then
  1371. begin
  1372. exemap.Add('');
  1373. exemap.Add('Entry symbol '+EntryName);
  1374. end;
  1375. end
  1376. else
  1377. Comment(V_Error,'Entrypoint '+EntryName+' not defined');
  1378. end;
  1379. procedure TExeOutput.ResolveExternals(const libname:string);
  1380. begin
  1381. end;
  1382. procedure TExeOutput.PrintMemoryMap;
  1383. var
  1384. exesec : TExeSection;
  1385. objsec : TObjSection;
  1386. objsym : TObjSymbol;
  1387. i,j,k : longint;
  1388. begin
  1389. if not assigned(exemap) then
  1390. exit;
  1391. exemap.AddMemoryMapHeader(ImageBase);
  1392. for i:=0 to ExeSections.Count-1 do
  1393. begin
  1394. exesec:=TExeSection(ExeSections[i]);
  1395. exemap.AddMemoryMapExeSection(exesec);
  1396. for j:=0 to exesec.ObjSectionList.count-1 do
  1397. begin
  1398. objsec:=TObjSection(exesec.ObjSectionList[j]);
  1399. exemap.AddMemoryMapObjectSection(objsec);
  1400. for k:=0 to objsec.ObjSymbolDefines.Count-1 do
  1401. begin
  1402. objsym:=TObjSymbol(objsec.ObjSymbolDefines[k]);
  1403. exemap.AddMemoryMapSymbol(objsym);
  1404. end;
  1405. end;
  1406. end;
  1407. end;
  1408. procedure TExeOutput.FixUpSymbols;
  1409. var
  1410. i : longint;
  1411. sym : TObjSymbol;
  1412. begin
  1413. { Update ImageBase to ObjData so it can access from ObjSymbols }
  1414. for i:=0 to ObjDataList.Count-1 do
  1415. TObjData(ObjDataList[i]).imagebase:=imagebase;
  1416. {
  1417. Fixing up symbols is done in the following steps:
  1418. 1. Update common references
  1419. 2. Update external references
  1420. }
  1421. { Step 1, Update commons }
  1422. for i:=0 to CommonObjSymbols.count-1 do
  1423. begin
  1424. sym:=TObjSymbol(CommonObjSymbols[i]);
  1425. if sym.bind=AB_COMMON then
  1426. begin
  1427. { update this symbol }
  1428. sym.bind:=sym.exesymbol.ObjSymbol.bind;
  1429. sym.offset:=sym.exesymbol.ObjSymbol.offset;
  1430. sym.size:=sym.exesymbol.ObjSymbol.size;
  1431. sym.typ:=sym.exesymbol.ObjSymbol.typ;
  1432. sym.ObjSection:=sym.exesymbol.ObjSymbol.ObjSection;
  1433. end;
  1434. end;
  1435. { Step 2, Update externals }
  1436. for i:=0 to ExternalObjSymbols.count-1 do
  1437. begin
  1438. sym:=TObjSymbol(ExternalObjSymbols[i]);
  1439. if sym.bind=AB_EXTERNAL then
  1440. begin
  1441. if assigned(sym.exesymbol.ObjSymbol) then
  1442. begin
  1443. { update this symbol }
  1444. sym.bind:=sym.exesymbol.ObjSymbol.bind;
  1445. sym.offset:=sym.exesymbol.ObjSymbol.offset;
  1446. sym.size:=sym.exesymbol.ObjSymbol.size;
  1447. sym.typ:=sym.exesymbol.ObjSymbol.typ;
  1448. sym.ObjSection:=sym.exesymbol.ObjSymbol.ObjSection;
  1449. end
  1450. else
  1451. Comment(V_Error,'Undefined symbol: '+sym.name);
  1452. end;
  1453. end;
  1454. end;
  1455. procedure TExeOutput.RemoveEmptySections;
  1456. var
  1457. i : longint;
  1458. exesec : TExeSection;
  1459. begin
  1460. for i:=0 to ExeSections.Count-1 do
  1461. begin
  1462. exesec:=TExeSection(ExeSections[i]);
  1463. if not(oso_keep in exesec.SecOptions) and
  1464. (
  1465. (exesec.ObjSectionlist.count=0) or
  1466. (
  1467. (cs_link_strip in aktglobalswitches) and
  1468. (oso_debug in exesec.SecOptions)
  1469. )
  1470. ) then
  1471. begin
  1472. Comment(V_Debug,'Deleting empty section '+exesec.name);
  1473. FExeSectionDict.Delete(exesec.name);
  1474. FExeSectionList[i]:=nil;
  1475. end;
  1476. end;
  1477. ExeSections.Pack;
  1478. end;
  1479. procedure TExeOutput.RemoveUnreferencedSections;
  1480. var
  1481. ObjSectionWorkList : TFPObjectList;
  1482. procedure AddToObjSectionWorkList(aobjsec:TObjSection);
  1483. begin
  1484. if not aobjsec.Used then
  1485. begin
  1486. aobjsec.Used:=true;
  1487. ObjSectionWorkList.Add(aobjsec);
  1488. end;
  1489. end;
  1490. var
  1491. i,j : longint;
  1492. exesec : TExeSection;
  1493. objdata : TObjData;
  1494. refobjsec,
  1495. objsec : TObjSection;
  1496. objsym : TObjSymbol;
  1497. begin
  1498. ObjSectionWorkList:=TFPObjectList.Create(false);
  1499. if assigned(exemap) then
  1500. exemap.AddHeader('Removing unreferenced sections');
  1501. { Initialize by marking all sections unused and
  1502. adding the sections with oso_keep flags to the ObjSectionWorkList }
  1503. for i:=0 to ObjDataList.Count-1 do
  1504. begin
  1505. objdata:=TObjData(ObjDataList[i]);
  1506. for j:=0 to objdata.ObjSectionList.Count-1 do
  1507. begin
  1508. objsec:=TObjSection(objdata.ObjSectionList[j]);
  1509. objsec.Used:=false;
  1510. {$warning TODO remove debug section always keep}
  1511. if oso_debug in objsec.secoptions then
  1512. objsec.Used:=true;
  1513. if (oso_keep in objsec.secoptions) then
  1514. AddToObjSectionWorkList(objsec);
  1515. end;
  1516. end;
  1517. AddToObjSectionWorkList(entrysym.exesymbol.objsymbol.objsection);
  1518. { Process all sections, add new sections to process based
  1519. on the symbol references }
  1520. while ObjSectionWorkList.Count>0 do
  1521. begin
  1522. objsec:=TObjSection(ObjSectionWorkList.Last);
  1523. if assigned(exemap) then
  1524. exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjSymbolRefs.Count)+' references');
  1525. ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1);
  1526. for i:=0 to objsec.ObjSymbolRefs.count-1 do
  1527. begin
  1528. objsym:=TObjSymbol(objsec.ObjSymbolRefs[i]);
  1529. if objsym.bind=AB_LOCAL then
  1530. begin
  1531. if not assigned(objsym.objsection) then
  1532. internalerror(200603062);
  1533. refobjsec:=objsym.objsection
  1534. end
  1535. else
  1536. begin
  1537. if not(assigned(objsym.exesymbol) and
  1538. assigned(objsym.exesymbol.objsymbol)) then
  1539. internalerror(200603063);
  1540. refobjsec:=objsym.exesymbol.objsymbol.objsection;
  1541. end;
  1542. if assigned(exemap) then
  1543. exemap.Add(' References '+refobjsec.fullname);
  1544. AddToObjSectionWorkList(refobjsec);
  1545. end;
  1546. end;
  1547. { Remove unused objsections from exesections }
  1548. for i:=0 to ExeSections.Count-1 do
  1549. begin
  1550. exesec:=TExeSection(ExeSections[i]);
  1551. for j:=0 to exesec.ObjSectionlist.count-1 do
  1552. begin
  1553. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  1554. if not objsec.used then
  1555. begin
  1556. if assigned(exemap) then
  1557. exemap.Add('Removing '+objsec.FullName);
  1558. exesec.ObjSectionlist[j]:=nil;
  1559. end;
  1560. end;
  1561. exesec.ObjSectionlist.Pack;
  1562. end;
  1563. end;
  1564. procedure TExeOutput.FixUpRelocations;
  1565. var
  1566. i : longint;
  1567. objdata : TObjData;
  1568. begin
  1569. for i:=0 to ObjDataList.Count-1 do
  1570. begin
  1571. objdata:=TObjData(ObjDataList[i]);
  1572. objdata.fixuprelocs;
  1573. end;
  1574. end;
  1575. {****************************************************************************
  1576. TObjInput
  1577. ****************************************************************************}
  1578. constructor TObjInput.create;
  1579. begin
  1580. { init reader }
  1581. FReader:=TObjectreader.create;
  1582. end;
  1583. destructor TObjInput.destroy;
  1584. begin
  1585. FReader.free;
  1586. end;
  1587. function TObjInput.newObjData(const n:string):TObjData;
  1588. begin
  1589. result:=CObjData.create(n);
  1590. end;
  1591. function TObjInput.readobjectfile(const fn:string;data:TObjData):boolean;
  1592. begin
  1593. result:=false;
  1594. { start the reader }
  1595. if FReader.openfile(fn) then
  1596. begin
  1597. result:=readObjData(data);
  1598. FReader.closefile;
  1599. end;
  1600. end;
  1601. end.