ogbase.pas 54 KB

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