ogomf.pas 77 KB

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