ogomf.pas 92 KB

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