ogbase.pas 54 KB

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