ogomf.pas 93 KB

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