ogomf.pas 97 KB

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