ogomf.pas 83 KB

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