ogomf.pas 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747
  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. FPubDefs: TFPHashObjectList;
  104. FRawRecord: TOmfRawRecord;
  105. FCaseSensitive: Boolean;
  106. function PeekNextRecordType: Byte;
  107. function ReadLNames(RawRec: TOmfRawRecord): Boolean;
  108. function ReadSegDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  109. function ReadGrpDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  110. function ReadExtDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  111. function ReadPubDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  112. function ReadModEnd(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  113. function ReadLEDataAndFixups(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  114. function ImportOmfFixup(objdata: TObjData; objsec: TOmfObjSection; Fixup: TOmfSubRecord_FIXUP): Boolean;
  115. property LNames: TOmfOrderedNameCollection read FLNames;
  116. property ExtDefs: TFPHashObjectList read FExtDefs;
  117. property PubDefs: TFPHashObjectList read FPubDefs;
  118. { Specifies whether we're case sensitive in regards to segment, class, overlay and group names.
  119. Symbols (in EXTDEF and PUBDEF records) are always case sensitive, regardless of the value of this property. }
  120. property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive;
  121. public
  122. constructor create;override;
  123. destructor destroy;override;
  124. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  125. function ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;override;
  126. end;
  127. { TMZExeRelocation }
  128. TMZExeRelocation = record
  129. offset: Word;
  130. segment: Word;
  131. end;
  132. TMZExeRelocations = array of TMZExeRelocation;
  133. TMZExeExtraHeaderData = array of Byte;
  134. { TMZExeHeader }
  135. TMZExeHeader = class
  136. private
  137. FChecksum: Word;
  138. FExtraHeaderData: TMZExeExtraHeaderData;
  139. FHeaderSizeAlignment: Integer;
  140. FInitialCS: Word;
  141. FInitialIP: Word;
  142. FInitialSP: Word;
  143. FInitialSS: Word;
  144. FLoadableImageSize: DWord;
  145. FMaxExtraParagraphs: Word;
  146. FMinExtraParagraphs: Word;
  147. FOverlayNumber: Word;
  148. FRelocations: TMZExeRelocations;
  149. procedure SetHeaderSizeAlignment(AValue: Integer);
  150. public
  151. constructor Create;
  152. procedure WriteTo(aWriter: TObjectWriter);
  153. property HeaderSizeAlignment: Integer read FHeaderSizeAlignment write SetHeaderSizeAlignment; {default=16, must be multiple of 16}
  154. property Relocations: TMZExeRelocations read FRelocations write FRelocations;
  155. property ExtraHeaderData: TMZExeExtraHeaderData read FExtraHeaderData write FExtraHeaderData;
  156. property LoadableImageSize: DWord read FLoadableImageSize write FLoadableImageSize;
  157. property MinExtraParagraphs: Word read FMinExtraParagraphs write FMinExtraParagraphs;
  158. property MaxExtraParagraphs: Word read FMaxExtraParagraphs write FMaxExtraParagraphs;
  159. property InitialSS: Word read FInitialSS write FInitialSS;
  160. property InitialSP: Word read FInitialSP write FInitialSP;
  161. property Checksum: Word read FChecksum write FChecksum;
  162. property InitialIP: Word read FInitialIP write FInitialIP;
  163. property InitialCS: Word read FInitialCS write FInitialCS;
  164. property OverlayNumber: Word read FOverlayNumber write FOverlayNumber;
  165. end;
  166. { TMZExeSection }
  167. TMZExeSection=class(TExeSection)
  168. public
  169. procedure AddObjSection(objsec:TObjSection;ignoreprops:boolean=false);override;
  170. end;
  171. { TMZExeOutput }
  172. TMZExeOutput = class(TExeOutput)
  173. protected
  174. procedure DoRelocationFixup(objsec:TObjSection);override;
  175. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList;const aPattern:string);override;
  176. function writeData:boolean;override;
  177. public
  178. constructor create;override;
  179. end;
  180. TOmfAssembler = class(tinternalassembler)
  181. constructor create(smart:boolean);override;
  182. end;
  183. implementation
  184. uses
  185. SysUtils,
  186. cutils,verbose,globals,
  187. fmodule,aasmtai,aasmdata,
  188. ogmap,owomflib,
  189. version
  190. ;
  191. {****************************************************************************
  192. TOmfRelocation
  193. ****************************************************************************}
  194. function TOmfRelocation.GetGroupIndex(const groupname: string): Integer;
  195. begin
  196. if groupname='dgroup' then
  197. Result:=1
  198. else
  199. internalerror(2014040703);
  200. end;
  201. constructor TOmfRelocation.CreateSection(ADataOffset: aword; aobjsec: TObjSection; Atyp: TObjRelocationType);
  202. begin
  203. if not (Atyp in [RELOC_DGROUP,RELOC_DGROUPREL]) and not assigned(aobjsec) then
  204. internalerror(200603036);
  205. DataOffset:=ADataOffset;
  206. Symbol:=nil;
  207. OrgSize:=0;
  208. ObjSection:=aobjsec;
  209. ftype:=ord(Atyp);
  210. end;
  211. destructor TOmfRelocation.Destroy;
  212. begin
  213. FOmfFixup.Free;
  214. inherited Destroy;
  215. end;
  216. procedure TOmfRelocation.BuildOmfFixup;
  217. begin
  218. FreeAndNil(FOmfFixup);
  219. FOmfFixup:=TOmfSubRecord_FIXUP.Create;
  220. if ObjSection<>nil then
  221. begin
  222. FOmfFixup.LocationOffset:=DataOffset;
  223. if typ in [RELOC_ABSOLUTE,RELOC_RELATIVE] then
  224. FOmfFixup.LocationType:=fltOffset
  225. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  226. FOmfFixup.LocationType:=fltBase
  227. else
  228. internalerror(2015041501);
  229. FOmfFixup.FrameDeterminedByThread:=False;
  230. FOmfFixup.TargetDeterminedByThread:=False;
  231. if typ in [RELOC_ABSOLUTE,RELOC_SEG] then
  232. FOmfFixup.Mode:=fmSegmentRelative
  233. else if typ in [RELOC_RELATIVE,RELOC_SEGREL] then
  234. FOmfFixup.Mode:=fmSelfRelative
  235. else
  236. internalerror(2015041401);
  237. if typ in [RELOC_ABSOLUTE,RELOC_RELATIVE] then
  238. begin
  239. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  240. FOmfFixup.TargetDatum:=ObjSection.Index;
  241. if TOmfObjSection(ObjSection).PrimaryGroup<>'' then
  242. begin
  243. FOmfFixup.FrameMethod:=ffmGroupIndex;
  244. FOmfFixup.FrameDatum:=GetGroupIndex(TOmfObjSection(ObjSection).PrimaryGroup);
  245. end
  246. else
  247. FOmfFixup.FrameMethod:=ffmTarget;
  248. end
  249. else
  250. begin
  251. FOmfFixup.FrameMethod:=ffmTarget;
  252. if TOmfObjSection(ObjSection).PrimaryGroup<>'' then
  253. begin
  254. FOmfFixup.TargetMethod:=ftmGroupIndexNoDisp;
  255. FOmfFixup.TargetDatum:=GetGroupIndex(TOmfObjSection(ObjSection).PrimaryGroup);
  256. end
  257. else
  258. begin
  259. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  260. FOmfFixup.TargetDatum:=ObjSection.Index;
  261. end;
  262. end;
  263. end
  264. else if symbol<>nil then
  265. begin
  266. FOmfFixup.LocationOffset:=DataOffset;
  267. if typ in [RELOC_ABSOLUTE,RELOC_RELATIVE] then
  268. FOmfFixup.LocationType:=fltOffset
  269. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  270. FOmfFixup.LocationType:=fltBase
  271. else
  272. internalerror(2015041501);
  273. FOmfFixup.FrameDeterminedByThread:=False;
  274. FOmfFixup.TargetDeterminedByThread:=False;
  275. if typ in [RELOC_ABSOLUTE,RELOC_SEG] then
  276. FOmfFixup.Mode:=fmSegmentRelative
  277. else if typ in [RELOC_RELATIVE,RELOC_SEGREL] then
  278. FOmfFixup.Mode:=fmSelfRelative
  279. else
  280. internalerror(2015041401);
  281. FOmfFixup.TargetMethod:=ftmExternalIndexNoDisp;
  282. FOmfFixup.TargetDatum:=symbol.symidx;
  283. FOmfFixup.FrameMethod:=ffmTarget;
  284. end
  285. else if typ in [RELOC_DGROUP,RELOC_DGROUPREL] then
  286. begin
  287. FOmfFixup.LocationOffset:=DataOffset;
  288. FOmfFixup.LocationType:=fltBase;
  289. FOmfFixup.FrameDeterminedByThread:=False;
  290. FOmfFixup.TargetDeterminedByThread:=False;
  291. if typ=RELOC_DGROUP then
  292. FOmfFixup.Mode:=fmSegmentRelative
  293. else if typ=RELOC_DGROUPREL then
  294. FOmfFixup.Mode:=fmSelfRelative
  295. else
  296. internalerror(2015041401);
  297. FOmfFixup.FrameMethod:=ffmTarget;
  298. FOmfFixup.TargetMethod:=ftmGroupIndexNoDisp;
  299. FOmfFixup.TargetDatum:=GetGroupIndex('dgroup');
  300. end
  301. else
  302. internalerror(2015040702);
  303. end;
  304. {****************************************************************************
  305. TOmfObjSection
  306. ****************************************************************************}
  307. function TOmfObjSection.GetOmfAlignment: TOmfSegmentAlignment;
  308. begin
  309. case SecAlign of
  310. 1:
  311. result:=saRelocatableByteAligned;
  312. 2:
  313. result:=saRelocatableWordAligned;
  314. 4:
  315. result:=saRelocatableDWordAligned;
  316. 16:
  317. result:=saRelocatableParaAligned;
  318. else
  319. internalerror(2015041504);
  320. end;
  321. end;
  322. constructor TOmfObjSection.create(AList: TFPHashObjectList;
  323. const Aname: string; Aalign: shortint; Aoptions: TObjSectionOptions);
  324. var
  325. dgroup: Boolean;
  326. begin
  327. inherited create(AList, Aname, Aalign, Aoptions);
  328. FCombination:=scPublic;
  329. FUse:=suUse16;
  330. if oso_executable in Aoptions then
  331. begin
  332. FClassName:='code';
  333. dgroup:=(current_settings.x86memorymodel=mm_tiny);
  334. end
  335. else if Aname='stack' then
  336. begin
  337. FClassName:='stack';
  338. FCombination:=scStack;
  339. dgroup:=current_settings.x86memorymodel in (x86_near_data_models-[mm_tiny]);
  340. end
  341. else if Aname='heap' then
  342. begin
  343. FClassName:='heap';
  344. dgroup:=current_settings.x86memorymodel in x86_near_data_models;
  345. end
  346. else if Aname='bss' then
  347. begin
  348. FClassName:='bss';
  349. dgroup:=true;
  350. end
  351. else if Aname='data' then
  352. begin
  353. FClassName:='data';
  354. dgroup:=true;
  355. end
  356. else if (Aname='debug_frame') or
  357. (Aname='debug_info') or
  358. (Aname='debug_line') or
  359. (Aname='debug_abbrev') then
  360. begin
  361. FClassName:='DWARF';
  362. FUse:=suUse32;
  363. dgroup:=false;
  364. end
  365. else
  366. begin
  367. FClassName:='data';
  368. dgroup:=true;
  369. end;
  370. if dgroup then
  371. FPrimaryGroup:='dgroup'
  372. else
  373. FPrimaryGroup:='';
  374. end;
  375. {****************************************************************************
  376. TOmfObjData
  377. ****************************************************************************}
  378. class function TOmfObjData.CodeSectionName(const aname: string): string;
  379. begin
  380. {$ifdef i8086}
  381. if current_settings.x86memorymodel in x86_far_code_models then
  382. begin
  383. if cs_huge_code in current_settings.moduleswitches then
  384. result:=aname + '_TEXT'
  385. else
  386. result:=current_module.modulename^ + '_TEXT';
  387. end
  388. else
  389. {$endif}
  390. result:='text';
  391. end;
  392. constructor TOmfObjData.create(const n: string);
  393. begin
  394. inherited create(n);
  395. CObjSection:=TOmfObjSection;
  396. end;
  397. function TOmfObjData.sectiontype2align(atype: TAsmSectiontype): shortint;
  398. begin
  399. case atype of
  400. sec_stabstr:
  401. result:=1;
  402. sec_code:
  403. result:=1;
  404. sec_data,
  405. sec_rodata,
  406. sec_rodata_norel,
  407. sec_bss:
  408. result:=2;
  409. { For idata (at least idata2) it must be 4 bytes, because
  410. an entry is always (also in win64) 20 bytes and aligning
  411. on 8 bytes will insert 4 bytes between the entries resulting
  412. in a corrupt idata section.
  413. Same story with .pdata, it has 4-byte elements which should
  414. be packed without gaps. }
  415. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
  416. result:=4;
  417. sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev:
  418. result:=4;
  419. sec_stack,
  420. sec_heap:
  421. result:=16;
  422. else
  423. result:=1;
  424. end;
  425. end;
  426. function TOmfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  427. const
  428. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  429. 'text',
  430. 'data',
  431. 'data',
  432. 'rodata',
  433. 'bss',
  434. 'tbss',
  435. 'pdata',
  436. 'text','data','data','data','data',
  437. 'stab',
  438. 'stabstr',
  439. 'idata2','idata4','idata5','idata6','idata7','edata',
  440. 'eh_frame',
  441. 'debug_frame','debug_info','debug_line','debug_abbrev',
  442. 'fpc',
  443. '',
  444. 'init',
  445. 'fini',
  446. 'objc_class',
  447. 'objc_meta_class',
  448. 'objc_cat_cls_meth',
  449. 'objc_cat_inst_meth',
  450. 'objc_protocol',
  451. 'objc_string_object',
  452. 'objc_cls_meth',
  453. 'objc_inst_meth',
  454. 'objc_cls_refs',
  455. 'objc_message_refs',
  456. 'objc_symbols',
  457. 'objc_category',
  458. 'objc_class_vars',
  459. 'objc_instance_vars',
  460. 'objc_module_info',
  461. 'objc_class_names',
  462. 'objc_meth_var_types',
  463. 'objc_meth_var_names',
  464. 'objc_selector_strs',
  465. 'objc_protocol_ext',
  466. 'objc_class_ext',
  467. 'objc_property',
  468. 'objc_image_info',
  469. 'objc_cstring_object',
  470. 'objc_sel_fixup',
  471. '__DATA,__objc_data',
  472. '__DATA,__objc_const',
  473. 'objc_superrefs',
  474. '__DATA, __datacoal_nt,coalesced',
  475. 'objc_classlist',
  476. 'objc_nlclasslist',
  477. 'objc_catlist',
  478. 'obcj_nlcatlist',
  479. 'objc_protolist',
  480. 'stack',
  481. 'heap'
  482. );
  483. begin
  484. if (atype=sec_user) then
  485. Result:=aname
  486. else if secnames[atype]='text' then
  487. Result:=CodeSectionName(aname)
  488. else
  489. Result:=secnames[atype];
  490. end;
  491. procedure TOmfObjData.writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  492. var
  493. objreloc: TOmfRelocation;
  494. symaddr: AWord;
  495. begin
  496. { RELOC_FARPTR = RELOC_ABSOLUTE+RELOC_SEG }
  497. if Reloctype=RELOC_FARPTR then
  498. begin
  499. if len<>4 then
  500. internalerror(2015041502);
  501. writeReloc(Data,2,p,RELOC_ABSOLUTE);
  502. writeReloc(0,2,p,RELOC_SEG);
  503. exit;
  504. end;
  505. if CurrObjSec=nil then
  506. internalerror(200403072);
  507. objreloc:=nil;
  508. if assigned(p) then
  509. begin
  510. { real address of the symbol }
  511. symaddr:=p.address;
  512. if p.bind=AB_EXTERNAL then
  513. begin
  514. objreloc:=TOmfRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  515. CurrObjSec.ObjRelocations.Add(objreloc);
  516. end
  517. { relative relocations within the same section can be calculated directly,
  518. without the need to emit a relocation entry }
  519. else if (p.objsection=CurrObjSec) and
  520. (p.bind<>AB_COMMON) and
  521. (Reloctype=RELOC_RELATIVE) then
  522. begin
  523. data:=data+symaddr-len-CurrObjSec.Size;
  524. end
  525. else
  526. begin
  527. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  528. CurrObjSec.ObjRelocations.Add(objreloc);
  529. if not (Reloctype in [RELOC_SEG,RELOC_SEGREL]) then
  530. inc(data,symaddr);
  531. end;
  532. end
  533. else if Reloctype in [RELOC_DGROUP,RELOC_DGROUPREL] then
  534. begin
  535. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,nil,Reloctype);
  536. CurrObjSec.ObjRelocations.Add(objreloc);
  537. end;
  538. CurrObjSec.write(data,len);
  539. end;
  540. {****************************************************************************
  541. TOmfObjOutput
  542. ****************************************************************************}
  543. procedure TOmfObjOutput.AddSegment(const name, segclass, ovlname: string;
  544. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  545. Use: TOmfSegmentUse; Size: aword);
  546. var
  547. s: TOmfRecord_SEGDEF;
  548. begin
  549. s:=TOmfRecord_SEGDEF.Create;
  550. Segments.Add(name,s);
  551. s.SegmentNameIndex:=LNames.Add(name);
  552. s.ClassNameIndex:=LNames.Add(segclass);
  553. s.OverlayNameIndex:=LNames.Add(ovlname);
  554. s.Alignment:=Alignment;
  555. s.Combination:=Combination;
  556. s.Use:=Use;
  557. s.SegmentLength:=Size;
  558. end;
  559. procedure TOmfObjOutput.AddGroup(const groupname: string; seglist: array of const);
  560. var
  561. g: TOmfRecord_GRPDEF;
  562. I: Integer;
  563. SegListStr: TSegmentList;
  564. begin
  565. g:=TOmfRecord_GRPDEF.Create;
  566. Groups.Add(groupname,g);
  567. g.GroupNameIndex:=LNames.Add(groupname);
  568. SetLength(SegListStr,Length(seglist));
  569. for I:=0 to High(seglist) do
  570. begin
  571. case seglist[I].VType of
  572. vtString:
  573. SegListStr[I]:=Segments.FindIndexOf(seglist[I].VString^);
  574. vtAnsiString:
  575. SegListStr[I]:=Segments.FindIndexOf(AnsiString(seglist[I].VAnsiString));
  576. vtWideString:
  577. SegListStr[I]:=Segments.FindIndexOf(AnsiString(WideString(seglist[I].VWideString)));
  578. vtUnicodeString:
  579. SegListStr[I]:=Segments.FindIndexOf(AnsiString(UnicodeString(seglist[I].VUnicodeString)));
  580. else
  581. internalerror(2015040402);
  582. end;
  583. end;
  584. g.SegmentList:=SegListStr;
  585. end;
  586. procedure TOmfObjOutput.AddGroup(const groupname: string; seglist: TSegmentList);
  587. var
  588. g: TOmfRecord_GRPDEF;
  589. begin
  590. g:=TOmfRecord_GRPDEF.Create;
  591. Groups.Add(groupname,g);
  592. g.GroupNameIndex:=LNames.Add(groupname);
  593. g.SegmentList:=Copy(seglist);
  594. end;
  595. procedure TOmfObjOutput.WriteSections(Data: TObjData);
  596. var
  597. i:longint;
  598. sec:TObjSection;
  599. begin
  600. for i:=0 to Data.ObjSectionList.Count-1 do
  601. begin
  602. sec:=TObjSection(Data.ObjSectionList[i]);
  603. WriteSectionContentAndFixups(sec);
  604. end;
  605. end;
  606. procedure TOmfObjOutput.WriteSectionContentAndFixups(sec: TObjSection);
  607. const
  608. MaxChunkSize=$3fa;
  609. var
  610. RawRecord: TOmfRawRecord;
  611. ChunkStart,ChunkLen: DWord;
  612. ChunkFixupStart,ChunkFixupEnd: Integer;
  613. SegIndex: Integer;
  614. NextOfs: Integer;
  615. I: Integer;
  616. begin
  617. if (oso_data in sec.SecOptions) then
  618. begin
  619. if sec.Data=nil then
  620. internalerror(200403073);
  621. for I:=0 to sec.ObjRelocations.Count-1 do
  622. TOmfRelocation(sec.ObjRelocations[I]).BuildOmfFixup;
  623. SegIndex:=Segments.FindIndexOf(sec.Name);
  624. RawRecord:=TOmfRawRecord.Create;
  625. sec.data.seek(0);
  626. ChunkFixupStart:=0;
  627. ChunkFixupEnd:=-1;
  628. ChunkStart:=0;
  629. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  630. while ChunkLen>0 do
  631. begin
  632. { find last fixup in the chunk }
  633. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  634. (TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  635. inc(ChunkFixupEnd);
  636. { check if last chunk is crossing the chunk boundary, and trim ChunkLen if necessary }
  637. if (ChunkFixupEnd>=ChunkFixupStart) and
  638. ((TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset+
  639. TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).OmfFixup.LocationSize)>(ChunkStart+ChunkLen)) then
  640. begin
  641. ChunkLen:=TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset-ChunkStart;
  642. Dec(ChunkFixupEnd);
  643. end;
  644. { write LEDATA record }
  645. RawRecord.RecordType:=RT_LEDATA;
  646. NextOfs:=RawRecord.WriteIndexedRef(0,SegIndex);
  647. RawRecord.RawData[NextOfs]:=Byte(ChunkStart);
  648. RawRecord.RawData[NextOfs+1]:=Byte(ChunkStart shr 8);
  649. Inc(NextOfs,2);
  650. sec.data.read(RawRecord.RawData[NextOfs], ChunkLen);
  651. Inc(NextOfs, ChunkLen);
  652. RawRecord.RecordLength:=NextOfs+1;
  653. RawRecord.CalculateChecksumByte;
  654. RawRecord.WriteTo(FWriter);
  655. { write FIXUPP record }
  656. if ChunkFixupEnd>=ChunkFixupStart then
  657. begin
  658. RawRecord.RecordType:=RT_FIXUPP;
  659. NextOfs:=0;
  660. for I:=ChunkFixupStart to ChunkFixupEnd do
  661. begin
  662. TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.DataRecordStartOffset:=ChunkStart;
  663. NextOfs:=TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.WriteAt(RawRecord,NextOfs);
  664. end;
  665. RawRecord.RecordLength:=NextOfs+1;
  666. RawRecord.CalculateChecksumByte;
  667. RawRecord.WriteTo(FWriter);
  668. end;
  669. { prepare next chunk }
  670. Inc(ChunkStart, ChunkLen);
  671. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  672. ChunkFixupStart:=ChunkFixupEnd+1;
  673. end;
  674. RawRecord.Free;
  675. end;
  676. end;
  677. procedure TOmfObjOutput.section_count_sections(p: TObject; arg: pointer);
  678. begin
  679. TOmfObjSection(p).index:=pinteger(arg)^;
  680. inc(pinteger(arg)^);
  681. end;
  682. procedure TOmfObjOutput.WritePUBDEFs(Data: TObjData);
  683. var
  684. PubNamesForSection: array of TFPHashObjectList;
  685. i: Integer;
  686. objsym: TObjSymbol;
  687. PublicNameElem: TOmfPublicNameElement;
  688. RawRecord: TOmfRawRecord;
  689. PubDefRec: TOmfRecord_PUBDEF;
  690. PrimaryGroupName: string;
  691. begin
  692. RawRecord:=TOmfRawRecord.Create;
  693. SetLength(PubNamesForSection,Data.ObjSectionList.Count);
  694. for i:=0 to Data.ObjSectionList.Count-1 do
  695. PubNamesForSection[i]:=TFPHashObjectList.Create;
  696. for i:=0 to Data.ObjSymbolList.Count-1 do
  697. begin
  698. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  699. if objsym.bind=AB_GLOBAL then
  700. begin
  701. PublicNameElem:=TOmfPublicNameElement.Create(PubNamesForSection[objsym.objsection.index-1],objsym.Name);
  702. PublicNameElem.PublicOffset:=objsym.offset;
  703. end;
  704. end;
  705. for i:=0 to Data.ObjSectionList.Count-1 do
  706. if PubNamesForSection[i].Count>0 then
  707. begin
  708. PubDefRec:=TOmfRecord_PUBDEF.Create;
  709. PubDefRec.BaseSegmentIndex:=i+1;
  710. PrimaryGroupName:=TOmfObjSection(Data.ObjSectionList[i]).PrimaryGroup;
  711. if PrimaryGroupName<>'' then
  712. PubDefRec.BaseGroupIndex:=Groups.FindIndexOf(PrimaryGroupName)
  713. else
  714. PubDefRec.BaseGroupIndex:=0;
  715. PubDefRec.PublicNames:=PubNamesForSection[i];
  716. while PubDefRec.NextIndex<PubDefRec.PublicNames.Count do
  717. begin
  718. PubDefRec.EncodeTo(RawRecord);
  719. RawRecord.WriteTo(FWriter);
  720. end;
  721. PubDefRec.Free;
  722. end;
  723. for i:=0 to Data.ObjSectionList.Count-1 do
  724. FreeAndNil(PubNamesForSection[i]);
  725. RawRecord.Free;
  726. end;
  727. procedure TOmfObjOutput.WriteEXTDEFs(Data: TObjData);
  728. var
  729. ExtNames: TFPHashObjectList;
  730. RawRecord: TOmfRawRecord;
  731. i,idx: Integer;
  732. objsym: TObjSymbol;
  733. ExternalNameElem: TOmfExternalNameElement;
  734. ExtDefRec: TOmfRecord_EXTDEF;
  735. begin
  736. ExtNames:=TFPHashObjectList.Create;
  737. RawRecord:=TOmfRawRecord.Create;
  738. idx:=1;
  739. for i:=0 to Data.ObjSymbolList.Count-1 do
  740. begin
  741. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  742. if objsym.bind=AB_EXTERNAL then
  743. begin
  744. ExternalNameElem:=TOmfExternalNameElement.Create(ExtNames,objsym.Name);
  745. objsym.symidx:=idx;
  746. Inc(idx);
  747. end;
  748. end;
  749. if ExtNames.Count>0 then
  750. begin
  751. ExtDefRec:=TOmfRecord_EXTDEF.Create;
  752. ExtDefRec.ExternalNames:=ExtNames;
  753. while ExtDefRec.NextIndex<ExtDefRec.ExternalNames.Count do
  754. begin
  755. ExtDefRec.EncodeTo(RawRecord);
  756. RawRecord.WriteTo(FWriter);
  757. end;
  758. ExtDefRec.Free;
  759. end;
  760. ExtNames.Free;
  761. RawRecord.Free;
  762. end;
  763. function TOmfObjOutput.writeData(Data:TObjData):boolean;
  764. var
  765. RawRecord: TOmfRawRecord;
  766. Header: TOmfRecord_THEADR;
  767. Translator_COMENT: TOmfRecord_COMENT;
  768. LinkPassSeparator_COMENT: TOmfRecord_COMENT;
  769. LNamesRec: TOmfRecord_LNAMES;
  770. ModEnd: TOmfRecord_MODEND;
  771. I: Integer;
  772. SegDef: TOmfRecord_SEGDEF;
  773. GrpDef: TOmfRecord_GRPDEF;
  774. DGroupSegments: TSegmentList;
  775. nsections: Integer;
  776. begin
  777. { calc amount of sections we have and set their index, starting with 1 }
  778. nsections:=1;
  779. data.ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  780. { maximum amount of sections supported in the omf format is $7fff }
  781. if (nsections-1)>$7fff then
  782. internalerror(2015040701);
  783. { write header record }
  784. RawRecord:=TOmfRawRecord.Create;
  785. Header:=TOmfRecord_THEADR.Create;
  786. Header.ModuleName:=Data.Name;
  787. Header.EncodeTo(RawRecord);
  788. RawRecord.WriteTo(FWriter);
  789. Header.Free;
  790. { write translator COMENT header }
  791. Translator_COMENT:=TOmfRecord_COMENT.Create;
  792. Translator_COMENT.CommentClass:=CC_Translator;
  793. Translator_COMENT.CommentString:='FPC '+full_version_string+
  794. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname;
  795. Translator_COMENT.EncodeTo(RawRecord);
  796. RawRecord.WriteTo(FWriter);
  797. Translator_COMENT.Free;
  798. LNames.Clear;
  799. LNames.Add(''); { insert an empty string, which has index 1 }
  800. FSegments.Clear;
  801. FSegments.Add('',nil);
  802. FGroups.Clear;
  803. FGroups.Add('',nil);
  804. for i:=0 to Data.ObjSectionList.Count-1 do
  805. with TOmfObjSection(Data.ObjSectionList[I]) do
  806. AddSegment(Name,ClassName,OverlayName,OmfAlignment,Combination,Use,Size);
  807. { create group "dgroup" }
  808. SetLength(DGroupSegments,0);
  809. for i:=0 to Data.ObjSectionList.Count-1 do
  810. with TOmfObjSection(Data.ObjSectionList[I]) do
  811. if PrimaryGroup='dgroup' then
  812. begin
  813. SetLength(DGroupSegments,Length(DGroupSegments)+1);
  814. DGroupSegments[High(DGroupSegments)]:=index;
  815. end;
  816. AddGroup('dgroup',DGroupSegments);
  817. { write LNAMES record(s) }
  818. LNamesRec:=TOmfRecord_LNAMES.Create;
  819. LNamesRec.Names:=LNames;
  820. while LNamesRec.NextIndex<=LNames.Count do
  821. begin
  822. LNamesRec.EncodeTo(RawRecord);
  823. RawRecord.WriteTo(FWriter);
  824. end;
  825. LNamesRec.Free;
  826. { write SEGDEF record(s) }
  827. for I:=1 to Segments.Count-1 do
  828. begin
  829. SegDef:=TOmfRecord_SEGDEF(Segments[I]);
  830. SegDef.EncodeTo(RawRecord);
  831. RawRecord.WriteTo(FWriter);
  832. end;
  833. { write GRPDEF record(s) }
  834. for I:=1 to Groups.Count-1 do
  835. begin
  836. GrpDef:=TOmfRecord_GRPDEF(Groups[I]);
  837. GrpDef.EncodeTo(RawRecord);
  838. RawRecord.WriteTo(FWriter);
  839. end;
  840. { write PUBDEF record(s) }
  841. WritePUBDEFs(Data);
  842. { write EXTDEF record(s) }
  843. WriteEXTDEFs(Data);
  844. { write link pass separator }
  845. LinkPassSeparator_COMENT:=TOmfRecord_COMENT.Create;
  846. LinkPassSeparator_COMENT.CommentClass:=CC_LinkPassSeparator;
  847. LinkPassSeparator_COMENT.CommentString:=#1;
  848. LinkPassSeparator_COMENT.NoList:=True;
  849. LinkPassSeparator_COMENT.EncodeTo(RawRecord);
  850. RawRecord.WriteTo(FWriter);
  851. LinkPassSeparator_COMENT.Free;
  852. { write section content, interleaved with fixups }
  853. WriteSections(Data);
  854. { write MODEND record }
  855. ModEnd:=TOmfRecord_MODEND.Create;
  856. ModEnd.EncodeTo(RawRecord);
  857. RawRecord.WriteTo(FWriter);
  858. ModEnd.Free;
  859. RawRecord.Free;
  860. result:=true;
  861. end;
  862. constructor TOmfObjOutput.create(AWriter:TObjectWriter);
  863. begin
  864. inherited create(AWriter);
  865. cobjdata:=TOmfObjData;
  866. FLNames:=TOmfOrderedNameCollection.Create;
  867. FSegments:=TFPHashObjectList.Create;
  868. FSegments.Add('',nil);
  869. FGroups:=TFPHashObjectList.Create;
  870. FGroups.Add('',nil);
  871. end;
  872. destructor TOmfObjOutput.Destroy;
  873. begin
  874. FGroups.Free;
  875. FSegments.Free;
  876. FLNames.Free;
  877. inherited Destroy;
  878. end;
  879. {****************************************************************************
  880. TOmfObjInput
  881. ****************************************************************************}
  882. function TOmfObjInput.PeekNextRecordType: Byte;
  883. var
  884. OldPos: LongInt;
  885. begin
  886. OldPos:=FReader.Pos;
  887. if not FReader.read(Result, 1) then
  888. begin
  889. InputError('Unexpected end of file');
  890. Result:=0;
  891. exit;
  892. end;
  893. FReader.seek(OldPos);
  894. end;
  895. function TOmfObjInput.ReadLNames(RawRec: TOmfRawRecord): Boolean;
  896. var
  897. LNamesRec: TOmfRecord_LNAMES;
  898. begin
  899. Result:=False;
  900. LNamesRec:=TOmfRecord_LNAMES.Create;
  901. LNamesRec.Names:=LNames;
  902. LNamesRec.DecodeFrom(RawRec);
  903. LNamesRec.Free;
  904. Result:=True;
  905. end;
  906. function TOmfObjInput.ReadSegDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  907. var
  908. SegDefRec: TOmfRecord_SEGDEF;
  909. SegmentName,SegClassName,OverlayName: string;
  910. SecAlign: ShortInt;
  911. secoptions: TObjSectionOptions;
  912. objsec: TOmfObjSection;
  913. begin
  914. Result:=False;
  915. SegDefRec:=TOmfRecord_SEGDEF.Create;
  916. SegDefRec.DecodeFrom(RawRec);
  917. if (SegDefRec.SegmentNameIndex<1) or (SegDefRec.SegmentNameIndex>LNames.Count) then
  918. begin
  919. InputError('Segment name index out of range');
  920. SegDefRec.Free;
  921. exit;
  922. end;
  923. SegmentName:=LNames[SegDefRec.SegmentNameIndex];
  924. if (SegDefRec.ClassNameIndex<1) or (SegDefRec.ClassNameIndex>LNames.Count) then
  925. begin
  926. InputError('Segment class name index out of range');
  927. SegDefRec.Free;
  928. exit;
  929. end;
  930. SegClassName:=LNames[SegDefRec.ClassNameIndex];
  931. if (SegDefRec.OverlayNameIndex<1) or (SegDefRec.OverlayNameIndex>LNames.Count) then
  932. begin
  933. InputError('Segment overlay name index out of range');
  934. SegDefRec.Free;
  935. exit;
  936. end;
  937. OverlayName:=LNames[SegDefRec.OverlayNameIndex];
  938. SecAlign:=1; // otherwise warning prohibits compilation
  939. case SegDefRec.Alignment of
  940. saRelocatableByteAligned:
  941. SecAlign:=1;
  942. saRelocatableWordAligned:
  943. SecAlign:=2;
  944. saRelocatableParaAligned:
  945. SecAlign:=16;
  946. saRelocatableDWordAligned:
  947. SecAlign:=4;
  948. saRelocatablePageAligned:
  949. begin
  950. InputError('Page segment alignment not supported');
  951. SegDefRec.Free;
  952. exit;
  953. end;
  954. saAbsolute:
  955. begin
  956. InputError('Absolute segment alignment not supported');
  957. SegDefRec.Free;
  958. exit;
  959. end;
  960. saNotSupported,
  961. saNotDefined:
  962. begin
  963. InputError('Invalid (unsupported/undefined) OMF segment alignment');
  964. SegDefRec.Free;
  965. exit;
  966. end;
  967. end;
  968. if not CaseSensitive then
  969. begin
  970. SegmentName:=UpCase(SegmentName);
  971. SegClassName:=UpCase(SegClassName);
  972. OverlayName:=UpCase(OverlayName);
  973. end;
  974. secoptions:=[];
  975. objsec:=TOmfObjSection(objdata.createsection(SegmentName+'||'+SegClassName,SecAlign,secoptions,false));
  976. objsec.FClassName:=SegClassName;
  977. objsec.FOverlayName:=OverlayName;
  978. objsec.FCombination:=SegDefRec.Combination;
  979. objsec.FUse:=SegDefRec.Use;
  980. if SegDefRec.SegmentLength>High(objsec.Size) then
  981. begin
  982. InputError('Segment too large');
  983. SegDefRec.Free;
  984. exit;
  985. end;
  986. objsec.Size:=SegDefRec.SegmentLength;
  987. SegDefRec.Free;
  988. Result:=True;
  989. end;
  990. function TOmfObjInput.ReadGrpDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  991. var
  992. GrpDefRec: TOmfRecord_GRPDEF;
  993. GroupName: string;
  994. SecGroup: TObjSectionGroup;
  995. i,SegIndex: Integer;
  996. begin
  997. Result:=False;
  998. GrpDefRec:=TOmfRecord_GRPDEF.Create;
  999. GrpDefRec.DecodeFrom(RawRec);
  1000. if (GrpDefRec.GroupNameIndex<1) or (GrpDefRec.GroupNameIndex>LNames.Count) then
  1001. begin
  1002. InputError('Group name index out of range');
  1003. GrpDefRec.Free;
  1004. exit;
  1005. end;
  1006. GroupName:=LNames[GrpDefRec.GroupNameIndex];
  1007. if not CaseSensitive then
  1008. GroupName:=UpCase(GroupName);
  1009. SecGroup:=objdata.createsectiongroup(GroupName);
  1010. SetLength(SecGroup.members,Length(GrpDefRec.SegmentList));
  1011. for i:=0 to Length(GrpDefRec.SegmentList)-1 do
  1012. begin
  1013. SegIndex:=GrpDefRec.SegmentList[i];
  1014. if (SegIndex<1) or (SegIndex>objdata.ObjSectionList.Count) then
  1015. begin
  1016. InputError('Segment name index out of range in group definition');
  1017. GrpDefRec.Free;
  1018. exit;
  1019. end;
  1020. SecGroup.members[i]:=TOmfObjSection(objdata.ObjSectionList[SegIndex-1]);
  1021. end;
  1022. GrpDefRec.Free;
  1023. Result:=True;
  1024. end;
  1025. function TOmfObjInput.ReadExtDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  1026. var
  1027. ExtDefRec: TOmfRecord_EXTDEF;
  1028. ExtDefElem: TOmfExternalNameElement;
  1029. OldCount,NewCount,i: Integer;
  1030. objsym: TObjSymbol;
  1031. begin
  1032. Result:=False;
  1033. ExtDefRec:=TOmfRecord_EXTDEF.Create;
  1034. ExtDefRec.ExternalNames:=ExtDefs;
  1035. OldCount:=ExtDefs.Count;
  1036. ExtDefRec.DecodeFrom(RawRec);
  1037. NewCount:=ExtDefs.Count;
  1038. for i:=OldCount to NewCount-1 do
  1039. begin
  1040. ExtDefElem:=TOmfExternalNameElement(ExtDefs[i]);
  1041. objsym:=objdata.CreateSymbol(ExtDefElem.Name);
  1042. objsym.bind:=AB_EXTERNAL;
  1043. objsym.typ:=AT_FUNCTION;
  1044. objsym.objsection:=nil;
  1045. objsym.offset:=0;
  1046. objsym.size:=0;
  1047. end;
  1048. ExtDefRec.Free;
  1049. Result:=True;
  1050. end;
  1051. function TOmfObjInput.ReadPubDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  1052. var
  1053. PubDefRec: TOmfRecord_PUBDEF;
  1054. PubDefElem: TOmfPublicNameElement;
  1055. OldCount,NewCount,i: Integer;
  1056. basegroup: TObjSectionGroup;
  1057. objsym: TObjSymbol;
  1058. objsec: TOmfObjSection;
  1059. begin
  1060. Result:=False;
  1061. PubDefRec:=TOmfRecord_PUBDEF.Create;
  1062. PubDefRec.PublicNames:=PubDefs;
  1063. OldCount:=PubDefs.Count;
  1064. PubDefRec.DecodeFrom(RawRec);
  1065. NewCount:=PubDefs.Count;
  1066. if (PubDefRec.BaseGroupIndex<0) or (PubDefRec.BaseGroupIndex>objdata.GroupsList.Count) then
  1067. begin
  1068. InputError('Public symbol''s group name index out of range');
  1069. PubDefRec.Free;
  1070. exit;
  1071. end;
  1072. if PubDefRec.BaseGroupIndex<>0 then
  1073. basegroup:=TObjSectionGroup(objdata.GroupsList[PubDefRec.BaseGroupIndex-1])
  1074. else
  1075. basegroup:=nil;
  1076. if (PubDefRec.BaseSegmentIndex<0) or (PubDefRec.BaseSegmentIndex>objdata.ObjSectionList.Count) then
  1077. begin
  1078. InputError('Public symbol''s segment name index out of range');
  1079. PubDefRec.Free;
  1080. exit;
  1081. end;
  1082. if PubDefRec.BaseSegmentIndex=0 then
  1083. begin
  1084. InputError('Public symbol uses absolute addressing, which is not supported by this linker');
  1085. PubDefRec.Free;
  1086. exit;
  1087. end;
  1088. objsec:=TOmfObjSection(objdata.ObjSectionList[PubDefRec.BaseSegmentIndex-1]);
  1089. for i:=OldCount to NewCount-1 do
  1090. begin
  1091. PubDefElem:=TOmfPublicNameElement(PubDefs[i]);
  1092. objsym:=objdata.CreateSymbol(PubDefElem.Name);
  1093. objsym.bind:=AB_GLOBAL;
  1094. objsym.typ:=AT_FUNCTION;
  1095. objsym.group:=basegroup;
  1096. objsym.objsection:=objsec;
  1097. objsym.offset:=PubDefElem.PublicOffset;
  1098. objsym.size:=0;
  1099. end;
  1100. PubDefRec.Free;
  1101. Result:=True;
  1102. end;
  1103. function TOmfObjInput.ReadModEnd(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  1104. var
  1105. ModEndRec: TOmfRecord_MODEND;
  1106. objsym: TObjSymbol;
  1107. objsec: TOmfObjSection;
  1108. begin
  1109. Result:=False;
  1110. ModEndRec:=TOmfRecord_MODEND.Create;
  1111. ModEndRec.DecodeFrom(RawRec);
  1112. if ModEndRec.HasStartAddress then
  1113. begin
  1114. if not ModEndRec.LogicalStartAddress then
  1115. begin
  1116. InputError('Physical start address not supported');
  1117. ModEndRec.Free;
  1118. exit;
  1119. end;
  1120. if not (ModEndRec.TargetMethod in [ftmSegmentIndex,ftmSegmentIndexNoDisp]) then
  1121. begin
  1122. InputError('Target method for start address other than "Segment Index" is not supported');
  1123. ModEndRec.Free;
  1124. exit;
  1125. end;
  1126. if (ModEndRec.TargetDatum<1) or (ModEndRec.TargetDatum>objdata.ObjSectionList.Count) then
  1127. begin
  1128. InputError('Segment name index for start address out of range');
  1129. ModEndRec.Free;
  1130. exit;
  1131. end;
  1132. objsec:=TOmfObjSection(objdata.ObjSectionList[ModEndRec.TargetDatum-1]);
  1133. objsym:=objdata.CreateSymbol('..start');
  1134. objsym.bind:=AB_GLOBAL;
  1135. objsym.typ:=AT_FUNCTION;
  1136. //objsym.group:=basegroup;
  1137. objsym.objsection:=objsec;
  1138. objsym.offset:=ModEndRec.TargetDisplacement;
  1139. objsym.size:=0;
  1140. end;
  1141. ModEndRec.Free;
  1142. Result:=True;
  1143. end;
  1144. function TOmfObjInput.ReadLEDataAndFixups(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  1145. var
  1146. Is32Bit: Boolean;
  1147. NextOfs: Integer;
  1148. SegmentIndex: Integer;
  1149. EnumeratedDataOffset: DWord;
  1150. BlockLength: Integer;
  1151. objsec: TOmfObjSection;
  1152. FixupRawRec: TOmfRawRecord;
  1153. Fixup: TOmfSubRecord_FIXUP;
  1154. begin
  1155. Result:=False;
  1156. if not (RawRec.RecordType in [RT_LEDATA,RT_LEDATA32]) then
  1157. internalerror(2015040301);
  1158. Is32Bit:=RawRec.RecordType=RT_LEDATA32;
  1159. NextOfs:=RawRec.ReadIndexedRef(0,SegmentIndex);
  1160. if Is32Bit then
  1161. begin
  1162. if (NextOfs+3)>=RawRec.RecordLength then
  1163. internalerror(2015040504);
  1164. EnumeratedDataOffset := RawRec.RawData[NextOfs]+
  1165. (RawRec.RawData[NextOfs+1] shl 8)+
  1166. (RawRec.RawData[NextOfs+2] shl 16)+
  1167. (RawRec.RawData[NextOfs+3] shl 24);
  1168. Inc(NextOfs,4);
  1169. end
  1170. else
  1171. begin
  1172. if (NextOfs+1)>=RawRec.RecordLength then
  1173. internalerror(2015040504);
  1174. EnumeratedDataOffset := RawRec.RawData[NextOfs]+
  1175. (RawRec.RawData[NextOfs+1] shl 8);
  1176. Inc(NextOfs,2);
  1177. end;
  1178. BlockLength:=RawRec.RecordLength-NextOfs-1;
  1179. if BlockLength<0 then
  1180. internalerror(2015060501);
  1181. if BlockLength>1024 then
  1182. begin
  1183. InputError('LEDATA contains more than 1024 bytes of data');
  1184. exit;
  1185. end;
  1186. if (SegmentIndex<1) or (SegmentIndex>objdata.ObjSectionList.Count) then
  1187. begin
  1188. InputError('Segment index in LEDATA field is out of range');
  1189. exit;
  1190. end;
  1191. objsec:=TOmfObjSection(objdata.ObjSectionList[SegmentIndex-1]);
  1192. objsec.SecOptions:=objsec.SecOptions+[oso_Data];
  1193. if (objsec.Data.Size<>EnumeratedDataOffset) then
  1194. begin
  1195. InputError('LEDATA enumerated data offset field out of sequence');
  1196. exit;
  1197. end;
  1198. if (EnumeratedDataOffset+BlockLength)>objsec.Size then
  1199. begin
  1200. InputError('LEDATA goes beyond the segment size declared in the SEGDEF record');
  1201. exit;
  1202. end;
  1203. objsec.Data.write(RawRec.RawData[NextOfs],BlockLength);
  1204. { also read all the FIXUPP records that may follow }
  1205. while PeekNextRecordType in [RT_FIXUPP,RT_FIXUPP32] do
  1206. begin
  1207. FixupRawRec:=TOmfRawRecord.Create;
  1208. FixupRawRec.ReadFrom(FReader);
  1209. if not FRawRecord.VerifyChecksumByte then
  1210. begin
  1211. InputError('Invalid checksum in OMF record');
  1212. FixupRawRec.Free;
  1213. exit;
  1214. end;
  1215. NextOfs:=0;
  1216. Fixup:=TOmfSubRecord_FIXUP.Create;
  1217. Fixup.Is32Bit:=FixupRawRec.RecordType=RT_FIXUPP32;
  1218. Fixup.DataRecordStartOffset:=EnumeratedDataOffset;
  1219. while NextOfs<(FixupRawRec.RecordLength-1) do
  1220. begin
  1221. NextOfs:=Fixup.ReadAt(FixupRawRec,NextOfs);
  1222. if Fixup.FrameDeterminedByThread or Fixup.TargetDeterminedByThread then
  1223. begin
  1224. InputError('Fixups determined by thread not supported');
  1225. Fixup.Free;
  1226. FixupRawRec.Free;
  1227. exit;
  1228. end;
  1229. ImportOmfFixup(objdata,objsec,Fixup);
  1230. end;
  1231. Fixup.Free;
  1232. FixupRawRec.Free;
  1233. end;
  1234. Result:=True;
  1235. end;
  1236. function TOmfObjInput.ImportOmfFixup(objdata: TObjData; objsec: TOmfObjSection; Fixup: TOmfSubRecord_FIXUP): Boolean;
  1237. var
  1238. reloc: TOmfRelocation;
  1239. sym: TObjSymbol;
  1240. RelocType: TObjRelocationType;
  1241. begin
  1242. Result:=False;
  1243. { range check location }
  1244. if (Fixup.LocationOffset+Fixup.LocationSize)>objsec.Size then
  1245. begin
  1246. InputError('Fixup location exceeds the current segment boundary');
  1247. exit;
  1248. end;
  1249. { range check target datum }
  1250. case Fixup.TargetMethod of
  1251. ftmSegmentIndex:
  1252. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.ObjSectionList.Count) then
  1253. begin
  1254. InputError('Segment name index in SI(<segment name>),<displacement> fixup target is out of range');
  1255. exit;
  1256. end;
  1257. ftmSegmentIndexNoDisp:
  1258. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.ObjSectionList.Count) then
  1259. begin
  1260. InputError('Segment name index in SI(<segment name>) fixup target is out of range');
  1261. exit;
  1262. end;
  1263. ftmGroupIndex:
  1264. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.GroupsList.Count) then
  1265. begin
  1266. InputError('Group name index in GI(<group name>),<displacement> fixup target is out of range');
  1267. exit;
  1268. end;
  1269. ftmGroupIndexNoDisp:
  1270. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.GroupsList.Count) then
  1271. begin
  1272. InputError('Group name index in GI(<group name>) fixup target is out of range');
  1273. exit;
  1274. end;
  1275. ftmExternalIndex:
  1276. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>ExtDefs.Count) then
  1277. begin
  1278. InputError('External symbol name index in EI(<symbol name>),<displacement> fixup target is out of range');
  1279. exit;
  1280. end;
  1281. ftmExternalIndexNoDisp:
  1282. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>ExtDefs.Count) then
  1283. begin
  1284. InputError('External symbol name index in EI(<symbol name>) fixup target is out of range');
  1285. exit;
  1286. end;
  1287. end;
  1288. { range check frame datum }
  1289. case Fixup.FrameMethod of
  1290. ffmSegmentIndex:
  1291. if (Fixup.FrameDatum<1) or (Fixup.FrameDatum>objdata.ObjSectionList.Count) then
  1292. begin
  1293. InputError('Segment name index in SI(<segment name>) fixup frame is out of range');
  1294. exit;
  1295. end;
  1296. ffmGroupIndex:
  1297. if (Fixup.FrameDatum<1) or (Fixup.FrameDatum>objdata.GroupsList.Count) then
  1298. begin
  1299. InputError('Group name index in GI(<group name>) fixup frame is out of range');
  1300. exit;
  1301. end;
  1302. ffmExternalIndex:
  1303. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>ExtDefs.Count) then
  1304. begin
  1305. InputError('External symbol name index in EI(<symbol name>) fixup frame is out of range');
  1306. exit;
  1307. end;
  1308. end;
  1309. if Fixup.TargetMethod in [ftmExternalIndex,ftmExternalIndexNoDisp] then
  1310. begin
  1311. sym:=objdata.symbolref(TOmfExternalNameElement(ExtDefs[Fixup.TargetDatum-1]).Name);
  1312. case Fixup.LocationType of
  1313. fltOffset:
  1314. case Fixup.Mode of
  1315. fmSegmentRelative:
  1316. RelocType:=RELOC_ABSOLUTE;
  1317. fmSelfRelative:
  1318. RelocType:=RELOC_RELATIVE;
  1319. end;
  1320. fltBase:
  1321. case Fixup.Mode of
  1322. fmSegmentRelative:
  1323. RelocType:=RELOC_SEG;
  1324. fmSelfRelative:
  1325. RelocType:=RELOC_SEGREL;
  1326. end;
  1327. else
  1328. begin
  1329. InputError('Unsupported fixup location type '+IntToStr(Ord(Fixup.LocationType))+' in external reference to '+sym.Name);
  1330. exit;
  1331. end;
  1332. end;
  1333. case Fixup.FrameMethod of
  1334. ffmTarget:
  1335. {nothing};
  1336. ffmGroupIndex:
  1337. begin
  1338. {todo: handle 'wrt dgroup' here}
  1339. end;
  1340. else
  1341. begin
  1342. InputError('Unsupported frame method '+IntToStr(Ord(Fixup.FrameMethod))+' in external reference to '+sym.Name);
  1343. exit;
  1344. end;
  1345. end;
  1346. if Fixup.TargetDisplacement<>0 then
  1347. begin
  1348. InputError('Unsupported nonzero target displacement '+IntToStr(Fixup.TargetDisplacement)+' in external reference to '+sym.Name);
  1349. exit;
  1350. end;
  1351. reloc:=TOmfRelocation.CreateSymbol(Fixup.LocationOffset,sym,RelocType);
  1352. objsec.ObjRelocations.Add(reloc);
  1353. end;
  1354. {todo: convert other fixup types as well }
  1355. Result:=True;
  1356. end;
  1357. constructor TOmfObjInput.create;
  1358. begin
  1359. inherited create;
  1360. cobjdata:=TOmfObjData;
  1361. FLNames:=TOmfOrderedNameCollection.Create;
  1362. FExtDefs:=TFPHashObjectList.Create;
  1363. FPubDefs:=TFPHashObjectList.Create;
  1364. FRawRecord:=TOmfRawRecord.Create;
  1365. CaseSensitive:=False;
  1366. end;
  1367. destructor TOmfObjInput.destroy;
  1368. begin
  1369. FRawRecord.Free;
  1370. FPubDefs.Free;
  1371. FExtDefs.Free;
  1372. FLNames.Free;
  1373. inherited destroy;
  1374. end;
  1375. class function TOmfObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  1376. var
  1377. b: Byte;
  1378. begin
  1379. result:=false;
  1380. if AReader.Read(b,sizeof(b)) then
  1381. begin
  1382. if b=RT_THEADR then
  1383. { TODO: check additional fields }
  1384. result:=true;
  1385. end;
  1386. AReader.Seek(0);
  1387. end;
  1388. function TOmfObjInput.ReadObjData(AReader: TObjectreader; out objdata: TObjData): boolean;
  1389. begin
  1390. FReader:=AReader;
  1391. InputFileName:=AReader.FileName;
  1392. objdata:=CObjData.Create(InputFileName);
  1393. result:=false;
  1394. LNames.Clear;
  1395. ExtDefs.Clear;
  1396. FRawRecord.ReadFrom(FReader);
  1397. if not FRawRecord.VerifyChecksumByte then
  1398. begin
  1399. InputError('Invalid checksum in OMF record');
  1400. exit;
  1401. end;
  1402. if FRawRecord.RecordType<>RT_THEADR then
  1403. begin
  1404. InputError('Can''t read OMF header');
  1405. exit;
  1406. end;
  1407. repeat
  1408. FRawRecord.ReadFrom(FReader);
  1409. if not FRawRecord.VerifyChecksumByte then
  1410. begin
  1411. InputError('Invalid checksum in OMF record');
  1412. exit;
  1413. end;
  1414. case FRawRecord.RecordType of
  1415. RT_LNAMES:
  1416. if not ReadLNames(FRawRecord) then
  1417. exit;
  1418. RT_SEGDEF,RT_SEGDEF32:
  1419. if not ReadSegDef(FRawRecord,objdata) then
  1420. exit;
  1421. RT_GRPDEF:
  1422. if not ReadGrpDef(FRawRecord,objdata) then
  1423. exit;
  1424. RT_COMENT:
  1425. begin
  1426. {todo}
  1427. end;
  1428. RT_EXTDEF:
  1429. if not ReadExtDef(FRawRecord,objdata) then
  1430. exit;
  1431. RT_PUBDEF,RT_PUBDEF32:
  1432. if not ReadPubDef(FRawRecord,objdata) then
  1433. exit;
  1434. RT_LEDATA,RT_LEDATA32:
  1435. if not ReadLEDataAndFixups(FRawRecord,objdata) then
  1436. exit;
  1437. RT_LIDATA,RT_LIDATA32:
  1438. begin
  1439. InputError('LIDATA records are not supported');
  1440. exit;
  1441. end;
  1442. RT_FIXUPP,RT_FIXUPP32:
  1443. begin
  1444. InputError('FIXUPP record is invalid, because it does not follow a LEDATA or LIDATA record');
  1445. exit;
  1446. end;
  1447. RT_MODEND,RT_MODEND32:
  1448. if not ReadModEnd(FRawRecord,objdata) then
  1449. exit;
  1450. else
  1451. begin
  1452. InputError('Unsupported OMF record type $'+HexStr(FRawRecord.RecordType,2));
  1453. exit;
  1454. end;
  1455. end;
  1456. until FRawRecord.RecordType in [RT_MODEND,RT_MODEND32];
  1457. result:=true;
  1458. end;
  1459. {****************************************************************************
  1460. TMZExeHeader
  1461. ****************************************************************************}
  1462. procedure TMZExeHeader.SetHeaderSizeAlignment(AValue: Integer);
  1463. begin
  1464. if (AValue<16) or ((AValue mod 16) <> 0) then
  1465. Internalerror(2015060601);
  1466. FHeaderSizeAlignment:=AValue;
  1467. end;
  1468. constructor TMZExeHeader.Create;
  1469. begin
  1470. FHeaderSizeAlignment:=16;
  1471. end;
  1472. procedure TMZExeHeader.WriteTo(aWriter: TObjectWriter);
  1473. var
  1474. NumRelocs: Word;
  1475. HeaderSizeInBytes: DWord;
  1476. HeaderParagraphs: Word;
  1477. RelocTableOffset: Word;
  1478. BytesInLastBlock: Word;
  1479. BlocksInFile: Word;
  1480. HeaderBytes: array [0..$1B] of Byte;
  1481. RelocBytes: array [0..3] of Byte;
  1482. TotalExeSize: DWord;
  1483. i: Integer;
  1484. begin
  1485. NumRelocs:=Length(Relocations);
  1486. RelocTableOffset:=$1C+Length(ExtraHeaderData);
  1487. HeaderSizeInBytes:=Align(RelocTableOffset+4*NumRelocs,16);
  1488. HeaderParagraphs:=HeaderSizeInBytes div 16;
  1489. TotalExeSize:=HeaderSizeInBytes+LoadableImageSize;
  1490. BlocksInFile:=(TotalExeSize+511) div 512;
  1491. BytesInLastBlock:=TotalExeSize mod 512;
  1492. HeaderBytes[$00]:=$4D; { 'M' }
  1493. HeaderBytes[$01]:=$5A; { 'Z' }
  1494. HeaderBytes[$02]:=Byte(BytesInLastBlock);
  1495. HeaderBytes[$03]:=Byte(BytesInLastBlock shr 8);
  1496. HeaderBytes[$04]:=Byte(BlocksInFile);
  1497. HeaderBytes[$05]:=Byte(BlocksInFile shr 8);
  1498. HeaderBytes[$06]:=Byte(NumRelocs);
  1499. HeaderBytes[$07]:=Byte(NumRelocs shr 8);
  1500. HeaderBytes[$08]:=Byte(HeaderParagraphs);
  1501. HeaderBytes[$09]:=Byte(HeaderParagraphs shr 8);
  1502. HeaderBytes[$0A]:=Byte(MinExtraParagraphs);
  1503. HeaderBytes[$0B]:=Byte(MinExtraParagraphs shr 8);
  1504. HeaderBytes[$0C]:=Byte(MaxExtraParagraphs);
  1505. HeaderBytes[$0D]:=Byte(MaxExtraParagraphs shr 8);
  1506. HeaderBytes[$0E]:=Byte(InitialSS);
  1507. HeaderBytes[$0F]:=Byte(InitialSS shr 8);
  1508. HeaderBytes[$10]:=Byte(InitialSP);
  1509. HeaderBytes[$11]:=Byte(InitialSP shr 8);
  1510. HeaderBytes[$12]:=Byte(Checksum);
  1511. HeaderBytes[$13]:=Byte(Checksum shr 8);
  1512. HeaderBytes[$14]:=Byte(InitialIP);
  1513. HeaderBytes[$15]:=Byte(InitialIP shr 8);
  1514. HeaderBytes[$16]:=Byte(InitialCS);
  1515. HeaderBytes[$17]:=Byte(InitialCS shr 8);
  1516. HeaderBytes[$18]:=Byte(RelocTableOffset);
  1517. HeaderBytes[$19]:=Byte(RelocTableOffset shr 8);
  1518. HeaderBytes[$1A]:=Byte(OverlayNumber);
  1519. HeaderBytes[$1B]:=Byte(OverlayNumber shr 8);
  1520. aWriter.write(HeaderBytes[0],$1C);
  1521. aWriter.write(ExtraHeaderData[0],Length(ExtraHeaderData));
  1522. for i:=0 to NumRelocs-1 do
  1523. with Relocations[i] do
  1524. begin
  1525. RelocBytes[0]:=Byte(offset);
  1526. RelocBytes[1]:=Byte(offset shr 8);
  1527. RelocBytes[2]:=Byte(segment);
  1528. RelocBytes[3]:=Byte(segment shr 8);
  1529. aWriter.write(RelocBytes[0],4);
  1530. end;
  1531. { pad with zeros until the end of header (paragraph aligned) }
  1532. aWriter.WriteZeros(HeaderSizeInBytes-aWriter.Size);
  1533. end;
  1534. {****************************************************************************
  1535. TMZExeSection
  1536. ****************************************************************************}
  1537. procedure TMZExeSection.AddObjSection(objsec: TObjSection; ignoreprops: boolean);
  1538. begin
  1539. { allow mixing initialized and uninitialized data in the same section
  1540. => set ignoreprops=true }
  1541. inherited AddObjSection(objsec,true);
  1542. end;
  1543. {****************************************************************************
  1544. TMZExeOutput
  1545. ****************************************************************************}
  1546. procedure TMZExeOutput.DoRelocationFixup(objsec: TObjSection);
  1547. var
  1548. i: Integer;
  1549. objreloc: TOmfRelocation;
  1550. begin
  1551. for i:=0 to objsec.ObjRelocations.Count-1 do
  1552. begin
  1553. objreloc:=TOmfRelocation(objsec.ObjRelocations[i]);
  1554. {todo}
  1555. end;
  1556. end;
  1557. function IOmfObjSectionClassNameCompare(Item1, Item2: Pointer): Integer;
  1558. var
  1559. I1 : TOmfObjSection absolute Item1;
  1560. I2 : TOmfObjSection absolute Item2;
  1561. begin
  1562. Result:=CompareStr(I1.ClassName,I2.ClassName);
  1563. if Result=0 then
  1564. Result:=CompareStr(I1.Name,I2.Name);
  1565. end;
  1566. procedure TMZExeOutput.Order_ObjSectionList(ObjSectionList: TFPObjectList; const aPattern: string);
  1567. begin
  1568. ObjSectionList.Sort(@IOmfObjSectionClassNameCompare);
  1569. end;
  1570. function TMZExeOutput.writeData: boolean;
  1571. var
  1572. Header: TMZExeHeader;
  1573. begin
  1574. Result:=False;
  1575. Header:=TMZExeHeader.Create;
  1576. {todo: fill header data}
  1577. Header.WriteTo(FWriter);
  1578. Header.Free;
  1579. Result:=True;
  1580. end;
  1581. constructor TMZExeOutput.create;
  1582. begin
  1583. inherited create;
  1584. CExeSection:=TMZExeSection;
  1585. CObjData:=TOmfObjData;
  1586. { "640K ought to be enough for anybody" :) }
  1587. MaxMemPos:=$9FFFF;
  1588. end;
  1589. {****************************************************************************
  1590. TOmfAssembler
  1591. ****************************************************************************}
  1592. constructor TOmfAssembler.Create(smart:boolean);
  1593. begin
  1594. inherited Create(smart);
  1595. CObjOutput:=TOmfObjOutput;
  1596. CInternalAr:=TOmfLibObjectWriter;
  1597. end;
  1598. {*****************************************************************************
  1599. Initialize
  1600. *****************************************************************************}
  1601. {$ifdef i8086}
  1602. const
  1603. as_i8086_omf_info : tasminfo =
  1604. (
  1605. id : as_i8086_omf;
  1606. idtxt : 'OMF';
  1607. asmbin : '';
  1608. asmcmd : '';
  1609. supported_targets : [system_i8086_msdos];
  1610. flags : [af_outputbinary,af_no_debug];
  1611. labelprefix : '..@';
  1612. comment : '; ';
  1613. dollarsign: '$';
  1614. );
  1615. {$endif i8086}
  1616. initialization
  1617. {$ifdef i8086}
  1618. RegisterAssembler(as_i8086_omf_info,TOmfAssembler);
  1619. {$endif i8086}
  1620. end.