ogomf.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. {
  2. Copyright (c) 2015 by Nikolay Nikolov
  3. Contains the binary Relocatable Object Module Format (OMF) reader and writer
  4. This is the object format used on the i8086-msdos platform.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ogomf;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. { common }
  23. cclasses,globtype,
  24. { target }
  25. systems,
  26. { assembler }
  27. cpuinfo,cpubase,aasmbase,assemble,link,
  28. { OMF definitions }
  29. omfbase,
  30. { output }
  31. ogbase,
  32. owbase;
  33. type
  34. { TOmfRelocation }
  35. TOmfRelocation = class(TObjRelocation)
  36. private
  37. FOmfFixup: TOmfSubRecord_FIXUP;
  38. function GetGroupIndex(const groupname: string): Integer;
  39. public
  40. destructor Destroy; override;
  41. procedure BuildOmfFixup;
  42. property OmfFixup: TOmfSubRecord_FIXUP read FOmfFixup;
  43. end;
  44. { TOmfObjSection }
  45. TOmfObjSection = class(TObjSection)
  46. private
  47. FClassName: string;
  48. FOverlayName: string;
  49. FOmfAlignment: TOmfSegmentAlignment;
  50. FCombination: TOmfSegmentCombination;
  51. FUse: TOmfSegmentUse;
  52. FPrimaryGroup: string;
  53. public
  54. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  55. property ClassName: string read FClassName;
  56. property OverlayName: string read FOverlayName;
  57. property OmfAlignment: TOmfSegmentAlignment read FOmfAlignment;
  58. property Combination: TOmfSegmentCombination read FCombination;
  59. property Use: TOmfSegmentUse read FUse;
  60. property PrimaryGroup: string read FPrimaryGroup;
  61. end;
  62. { TOmfObjData }
  63. TOmfObjData = class(TObjData)
  64. private
  65. class function CodeSectionName(const aname:string): string;
  66. public
  67. constructor create(const n:string);override;
  68. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  69. procedure writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  70. end;
  71. { TOmfObjOutput }
  72. TOmfObjOutput = class(tObjOutput)
  73. private
  74. FLNames: TOmfOrderedNameCollection;
  75. FSegments: TFPHashObjectList;
  76. FGroups: TFPHashObjectList;
  77. procedure AddSegment(const name,segclass,ovlname: string;
  78. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  79. Use: TOmfSegmentUse; Size: aword);
  80. procedure AddGroup(const groupname: string; seglist: array of const);
  81. procedure AddGroup(const groupname: string; seglist: TSegmentList);
  82. procedure WriteSections(Data:TObjData);
  83. procedure WriteSectionContentAndFixups(sec: TObjSection);
  84. procedure section_count_sections(p:TObject;arg:pointer);
  85. procedure WritePUBDEFs(Data: TObjData);
  86. property LNames: TOmfOrderedNameCollection read FLNames;
  87. property Segments: TFPHashObjectList read FSegments;
  88. property Groups: TFPHashObjectList read FGroups;
  89. protected
  90. function writeData(Data:TObjData):boolean;override;
  91. public
  92. constructor create(AWriter:TObjectWriter);override;
  93. destructor Destroy;override;
  94. end;
  95. TOmfAssembler = class(tinternalassembler)
  96. constructor create(smart:boolean);override;
  97. end;
  98. implementation
  99. uses
  100. SysUtils,
  101. cutils,verbose,globals,
  102. fmodule,aasmtai,aasmdata,
  103. ogmap,
  104. version
  105. ;
  106. {****************************************************************************
  107. TOmfRelocation
  108. ****************************************************************************}
  109. function TOmfRelocation.GetGroupIndex(const groupname: string): Integer;
  110. begin
  111. if groupname='dgroup' then
  112. Result:=1
  113. else
  114. internalerror(2014040703);
  115. end;
  116. destructor TOmfRelocation.Destroy;
  117. begin
  118. FOmfFixup.Free;
  119. inherited Destroy;
  120. end;
  121. procedure TOmfRelocation.BuildOmfFixup;
  122. begin
  123. FreeAndNil(FOmfFixup);
  124. FOmfFixup:=TOmfSubRecord_FIXUP.Create;
  125. if ObjSection<>nil then
  126. begin
  127. FOmfFixup.LocationOffset:=DataOffset;
  128. FOmfFixup.LocationType:=fltOffset;
  129. FOmfFixup.FrameDeterminedByThread:=False;
  130. FOmfFixup.TargetDeterminedByThread:=False;
  131. FOmfFixup.Mode:=fmSegmentRelative;
  132. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  133. FOmfFixup.TargetDatum:=ObjSection.Index;
  134. if TOmfObjSection(ObjSection).PrimaryGroup<>'' then
  135. begin
  136. FOmfFixup.FrameMethod:=ffmGroupIndex;
  137. FOmfFixup.FrameDatum:=GetGroupIndex(TOmfObjSection(ObjSection).PrimaryGroup);
  138. end
  139. else
  140. FOmfFixup.FrameMethod:=ffmTarget;
  141. end
  142. else if symbol<>nil then
  143. begin
  144. FOmfFixup.LocationOffset:=DataOffset;
  145. FOmfFixup.LocationType:=fltOffset;
  146. FOmfFixup.FrameDeterminedByThread:=False;
  147. FOmfFixup.TargetDeterminedByThread:=False;
  148. FOmfFixup.Mode:=fmSegmentRelative;
  149. FOmfFixup.TargetMethod:=ftmExternalIndexNoDisp;
  150. FOmfFixup.TargetDatum:=0; {TODO}
  151. FOmfFixup.FrameMethod:=ffmTarget;
  152. end
  153. else
  154. internalerror(2015040702);
  155. end;
  156. {****************************************************************************
  157. TOmfObjSection
  158. ****************************************************************************}
  159. constructor TOmfObjSection.create(AList: TFPHashObjectList;
  160. const Aname: string; Aalign: shortint; Aoptions: TObjSectionOptions);
  161. var
  162. dgroup: Boolean;
  163. begin
  164. inherited create(AList, Aname, Aalign, Aoptions);
  165. FCombination:=scPublic;
  166. FUse:=suUse16;
  167. FOmfAlignment:=saRelocatableByteAligned;
  168. if oso_executable in Aoptions then
  169. begin
  170. FClassName:='code';
  171. dgroup:=(current_settings.x86memorymodel=mm_tiny);
  172. end
  173. else if Aname='stack' then
  174. begin
  175. FClassName:='stack';
  176. FCombination:=scStack;
  177. FOmfAlignment:=saRelocatableParaAligned;
  178. dgroup:=current_settings.x86memorymodel in (x86_near_data_models-[mm_tiny]);
  179. end
  180. else if Aname='heap' then
  181. begin
  182. FClassName:='heap';
  183. FOmfAlignment:=saRelocatableParaAligned;
  184. dgroup:=current_settings.x86memorymodel in x86_near_data_models;
  185. end
  186. else if Aname='bss' then
  187. begin
  188. FClassName:='bss';
  189. dgroup:=true;
  190. end
  191. else if Aname='data' then
  192. begin
  193. FClassName:='data';
  194. FOmfAlignment:=saRelocatableWordAligned;
  195. dgroup:=true;
  196. end
  197. else
  198. begin
  199. FClassName:='data';
  200. dgroup:=true;
  201. end;
  202. if dgroup then
  203. FPrimaryGroup:='dgroup'
  204. else
  205. FPrimaryGroup:='';
  206. end;
  207. {****************************************************************************
  208. TOmfObjData
  209. ****************************************************************************}
  210. class function TOmfObjData.CodeSectionName(const aname: string): string;
  211. begin
  212. {$ifdef i8086}
  213. if current_settings.x86memorymodel in x86_far_code_models then
  214. begin
  215. if cs_huge_code in current_settings.moduleswitches then
  216. result:=aname + '_TEXT'
  217. else
  218. result:=current_module.modulename^ + '_TEXT';
  219. end
  220. else
  221. {$endif}
  222. result:='text';
  223. end;
  224. constructor TOmfObjData.create(const n: string);
  225. begin
  226. inherited create(n);
  227. CObjSection:=TOmfObjSection;
  228. end;
  229. function TOmfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  230. const
  231. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  232. 'text',
  233. 'data',
  234. 'data',
  235. 'rodata',
  236. 'bss',
  237. 'tbss',
  238. 'pdata',
  239. 'text','data','data','data','data',
  240. 'stab',
  241. 'stabstr',
  242. 'idata2','idata4','idata5','idata6','idata7','edata',
  243. 'eh_frame',
  244. 'debug_frame','debug_info','debug_line','debug_abbrev',
  245. 'fpc',
  246. '',
  247. 'init',
  248. 'fini',
  249. 'objc_class',
  250. 'objc_meta_class',
  251. 'objc_cat_cls_meth',
  252. 'objc_cat_inst_meth',
  253. 'objc_protocol',
  254. 'objc_string_object',
  255. 'objc_cls_meth',
  256. 'objc_inst_meth',
  257. 'objc_cls_refs',
  258. 'objc_message_refs',
  259. 'objc_symbols',
  260. 'objc_category',
  261. 'objc_class_vars',
  262. 'objc_instance_vars',
  263. 'objc_module_info',
  264. 'objc_class_names',
  265. 'objc_meth_var_types',
  266. 'objc_meth_var_names',
  267. 'objc_selector_strs',
  268. 'objc_protocol_ext',
  269. 'objc_class_ext',
  270. 'objc_property',
  271. 'objc_image_info',
  272. 'objc_cstring_object',
  273. 'objc_sel_fixup',
  274. '__DATA,__objc_data',
  275. '__DATA,__objc_const',
  276. 'objc_superrefs',
  277. '__DATA, __datacoal_nt,coalesced',
  278. 'objc_classlist',
  279. 'objc_nlclasslist',
  280. 'objc_catlist',
  281. 'obcj_nlcatlist',
  282. 'objc_protolist',
  283. 'stack',
  284. 'heap'
  285. );
  286. begin
  287. if (atype=sec_user) then
  288. Result:=aname
  289. else if secnames[atype]='text' then
  290. Result:=CodeSectionName(aname)
  291. else
  292. Result:=secnames[atype];
  293. end;
  294. procedure TOmfObjData.writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  295. var
  296. objreloc: TOmfRelocation;
  297. symaddr: AWord;
  298. begin
  299. { Write('writeReloc(', data, ',', len, ',');
  300. if p<>nil then
  301. write(p.Name)
  302. else
  303. write('nil');
  304. Writeln(',',Reloctype,')');}
  305. if CurrObjSec=nil then
  306. internalerror(200403072);
  307. objreloc:=nil;
  308. if assigned(p) then
  309. begin
  310. { real address of the symbol }
  311. symaddr:=p.address;
  312. if p.bind=AB_EXTERNAL then
  313. begin
  314. objreloc:=TOmfRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  315. CurrObjSec.ObjRelocations.Add(objreloc);
  316. end
  317. else
  318. begin
  319. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  320. CurrObjSec.ObjRelocations.Add(objreloc);
  321. inc(data,symaddr);
  322. end;
  323. end;
  324. CurrObjSec.write(data,len);
  325. end;
  326. {****************************************************************************
  327. TOmfObjOutput
  328. ****************************************************************************}
  329. procedure TOmfObjOutput.AddSegment(const name, segclass, ovlname: string;
  330. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  331. Use: TOmfSegmentUse; Size: aword);
  332. var
  333. s: TOmfRecord_SEGDEF;
  334. begin
  335. s:=TOmfRecord_SEGDEF.Create;
  336. Segments.Add(name,s);
  337. s.SegmentNameIndex:=LNames.Add(name);
  338. s.ClassNameIndex:=LNames.Add(segclass);
  339. s.OverlayNameIndex:=LNames.Add(ovlname);
  340. s.Alignment:=Alignment;
  341. s.Combination:=Combination;
  342. s.Use:=Use;
  343. s.SegmentLength:=Size;
  344. end;
  345. procedure TOmfObjOutput.AddGroup(const groupname: string; seglist: array of const);
  346. var
  347. g: TOmfRecord_GRPDEF;
  348. I: Integer;
  349. SegListStr: TSegmentList;
  350. begin
  351. g:=TOmfRecord_GRPDEF.Create;
  352. Groups.Add(groupname,g);
  353. g.GroupNameIndex:=LNames.Add(groupname);
  354. SetLength(SegListStr,Length(seglist));
  355. for I:=0 to High(seglist) do
  356. begin
  357. case seglist[I].VType of
  358. vtString:
  359. SegListStr[I]:=Segments.FindIndexOf(seglist[I].VString^);
  360. vtAnsiString:
  361. SegListStr[I]:=Segments.FindIndexOf(AnsiString(seglist[I].VAnsiString));
  362. vtWideString:
  363. SegListStr[I]:=Segments.FindIndexOf(AnsiString(WideString(seglist[I].VWideString)));
  364. vtUnicodeString:
  365. SegListStr[I]:=Segments.FindIndexOf(AnsiString(UnicodeString(seglist[I].VUnicodeString)));
  366. else
  367. internalerror(2015040402);
  368. end;
  369. end;
  370. g.SegmentList:=SegListStr;
  371. end;
  372. procedure TOmfObjOutput.AddGroup(const groupname: string; seglist: TSegmentList);
  373. var
  374. g: TOmfRecord_GRPDEF;
  375. begin
  376. g:=TOmfRecord_GRPDEF.Create;
  377. Groups.Add(groupname,g);
  378. g.GroupNameIndex:=LNames.Add(groupname);
  379. g.SegmentList:=Copy(seglist);
  380. end;
  381. procedure TOmfObjOutput.WriteSections(Data: TObjData);
  382. var
  383. i:longint;
  384. sec:TObjSection;
  385. begin
  386. for i:=0 to Data.ObjSectionList.Count-1 do
  387. begin
  388. sec:=TObjSection(Data.ObjSectionList[i]);
  389. WriteSectionContentAndFixups(sec);
  390. end;
  391. end;
  392. procedure TOmfObjOutput.WriteSectionContentAndFixups(sec: TObjSection);
  393. const
  394. MaxChunkSize=$3fa;
  395. var
  396. RawRecord: TOmfRawRecord;
  397. ChunkStart,ChunkLen: DWord;
  398. ChunkFixupStart,ChunkFixupEnd: Integer;
  399. SegIndex: Integer;
  400. NextOfs: Integer;
  401. I: Integer;
  402. begin
  403. if (oso_data in sec.SecOptions) then
  404. begin
  405. if sec.Data=nil then
  406. internalerror(200403073);
  407. SegIndex:=Segments.FindIndexOf(sec.Name);
  408. RawRecord:=TOmfRawRecord.Create;
  409. sec.data.seek(0);
  410. ChunkFixupStart:=0;
  411. ChunkFixupEnd:=-1;
  412. ChunkStart:=0;
  413. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  414. while ChunkLen>0 do
  415. begin
  416. { write LEDATA record }
  417. RawRecord.RecordType:=RT_LEDATA;
  418. NextOfs:=RawRecord.WriteIndexedRef(0,SegIndex);
  419. RawRecord.RawData[NextOfs]:=Byte(ChunkStart);
  420. RawRecord.RawData[NextOfs+1]:=Byte(ChunkStart shr 8);
  421. Inc(NextOfs,2);
  422. sec.data.read(RawRecord.RawData[NextOfs], ChunkLen);
  423. Inc(NextOfs, ChunkLen);
  424. RawRecord.RecordLength:=NextOfs+1;
  425. RawRecord.CalculateChecksumByte;
  426. RawRecord.WriteTo(FWriter);
  427. { write FIXUPP record }
  428. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  429. (TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  430. inc(ChunkFixupEnd);
  431. if ChunkFixupEnd>=ChunkFixupStart then
  432. begin
  433. RawRecord.RecordType:=RT_FIXUPP;
  434. NextOfs:=0;
  435. for I:=ChunkFixupStart to ChunkFixupEnd do
  436. begin
  437. TOmfRelocation(sec.ObjRelocations[I]).BuildOmfFixup;
  438. TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.DataRecordStartOffset:=ChunkStart;
  439. NextOfs:=TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.WriteAt(RawRecord,NextOfs);
  440. end;
  441. RawRecord.RecordLength:=NextOfs+1;
  442. RawRecord.CalculateChecksumByte;
  443. RawRecord.WriteTo(FWriter);
  444. end;
  445. { prepare next chunk }
  446. Inc(ChunkStart, ChunkLen);
  447. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  448. ChunkFixupStart:=ChunkFixupEnd+1;
  449. end;
  450. RawRecord.Free;
  451. end;
  452. end;
  453. procedure TOmfObjOutput.section_count_sections(p: TObject; arg: pointer);
  454. begin
  455. TOmfObjSection(p).index:=pinteger(arg)^;
  456. inc(pinteger(arg)^);
  457. end;
  458. procedure TOmfObjOutput.WritePUBDEFs(Data: TObjData);
  459. var
  460. PubNamesForSection: array of TFPHashObjectList;
  461. i: Integer;
  462. objsym: TObjSymbol;
  463. PublicNameElem: TOmfPublicNameElement;
  464. RawRecord: TOmfRawRecord;
  465. PubDefRec: TOmfRecord_PUBDEF;
  466. PrimaryGroupName: string;
  467. begin
  468. RawRecord:=TOmfRawRecord.Create;
  469. SetLength(PubNamesForSection,Data.ObjSectionList.Count);
  470. for i:=0 to Data.ObjSectionList.Count-1 do
  471. PubNamesForSection[i]:=TFPHashObjectList.Create;
  472. for i:=0 to Data.ObjSymbolList.Count-1 do
  473. begin
  474. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  475. if objsym.bind=AB_GLOBAL then
  476. begin
  477. PublicNameElem:=TOmfPublicNameElement.Create(PubNamesForSection[objsym.objsection.index-1],objsym.Name);
  478. PublicNameElem.PublicOffset:=objsym.offset;
  479. end;
  480. end;
  481. for i:=0 to Data.ObjSectionList.Count-1 do
  482. if PubNamesForSection[i].Count>0 then
  483. begin
  484. PubDefRec:=TOmfRecord_PUBDEF.Create;
  485. PubDefRec.BaseSegmentIndex:=i+1;
  486. PrimaryGroupName:=TOmfObjSection(Data.ObjSectionList[i]).PrimaryGroup;
  487. if PrimaryGroupName<>'' then
  488. PubDefRec.BaseGroupIndex:=Groups.FindIndexOf(PrimaryGroupName)
  489. else
  490. PubDefRec.BaseGroupIndex:=0;
  491. PubDefRec.PublicNames:=PubNamesForSection[i];
  492. while PubDefRec.NextIndex<PubDefRec.PublicNames.Count do
  493. begin
  494. PubDefRec.EncodeTo(RawRecord);
  495. RawRecord.WriteTo(FWriter);
  496. end;
  497. PubDefRec.Free;
  498. end;
  499. for i:=0 to Data.ObjSectionList.Count-1 do
  500. FreeAndNil(PubNamesForSection[i]);
  501. RawRecord.Free;
  502. end;
  503. function TOmfObjOutput.writeData(Data:TObjData):boolean;
  504. var
  505. RawRecord: TOmfRawRecord;
  506. Header: TOmfRecord_THEADR;
  507. Translator_COMENT: TOmfRecord_COMENT;
  508. LinkPassSeparator_COMENT: TOmfRecord_COMENT;
  509. LNamesRec: TOmfRecord_LNAMES;
  510. ModEnd: TOmfRecord_MODEND;
  511. I: Integer;
  512. SegDef: TOmfRecord_SEGDEF;
  513. GrpDef: TOmfRecord_GRPDEF;
  514. DGroupSegments: TSegmentList;
  515. nsections: Integer;
  516. begin
  517. { calc amount of sections we have and set their index, starting with 1 }
  518. nsections:=1;
  519. data.ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  520. { maximum amount of sections supported in the omf format is $7fff }
  521. if (nsections-1)>$7fff then
  522. internalerror(2015040701);
  523. { write header record }
  524. RawRecord:=TOmfRawRecord.Create;
  525. Header:=TOmfRecord_THEADR.Create;
  526. Header.ModuleName:=Data.Name;
  527. Header.EncodeTo(RawRecord);
  528. RawRecord.WriteTo(FWriter);
  529. Header.Free;
  530. { write translator COMENT header }
  531. Translator_COMENT:=TOmfRecord_COMENT.Create;
  532. Translator_COMENT.CommentClass:=CC_Translator;
  533. Translator_COMENT.CommentString:='FPC '+full_version_string+
  534. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname;
  535. Translator_COMENT.EncodeTo(RawRecord);
  536. RawRecord.WriteTo(FWriter);
  537. Translator_COMENT.Free;
  538. LNames.Clear;
  539. LNames.Add(''); { insert an empty string, which has index 1 }
  540. FSegments.Clear;
  541. FSegments.Add('',nil);
  542. FGroups.Clear;
  543. FGroups.Add('',nil);
  544. for i:=0 to Data.ObjSectionList.Count-1 do
  545. with TOmfObjSection(Data.ObjSectionList[I]) do
  546. AddSegment(Name,ClassName,OverlayName,OmfAlignment,Combination,Use,Size);
  547. { create group "dgroup" }
  548. SetLength(DGroupSegments,0);
  549. for i:=0 to Data.ObjSectionList.Count-1 do
  550. with TOmfObjSection(Data.ObjSectionList[I]) do
  551. if PrimaryGroup='dgroup' then
  552. begin
  553. SetLength(DGroupSegments,Length(DGroupSegments)+1);
  554. DGroupSegments[High(DGroupSegments)]:=index;
  555. end;
  556. AddGroup('dgroup',DGroupSegments);
  557. { write LNAMES record(s) }
  558. LNamesRec:=TOmfRecord_LNAMES.Create;
  559. LNamesRec.Names:=LNames;
  560. while LNamesRec.NextIndex<=LNames.Count do
  561. begin
  562. LNamesRec.EncodeTo(RawRecord);
  563. RawRecord.WriteTo(FWriter);
  564. end;
  565. LNamesRec.Free;
  566. { write SEGDEF record(s) }
  567. for I:=1 to Segments.Count-1 do
  568. begin
  569. SegDef:=TOmfRecord_SEGDEF(Segments[I]);
  570. SegDef.EncodeTo(RawRecord);
  571. RawRecord.WriteTo(FWriter);
  572. end;
  573. { write GRPDEF record(s) }
  574. for I:=1 to Groups.Count-1 do
  575. begin
  576. GrpDef:=TOmfRecord_GRPDEF(Groups[I]);
  577. GrpDef.EncodeTo(RawRecord);
  578. RawRecord.WriteTo(FWriter);
  579. end;
  580. { write PUBDEF record(s) }
  581. WritePUBDEFs(Data);
  582. { write link pass separator }
  583. LinkPassSeparator_COMENT:=TOmfRecord_COMENT.Create;
  584. LinkPassSeparator_COMENT.CommentClass:=CC_LinkPassSeparator;
  585. LinkPassSeparator_COMENT.CommentString:=#1;
  586. LinkPassSeparator_COMENT.NoList:=True;
  587. LinkPassSeparator_COMENT.EncodeTo(RawRecord);
  588. RawRecord.WriteTo(FWriter);
  589. LinkPassSeparator_COMENT.Free;
  590. { write section content, interleaved with fixups }
  591. WriteSections(Data);
  592. { write MODEND record }
  593. ModEnd:=TOmfRecord_MODEND.Create;
  594. ModEnd.EncodeTo(RawRecord);
  595. RawRecord.WriteTo(FWriter);
  596. ModEnd.Free;
  597. RawRecord.Free;
  598. result:=true;
  599. end;
  600. constructor TOmfObjOutput.create(AWriter:TObjectWriter);
  601. begin
  602. inherited create(AWriter);
  603. cobjdata:=TOmfObjData;
  604. FLNames:=TOmfOrderedNameCollection.Create;
  605. FSegments:=TFPHashObjectList.Create;
  606. FSegments.Add('',nil);
  607. FGroups:=TFPHashObjectList.Create;
  608. FGroups.Add('',nil);
  609. end;
  610. destructor TOmfObjOutput.Destroy;
  611. begin
  612. FGroups.Free;
  613. FSegments.Free;
  614. FLNames.Free;
  615. inherited Destroy;
  616. end;
  617. {****************************************************************************
  618. TOmfAssembler
  619. ****************************************************************************}
  620. constructor TOmfAssembler.Create(smart:boolean);
  621. begin
  622. inherited Create(smart);
  623. CObjOutput:=TOmfObjOutput;
  624. end;
  625. {*****************************************************************************
  626. Initialize
  627. *****************************************************************************}
  628. {$ifdef i8086}
  629. const
  630. as_i8086_omf_info : tasminfo =
  631. (
  632. id : as_i8086_omf;
  633. idtxt : 'OMF';
  634. asmbin : '';
  635. asmcmd : '';
  636. supported_targets : [system_i8086_msdos];
  637. flags : [af_outputbinary,af_needar,af_no_debug];
  638. labelprefix : '..@';
  639. comment : '; ';
  640. dollarsign: '$';
  641. );
  642. {$endif i8086}
  643. initialization
  644. {$ifdef i8086}
  645. RegisterAssembler(as_i8086_omf_info,TOmfAssembler);
  646. {$endif i8086}
  647. end.