ogbase.pas 58 KB

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