ogomf.pas 79 KB

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