ogomf.pas 92 KB

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