ogomf.pas 94 KB

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