ogomf.pas 61 KB

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