ogomf.pas 91 KB

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