ogomf.pas 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  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. constructor CreateSection(ADataOffset:aword;aobjsec:TObjSection;Atyp:TObjRelocationType);
  41. destructor Destroy; override;
  42. procedure BuildOmfFixup;
  43. property OmfFixup: TOmfSubRecord_FIXUP read FOmfFixup;
  44. end;
  45. { TOmfObjSection }
  46. TOmfObjSection = class(TObjSection)
  47. private
  48. FClassName: string;
  49. FOverlayName: string;
  50. FCombination: TOmfSegmentCombination;
  51. FUse: TOmfSegmentUse;
  52. FPrimaryGroup: string;
  53. function GetOmfAlignment: TOmfSegmentAlignment;
  54. public
  55. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  56. property ClassName: string read FClassName;
  57. property OverlayName: string read FOverlayName;
  58. property OmfAlignment: TOmfSegmentAlignment read GetOmfAlignment;
  59. property Combination: TOmfSegmentCombination read FCombination;
  60. property Use: TOmfSegmentUse read FUse;
  61. property PrimaryGroup: string read FPrimaryGroup;
  62. end;
  63. { TOmfObjData }
  64. TOmfObjData = class(TObjData)
  65. private
  66. class function CodeSectionName(const aname:string): string;
  67. public
  68. constructor create(const n:string);override;
  69. function sectiontype2align(atype:TAsmSectiontype):shortint;override;
  70. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  71. procedure writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  72. end;
  73. { TOmfObjOutput }
  74. TOmfObjOutput = class(tObjOutput)
  75. private
  76. FLNames: TOmfOrderedNameCollection;
  77. FSegments: TFPHashObjectList;
  78. FGroups: TFPHashObjectList;
  79. procedure AddSegment(const name,segclass,ovlname: string;
  80. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  81. Use: TOmfSegmentUse; Size: aword);
  82. procedure AddGroup(const groupname: string; seglist: array of const);
  83. procedure AddGroup(const groupname: string; seglist: TSegmentList);
  84. procedure WriteSections(Data:TObjData);
  85. procedure WriteSectionContentAndFixups(sec: TObjSection);
  86. procedure section_count_sections(p:TObject;arg:pointer);
  87. procedure WritePUBDEFs(Data: TObjData);
  88. procedure WriteEXTDEFs(Data: TObjData);
  89. property LNames: TOmfOrderedNameCollection read FLNames;
  90. property Segments: TFPHashObjectList read FSegments;
  91. property Groups: TFPHashObjectList read FGroups;
  92. protected
  93. function writeData(Data:TObjData):boolean;override;
  94. public
  95. constructor create(AWriter:TObjectWriter);override;
  96. destructor Destroy;override;
  97. end;
  98. { TOmfObjInput }
  99. TOmfObjInput = class(TObjInput)
  100. private
  101. FLNames: TOmfOrderedNameCollection;
  102. FExtDefs: TFPHashObjectList;
  103. FRawRecord: TOmfRawRecord;
  104. function ReadLNames(RawRec: TOmfRawRecord): Boolean;
  105. function ReadSegDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  106. function ReadGrpDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  107. function ReadExtDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  108. function ReadLEDataAndFixups(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  109. property LNames: TOmfOrderedNameCollection read FLNames;
  110. property ExtDefs: TFPHashObjectList read FExtDefs;
  111. public
  112. constructor create;override;
  113. destructor destroy;override;
  114. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  115. function ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;override;
  116. end;
  117. { TMZExeOutput }
  118. TMZExeOutput = class(TExeOutput)
  119. constructor create;override;
  120. end;
  121. TOmfAssembler = class(tinternalassembler)
  122. constructor create(smart:boolean);override;
  123. end;
  124. implementation
  125. uses
  126. SysUtils,
  127. cutils,verbose,globals,
  128. fmodule,aasmtai,aasmdata,
  129. ogmap,owomflib,
  130. version
  131. ;
  132. {****************************************************************************
  133. TOmfRelocation
  134. ****************************************************************************}
  135. function TOmfRelocation.GetGroupIndex(const groupname: string): Integer;
  136. begin
  137. if groupname='dgroup' then
  138. Result:=1
  139. else
  140. internalerror(2014040703);
  141. end;
  142. constructor TOmfRelocation.CreateSection(ADataOffset: aword; aobjsec: TObjSection; Atyp: TObjRelocationType);
  143. begin
  144. if not (Atyp in [RELOC_DGROUP,RELOC_DGROUPREL]) and not assigned(aobjsec) then
  145. internalerror(200603036);
  146. DataOffset:=ADataOffset;
  147. Symbol:=nil;
  148. OrgSize:=0;
  149. ObjSection:=aobjsec;
  150. ftype:=ord(Atyp);
  151. end;
  152. destructor TOmfRelocation.Destroy;
  153. begin
  154. FOmfFixup.Free;
  155. inherited Destroy;
  156. end;
  157. procedure TOmfRelocation.BuildOmfFixup;
  158. begin
  159. FreeAndNil(FOmfFixup);
  160. FOmfFixup:=TOmfSubRecord_FIXUP.Create;
  161. if ObjSection<>nil then
  162. begin
  163. FOmfFixup.LocationOffset:=DataOffset;
  164. if typ in [RELOC_ABSOLUTE,RELOC_RELATIVE] then
  165. FOmfFixup.LocationType:=fltOffset
  166. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  167. FOmfFixup.LocationType:=fltBase
  168. else
  169. internalerror(2015041501);
  170. FOmfFixup.FrameDeterminedByThread:=False;
  171. FOmfFixup.TargetDeterminedByThread:=False;
  172. if typ in [RELOC_ABSOLUTE,RELOC_SEG] then
  173. FOmfFixup.Mode:=fmSegmentRelative
  174. else if typ in [RELOC_RELATIVE,RELOC_SEGREL] then
  175. FOmfFixup.Mode:=fmSelfRelative
  176. else
  177. internalerror(2015041401);
  178. if typ in [RELOC_ABSOLUTE,RELOC_RELATIVE] then
  179. begin
  180. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  181. FOmfFixup.TargetDatum:=ObjSection.Index;
  182. if TOmfObjSection(ObjSection).PrimaryGroup<>'' then
  183. begin
  184. FOmfFixup.FrameMethod:=ffmGroupIndex;
  185. FOmfFixup.FrameDatum:=GetGroupIndex(TOmfObjSection(ObjSection).PrimaryGroup);
  186. end
  187. else
  188. FOmfFixup.FrameMethod:=ffmTarget;
  189. end
  190. else
  191. begin
  192. FOmfFixup.FrameMethod:=ffmTarget;
  193. if TOmfObjSection(ObjSection).PrimaryGroup<>'' then
  194. begin
  195. FOmfFixup.TargetMethod:=ftmGroupIndexNoDisp;
  196. FOmfFixup.TargetDatum:=GetGroupIndex(TOmfObjSection(ObjSection).PrimaryGroup);
  197. end
  198. else
  199. begin
  200. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  201. FOmfFixup.TargetDatum:=ObjSection.Index;
  202. end;
  203. end;
  204. end
  205. else if symbol<>nil then
  206. begin
  207. FOmfFixup.LocationOffset:=DataOffset;
  208. if typ in [RELOC_ABSOLUTE,RELOC_RELATIVE] then
  209. FOmfFixup.LocationType:=fltOffset
  210. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  211. FOmfFixup.LocationType:=fltBase
  212. else
  213. internalerror(2015041501);
  214. FOmfFixup.FrameDeterminedByThread:=False;
  215. FOmfFixup.TargetDeterminedByThread:=False;
  216. if typ in [RELOC_ABSOLUTE,RELOC_SEG] then
  217. FOmfFixup.Mode:=fmSegmentRelative
  218. else if typ in [RELOC_RELATIVE,RELOC_SEGREL] then
  219. FOmfFixup.Mode:=fmSelfRelative
  220. else
  221. internalerror(2015041401);
  222. FOmfFixup.TargetMethod:=ftmExternalIndexNoDisp;
  223. FOmfFixup.TargetDatum:=symbol.symidx;
  224. FOmfFixup.FrameMethod:=ffmTarget;
  225. end
  226. else if typ in [RELOC_DGROUP,RELOC_DGROUPREL] then
  227. begin
  228. FOmfFixup.LocationOffset:=DataOffset;
  229. FOmfFixup.LocationType:=fltBase;
  230. FOmfFixup.FrameDeterminedByThread:=False;
  231. FOmfFixup.TargetDeterminedByThread:=False;
  232. if typ=RELOC_DGROUP then
  233. FOmfFixup.Mode:=fmSegmentRelative
  234. else if typ=RELOC_DGROUPREL then
  235. FOmfFixup.Mode:=fmSelfRelative
  236. else
  237. internalerror(2015041401);
  238. FOmfFixup.FrameMethod:=ffmTarget;
  239. FOmfFixup.TargetMethod:=ftmGroupIndexNoDisp;
  240. FOmfFixup.TargetDatum:=GetGroupIndex('dgroup');
  241. end
  242. else
  243. internalerror(2015040702);
  244. end;
  245. {****************************************************************************
  246. TOmfObjSection
  247. ****************************************************************************}
  248. function TOmfObjSection.GetOmfAlignment: TOmfSegmentAlignment;
  249. begin
  250. case SecAlign of
  251. 1:
  252. result:=saRelocatableByteAligned;
  253. 2:
  254. result:=saRelocatableWordAligned;
  255. 4:
  256. result:=saRelocatableDWordAligned;
  257. 16:
  258. result:=saRelocatableParaAligned;
  259. else
  260. internalerror(2015041504);
  261. end;
  262. end;
  263. constructor TOmfObjSection.create(AList: TFPHashObjectList;
  264. const Aname: string; Aalign: shortint; Aoptions: TObjSectionOptions);
  265. var
  266. dgroup: Boolean;
  267. begin
  268. inherited create(AList, Aname, Aalign, Aoptions);
  269. FCombination:=scPublic;
  270. FUse:=suUse16;
  271. if oso_executable in Aoptions then
  272. begin
  273. FClassName:='code';
  274. dgroup:=(current_settings.x86memorymodel=mm_tiny);
  275. end
  276. else if Aname='stack' then
  277. begin
  278. FClassName:='stack';
  279. FCombination:=scStack;
  280. dgroup:=current_settings.x86memorymodel in (x86_near_data_models-[mm_tiny]);
  281. end
  282. else if Aname='heap' then
  283. begin
  284. FClassName:='heap';
  285. dgroup:=current_settings.x86memorymodel in x86_near_data_models;
  286. end
  287. else if Aname='bss' then
  288. begin
  289. FClassName:='bss';
  290. dgroup:=true;
  291. end
  292. else if Aname='data' then
  293. begin
  294. FClassName:='data';
  295. dgroup:=true;
  296. end
  297. else if (Aname='debug_frame') or
  298. (Aname='debug_info') or
  299. (Aname='debug_line') or
  300. (Aname='debug_abbrev') then
  301. begin
  302. FClassName:='DWARF';
  303. FUse:=suUse32;
  304. dgroup:=false;
  305. end
  306. else
  307. begin
  308. FClassName:='data';
  309. dgroup:=true;
  310. end;
  311. if dgroup then
  312. FPrimaryGroup:='dgroup'
  313. else
  314. FPrimaryGroup:='';
  315. end;
  316. {****************************************************************************
  317. TOmfObjData
  318. ****************************************************************************}
  319. class function TOmfObjData.CodeSectionName(const aname: string): string;
  320. begin
  321. {$ifdef i8086}
  322. if current_settings.x86memorymodel in x86_far_code_models then
  323. begin
  324. if cs_huge_code in current_settings.moduleswitches then
  325. result:=aname + '_TEXT'
  326. else
  327. result:=current_module.modulename^ + '_TEXT';
  328. end
  329. else
  330. {$endif}
  331. result:='text';
  332. end;
  333. constructor TOmfObjData.create(const n: string);
  334. begin
  335. inherited create(n);
  336. CObjSection:=TOmfObjSection;
  337. end;
  338. function TOmfObjData.sectiontype2align(atype: TAsmSectiontype): shortint;
  339. begin
  340. case atype of
  341. sec_stabstr:
  342. result:=1;
  343. sec_code:
  344. result:=1;
  345. sec_data,
  346. sec_rodata,
  347. sec_rodata_norel,
  348. sec_bss:
  349. result:=2;
  350. { For idata (at least idata2) it must be 4 bytes, because
  351. an entry is always (also in win64) 20 bytes and aligning
  352. on 8 bytes will insert 4 bytes between the entries resulting
  353. in a corrupt idata section.
  354. Same story with .pdata, it has 4-byte elements which should
  355. be packed without gaps. }
  356. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
  357. result:=4;
  358. sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev:
  359. result:=4;
  360. sec_stack,
  361. sec_heap:
  362. result:=16;
  363. else
  364. result:=1;
  365. end;
  366. end;
  367. function TOmfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  368. const
  369. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  370. 'text',
  371. 'data',
  372. 'data',
  373. 'rodata',
  374. 'bss',
  375. 'tbss',
  376. 'pdata',
  377. 'text','data','data','data','data',
  378. 'stab',
  379. 'stabstr',
  380. 'idata2','idata4','idata5','idata6','idata7','edata',
  381. 'eh_frame',
  382. 'debug_frame','debug_info','debug_line','debug_abbrev',
  383. 'fpc',
  384. '',
  385. 'init',
  386. 'fini',
  387. 'objc_class',
  388. 'objc_meta_class',
  389. 'objc_cat_cls_meth',
  390. 'objc_cat_inst_meth',
  391. 'objc_protocol',
  392. 'objc_string_object',
  393. 'objc_cls_meth',
  394. 'objc_inst_meth',
  395. 'objc_cls_refs',
  396. 'objc_message_refs',
  397. 'objc_symbols',
  398. 'objc_category',
  399. 'objc_class_vars',
  400. 'objc_instance_vars',
  401. 'objc_module_info',
  402. 'objc_class_names',
  403. 'objc_meth_var_types',
  404. 'objc_meth_var_names',
  405. 'objc_selector_strs',
  406. 'objc_protocol_ext',
  407. 'objc_class_ext',
  408. 'objc_property',
  409. 'objc_image_info',
  410. 'objc_cstring_object',
  411. 'objc_sel_fixup',
  412. '__DATA,__objc_data',
  413. '__DATA,__objc_const',
  414. 'objc_superrefs',
  415. '__DATA, __datacoal_nt,coalesced',
  416. 'objc_classlist',
  417. 'objc_nlclasslist',
  418. 'objc_catlist',
  419. 'obcj_nlcatlist',
  420. 'objc_protolist',
  421. 'stack',
  422. 'heap'
  423. );
  424. begin
  425. if (atype=sec_user) then
  426. Result:=aname
  427. else if secnames[atype]='text' then
  428. Result:=CodeSectionName(aname)
  429. else
  430. Result:=secnames[atype];
  431. end;
  432. procedure TOmfObjData.writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  433. var
  434. objreloc: TOmfRelocation;
  435. symaddr: AWord;
  436. begin
  437. { RELOC_FARPTR = RELOC_ABSOLUTE+RELOC_SEG }
  438. if Reloctype=RELOC_FARPTR then
  439. begin
  440. if len<>4 then
  441. internalerror(2015041502);
  442. writeReloc(Data,2,p,RELOC_ABSOLUTE);
  443. writeReloc(0,2,p,RELOC_SEG);
  444. exit;
  445. end;
  446. if CurrObjSec=nil then
  447. internalerror(200403072);
  448. objreloc:=nil;
  449. if assigned(p) then
  450. begin
  451. { real address of the symbol }
  452. symaddr:=p.address;
  453. if p.bind=AB_EXTERNAL then
  454. begin
  455. objreloc:=TOmfRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  456. CurrObjSec.ObjRelocations.Add(objreloc);
  457. end
  458. { relative relocations within the same section can be calculated directly,
  459. without the need to emit a relocation entry }
  460. else if (p.objsection=CurrObjSec) and
  461. (p.bind<>AB_COMMON) and
  462. (Reloctype=RELOC_RELATIVE) then
  463. begin
  464. data:=data+symaddr-len-CurrObjSec.Size;
  465. end
  466. else
  467. begin
  468. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  469. CurrObjSec.ObjRelocations.Add(objreloc);
  470. if not (Reloctype in [RELOC_SEG,RELOC_SEGREL]) then
  471. inc(data,symaddr);
  472. end;
  473. end
  474. else if Reloctype in [RELOC_DGROUP,RELOC_DGROUPREL] then
  475. begin
  476. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,nil,Reloctype);
  477. CurrObjSec.ObjRelocations.Add(objreloc);
  478. end;
  479. CurrObjSec.write(data,len);
  480. end;
  481. {****************************************************************************
  482. TOmfObjOutput
  483. ****************************************************************************}
  484. procedure TOmfObjOutput.AddSegment(const name, segclass, ovlname: string;
  485. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  486. Use: TOmfSegmentUse; Size: aword);
  487. var
  488. s: TOmfRecord_SEGDEF;
  489. begin
  490. s:=TOmfRecord_SEGDEF.Create;
  491. Segments.Add(name,s);
  492. s.SegmentNameIndex:=LNames.Add(name);
  493. s.ClassNameIndex:=LNames.Add(segclass);
  494. s.OverlayNameIndex:=LNames.Add(ovlname);
  495. s.Alignment:=Alignment;
  496. s.Combination:=Combination;
  497. s.Use:=Use;
  498. s.SegmentLength:=Size;
  499. end;
  500. procedure TOmfObjOutput.AddGroup(const groupname: string; seglist: array of const);
  501. var
  502. g: TOmfRecord_GRPDEF;
  503. I: Integer;
  504. SegListStr: TSegmentList;
  505. begin
  506. g:=TOmfRecord_GRPDEF.Create;
  507. Groups.Add(groupname,g);
  508. g.GroupNameIndex:=LNames.Add(groupname);
  509. SetLength(SegListStr,Length(seglist));
  510. for I:=0 to High(seglist) do
  511. begin
  512. case seglist[I].VType of
  513. vtString:
  514. SegListStr[I]:=Segments.FindIndexOf(seglist[I].VString^);
  515. vtAnsiString:
  516. SegListStr[I]:=Segments.FindIndexOf(AnsiString(seglist[I].VAnsiString));
  517. vtWideString:
  518. SegListStr[I]:=Segments.FindIndexOf(AnsiString(WideString(seglist[I].VWideString)));
  519. vtUnicodeString:
  520. SegListStr[I]:=Segments.FindIndexOf(AnsiString(UnicodeString(seglist[I].VUnicodeString)));
  521. else
  522. internalerror(2015040402);
  523. end;
  524. end;
  525. g.SegmentList:=SegListStr;
  526. end;
  527. procedure TOmfObjOutput.AddGroup(const groupname: string; seglist: TSegmentList);
  528. var
  529. g: TOmfRecord_GRPDEF;
  530. begin
  531. g:=TOmfRecord_GRPDEF.Create;
  532. Groups.Add(groupname,g);
  533. g.GroupNameIndex:=LNames.Add(groupname);
  534. g.SegmentList:=Copy(seglist);
  535. end;
  536. procedure TOmfObjOutput.WriteSections(Data: TObjData);
  537. var
  538. i:longint;
  539. sec:TObjSection;
  540. begin
  541. for i:=0 to Data.ObjSectionList.Count-1 do
  542. begin
  543. sec:=TObjSection(Data.ObjSectionList[i]);
  544. WriteSectionContentAndFixups(sec);
  545. end;
  546. end;
  547. procedure TOmfObjOutput.WriteSectionContentAndFixups(sec: TObjSection);
  548. const
  549. MaxChunkSize=$3fa;
  550. var
  551. RawRecord: TOmfRawRecord;
  552. ChunkStart,ChunkLen: DWord;
  553. ChunkFixupStart,ChunkFixupEnd: Integer;
  554. SegIndex: Integer;
  555. NextOfs: Integer;
  556. I: Integer;
  557. begin
  558. if (oso_data in sec.SecOptions) then
  559. begin
  560. if sec.Data=nil then
  561. internalerror(200403073);
  562. for I:=0 to sec.ObjRelocations.Count-1 do
  563. TOmfRelocation(sec.ObjRelocations[I]).BuildOmfFixup;
  564. SegIndex:=Segments.FindIndexOf(sec.Name);
  565. RawRecord:=TOmfRawRecord.Create;
  566. sec.data.seek(0);
  567. ChunkFixupStart:=0;
  568. ChunkFixupEnd:=-1;
  569. ChunkStart:=0;
  570. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  571. while ChunkLen>0 do
  572. begin
  573. { find last fixup in the chunk }
  574. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  575. (TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  576. inc(ChunkFixupEnd);
  577. { check if last chunk is crossing the chunk boundary, and trim ChunkLen if necessary }
  578. if (ChunkFixupEnd>=ChunkFixupStart) and
  579. ((TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset+
  580. TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).OmfFixup.LocationSize)>(ChunkStart+ChunkLen)) then
  581. begin
  582. ChunkLen:=TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset-ChunkStart;
  583. Dec(ChunkFixupEnd);
  584. end;
  585. { write LEDATA record }
  586. RawRecord.RecordType:=RT_LEDATA;
  587. NextOfs:=RawRecord.WriteIndexedRef(0,SegIndex);
  588. RawRecord.RawData[NextOfs]:=Byte(ChunkStart);
  589. RawRecord.RawData[NextOfs+1]:=Byte(ChunkStart shr 8);
  590. Inc(NextOfs,2);
  591. sec.data.read(RawRecord.RawData[NextOfs], ChunkLen);
  592. Inc(NextOfs, ChunkLen);
  593. RawRecord.RecordLength:=NextOfs+1;
  594. RawRecord.CalculateChecksumByte;
  595. RawRecord.WriteTo(FWriter);
  596. { write FIXUPP record }
  597. if ChunkFixupEnd>=ChunkFixupStart then
  598. begin
  599. RawRecord.RecordType:=RT_FIXUPP;
  600. NextOfs:=0;
  601. for I:=ChunkFixupStart to ChunkFixupEnd do
  602. begin
  603. TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.DataRecordStartOffset:=ChunkStart;
  604. NextOfs:=TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.WriteAt(RawRecord,NextOfs);
  605. end;
  606. RawRecord.RecordLength:=NextOfs+1;
  607. RawRecord.CalculateChecksumByte;
  608. RawRecord.WriteTo(FWriter);
  609. end;
  610. { prepare next chunk }
  611. Inc(ChunkStart, ChunkLen);
  612. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  613. ChunkFixupStart:=ChunkFixupEnd+1;
  614. end;
  615. RawRecord.Free;
  616. end;
  617. end;
  618. procedure TOmfObjOutput.section_count_sections(p: TObject; arg: pointer);
  619. begin
  620. TOmfObjSection(p).index:=pinteger(arg)^;
  621. inc(pinteger(arg)^);
  622. end;
  623. procedure TOmfObjOutput.WritePUBDEFs(Data: TObjData);
  624. var
  625. PubNamesForSection: array of TFPHashObjectList;
  626. i: Integer;
  627. objsym: TObjSymbol;
  628. PublicNameElem: TOmfPublicNameElement;
  629. RawRecord: TOmfRawRecord;
  630. PubDefRec: TOmfRecord_PUBDEF;
  631. PrimaryGroupName: string;
  632. begin
  633. RawRecord:=TOmfRawRecord.Create;
  634. SetLength(PubNamesForSection,Data.ObjSectionList.Count);
  635. for i:=0 to Data.ObjSectionList.Count-1 do
  636. PubNamesForSection[i]:=TFPHashObjectList.Create;
  637. for i:=0 to Data.ObjSymbolList.Count-1 do
  638. begin
  639. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  640. if objsym.bind=AB_GLOBAL then
  641. begin
  642. PublicNameElem:=TOmfPublicNameElement.Create(PubNamesForSection[objsym.objsection.index-1],objsym.Name);
  643. PublicNameElem.PublicOffset:=objsym.offset;
  644. end;
  645. end;
  646. for i:=0 to Data.ObjSectionList.Count-1 do
  647. if PubNamesForSection[i].Count>0 then
  648. begin
  649. PubDefRec:=TOmfRecord_PUBDEF.Create;
  650. PubDefRec.BaseSegmentIndex:=i+1;
  651. PrimaryGroupName:=TOmfObjSection(Data.ObjSectionList[i]).PrimaryGroup;
  652. if PrimaryGroupName<>'' then
  653. PubDefRec.BaseGroupIndex:=Groups.FindIndexOf(PrimaryGroupName)
  654. else
  655. PubDefRec.BaseGroupIndex:=0;
  656. PubDefRec.PublicNames:=PubNamesForSection[i];
  657. while PubDefRec.NextIndex<PubDefRec.PublicNames.Count do
  658. begin
  659. PubDefRec.EncodeTo(RawRecord);
  660. RawRecord.WriteTo(FWriter);
  661. end;
  662. PubDefRec.Free;
  663. end;
  664. for i:=0 to Data.ObjSectionList.Count-1 do
  665. FreeAndNil(PubNamesForSection[i]);
  666. RawRecord.Free;
  667. end;
  668. procedure TOmfObjOutput.WriteEXTDEFs(Data: TObjData);
  669. var
  670. ExtNames: TFPHashObjectList;
  671. RawRecord: TOmfRawRecord;
  672. i,idx: Integer;
  673. objsym: TObjSymbol;
  674. ExternalNameElem: TOmfExternalNameElement;
  675. ExtDefRec: TOmfRecord_EXTDEF;
  676. begin
  677. ExtNames:=TFPHashObjectList.Create;
  678. RawRecord:=TOmfRawRecord.Create;
  679. idx:=1;
  680. for i:=0 to Data.ObjSymbolList.Count-1 do
  681. begin
  682. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  683. if objsym.bind=AB_EXTERNAL then
  684. begin
  685. ExternalNameElem:=TOmfExternalNameElement.Create(ExtNames,objsym.Name);
  686. objsym.symidx:=idx;
  687. Inc(idx);
  688. end;
  689. end;
  690. if ExtNames.Count>0 then
  691. begin
  692. ExtDefRec:=TOmfRecord_EXTDEF.Create;
  693. ExtDefRec.ExternalNames:=ExtNames;
  694. while ExtDefRec.NextIndex<ExtDefRec.ExternalNames.Count do
  695. begin
  696. ExtDefRec.EncodeTo(RawRecord);
  697. RawRecord.WriteTo(FWriter);
  698. end;
  699. ExtDefRec.Free;
  700. end;
  701. ExtNames.Free;
  702. RawRecord.Free;
  703. end;
  704. function TOmfObjOutput.writeData(Data:TObjData):boolean;
  705. var
  706. RawRecord: TOmfRawRecord;
  707. Header: TOmfRecord_THEADR;
  708. Translator_COMENT: TOmfRecord_COMENT;
  709. LinkPassSeparator_COMENT: TOmfRecord_COMENT;
  710. LNamesRec: TOmfRecord_LNAMES;
  711. ModEnd: TOmfRecord_MODEND;
  712. I: Integer;
  713. SegDef: TOmfRecord_SEGDEF;
  714. GrpDef: TOmfRecord_GRPDEF;
  715. DGroupSegments: TSegmentList;
  716. nsections: Integer;
  717. begin
  718. { calc amount of sections we have and set their index, starting with 1 }
  719. nsections:=1;
  720. data.ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  721. { maximum amount of sections supported in the omf format is $7fff }
  722. if (nsections-1)>$7fff then
  723. internalerror(2015040701);
  724. { write header record }
  725. RawRecord:=TOmfRawRecord.Create;
  726. Header:=TOmfRecord_THEADR.Create;
  727. Header.ModuleName:=Data.Name;
  728. Header.EncodeTo(RawRecord);
  729. RawRecord.WriteTo(FWriter);
  730. Header.Free;
  731. { write translator COMENT header }
  732. Translator_COMENT:=TOmfRecord_COMENT.Create;
  733. Translator_COMENT.CommentClass:=CC_Translator;
  734. Translator_COMENT.CommentString:='FPC '+full_version_string+
  735. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname;
  736. Translator_COMENT.EncodeTo(RawRecord);
  737. RawRecord.WriteTo(FWriter);
  738. Translator_COMENT.Free;
  739. LNames.Clear;
  740. LNames.Add(''); { insert an empty string, which has index 1 }
  741. FSegments.Clear;
  742. FSegments.Add('',nil);
  743. FGroups.Clear;
  744. FGroups.Add('',nil);
  745. for i:=0 to Data.ObjSectionList.Count-1 do
  746. with TOmfObjSection(Data.ObjSectionList[I]) do
  747. AddSegment(Name,ClassName,OverlayName,OmfAlignment,Combination,Use,Size);
  748. { create group "dgroup" }
  749. SetLength(DGroupSegments,0);
  750. for i:=0 to Data.ObjSectionList.Count-1 do
  751. with TOmfObjSection(Data.ObjSectionList[I]) do
  752. if PrimaryGroup='dgroup' then
  753. begin
  754. SetLength(DGroupSegments,Length(DGroupSegments)+1);
  755. DGroupSegments[High(DGroupSegments)]:=index;
  756. end;
  757. AddGroup('dgroup',DGroupSegments);
  758. { write LNAMES record(s) }
  759. LNamesRec:=TOmfRecord_LNAMES.Create;
  760. LNamesRec.Names:=LNames;
  761. while LNamesRec.NextIndex<=LNames.Count do
  762. begin
  763. LNamesRec.EncodeTo(RawRecord);
  764. RawRecord.WriteTo(FWriter);
  765. end;
  766. LNamesRec.Free;
  767. { write SEGDEF record(s) }
  768. for I:=1 to Segments.Count-1 do
  769. begin
  770. SegDef:=TOmfRecord_SEGDEF(Segments[I]);
  771. SegDef.EncodeTo(RawRecord);
  772. RawRecord.WriteTo(FWriter);
  773. end;
  774. { write GRPDEF record(s) }
  775. for I:=1 to Groups.Count-1 do
  776. begin
  777. GrpDef:=TOmfRecord_GRPDEF(Groups[I]);
  778. GrpDef.EncodeTo(RawRecord);
  779. RawRecord.WriteTo(FWriter);
  780. end;
  781. { write PUBDEF record(s) }
  782. WritePUBDEFs(Data);
  783. { write EXTDEF record(s) }
  784. WriteEXTDEFs(Data);
  785. { write link pass separator }
  786. LinkPassSeparator_COMENT:=TOmfRecord_COMENT.Create;
  787. LinkPassSeparator_COMENT.CommentClass:=CC_LinkPassSeparator;
  788. LinkPassSeparator_COMENT.CommentString:=#1;
  789. LinkPassSeparator_COMENT.NoList:=True;
  790. LinkPassSeparator_COMENT.EncodeTo(RawRecord);
  791. RawRecord.WriteTo(FWriter);
  792. LinkPassSeparator_COMENT.Free;
  793. { write section content, interleaved with fixups }
  794. WriteSections(Data);
  795. { write MODEND record }
  796. ModEnd:=TOmfRecord_MODEND.Create;
  797. ModEnd.EncodeTo(RawRecord);
  798. RawRecord.WriteTo(FWriter);
  799. ModEnd.Free;
  800. RawRecord.Free;
  801. result:=true;
  802. end;
  803. constructor TOmfObjOutput.create(AWriter:TObjectWriter);
  804. begin
  805. inherited create(AWriter);
  806. cobjdata:=TOmfObjData;
  807. FLNames:=TOmfOrderedNameCollection.Create;
  808. FSegments:=TFPHashObjectList.Create;
  809. FSegments.Add('',nil);
  810. FGroups:=TFPHashObjectList.Create;
  811. FGroups.Add('',nil);
  812. end;
  813. destructor TOmfObjOutput.Destroy;
  814. begin
  815. FGroups.Free;
  816. FSegments.Free;
  817. FLNames.Free;
  818. inherited Destroy;
  819. end;
  820. {****************************************************************************
  821. TOmfObjInput
  822. ****************************************************************************}
  823. function TOmfObjInput.ReadLNames(RawRec: TOmfRawRecord): Boolean;
  824. var
  825. LNamesRec: TOmfRecord_LNAMES;
  826. begin
  827. Result:=False;
  828. LNamesRec:=TOmfRecord_LNAMES.Create;
  829. LNamesRec.Names:=LNames;
  830. LNamesRec.DecodeFrom(RawRec);
  831. LNamesRec.Free;
  832. Result:=True;
  833. end;
  834. function TOmfObjInput.ReadSegDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  835. var
  836. SegDefRec: TOmfRecord_SEGDEF;
  837. SegmentName,SegClassName,OverlayName: string;
  838. SecAlign: ShortInt;
  839. secoptions: TObjSectionOptions;
  840. objsec: TOmfObjSection;
  841. begin
  842. Result:=False;
  843. SegDefRec:=TOmfRecord_SEGDEF.Create;
  844. SegDefRec.DecodeFrom(RawRec);
  845. if (SegDefRec.SegmentNameIndex<1) or (SegDefRec.SegmentNameIndex>LNames.Count) then
  846. begin
  847. InputError('Segment name index out of range');
  848. SegDefRec.Free;
  849. exit;
  850. end;
  851. SegmentName:=LNames[SegDefRec.SegmentNameIndex];
  852. if (SegDefRec.ClassNameIndex<1) or (SegDefRec.ClassNameIndex>LNames.Count) then
  853. begin
  854. InputError('Segment class name index out of range');
  855. SegDefRec.Free;
  856. exit;
  857. end;
  858. SegClassName:=LNames[SegDefRec.ClassNameIndex];
  859. if (SegDefRec.OverlayNameIndex<1) or (SegDefRec.OverlayNameIndex>LNames.Count) then
  860. begin
  861. InputError('Segment overlay name index out of range');
  862. SegDefRec.Free;
  863. exit;
  864. end;
  865. OverlayName:=LNames[SegDefRec.OverlayNameIndex];
  866. case SegDefRec.Alignment of
  867. saRelocatableByteAligned:
  868. SecAlign:=1;
  869. saRelocatableWordAligned:
  870. SecAlign:=2;
  871. saRelocatableParaAligned:
  872. SecAlign:=16;
  873. saRelocatableDWordAligned:
  874. SecAlign:=4;
  875. saRelocatablePageAligned:
  876. begin
  877. InputError('Page segment alignment not supported');
  878. SegDefRec.Free;
  879. exit;
  880. end;
  881. saAbsolute:
  882. begin
  883. InputError('Absolute segment alignment not supported');
  884. SegDefRec.Free;
  885. exit;
  886. end;
  887. saNotSupported,
  888. saNotDefined:
  889. begin
  890. InputError('Invalid (unsupported/undefined) OMF segment alignment');
  891. SegDefRec.Free;
  892. exit;
  893. end;
  894. end;
  895. secoptions:=[];
  896. objsec:=TOmfObjSection(objdata.createsection(SegmentName,SecAlign,secoptions,false));
  897. objsec.FClassName:=SegClassName;
  898. objsec.FOverlayName:=OverlayName;
  899. objsec.FCombination:=SegDefRec.Combination;
  900. objsec.FUse:=SegDefRec.Use;
  901. if SegDefRec.SegmentLength>High(objsec.Size) then
  902. begin
  903. InputError('Segment too large');
  904. SegDefRec.Free;
  905. exit;
  906. end;
  907. objsec.Size:=SegDefRec.SegmentLength;
  908. SegDefRec.Free;
  909. Result:=True;
  910. end;
  911. function TOmfObjInput.ReadGrpDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  912. var
  913. GrpDefRec: TOmfRecord_GRPDEF;
  914. GroupName: string;
  915. SecGroup: TObjSectionGroup;
  916. i,SegIndex: Integer;
  917. begin
  918. Result:=False;
  919. GrpDefRec:=TOmfRecord_GRPDEF.Create;
  920. GrpDefRec.DecodeFrom(RawRec);
  921. if (GrpDefRec.GroupNameIndex<1) or (GrpDefRec.GroupNameIndex>LNames.Count) then
  922. begin
  923. InputError('Group name index out of range');
  924. GrpDefRec.Free;
  925. exit;
  926. end;
  927. GroupName:=LNames[GrpDefRec.GroupNameIndex];
  928. SecGroup:=objdata.createsectiongroup(GroupName);
  929. SetLength(SecGroup.members,Length(GrpDefRec.SegmentList));
  930. for i:=0 to Length(GrpDefRec.SegmentList)-1 do
  931. begin
  932. SegIndex:=GrpDefRec.SegmentList[i];
  933. if (SegIndex<1) or (SegIndex>objdata.ObjSectionList.Count) then
  934. begin
  935. InputError('Segment name index out of range in group definition');
  936. GrpDefRec.Free;
  937. exit;
  938. end;
  939. SecGroup.members[i]:=TOmfObjSection(objdata.ObjSectionList[SegIndex-1]);
  940. end;
  941. GrpDefRec.Free;
  942. Result:=True;
  943. end;
  944. function TOmfObjInput.ReadExtDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  945. var
  946. ExtDefRec: TOmfRecord_EXTDEF;
  947. ExtDefElem: TOmfExternalNameElement;
  948. OldCount,NewCount,i: Integer;
  949. objsym: TObjSymbol;
  950. begin
  951. Result:=False;
  952. ExtDefRec:=TOmfRecord_EXTDEF.Create;
  953. ExtDefRec.ExternalNames:=ExtDefs;
  954. OldCount:=ExtDefs.Count;
  955. ExtDefRec.DecodeFrom(RawRec);
  956. NewCount:=ExtDefs.Count;
  957. for i:=OldCount to NewCount-1 do
  958. begin
  959. ExtDefElem:=TOmfExternalNameElement(ExtDefs[i]);
  960. objsym:=objdata.CreateSymbol(ExtDefElem.Name);
  961. objsym.bind:=AB_EXTERNAL;
  962. objsym.typ:=AT_FUNCTION;
  963. objsym.objsection:=nil;
  964. objsym.offset:=0;
  965. objsym.size:=0;
  966. end;
  967. Result:=True;
  968. end;
  969. function TOmfObjInput.ReadLEDataAndFixups(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  970. var
  971. Is32Bit: Boolean;
  972. NextOfs: Integer;
  973. SegmentIndex: Integer;
  974. EnumeratedDataOffset: DWord;
  975. BlockLength: Integer;
  976. objsec: TOmfObjSection;
  977. begin
  978. Result:=False;
  979. if not (RawRec.RecordType in [RT_LEDATA,RT_LEDATA32]) then
  980. internalerror(2015040301);
  981. Is32Bit:=RawRec.RecordType=RT_LEDATA32;
  982. NextOfs:=RawRec.ReadIndexedRef(0,SegmentIndex);
  983. if Is32Bit then
  984. begin
  985. if (NextOfs+3)>=RawRec.RecordLength then
  986. internalerror(2015040504);
  987. EnumeratedDataOffset := RawRec.RawData[NextOfs]+
  988. (RawRec.RawData[NextOfs+1] shl 8)+
  989. (RawRec.RawData[NextOfs+2] shl 16)+
  990. (RawRec.RawData[NextOfs+3] shl 24);
  991. Inc(NextOfs,4);
  992. end
  993. else
  994. begin
  995. if (NextOfs+1)>=RawRec.RecordLength then
  996. internalerror(2015040504);
  997. EnumeratedDataOffset := RawRec.RawData[NextOfs]+
  998. (RawRec.RawData[NextOfs+1] shl 8);
  999. Inc(NextOfs,2);
  1000. end;
  1001. BlockLength:=RawRec.RecordLength-NextOfs-1;
  1002. if BlockLength<0 then
  1003. internalerror(2015060501);
  1004. if BlockLength>1024 then
  1005. begin
  1006. InputError('LEDATA contains more than 1024 bytes of data');
  1007. exit;
  1008. end;
  1009. if (SegmentIndex<1) or (SegmentIndex>objdata.ObjSectionList.Count) then
  1010. begin
  1011. InputError('Segment index in LEDATA field is out of range');
  1012. exit;
  1013. end;
  1014. objsec:=TOmfObjSection(objdata.ObjSectionList[SegmentIndex-1]);
  1015. objsec.SecOptions:=objsec.SecOptions+[oso_Data];
  1016. if (objsec.Data.Size<>EnumeratedDataOffset) then
  1017. begin
  1018. InputError('LEDATA enumerated data offset field out of sequence');
  1019. exit;
  1020. end;
  1021. if (EnumeratedDataOffset+BlockLength)>objsec.Size then
  1022. begin
  1023. InputError('LEDATA goes beyond the segment size declared in the SEGDEF record');
  1024. exit;
  1025. end;
  1026. objsec.Data.write(RawRec.RawData[NextOfs],BlockLength);
  1027. {todo: read also the FIXUPP record that may follow}
  1028. Result:=True;
  1029. end;
  1030. constructor TOmfObjInput.create;
  1031. begin
  1032. inherited create;
  1033. cobjdata:=TOmfObjData;
  1034. FLNames:=TOmfOrderedNameCollection.Create;
  1035. FExtDefs:=TFPHashObjectList.Create;
  1036. FRawRecord:=TOmfRawRecord.Create;
  1037. end;
  1038. destructor TOmfObjInput.destroy;
  1039. begin
  1040. FRawRecord.Free;
  1041. FExtDefs.Free;
  1042. FLNames.Free;
  1043. inherited destroy;
  1044. end;
  1045. class function TOmfObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  1046. var
  1047. b: Byte;
  1048. begin
  1049. result:=false;
  1050. if AReader.Read(b,sizeof(b)) then
  1051. begin
  1052. if b=RT_THEADR then
  1053. { TODO: check additional fields }
  1054. result:=true;
  1055. end;
  1056. AReader.Seek(0);
  1057. end;
  1058. function TOmfObjInput.ReadObjData(AReader: TObjectreader; out objdata: TObjData): boolean;
  1059. begin
  1060. FReader:=AReader;
  1061. InputFileName:=AReader.FileName;
  1062. objdata:=CObjData.Create(InputFileName);
  1063. result:=false;
  1064. LNames.Clear;
  1065. ExtDefs.Clear;
  1066. FRawRecord.ReadFrom(FReader);
  1067. if not FRawRecord.VerifyChecksumByte then
  1068. begin
  1069. InputError('Invalid checksum in OMF record');
  1070. exit;
  1071. end;
  1072. if FRawRecord.RecordType<>RT_THEADR then
  1073. begin
  1074. InputError('Can''t read OMF header');
  1075. exit;
  1076. end;
  1077. repeat
  1078. FRawRecord.ReadFrom(FReader);
  1079. if not FRawRecord.VerifyChecksumByte then
  1080. begin
  1081. InputError('Invalid checksum in OMF record');
  1082. exit;
  1083. end;
  1084. case FRawRecord.RecordType of
  1085. RT_LNAMES:
  1086. if not ReadLNames(FRawRecord) then
  1087. exit;
  1088. RT_SEGDEF,RT_SEGDEF32:
  1089. if not ReadSegDef(FRawRecord,objdata) then
  1090. exit;
  1091. RT_GRPDEF:
  1092. if not ReadGrpDef(FRawRecord,objdata) then
  1093. exit;
  1094. RT_COMENT:
  1095. begin
  1096. {todo}
  1097. end;
  1098. RT_EXTDEF:
  1099. if not ReadExtDef(FRawRecord,objdata) then
  1100. exit;
  1101. RT_PUBDEF,RT_PUBDEF32:
  1102. begin
  1103. {todo}
  1104. end;
  1105. RT_LEDATA,RT_LEDATA32:
  1106. if not ReadLEDataAndFixups(FRawRecord,objdata) then
  1107. exit;
  1108. RT_FIXUPP,RT_FIXUPP32:
  1109. begin
  1110. {todo}
  1111. end;
  1112. RT_MODEND,RT_MODEND32:
  1113. begin
  1114. {todo}
  1115. end;
  1116. else
  1117. begin
  1118. InputError('Unsupported OMF record type $'+HexStr(FRawRecord.RecordType,2));
  1119. exit;
  1120. end;
  1121. end;
  1122. until FRawRecord.RecordType in [RT_MODEND,RT_MODEND32];
  1123. end;
  1124. {****************************************************************************
  1125. TMZExeOutput
  1126. ****************************************************************************}
  1127. constructor TMZExeOutput.create;
  1128. begin
  1129. inherited create;
  1130. CObjData:=TOmfObjData;
  1131. end;
  1132. {****************************************************************************
  1133. TOmfAssembler
  1134. ****************************************************************************}
  1135. constructor TOmfAssembler.Create(smart:boolean);
  1136. begin
  1137. inherited Create(smart);
  1138. CObjOutput:=TOmfObjOutput;
  1139. CInternalAr:=TOmfLibObjectWriter;
  1140. end;
  1141. {*****************************************************************************
  1142. Initialize
  1143. *****************************************************************************}
  1144. {$ifdef i8086}
  1145. const
  1146. as_i8086_omf_info : tasminfo =
  1147. (
  1148. id : as_i8086_omf;
  1149. idtxt : 'OMF';
  1150. asmbin : '';
  1151. asmcmd : '';
  1152. supported_targets : [system_i8086_msdos];
  1153. flags : [af_outputbinary,af_no_debug];
  1154. labelprefix : '..@';
  1155. comment : '; ';
  1156. dollarsign: '$';
  1157. );
  1158. {$endif i8086}
  1159. initialization
  1160. {$ifdef i8086}
  1161. RegisterAssembler(as_i8086_omf_info,TOmfAssembler);
  1162. {$endif i8086}
  1163. end.