ogomf.pas 90 KB

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