ogomf.pas 137 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561
  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. {$PackSet 1}
  21. interface
  22. uses
  23. { common }
  24. cclasses,globtype,
  25. { target }
  26. systems,
  27. { assembler }
  28. cpuinfo,cpubase,aasmbase,assemble,link,
  29. { OMF definitions }
  30. omfbase,
  31. { output }
  32. ogbase,
  33. owbase;
  34. type
  35. { TOmfObjSymbol }
  36. TOmfObjSymbol = class(TObjSymbol)
  37. public
  38. { string representation for the linker map file }
  39. function AddressStr(AImageBase: qword): string;override;
  40. end;
  41. { TOmfRelocation }
  42. TOmfRelocation = class(TObjRelocation)
  43. private
  44. FFrameGroup: string;
  45. FOmfFixup: TOmfSubRecord_FIXUP;
  46. public
  47. destructor Destroy; override;
  48. procedure BuildOmfFixup;
  49. property FrameGroup: string read FFrameGroup write FFrameGroup;
  50. property OmfFixup: TOmfSubRecord_FIXUP read FOmfFixup;
  51. end;
  52. TMZExeUnifiedLogicalSegment=class;
  53. { TOmfObjSection }
  54. TOmfObjSection = class(TObjSection)
  55. private
  56. FClassName: string;
  57. FOverlayName: string;
  58. FCombination: TOmfSegmentCombination;
  59. FUse: TOmfSegmentUse;
  60. FPrimaryGroup: TObjSectionGroup;
  61. FSortOrder: Integer;
  62. FMZExeUnifiedLogicalSegment: TMZExeUnifiedLogicalSegment;
  63. FLinNumEntries: TOmfSubRecord_LINNUM_MsLink_LineNumberList;
  64. function GetOmfAlignment: TOmfSegmentAlignment;
  65. public
  66. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
  67. destructor destroy;override;
  68. function MemPosStr(AImageBase: qword): string;override;
  69. property ClassName: string read FClassName;
  70. property OverlayName: string read FOverlayName;
  71. property OmfAlignment: TOmfSegmentAlignment read GetOmfAlignment;
  72. property Combination: TOmfSegmentCombination read FCombination;
  73. property Use: TOmfSegmentUse read FUse;
  74. property PrimaryGroup: TObjSectionGroup read FPrimaryGroup;
  75. property SortOrder: Integer read FSortOrder write FSortOrder;
  76. property MZExeUnifiedLogicalSegment: TMZExeUnifiedLogicalSegment read FMZExeUnifiedLogicalSegment write FMZExeUnifiedLogicalSegment;
  77. property LinNumEntries: TOmfSubRecord_LINNUM_MsLink_LineNumberList read FLinNumEntries;
  78. end;
  79. { TOmfObjData }
  80. TOmfObjData = class(TObjData)
  81. private
  82. FMainSource: TPathStr;
  83. class function CodeSectionName(const aname:string): string;
  84. public
  85. constructor create(const n:string);override;
  86. function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;override;
  87. function sectiontype2align(atype:TAsmSectiontype):longint;override;
  88. function sectiontype2class(atype:TAsmSectiontype):string;
  89. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  90. function createsection(atype:TAsmSectionType;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;override;
  91. function reffardatasection:TObjSection;
  92. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  93. property MainSource: TPathStr read FMainSource;
  94. end;
  95. { TOmfObjOutput }
  96. TOmfObjOutput = class(tObjOutput)
  97. private
  98. FLNames: TOmfOrderedNameCollection;
  99. FSegments: TFPHashObjectList;
  100. FGroups: TFPHashObjectList;
  101. procedure AddSegment(const name,segclass,ovlname: string;
  102. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  103. Use: TOmfSegmentUse; Size: TObjSectionOfs);
  104. procedure AddGroup(group: TObjSectionGroup);
  105. procedure WriteSections(Data:TObjData);
  106. procedure WriteSectionContentAndFixups(sec: TObjSection);
  107. procedure WriteLinNumRecords(sec: TOmfObjSection);
  108. procedure section_count_sections(p:TObject;arg:pointer);
  109. procedure group_count_groups(p:TObject;arg:pointer);
  110. procedure WritePUBDEFs(Data: TObjData);
  111. procedure WriteEXTDEFs(Data: TObjData);
  112. property LNames: TOmfOrderedNameCollection read FLNames;
  113. property Segments: TFPHashObjectList read FSegments;
  114. property Groups: TFPHashObjectList read FGroups;
  115. protected
  116. function writeData(Data:TObjData):boolean;override;
  117. public
  118. constructor create(AWriter:TObjectWriter);override;
  119. destructor Destroy;override;
  120. procedure WriteDllImport(const dllname,afuncname,mangledname:string;ordnr:longint;isvar:boolean);
  121. end;
  122. { TOmfObjInput }
  123. TOmfObjInput = class(TObjInput)
  124. private
  125. FLNames: TOmfOrderedNameCollection;
  126. FExtDefs: TFPHashObjectList;
  127. FPubDefs: TFPHashObjectList;
  128. FFixupThreads: TOmfThreads;
  129. FRawRecord: TOmfRawRecord;
  130. FCOMENTRecord: TOmfRecord_COMENT;
  131. FCaseSensitiveSegments: Boolean;
  132. FCaseSensitiveSymbols: Boolean;
  133. function PeekNextRecordType: Byte;
  134. function ReadLNames(RawRec: TOmfRawRecord): Boolean;
  135. function ReadSegDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  136. function ReadGrpDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  137. function ReadExtDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  138. function ReadPubDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  139. function ReadModEnd(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  140. function ReadLeOrLiDataAndFixups(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  141. function ReadImpDef(Rec: TOmfRecord_COMENT): Boolean;
  142. function ReadExpDef(Rec: TOmfRecord_COMENT): Boolean;
  143. function ImportOmfFixup(objdata: TObjData; objsec: TOmfObjSection; Fixup: TOmfSubRecord_FIXUP): Boolean;
  144. property LNames: TOmfOrderedNameCollection read FLNames;
  145. property ExtDefs: TFPHashObjectList read FExtDefs;
  146. property PubDefs: TFPHashObjectList read FPubDefs;
  147. { Specifies whether we're case sensitive in regards to segment, class, overlay and group names. }
  148. property CaseSensitiveSegments: Boolean read FCaseSensitiveSegments write FCaseSensitiveSegments;
  149. { Specifies whether symbol names (in EXTDEF and PUBDEF records) are case sensitive. }
  150. property CaseSensitiveSymbols: Boolean read FCaseSensitiveSymbols write FCaseSensitiveSymbols;
  151. public
  152. constructor create;override;
  153. destructor destroy;override;
  154. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  155. function ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;override;
  156. end;
  157. { TMZExeRelocation }
  158. TMZExeRelocation = record
  159. offset: Word;
  160. segment: Word;
  161. end;
  162. TMZExeRelocations = array of TMZExeRelocation;
  163. TMZExeExtraHeaderData = array of Byte;
  164. { TMZExeHeader }
  165. TMZExeHeader = class
  166. private
  167. FChecksum: Word;
  168. FExtraHeaderData: TMZExeExtraHeaderData;
  169. FHeaderSizeAlignment: Integer;
  170. FInitialCS: Word;
  171. FInitialIP: Word;
  172. FInitialSP: Word;
  173. FInitialSS: Word;
  174. FLoadableImageSize: DWord;
  175. FMaxExtraParagraphs: Word;
  176. FMinExtraParagraphs: Word;
  177. FOverlayNumber: Word;
  178. FRelocations: TMZExeRelocations;
  179. procedure SetHeaderSizeAlignment(AValue: Integer);
  180. public
  181. constructor Create;
  182. procedure WriteTo(aWriter: TObjectWriter);
  183. procedure AddRelocation(aSegment,aOffset: Word);
  184. property HeaderSizeAlignment: Integer read FHeaderSizeAlignment write SetHeaderSizeAlignment; {default=16, must be multiple of 16}
  185. property Relocations: TMZExeRelocations read FRelocations write FRelocations;
  186. property ExtraHeaderData: TMZExeExtraHeaderData read FExtraHeaderData write FExtraHeaderData;
  187. property LoadableImageSize: DWord read FLoadableImageSize write FLoadableImageSize;
  188. property MinExtraParagraphs: Word read FMinExtraParagraphs write FMinExtraParagraphs;
  189. property MaxExtraParagraphs: Word read FMaxExtraParagraphs write FMaxExtraParagraphs;
  190. property InitialSS: Word read FInitialSS write FInitialSS;
  191. property InitialSP: Word read FInitialSP write FInitialSP;
  192. property Checksum: Word read FChecksum write FChecksum;
  193. property InitialIP: Word read FInitialIP write FInitialIP;
  194. property InitialCS: Word read FInitialCS write FInitialCS;
  195. property OverlayNumber: Word read FOverlayNumber write FOverlayNumber;
  196. end;
  197. { TMZExeSection }
  198. TMZExeSection=class(TExeSection)
  199. public
  200. procedure AddObjSection(objsec:TObjSection;ignoreprops:boolean=false);override;
  201. end;
  202. { TMZExeUnifiedLogicalSegment }
  203. TMZExeUnifiedLogicalSegment=class(TFPHashObject)
  204. private
  205. FObjSectionList: TFPObjectList;
  206. FSegName: TSymStr;
  207. FSegClass: TSymStr;
  208. FPrimaryGroup: string;
  209. public
  210. Size,
  211. MemPos,
  212. MemBasePos: qword;
  213. IsStack: Boolean;
  214. constructor create(HashObjectList:TFPHashObjectList;const s:TSymStr);
  215. destructor destroy;override;
  216. procedure AddObjSection(ObjSec: TOmfObjSection);
  217. procedure CalcMemPos;
  218. function MemPosStr:string;
  219. property ObjSectionList: TFPObjectList read FObjSectionList;
  220. property SegName: TSymStr read FSegName;
  221. property SegClass: TSymStr read FSegClass;
  222. property PrimaryGroup: string read FPrimaryGroup write FPrimaryGroup;
  223. end;
  224. { TMZExeUnifiedLogicalGroup }
  225. TMZExeUnifiedLogicalGroup=class(TFPHashObject)
  226. private
  227. FSegmentList: TFPHashObjectList;
  228. public
  229. Size,
  230. MemPos: qword;
  231. constructor create(HashObjectList:TFPHashObjectList;const s:TSymStr);
  232. destructor destroy;override;
  233. procedure CalcMemPos;
  234. function MemPosStr:string;
  235. procedure AddSegment(UniSeg: TMZExeUnifiedLogicalSegment);
  236. property SegmentList: TFPHashObjectList read FSegmentList;
  237. end;
  238. { TMZExeOutput }
  239. TMZExeOutput = class(TExeOutput)
  240. private
  241. FMZFlatContentSection: TMZExeSection;
  242. FExeUnifiedLogicalSegments: TFPHashObjectList;
  243. FExeUnifiedLogicalGroups: TFPHashObjectList;
  244. FDwarfUnifiedLogicalSegments: TFPHashObjectList;
  245. FHeader: TMZExeHeader;
  246. function GetMZFlatContentSection: TMZExeSection;
  247. procedure CalcDwarfUnifiedLogicalSegmentsForSection(const SecName: TSymStr);
  248. procedure CalcExeUnifiedLogicalSegments;
  249. procedure CalcExeGroups;
  250. procedure CalcSegments_MemBasePos;
  251. procedure WriteMap_SegmentsAndGroups;
  252. procedure WriteMap_HeaderData;
  253. function FindStackSegment: TMZExeUnifiedLogicalSegment;
  254. procedure FillLoadableImageSize;
  255. procedure FillMinExtraParagraphs;
  256. procedure FillMaxExtraParagraphs;
  257. procedure FillStartAddress;
  258. procedure FillStackAddress;
  259. procedure FillHeaderData;
  260. function writeExe:boolean;
  261. function writeCom:boolean;
  262. function writeDebugElf:boolean;
  263. property ExeUnifiedLogicalSegments: TFPHashObjectList read FExeUnifiedLogicalSegments;
  264. property ExeUnifiedLogicalGroups: TFPHashObjectList read FExeUnifiedLogicalGroups;
  265. property DwarfUnifiedLogicalSegments: TFPHashObjectList read FExeUnifiedLogicalSegments;
  266. property Header: TMZExeHeader read FHeader;
  267. protected
  268. procedure Load_Symbol(const aname:string);override;
  269. procedure DoRelocationFixup(objsec:TObjSection);override;
  270. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList;const aPattern:string);override;
  271. procedure MemPos_ExeSection(const aname:string);override;
  272. procedure MemPos_EndExeSection;override;
  273. function writeData:boolean;override;
  274. public
  275. constructor create;override;
  276. destructor destroy;override;
  277. property MZFlatContentSection: TMZExeSection read GetMZFlatContentSection;
  278. end;
  279. TNewExeHeaderFlag = (
  280. nehfSingleData, { bit 0 }
  281. nehfMultipleData, { bit 1 }
  282. { 'Global initialization' according to BP7's TDUMP.EXE }
  283. nehfRealMode, { bit 2 }
  284. nehfProtectedModeOnly, { bit 3 }
  285. { 'EMSDIRECT' according to OpenWatcom's wdump }
  286. { '8086 instructions' according to Ralf Brown's Interrupt List }
  287. nehfReserved4, { bit 4 }
  288. { 'EMSBANK' according to OpenWatcom's wdump }
  289. { '80286 instructions' according to Ralf Brown's Interrupt List }
  290. nehfReserved5, { bit 5 }
  291. { 'EMSGLOBAL' according to OpenWatcom's wdump }
  292. { '80386 instructions' according to Ralf Brown's Interrupt List }
  293. nehfReserved6, { bit 6 }
  294. nehfNeedsFPU, { bit 7 }
  295. { Not compatible with windowing API }
  296. nehfNotWindowAPICompatible, { bit 8 }
  297. { Compatible with windowing API }
  298. { (NotWindowAPICompatible + WindowAPICompatible) = Uses windowing API }
  299. nehfWindowAPICompatible, { bit 9 }
  300. { Family Application (OS/2) according to Ralf Brown's Interrupt List }
  301. nehfReserved10, { bit 10 }
  302. nehfSelfLoading, { bit 11 }
  303. nehfReserved12, { bit 12 }
  304. nehfLinkErrors, { bit 13 }
  305. nehfReserved14, { bit 14 }
  306. nehfIsDLL); { bit 15 }
  307. TNewExeHeaderFlags = set of TNewExeHeaderFlag;
  308. TNewExeAdditionalHeaderFlag = (
  309. neahfLFNSupport, { bit 0 }
  310. neahfWindows2ProtectedMode, { bit 1 }
  311. neahfWindows2ProportionalFonts, { bit 2 }
  312. neahfHasGangloadArea); { bit 3 }
  313. TNewExeAdditionalHeaderFlags = set of TNewExeAdditionalHeaderFlag;
  314. TNewExeTargetOS = (
  315. netoUnknown = $00,
  316. netoOS2 = $01,
  317. netoWindows = $02,
  318. netoMultitaskingMsDos4 = $03,
  319. netoWindows386 = $04,
  320. netoBorlandOperatingSystemServices = $05,
  321. netoPharLap286DosExtenderOS2 = $81,
  322. netoPharLap286DosExtenderWindows = $82);
  323. TNewExeSegmentFlag = (
  324. nesfData, { bit 0 }
  325. nesfLoaderAllocatedMemory, { bit 1 }
  326. nesfLoaded, { bit 2 }
  327. nesfReserved3, { bit 3 }
  328. nesfMovable, { bit 4 }
  329. nesfShareable, { bit 5 }
  330. nesfPreload, { bit 6 }
  331. nesfExecuteOnlyCodeOrReadOnlyData, { bit 7 }
  332. nesfHasRelocationData, { bit 8 }
  333. nesfReserved9, { bit 9 }
  334. nesfReserved10, { bit 10 }
  335. nesfReserved11, { bit 11 }
  336. nesfDiscardable, { bit 12 }
  337. nesfReserved13, { bit 13 }
  338. nesfReserved14, { bit 14 }
  339. nesfReserved15); { bit 15 }
  340. TNewExeSegmentFlags = set of TNewExeSegmentFlag;
  341. TNewExeMsDosStub = array of byte;
  342. { TNewExeHeader }
  343. TNewExeHeader = class
  344. private
  345. FMsDosStub: TNewExeMsDosStub;
  346. FLinkerVersion: Byte;
  347. FLinkerRevision: Byte;
  348. FEntryTableOffset: Word;
  349. FEntryTableLength: Word;
  350. FReserved: LongWord;
  351. FFlags: TNewExeHeaderFlags;
  352. FAutoDataSegmentNumber: Word;
  353. FInitialLocalHeapSize: Word;
  354. FInitialStackSize: Word;
  355. FInitialIP: Word;
  356. FInitialCS: Word;
  357. FInitialSP: Word;
  358. FInitialSS: Word;
  359. FSegmentTableEntriesCount: Word;
  360. FModuleReferenceTableEntriesCount: Word;
  361. FNonresidentNameTableLength: Word;
  362. FSegmentTableStart: Word;
  363. FResourceTableStart: Word;
  364. FResidentNameTableStart: Word;
  365. FModuleReferenceTableStart: Word;
  366. FImportedNameTableStart: Word;
  367. FNonresidentNameTableStart: LongWord;
  368. FMovableEntryPointsCount: Word;
  369. FLogicalSectorAlignmentShiftCount: Word;
  370. FResourceSegmentsCount: Word;
  371. FTargetOS: TNewExeTargetOS;
  372. FAdditionalFlags: TNewExeAdditionalHeaderFlags;
  373. FGangLoadAreaStart: Word;
  374. FGangLoadAreaLength: Word;
  375. FReserved2: Word;
  376. FExpectedWindowsVersion: Word;
  377. public
  378. constructor Create;
  379. procedure WriteTo(aWriter: TObjectWriter);
  380. property MsDosStub: TNewExeMsDosStub read FMsDosStub write FMsDosStub;
  381. property LinkerVersion: Byte read FLinkerVersion write FLinkerVersion;
  382. property LinkerRevision: Byte read FLinkerRevision write FLinkerRevision;
  383. property EntryTableOffset: Word read FEntryTableOffset write FEntryTableOffset;
  384. property EntryTableLength: Word read FEntryTableLength write FEntryTableLength;
  385. property Reserved: LongWord read FReserved write FReserved;
  386. property Flags: TNewExeHeaderFlags read FFlags write FFlags;
  387. property AutoDataSegmentNumber: Word read FAutoDataSegmentNumber write FAutoDataSegmentNumber;
  388. property InitialLocalHeapSize: Word read FInitialLocalHeapSize write FInitialLocalHeapSize;
  389. property InitialStackSize: Word read FInitialStackSize write FInitialStackSize;
  390. property InitialIP: Word read FInitialIP write FInitialIP;
  391. property InitialCS: Word read FInitialCS write FInitialCS;
  392. property InitialSP: Word read FInitialSP write FInitialSP;
  393. property InitialSS: Word read FInitialSS write FInitialSS;
  394. property SegmentTableEntriesCount: Word read FSegmentTableEntriesCount write FSegmentTableEntriesCount;
  395. property ModuleReferenceTableEntriesCount: Word read FModuleReferenceTableEntriesCount write FModuleReferenceTableEntriesCount;
  396. property NonresidentNameTableLength: Word read FNonresidentNameTableLength write FNonresidentNameTableLength;
  397. property SegmentTableStart: Word read FSegmentTableStart write FSegmentTableStart;
  398. property ResourceTableStart: Word read FResourceTableStart write FResourceTableStart;
  399. property ResidentNameTableStart: Word read FResidentNameTableStart write FResidentNameTableStart;
  400. property ModuleReferenceTableStart: Word read FModuleReferenceTableStart write FModuleReferenceTableStart;
  401. property ImportedNameTableStart: Word read FImportedNameTableStart write FImportedNameTableStart;
  402. property NonresidentNameTableStart: LongWord read FNonresidentNameTableStart write FNonresidentNameTableStart;
  403. property MovableEntryPointsCount: Word read FMovableEntryPointsCount write FMovableEntryPointsCount;
  404. property LogicalSectorAlignmentShiftCount: Word read FLogicalSectorAlignmentShiftCount write FLogicalSectorAlignmentShiftCount;
  405. property ResourceSegmentsCount: Word read FResourceSegmentsCount write FResourceSegmentsCount;
  406. property TargetOS: TNewExeTargetOS read FTargetOS write FTargetOS;
  407. property AdditionalFlags: TNewExeAdditionalHeaderFlags read FAdditionalFlags write FAdditionalFlags;
  408. property GangLoadAreaStart: Word read FGangLoadAreaStart write FGangLoadAreaStart;
  409. property GangLoadAreaLength: Word read FGangLoadAreaLength write FGangLoadAreaLength;
  410. property Reserved2: Word read FReserved2 write FReserved2;
  411. property ExpectedWindowsVersion: Word read FExpectedWindowsVersion write FExpectedWindowsVersion;
  412. end;
  413. { TNewExeOutput }
  414. TNewExeOutput = class(TExeOutput)
  415. private
  416. FHeader: TNewExeHeader;
  417. protected
  418. procedure DoRelocationFixup(objsec:TObjSection);override;
  419. public
  420. constructor create;override;
  421. destructor destroy;override;
  422. function writeData:boolean;override;
  423. end;
  424. TOmfAssembler = class(tinternalassembler)
  425. constructor create(info: pasminfo; smart:boolean);override;
  426. end;
  427. implementation
  428. uses
  429. SysUtils,
  430. cutils,verbose,globals,
  431. fmodule,aasmtai,aasmdata,
  432. ogmap,owomflib,elfbase,
  433. version
  434. ;
  435. const win16stub : array[0..255] of byte=(
  436. $4d,$5a,$00,$01,$01,$00,$00,$00,$08,$00,$10,$00,$ff,$ff,$08,$00,
  437. $00,$01,$00,$00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,
  438. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  439. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$00,
  440. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  441. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  442. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  443. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  444. $ba,$10,$00,$0e,$1f,$b4,$09,$cd,$21,$b8,$01,$4c,$cd,$21,$90,$90,
  445. $54,$68,$69,$73,$20,$70,$72,$6f,$67,$72,$61,$6d,$20,$72,$65,$71,
  446. $75,$69,$72,$65,$73,$20,$4d,$69,$63,$72,$6f,$73,$6f,$66,$74,$20,
  447. $57,$69,$6e,$64,$6f,$77,$73,$2e,$0d,$0a,$24,$20,$20,$20,$20,$20,
  448. $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
  449. $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
  450. $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
  451. $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20);
  452. {****************************************************************************
  453. TTISTrailer
  454. ****************************************************************************}
  455. const
  456. TIS_TRAILER_SIGNATURE: array[1..4] of char='TIS'#0;
  457. TIS_TRAILER_VENDOR_TIS=0;
  458. TIS_TRAILER_TYPE_TIS_DWARF=0;
  459. type
  460. TTISTrailer=record
  461. tis_signature: array[1..4] of char;
  462. tis_vendor,
  463. tis_type,
  464. tis_size: LongWord;
  465. end;
  466. procedure MayBeSwapTISTrailer(var h: TTISTrailer);
  467. begin
  468. if source_info.endian<>target_info.endian then
  469. with h do
  470. begin
  471. tis_vendor:=swapendian(tis_vendor);
  472. tis_type:=swapendian(tis_type);
  473. tis_size:=swapendian(tis_size);
  474. end;
  475. end;
  476. {****************************************************************************
  477. TOmfObjSymbol
  478. ****************************************************************************}
  479. function TOmfObjSymbol.AddressStr(AImageBase: qword): string;
  480. var
  481. base: qword;
  482. begin
  483. if assigned(TOmfObjSection(objsection).MZExeUnifiedLogicalSegment) then
  484. base:=TOmfObjSection(objsection).MZExeUnifiedLogicalSegment.MemBasePos
  485. else
  486. base:=(address shr 4) shl 4;
  487. Result:=HexStr(base shr 4,4)+':'+HexStr(address-base,4);
  488. end;
  489. {****************************************************************************
  490. TOmfRelocation
  491. ****************************************************************************}
  492. destructor TOmfRelocation.Destroy;
  493. begin
  494. FOmfFixup.Free;
  495. inherited Destroy;
  496. end;
  497. procedure TOmfRelocation.BuildOmfFixup;
  498. begin
  499. FreeAndNil(FOmfFixup);
  500. FOmfFixup:=TOmfSubRecord_FIXUP.Create;
  501. if ObjSection<>nil then
  502. begin
  503. FOmfFixup.LocationOffset:=DataOffset;
  504. if typ in [RELOC_ABSOLUTE16,RELOC_RELATIVE16] then
  505. FOmfFixup.LocationType:=fltOffset
  506. else if typ in [RELOC_ABSOLUTE32,RELOC_RELATIVE32] then
  507. FOmfFixup.LocationType:=fltOffset32
  508. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  509. FOmfFixup.LocationType:=fltBase
  510. else
  511. internalerror(2015041501);
  512. FOmfFixup.FrameDeterminedByThread:=False;
  513. FOmfFixup.TargetDeterminedByThread:=False;
  514. if typ in [RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_SEG] then
  515. FOmfFixup.Mode:=fmSegmentRelative
  516. else if typ in [RELOC_RELATIVE16,RELOC_RELATIVE32,RELOC_SEGREL] then
  517. FOmfFixup.Mode:=fmSelfRelative
  518. else
  519. internalerror(2015041401);
  520. if typ in [RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_RELATIVE16,RELOC_RELATIVE32] then
  521. begin
  522. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  523. FOmfFixup.TargetDatum:=ObjSection.Index;
  524. if TOmfObjSection(ObjSection).PrimaryGroup<>nil then
  525. begin
  526. FOmfFixup.FrameMethod:=ffmGroupIndex;
  527. FOmfFixup.FrameDatum:=TOmfObjSection(ObjSection).PrimaryGroup.index;
  528. end
  529. else
  530. FOmfFixup.FrameMethod:=ffmTarget;
  531. end
  532. else
  533. begin
  534. FOmfFixup.FrameMethod:=ffmTarget;
  535. if TOmfObjSection(ObjSection).PrimaryGroup<>nil then
  536. begin
  537. FOmfFixup.TargetMethod:=ftmGroupIndexNoDisp;
  538. FOmfFixup.TargetDatum:=TOmfObjSection(ObjSection).PrimaryGroup.index;
  539. end
  540. else
  541. begin
  542. FOmfFixup.TargetMethod:=ftmSegmentIndexNoDisp;
  543. FOmfFixup.TargetDatum:=ObjSection.Index;
  544. end;
  545. end;
  546. end
  547. else if symbol<>nil then
  548. begin
  549. FOmfFixup.LocationOffset:=DataOffset;
  550. if typ in [RELOC_ABSOLUTE16,RELOC_RELATIVE16] then
  551. FOmfFixup.LocationType:=fltOffset
  552. else if typ in [RELOC_ABSOLUTE32,RELOC_RELATIVE32] then
  553. FOmfFixup.LocationType:=fltOffset32
  554. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  555. FOmfFixup.LocationType:=fltBase
  556. else
  557. internalerror(2015041501);
  558. FOmfFixup.FrameDeterminedByThread:=False;
  559. FOmfFixup.TargetDeterminedByThread:=False;
  560. if typ in [RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_SEG] then
  561. FOmfFixup.Mode:=fmSegmentRelative
  562. else if typ in [RELOC_RELATIVE16,RELOC_RELATIVE32,RELOC_SEGREL] then
  563. FOmfFixup.Mode:=fmSelfRelative
  564. else
  565. internalerror(2015041401);
  566. FOmfFixup.TargetMethod:=ftmExternalIndexNoDisp;
  567. FOmfFixup.TargetDatum:=symbol.symidx;
  568. FOmfFixup.FrameMethod:=ffmTarget;
  569. end
  570. else if group<>nil then
  571. begin
  572. FOmfFixup.LocationOffset:=DataOffset;
  573. if typ in [RELOC_ABSOLUTE16,RELOC_RELATIVE16] then
  574. FOmfFixup.LocationType:=fltOffset
  575. else if typ in [RELOC_ABSOLUTE32,RELOC_RELATIVE32] then
  576. FOmfFixup.LocationType:=fltOffset32
  577. else if typ in [RELOC_SEG,RELOC_SEGREL] then
  578. FOmfFixup.LocationType:=fltBase
  579. else
  580. internalerror(2015041501);
  581. FOmfFixup.FrameDeterminedByThread:=False;
  582. FOmfFixup.TargetDeterminedByThread:=False;
  583. if typ in [RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_SEG] then
  584. FOmfFixup.Mode:=fmSegmentRelative
  585. else if typ in [RELOC_RELATIVE16,RELOC_RELATIVE32,RELOC_SEGREL] then
  586. FOmfFixup.Mode:=fmSelfRelative
  587. else
  588. internalerror(2015041401);
  589. FOmfFixup.FrameMethod:=ffmTarget;
  590. FOmfFixup.TargetMethod:=ftmGroupIndexNoDisp;
  591. FOmfFixup.TargetDatum:=group.index;
  592. end
  593. else
  594. internalerror(2015040702);
  595. end;
  596. {****************************************************************************
  597. TOmfObjSection
  598. ****************************************************************************}
  599. function TOmfObjSection.GetOmfAlignment: TOmfSegmentAlignment;
  600. begin
  601. case SecAlign of
  602. 1:
  603. result:=saRelocatableByteAligned;
  604. 2:
  605. result:=saRelocatableWordAligned;
  606. 4:
  607. result:=saRelocatableDWordAligned;
  608. 16:
  609. result:=saRelocatableParaAligned;
  610. 256:
  611. result:=saRelocatablePageAligned;
  612. 4096:
  613. result:=saNotSupported;
  614. else
  615. internalerror(2015041504);
  616. end;
  617. end;
  618. constructor TOmfObjSection.create(AList: TFPHashObjectList;
  619. const Aname: string; Aalign: longint; Aoptions: TObjSectionOptions);
  620. begin
  621. inherited create(AList, Aname, Aalign, Aoptions);
  622. FCombination:=scPublic;
  623. FUse:=suUse16;
  624. FLinNumEntries:=TOmfSubRecord_LINNUM_MsLink_LineNumberList.Create;
  625. end;
  626. destructor TOmfObjSection.destroy;
  627. begin
  628. FLinNumEntries.Free;
  629. inherited destroy;
  630. end;
  631. function TOmfObjSection.MemPosStr(AImageBase: qword): string;
  632. begin
  633. Result:=HexStr(MZExeUnifiedLogicalSegment.MemBasePos shr 4,4)+':'+
  634. HexStr(MemPos-MZExeUnifiedLogicalSegment.MemBasePos,4);
  635. end;
  636. {****************************************************************************
  637. TOmfObjData
  638. ****************************************************************************}
  639. class function TOmfObjData.CodeSectionName(const aname: string): string;
  640. begin
  641. {$ifdef i8086}
  642. if current_settings.x86memorymodel in x86_far_code_models then
  643. begin
  644. if cs_huge_code in current_settings.moduleswitches then
  645. result:=aname + '_TEXT'
  646. else
  647. result:=current_module.modulename^ + '_TEXT';
  648. end
  649. else
  650. {$endif}
  651. result:='_TEXT';
  652. end;
  653. constructor TOmfObjData.create(const n: string);
  654. begin
  655. inherited create(n);
  656. CObjSymbol:=TOmfObjSymbol;
  657. CObjSection:=TOmfObjSection;
  658. createsectiongroup('DGROUP');
  659. FMainSource:=current_module.mainsource;
  660. end;
  661. function TOmfObjData.sectiontype2options(atype: TAsmSectiontype): TObjSectionOptions;
  662. begin
  663. Result:=inherited sectiontype2options(atype);
  664. { in the huge memory model, BSS data is actually written in the regular
  665. FAR_DATA segment of the module }
  666. if sectiontype2class(atype)='FAR_DATA' then
  667. Result:=Result+[oso_data,oso_sparse_data];
  668. end;
  669. function TOmfObjData.sectiontype2align(atype: TAsmSectiontype): longint;
  670. begin
  671. Result:=omf_sectiontype2align(atype);
  672. end;
  673. function TOmfObjData.sectiontype2class(atype: TAsmSectiontype): string;
  674. begin
  675. Result:=omf_segclass(atype);
  676. end;
  677. function TOmfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  678. var
  679. sep : string[3];
  680. secname : string;
  681. begin
  682. if (atype=sec_user) then
  683. Result:=aname
  684. else
  685. begin
  686. if omf_secnames[atype]=omf_secnames[sec_code] then
  687. secname:=CodeSectionName(aname)
  688. else if omf_segclass(atype)='FAR_DATA' then
  689. secname:=current_module.modulename^ + '_DATA'
  690. else
  691. secname:=omf_secnames[atype];
  692. if create_smartlink_sections and (aname<>'') then
  693. begin
  694. case aorder of
  695. secorder_begin :
  696. sep:='.b_';
  697. secorder_end :
  698. sep:='.z_';
  699. else
  700. sep:='.n_';
  701. end;
  702. result:=UpCase(secname+sep+aname);
  703. end
  704. else
  705. result:=secname;
  706. end;
  707. end;
  708. function TOmfObjData.createsection(atype: TAsmSectionType; const aname: string; aorder: TAsmSectionOrder): TObjSection;
  709. var
  710. is_new: Boolean;
  711. primary_group: String;
  712. grp: TObjSectionGroup;
  713. begin
  714. is_new:=TObjSection(ObjSectionList.Find(sectionname(atype,aname,aorder)))=nil;
  715. Result:=inherited createsection(atype, aname, aorder);
  716. if is_new then
  717. begin
  718. TOmfObjSection(Result).FClassName:=sectiontype2class(atype);
  719. if atype=sec_stack then
  720. TOmfObjSection(Result).FCombination:=scStack
  721. else if atype in [sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev,sec_debug_aranges,sec_debug_ranges] then
  722. begin
  723. TOmfObjSection(Result).FUse:=suUse32;
  724. TOmfObjSection(Result).SizeLimit:=high(longword);
  725. end;
  726. primary_group:=omf_section_primary_group(atype,aname);
  727. if primary_group<>'' then
  728. begin
  729. { find the primary group, if it already exists, else create it }
  730. grp:=nil;
  731. if GroupsList<>nil then
  732. grp:=TObjSectionGroup(GroupsList.Find(primary_group));
  733. if grp=nil then
  734. grp:=createsectiongroup(primary_group);
  735. { add the current section to the group }
  736. SetLength(grp.members,Length(grp.members)+1);
  737. grp.members[High(grp.members)]:=Result;
  738. TOmfObjSection(Result).FPrimaryGroup:=grp;
  739. end;
  740. end;
  741. end;
  742. function TOmfObjData.reffardatasection: TObjSection;
  743. var
  744. secname: string;
  745. begin
  746. secname:=current_module.modulename^ + '_DATA';
  747. result:=TObjSection(ObjSectionList.Find(secname));
  748. if not assigned(result) then
  749. begin
  750. result:=CObjSection.create(ObjSectionList,secname,2,[oso_Data,oso_load,oso_write]);
  751. result.ObjData:=self;
  752. TOmfObjSection(Result).FClassName:='FAR_DATA';
  753. end;
  754. end;
  755. procedure TOmfObjData.writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  756. var
  757. objreloc: TOmfRelocation;
  758. symaddr: AWord;
  759. begin
  760. { RELOC_FARPTR = RELOC_ABSOLUTE16+RELOC_SEG }
  761. if Reloctype=RELOC_FARPTR then
  762. begin
  763. if len<>4 then
  764. internalerror(2015041502);
  765. writeReloc(Data,2,p,RELOC_ABSOLUTE16);
  766. writeReloc(0,2,p,RELOC_SEG);
  767. exit;
  768. end
  769. { RELOC_FARPTR48 = RELOC_ABSOLUTE16+RELOC_SEG }
  770. else if Reloctype=RELOC_FARPTR48 then
  771. begin
  772. if len<>6 then
  773. internalerror(2015041502);
  774. writeReloc(Data,4,p,RELOC_ABSOLUTE32);
  775. writeReloc(0,2,p,RELOC_SEG);
  776. exit;
  777. end;
  778. if CurrObjSec=nil then
  779. internalerror(200403072);
  780. objreloc:=nil;
  781. if Reloctype in [RELOC_FARDATASEG,RELOC_FARDATASEGREL] then
  782. begin
  783. if Reloctype=RELOC_FARDATASEG then
  784. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,reffardatasection,RELOC_SEG)
  785. else
  786. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,reffardatasection,RELOC_SEGREL);
  787. CurrObjSec.ObjRelocations.Add(objreloc);
  788. end
  789. else if assigned(p) then
  790. begin
  791. { real address of the symbol }
  792. symaddr:=p.address;
  793. if p.bind=AB_EXTERNAL then
  794. begin
  795. objreloc:=TOmfRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  796. CurrObjSec.ObjRelocations.Add(objreloc);
  797. end
  798. { relative relocations within the same section can be calculated directly,
  799. without the need to emit a relocation entry }
  800. else if (p.objsection=CurrObjSec) and
  801. (p.bind<>AB_COMMON) and
  802. (Reloctype=RELOC_RELATIVE) then
  803. begin
  804. data:=data+symaddr-len-CurrObjSec.Size;
  805. end
  806. else
  807. begin
  808. objreloc:=TOmfRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  809. CurrObjSec.ObjRelocations.Add(objreloc);
  810. if not (Reloctype in [RELOC_SEG,RELOC_SEGREL]) then
  811. inc(data,symaddr);
  812. end;
  813. end
  814. else if Reloctype in [RELOC_DGROUP,RELOC_DGROUPREL] then
  815. begin
  816. if Reloctype=RELOC_DGROUP then
  817. objreloc:=TOmfRelocation.CreateGroup(CurrObjSec.Size,TObjSectionGroup(GroupsList.Find('DGROUP')),RELOC_SEG)
  818. else
  819. objreloc:=TOmfRelocation.CreateGroup(CurrObjSec.Size,TObjSectionGroup(GroupsList.Find('DGROUP')),RELOC_SEGREL);
  820. CurrObjSec.ObjRelocations.Add(objreloc);
  821. end;
  822. CurrObjSec.write(data,len);
  823. end;
  824. {****************************************************************************
  825. TOmfObjOutput
  826. ****************************************************************************}
  827. procedure TOmfObjOutput.AddSegment(const name, segclass, ovlname: string;
  828. Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination;
  829. Use: TOmfSegmentUse; Size: TObjSectionOfs);
  830. var
  831. s: TOmfRecord_SEGDEF;
  832. begin
  833. s:=TOmfRecord_SEGDEF.Create;
  834. Segments.Add(name,s);
  835. s.SegmentNameIndex:=LNames.Add(name);
  836. s.ClassNameIndex:=LNames.Add(segclass);
  837. s.OverlayNameIndex:=LNames.Add(ovlname);
  838. s.Alignment:=Alignment;
  839. s.Combination:=Combination;
  840. s.Use:=Use;
  841. s.SegmentLength:=Size;
  842. end;
  843. procedure TOmfObjOutput.AddGroup(group: TObjSectionGroup);
  844. var
  845. g: TOmfRecord_GRPDEF;
  846. seglist: TSegmentList;
  847. I: Integer;
  848. begin
  849. seglist:=nil;
  850. g:=TOmfRecord_GRPDEF.Create;
  851. Groups.Add(group.Name,g);
  852. g.GroupNameIndex:=LNames.Add(group.Name);
  853. SetLength(seglist,Length(group.members));
  854. for I:=Low(group.members) to High(group.members) do
  855. seglist[I]:=group.members[I].index;
  856. g.SegmentList:=seglist;
  857. end;
  858. procedure TOmfObjOutput.WriteSections(Data: TObjData);
  859. var
  860. i:longint;
  861. sec:TObjSection;
  862. begin
  863. for i:=0 to Data.ObjSectionList.Count-1 do
  864. begin
  865. sec:=TObjSection(Data.ObjSectionList[i]);
  866. WriteSectionContentAndFixups(sec);
  867. WriteLinNumRecords(TOmfObjSection(sec));
  868. end;
  869. end;
  870. procedure TOmfObjOutput.WriteSectionContentAndFixups(sec: TObjSection);
  871. const
  872. MaxChunkSize=$3fa;
  873. var
  874. RawRecord: TOmfRawRecord;
  875. ChunkStart,ChunkLen: DWord;
  876. ChunkFixupStart,ChunkFixupEnd: Integer;
  877. SegIndex: Integer;
  878. NextOfs: Integer;
  879. Is32BitLEDATA: Boolean;
  880. I: Integer;
  881. begin
  882. if (oso_data in sec.SecOptions) then
  883. begin
  884. if sec.Data=nil then
  885. internalerror(200403073);
  886. for I:=0 to sec.ObjRelocations.Count-1 do
  887. TOmfRelocation(sec.ObjRelocations[I]).BuildOmfFixup;
  888. SegIndex:=Segments.FindIndexOf(sec.Name);
  889. RawRecord:=TOmfRawRecord.Create;
  890. sec.data.seek(0);
  891. ChunkFixupStart:=0;
  892. ChunkFixupEnd:=-1;
  893. ChunkStart:=0;
  894. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  895. while ChunkLen>0 do
  896. begin
  897. { find last fixup in the chunk }
  898. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  899. (TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  900. inc(ChunkFixupEnd);
  901. { check if last chunk is crossing the chunk boundary, and trim ChunkLen if necessary }
  902. if (ChunkFixupEnd>=ChunkFixupStart) and
  903. ((TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset+
  904. TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).OmfFixup.LocationSize)>(ChunkStart+ChunkLen)) then
  905. begin
  906. ChunkLen:=TOmfRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset-ChunkStart;
  907. Dec(ChunkFixupEnd);
  908. end;
  909. { write LEDATA record }
  910. Is32BitLEDATA:=TOmfObjSection(sec).Use=suUse32;
  911. if Is32BitLEDATA then
  912. RawRecord.RecordType:=RT_LEDATA32
  913. else
  914. RawRecord.RecordType:=RT_LEDATA;
  915. NextOfs:=RawRecord.WriteIndexedRef(0,SegIndex);
  916. if Is32BitLEDATA then
  917. begin
  918. RawRecord.RawData[NextOfs]:=Byte(ChunkStart);
  919. RawRecord.RawData[NextOfs+1]:=Byte(ChunkStart shr 8);
  920. RawRecord.RawData[NextOfs+2]:=Byte(ChunkStart shr 16);
  921. RawRecord.RawData[NextOfs+3]:=Byte(ChunkStart shr 24);
  922. Inc(NextOfs,4);
  923. end
  924. else
  925. begin
  926. if ChunkStart>$ffff then
  927. internalerror(2018052201);
  928. RawRecord.RawData[NextOfs]:=Byte(ChunkStart);
  929. RawRecord.RawData[NextOfs+1]:=Byte(ChunkStart shr 8);
  930. Inc(NextOfs,2);
  931. end;
  932. sec.data.read(RawRecord.RawData[NextOfs], ChunkLen);
  933. Inc(NextOfs, ChunkLen);
  934. RawRecord.RecordLength:=NextOfs+1;
  935. RawRecord.CalculateChecksumByte;
  936. RawRecord.WriteTo(FWriter);
  937. { write FIXUPP record }
  938. if ChunkFixupEnd>=ChunkFixupStart then
  939. begin
  940. RawRecord.RecordType:=RT_FIXUPP;
  941. NextOfs:=0;
  942. for I:=ChunkFixupStart to ChunkFixupEnd do
  943. begin
  944. TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.DataRecordStartOffset:=ChunkStart;
  945. NextOfs:=TOmfRelocation(sec.ObjRelocations[I]).OmfFixup.WriteAt(RawRecord,NextOfs);
  946. end;
  947. RawRecord.RecordLength:=NextOfs+1;
  948. RawRecord.CalculateChecksumByte;
  949. RawRecord.WriteTo(FWriter);
  950. end;
  951. { prepare next chunk }
  952. Inc(ChunkStart, ChunkLen);
  953. ChunkLen:=Min(MaxChunkSize, sec.Data.size-ChunkStart);
  954. ChunkFixupStart:=ChunkFixupEnd+1;
  955. end;
  956. RawRecord.Free;
  957. end;
  958. end;
  959. procedure TOmfObjOutput.WriteLinNumRecords(sec: TOmfObjSection);
  960. var
  961. SegIndex: Integer;
  962. RawRecord: TOmfRawRecord;
  963. LinNumRec: TOmfRecord_LINNUM_MsLink;
  964. begin
  965. if (oso_data in sec.SecOptions) then
  966. begin
  967. if sec.Data=nil then
  968. internalerror(200403073);
  969. if sec.LinNumEntries.Count=0 then
  970. exit;
  971. SegIndex:=Segments.FindIndexOf(sec.Name);
  972. RawRecord:=TOmfRawRecord.Create;
  973. LinNumRec:=TOmfRecord_LINNUM_MsLink.Create;
  974. LinNumRec.BaseGroup:=0;
  975. LinNumRec.BaseSegment:=SegIndex;
  976. LinNumRec.LineNumberList:=sec.LinNumEntries;
  977. while LinNumRec.NextIndex<sec.LinNumEntries.Count do
  978. begin
  979. LinNumRec.EncodeTo(RawRecord);
  980. RawRecord.WriteTo(FWriter);
  981. end;
  982. LinNumRec.Free;
  983. RawRecord.Free;
  984. end;
  985. end;
  986. procedure TOmfObjOutput.section_count_sections(p: TObject; arg: pointer);
  987. begin
  988. TOmfObjSection(p).index:=pinteger(arg)^;
  989. inc(pinteger(arg)^);
  990. end;
  991. procedure TOmfObjOutput.group_count_groups(p: TObject; arg: pointer);
  992. begin
  993. TObjSectionGroup(p).index:=pinteger(arg)^;
  994. inc(pinteger(arg)^);
  995. end;
  996. procedure TOmfObjOutput.WritePUBDEFs(Data: TObjData);
  997. var
  998. PubNamesForSection: array of TFPHashObjectList;
  999. i: Integer;
  1000. objsym: TObjSymbol;
  1001. PublicNameElem: TOmfPublicNameElement;
  1002. RawRecord: TOmfRawRecord;
  1003. PubDefRec: TOmfRecord_PUBDEF;
  1004. begin
  1005. PubNamesForSection:=nil;
  1006. RawRecord:=TOmfRawRecord.Create;
  1007. SetLength(PubNamesForSection,Data.ObjSectionList.Count);
  1008. for i:=0 to Data.ObjSectionList.Count-1 do
  1009. PubNamesForSection[i]:=TFPHashObjectList.Create;
  1010. for i:=0 to Data.ObjSymbolList.Count-1 do
  1011. begin
  1012. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  1013. if objsym.bind=AB_GLOBAL then
  1014. begin
  1015. PublicNameElem:=TOmfPublicNameElement.Create(PubNamesForSection[objsym.objsection.index-1],objsym.Name);
  1016. PublicNameElem.PublicOffset:=objsym.offset;
  1017. PublicNameElem.IsLocal:=False;
  1018. end
  1019. else if objsym.bind=AB_LOCAL then
  1020. begin
  1021. PublicNameElem:=TOmfPublicNameElement.Create(PubNamesForSection[objsym.objsection.index-1],objsym.Name);
  1022. PublicNameElem.PublicOffset:=objsym.offset;
  1023. PublicNameElem.IsLocal:=True;
  1024. end
  1025. end;
  1026. for i:=0 to Data.ObjSectionList.Count-1 do
  1027. if PubNamesForSection[i].Count>0 then
  1028. begin
  1029. PubDefRec:=TOmfRecord_PUBDEF.Create;
  1030. PubDefRec.BaseSegmentIndex:=i+1;
  1031. if TOmfObjSection(Data.ObjSectionList[i]).PrimaryGroup<>nil then
  1032. PubDefRec.BaseGroupIndex:=Groups.FindIndexOf(TOmfObjSection(Data.ObjSectionList[i]).PrimaryGroup.Name)
  1033. else
  1034. PubDefRec.BaseGroupIndex:=0;
  1035. PubDefRec.PublicNames:=PubNamesForSection[i];
  1036. while PubDefRec.NextIndex<PubDefRec.PublicNames.Count do
  1037. begin
  1038. PubDefRec.EncodeTo(RawRecord);
  1039. RawRecord.WriteTo(FWriter);
  1040. end;
  1041. PubDefRec.Free;
  1042. end;
  1043. for i:=0 to Data.ObjSectionList.Count-1 do
  1044. FreeAndNil(PubNamesForSection[i]);
  1045. RawRecord.Free;
  1046. end;
  1047. procedure TOmfObjOutput.WriteEXTDEFs(Data: TObjData);
  1048. var
  1049. ExtNames: TFPHashObjectList;
  1050. RawRecord: TOmfRawRecord;
  1051. i,idx: Integer;
  1052. objsym: TObjSymbol;
  1053. ExternalNameElem: TOmfExternalNameElement;
  1054. ExtDefRec: TOmfRecord_EXTDEF;
  1055. begin
  1056. ExtNames:=TFPHashObjectList.Create;
  1057. RawRecord:=TOmfRawRecord.Create;
  1058. idx:=1;
  1059. for i:=0 to Data.ObjSymbolList.Count-1 do
  1060. begin
  1061. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  1062. if objsym.bind=AB_EXTERNAL then
  1063. begin
  1064. ExternalNameElem:=TOmfExternalNameElement.Create(ExtNames,objsym.Name);
  1065. objsym.symidx:=idx;
  1066. Inc(idx);
  1067. end;
  1068. end;
  1069. if ExtNames.Count>0 then
  1070. begin
  1071. ExtDefRec:=TOmfRecord_EXTDEF.Create;
  1072. ExtDefRec.ExternalNames:=ExtNames;
  1073. while ExtDefRec.NextIndex<ExtDefRec.ExternalNames.Count do
  1074. begin
  1075. ExtDefRec.EncodeTo(RawRecord);
  1076. RawRecord.WriteTo(FWriter);
  1077. end;
  1078. ExtDefRec.Free;
  1079. end;
  1080. ExtNames.Free;
  1081. RawRecord.Free;
  1082. end;
  1083. function TOmfObjOutput.writeData(Data:TObjData):boolean;
  1084. var
  1085. RawRecord: TOmfRawRecord;
  1086. Header: TOmfRecord_THEADR;
  1087. Translator_COMENT: TOmfRecord_COMENT;
  1088. DebugFormat_COMENT: TOmfRecord_COMENT;
  1089. LinkPassSeparator_COMENT: TOmfRecord_COMENT;
  1090. LNamesRec: TOmfRecord_LNAMES;
  1091. ModEnd: TOmfRecord_MODEND;
  1092. I: Integer;
  1093. SegDef: TOmfRecord_SEGDEF;
  1094. GrpDef: TOmfRecord_GRPDEF;
  1095. nsections,ngroups: Integer;
  1096. objsym: TObjSymbol;
  1097. begin
  1098. { calc amount of sections we have and set their index, starting with 1 }
  1099. nsections:=1;
  1100. data.ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1101. { calc amount of groups we have and set their index, starting with 1 }
  1102. ngroups:=1;
  1103. data.GroupsList.ForEachCall(@group_count_groups,@ngroups);
  1104. { maximum amount of sections supported in the omf format is $7fff }
  1105. if (nsections-1)>$7fff then
  1106. internalerror(2015040701);
  1107. { maximum amount of groups supported in the omf format is $7fff }
  1108. if (ngroups-1)>$7fff then
  1109. internalerror(2018062101);
  1110. { write header record }
  1111. RawRecord:=TOmfRawRecord.Create;
  1112. Header:=TOmfRecord_THEADR.Create;
  1113. if cs_debuginfo in current_settings.moduleswitches then
  1114. Header.ModuleName:=TOmfObjData(Data).MainSource
  1115. else
  1116. Header.ModuleName:=Data.Name;
  1117. Header.EncodeTo(RawRecord);
  1118. RawRecord.WriteTo(FWriter);
  1119. Header.Free;
  1120. { write translator COMENT header }
  1121. Translator_COMENT:=TOmfRecord_COMENT.Create;
  1122. Translator_COMENT.CommentClass:=CC_Translator;
  1123. Translator_COMENT.CommentString:='FPC '+full_version_string+
  1124. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname;
  1125. Translator_COMENT.EncodeTo(RawRecord);
  1126. RawRecord.WriteTo(FWriter);
  1127. Translator_COMENT.Free;
  1128. if (target_dbg.id=dbg_codeview) or
  1129. ((ds_dwarf_omf_linnum in current_settings.debugswitches) and
  1130. (target_dbg.id in [dbg_dwarf2,dbg_dwarf3,dbg_dwarf4])) then
  1131. begin
  1132. DebugFormat_COMENT:=TOmfRecord_COMENT.Create;
  1133. DebugFormat_COMENT.CommentClass:=CC_NewOmfExtension;
  1134. DebugFormat_COMENT.CommentString:='';
  1135. DebugFormat_COMENT.EncodeTo(RawRecord);
  1136. RawRecord.WriteTo(FWriter);
  1137. DebugFormat_COMENT.Free;
  1138. end;
  1139. LNames.Clear;
  1140. LNames.Add(''); { insert an empty string, which has index 1 }
  1141. FSegments.Clear;
  1142. FSegments.Add('',nil);
  1143. FGroups.Clear;
  1144. FGroups.Add('',nil);
  1145. for i:=0 to Data.GroupsList.Count-1 do
  1146. AddGroup(TObjSectionGroup(Data.GroupsList[I]));
  1147. for i:=0 to Data.ObjSectionList.Count-1 do
  1148. with TOmfObjSection(Data.ObjSectionList[I]) do
  1149. AddSegment(Name,ClassName,OverlayName,OmfAlignment,Combination,Use,Size);
  1150. { write LNAMES record(s) }
  1151. LNamesRec:=TOmfRecord_LNAMES.Create;
  1152. LNamesRec.Names:=LNames;
  1153. while LNamesRec.NextIndex<=LNames.Count do
  1154. begin
  1155. LNamesRec.EncodeTo(RawRecord);
  1156. RawRecord.WriteTo(FWriter);
  1157. end;
  1158. LNamesRec.Free;
  1159. { write SEGDEF record(s) }
  1160. for I:=1 to Segments.Count-1 do
  1161. begin
  1162. SegDef:=TOmfRecord_SEGDEF(Segments[I]);
  1163. SegDef.EncodeTo(RawRecord);
  1164. RawRecord.WriteTo(FWriter);
  1165. end;
  1166. { write GRPDEF record(s) }
  1167. for I:=1 to Groups.Count-1 do
  1168. begin
  1169. GrpDef:=TOmfRecord_GRPDEF(Groups[I]);
  1170. GrpDef.EncodeTo(RawRecord);
  1171. RawRecord.WriteTo(FWriter);
  1172. end;
  1173. { write PUBDEF record(s) }
  1174. WritePUBDEFs(Data);
  1175. { write EXTDEF record(s) }
  1176. WriteEXTDEFs(Data);
  1177. { write link pass separator }
  1178. LinkPassSeparator_COMENT:=TOmfRecord_COMENT.Create;
  1179. LinkPassSeparator_COMENT.CommentClass:=CC_LinkPassSeparator;
  1180. LinkPassSeparator_COMENT.CommentString:=#1;
  1181. LinkPassSeparator_COMENT.NoList:=True;
  1182. LinkPassSeparator_COMENT.EncodeTo(RawRecord);
  1183. RawRecord.WriteTo(FWriter);
  1184. LinkPassSeparator_COMENT.Free;
  1185. { write section content, interleaved with fixups }
  1186. WriteSections(Data);
  1187. { write MODEND record }
  1188. ModEnd:=TOmfRecord_MODEND.Create;
  1189. ModEnd.EncodeTo(RawRecord);
  1190. RawRecord.WriteTo(FWriter);
  1191. ModEnd.Free;
  1192. RawRecord.Free;
  1193. result:=true;
  1194. end;
  1195. constructor TOmfObjOutput.create(AWriter:TObjectWriter);
  1196. begin
  1197. inherited create(AWriter);
  1198. cobjdata:=TOmfObjData;
  1199. FLNames:=TOmfOrderedNameCollection.Create(False);
  1200. FSegments:=TFPHashObjectList.Create;
  1201. FSegments.Add('',nil);
  1202. FGroups:=TFPHashObjectList.Create;
  1203. FGroups.Add('',nil);
  1204. end;
  1205. destructor TOmfObjOutput.Destroy;
  1206. begin
  1207. FGroups.Free;
  1208. FSegments.Free;
  1209. FLNames.Free;
  1210. inherited Destroy;
  1211. end;
  1212. procedure TOmfObjOutput.WriteDllImport(const dllname,afuncname,mangledname: string; ordnr: longint; isvar: boolean);
  1213. var
  1214. RawRecord: TOmfRawRecord;
  1215. Header: TOmfRecord_THEADR;
  1216. DllImport_COMENT: TOmfRecord_COMENT=nil;
  1217. DllImport_COMENT_IMPDEF: TOmfRecord_COMENT_IMPDEF=nil;
  1218. ModEnd: TOmfRecord_MODEND;
  1219. begin
  1220. { write header record }
  1221. RawRecord:=TOmfRawRecord.Create;
  1222. Header:=TOmfRecord_THEADR.Create;
  1223. Header.ModuleName:=mangledname;
  1224. Header.EncodeTo(RawRecord);
  1225. RawRecord.WriteTo(FWriter);
  1226. Header.Free;
  1227. { write IMPDEF record }
  1228. DllImport_COMENT_IMPDEF:=TOmfRecord_COMENT_IMPDEF.Create;
  1229. DllImport_COMENT_IMPDEF.InternalName:=mangledname;
  1230. DllImport_COMENT_IMPDEF.ModuleName:=dllname;
  1231. if ordnr <= 0 then
  1232. begin
  1233. DllImport_COMENT_IMPDEF.ImportByOrdinal:=False;
  1234. DllImport_COMENT_IMPDEF.Name:=afuncname;
  1235. end
  1236. else
  1237. begin
  1238. DllImport_COMENT_IMPDEF.ImportByOrdinal:=True;
  1239. DllImport_COMENT_IMPDEF.Ordinal:=ordnr;
  1240. end;
  1241. DllImport_COMENT:=TOmfRecord_COMENT.Create;
  1242. DllImport_COMENT_IMPDEF.EncodeTo(DllImport_COMENT);
  1243. FreeAndNil(DllImport_COMENT_IMPDEF);
  1244. DllImport_COMENT.EncodeTo(RawRecord);
  1245. FreeAndNil(DllImport_COMENT);
  1246. RawRecord.WriteTo(FWriter);
  1247. { write MODEND record }
  1248. ModEnd:=TOmfRecord_MODEND.Create;
  1249. ModEnd.EncodeTo(RawRecord);
  1250. RawRecord.WriteTo(FWriter);
  1251. ModEnd.Free;
  1252. RawRecord.Free;
  1253. end;
  1254. {****************************************************************************
  1255. TOmfObjInput
  1256. ****************************************************************************}
  1257. function TOmfObjInput.PeekNextRecordType: Byte;
  1258. var
  1259. OldPos: LongInt;
  1260. begin
  1261. OldPos:=FReader.Pos;
  1262. if not FReader.read(Result, 1) then
  1263. begin
  1264. InputError('Unexpected end of file');
  1265. Result:=0;
  1266. exit;
  1267. end;
  1268. FReader.seek(OldPos);
  1269. end;
  1270. function TOmfObjInput.ReadLNames(RawRec: TOmfRawRecord): Boolean;
  1271. var
  1272. LNamesRec: TOmfRecord_LNAMES;
  1273. begin
  1274. Result:=False;
  1275. LNamesRec:=TOmfRecord_LNAMES.Create;
  1276. LNamesRec.Names:=LNames;
  1277. LNamesRec.DecodeFrom(RawRec);
  1278. LNamesRec.Free;
  1279. Result:=True;
  1280. end;
  1281. function TOmfObjInput.ReadSegDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  1282. var
  1283. SegDefRec: TOmfRecord_SEGDEF;
  1284. SegmentName,SegClassName,OverlayName: string;
  1285. SecAlign: LongInt;
  1286. secoptions: TObjSectionOptions;
  1287. objsec: TOmfObjSection;
  1288. begin
  1289. Result:=False;
  1290. SegDefRec:=TOmfRecord_SEGDEF.Create;
  1291. SegDefRec.DecodeFrom(RawRec);
  1292. if (SegDefRec.SegmentNameIndex<1) or (SegDefRec.SegmentNameIndex>LNames.Count) then
  1293. begin
  1294. InputError('Segment name index out of range');
  1295. SegDefRec.Free;
  1296. exit;
  1297. end;
  1298. SegmentName:=LNames[SegDefRec.SegmentNameIndex];
  1299. if (SegDefRec.ClassNameIndex<1) or (SegDefRec.ClassNameIndex>LNames.Count) then
  1300. begin
  1301. InputError('Segment class name index out of range');
  1302. SegDefRec.Free;
  1303. exit;
  1304. end;
  1305. SegClassName:=LNames[SegDefRec.ClassNameIndex];
  1306. if (SegDefRec.OverlayNameIndex<1) or (SegDefRec.OverlayNameIndex>LNames.Count) then
  1307. begin
  1308. InputError('Segment overlay name index out of range');
  1309. SegDefRec.Free;
  1310. exit;
  1311. end;
  1312. OverlayName:=LNames[SegDefRec.OverlayNameIndex];
  1313. SecAlign:=1; // otherwise warning prohibits compilation
  1314. case SegDefRec.Alignment of
  1315. saRelocatableByteAligned:
  1316. SecAlign:=1;
  1317. saRelocatableWordAligned:
  1318. SecAlign:=2;
  1319. saRelocatableParaAligned:
  1320. SecAlign:=16;
  1321. saRelocatableDWordAligned:
  1322. SecAlign:=4;
  1323. saRelocatablePageAligned:
  1324. SecAlign:=256;
  1325. saNotSupported:
  1326. SecAlign:=4096;
  1327. saAbsolute:
  1328. begin
  1329. InputError('Absolute segment alignment not supported');
  1330. SegDefRec.Free;
  1331. exit;
  1332. end;
  1333. saNotDefined:
  1334. begin
  1335. InputError('Invalid (unsupported/undefined) OMF segment alignment');
  1336. SegDefRec.Free;
  1337. exit;
  1338. end;
  1339. end;
  1340. if not CaseSensitiveSegments then
  1341. begin
  1342. SegmentName:=UpCase(SegmentName);
  1343. SegClassName:=UpCase(SegClassName);
  1344. OverlayName:=UpCase(OverlayName);
  1345. end;
  1346. { hack for supporting object modules, generated by Borland's BINOBJ tool }
  1347. if (SegClassName='') and (SegmentName='CODE') then
  1348. begin
  1349. SegmentName:=InputFileName;
  1350. SegClassName:='CODE';
  1351. end;
  1352. secoptions:=[];
  1353. objsec:=TOmfObjSection(objdata.createsection(SegmentName+'||'+SegClassName,SecAlign,secoptions,false));
  1354. objsec.FClassName:=SegClassName;
  1355. objsec.FOverlayName:=OverlayName;
  1356. objsec.FCombination:=SegDefRec.Combination;
  1357. objsec.FUse:=SegDefRec.Use;
  1358. if SegDefRec.SegmentLength>High(objsec.Size) then
  1359. begin
  1360. InputError('Segment too large');
  1361. SegDefRec.Free;
  1362. exit;
  1363. end;
  1364. objsec.Size:=SegDefRec.SegmentLength;
  1365. if SegClassName='DWARF' then
  1366. objsec.SecOptions:=objsec.SecOptions+[oso_debug];
  1367. if (SegClassName='HEAP') or
  1368. (SegClassName='STACK') or (SegDefRec.Combination=scStack) or
  1369. (SegClassName='BEGDATA') or
  1370. (SegmentName='FPC') then
  1371. objsec.SecOptions:=objsec.SecOptions+[oso_keep];
  1372. SegDefRec.Free;
  1373. Result:=True;
  1374. end;
  1375. function TOmfObjInput.ReadGrpDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  1376. var
  1377. GrpDefRec: TOmfRecord_GRPDEF;
  1378. GroupName: string;
  1379. SecGroup: TObjSectionGroup;
  1380. i,SegIndex: Integer;
  1381. begin
  1382. Result:=False;
  1383. GrpDefRec:=TOmfRecord_GRPDEF.Create;
  1384. GrpDefRec.DecodeFrom(RawRec);
  1385. if (GrpDefRec.GroupNameIndex<1) or (GrpDefRec.GroupNameIndex>LNames.Count) then
  1386. begin
  1387. InputError('Group name index out of range');
  1388. GrpDefRec.Free;
  1389. exit;
  1390. end;
  1391. GroupName:=LNames[GrpDefRec.GroupNameIndex];
  1392. if not CaseSensitiveSegments then
  1393. GroupName:=UpCase(GroupName);
  1394. SecGroup:=objdata.createsectiongroup(GroupName);
  1395. SetLength(SecGroup.members,Length(GrpDefRec.SegmentList));
  1396. for i:=0 to Length(GrpDefRec.SegmentList)-1 do
  1397. begin
  1398. SegIndex:=GrpDefRec.SegmentList[i];
  1399. if (SegIndex<1) or (SegIndex>objdata.ObjSectionList.Count) then
  1400. begin
  1401. InputError('Segment name index out of range in group definition');
  1402. GrpDefRec.Free;
  1403. exit;
  1404. end;
  1405. SecGroup.members[i]:=TOmfObjSection(objdata.ObjSectionList[SegIndex-1]);
  1406. end;
  1407. GrpDefRec.Free;
  1408. Result:=True;
  1409. end;
  1410. function TOmfObjInput.ReadExtDef(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  1411. var
  1412. ExtDefRec: TOmfRecord_EXTDEF;
  1413. ExtDefElem: TOmfExternalNameElement;
  1414. OldCount,NewCount,i: Integer;
  1415. objsym: TObjSymbol;
  1416. symname: TSymStr;
  1417. begin
  1418. Result:=False;
  1419. ExtDefRec:=TOmfRecord_EXTDEF.Create;
  1420. ExtDefRec.ExternalNames:=ExtDefs;
  1421. OldCount:=ExtDefs.Count;
  1422. ExtDefRec.DecodeFrom(RawRec);
  1423. NewCount:=ExtDefs.Count;
  1424. for i:=OldCount to NewCount-1 do
  1425. begin
  1426. ExtDefElem:=TOmfExternalNameElement(ExtDefs[i]);
  1427. symname:=ExtDefElem.Name;
  1428. if not CaseSensitiveSymbols then
  1429. symname:=UpCase(symname);
  1430. objsym:=objdata.CreateSymbol(symname);
  1431. objsym.bind:=AB_EXTERNAL;
  1432. objsym.typ:=AT_FUNCTION;
  1433. objsym.objsection:=nil;
  1434. objsym.offset:=0;
  1435. objsym.size:=0;
  1436. end;
  1437. ExtDefRec.Free;
  1438. Result:=True;
  1439. end;
  1440. function TOmfObjInput.ReadPubDef(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  1441. var
  1442. PubDefRec: TOmfRecord_PUBDEF;
  1443. PubDefElem: TOmfPublicNameElement;
  1444. OldCount,NewCount,i: Integer;
  1445. basegroup: TObjSectionGroup;
  1446. objsym: TObjSymbol;
  1447. objsec: TOmfObjSection;
  1448. symname: TSymStr;
  1449. begin
  1450. Result:=False;
  1451. PubDefRec:=TOmfRecord_PUBDEF.Create;
  1452. PubDefRec.PublicNames:=PubDefs;
  1453. OldCount:=PubDefs.Count;
  1454. PubDefRec.DecodeFrom(RawRec);
  1455. NewCount:=PubDefs.Count;
  1456. if (PubDefRec.BaseGroupIndex<0) or (PubDefRec.BaseGroupIndex>objdata.GroupsList.Count) then
  1457. begin
  1458. InputError('Public symbol''s group name index out of range');
  1459. PubDefRec.Free;
  1460. exit;
  1461. end;
  1462. if PubDefRec.BaseGroupIndex<>0 then
  1463. basegroup:=TObjSectionGroup(objdata.GroupsList[PubDefRec.BaseGroupIndex-1])
  1464. else
  1465. basegroup:=nil;
  1466. if (PubDefRec.BaseSegmentIndex<0) or (PubDefRec.BaseSegmentIndex>objdata.ObjSectionList.Count) then
  1467. begin
  1468. InputError('Public symbol''s segment name index out of range');
  1469. PubDefRec.Free;
  1470. exit;
  1471. end;
  1472. if PubDefRec.BaseSegmentIndex=0 then
  1473. begin
  1474. InputError('Public symbol uses absolute addressing, which is not supported by this linker');
  1475. PubDefRec.Free;
  1476. exit;
  1477. end;
  1478. objsec:=TOmfObjSection(objdata.ObjSectionList[PubDefRec.BaseSegmentIndex-1]);
  1479. for i:=OldCount to NewCount-1 do
  1480. begin
  1481. PubDefElem:=TOmfPublicNameElement(PubDefs[i]);
  1482. symname:=PubDefElem.Name;
  1483. if not CaseSensitiveSymbols then
  1484. symname:=UpCase(symname);
  1485. objsym:=objdata.CreateSymbol(symname);
  1486. if PubDefElem.IsLocal then
  1487. objsym.bind:=AB_LOCAL
  1488. else
  1489. objsym.bind:=AB_GLOBAL;
  1490. objsym.typ:=AT_FUNCTION;
  1491. objsym.group:=basegroup;
  1492. objsym.objsection:=objsec;
  1493. objsym.offset:=PubDefElem.PublicOffset;
  1494. objsym.size:=0;
  1495. end;
  1496. PubDefRec.Free;
  1497. Result:=True;
  1498. end;
  1499. function TOmfObjInput.ReadModEnd(RawRec: TOmfRawRecord; objdata:TObjData): Boolean;
  1500. var
  1501. ModEndRec: TOmfRecord_MODEND;
  1502. objsym: TObjSymbol;
  1503. objsec: TOmfObjSection;
  1504. basegroup: TObjSectionGroup;
  1505. begin
  1506. Result:=False;
  1507. ModEndRec:=TOmfRecord_MODEND.Create;
  1508. ModEndRec.DecodeFrom(RawRec);
  1509. if ModEndRec.HasStartAddress then
  1510. begin
  1511. if not ModEndRec.LogicalStartAddress then
  1512. begin
  1513. InputError('Physical start address not supported');
  1514. ModEndRec.Free;
  1515. exit;
  1516. end;
  1517. if not (ModEndRec.TargetMethod in [ftmSegmentIndex,ftmSegmentIndexNoDisp]) then
  1518. begin
  1519. InputError('Target method for start address other than "Segment Index" is not supported');
  1520. ModEndRec.Free;
  1521. exit;
  1522. end;
  1523. if (ModEndRec.TargetDatum<1) or (ModEndRec.TargetDatum>objdata.ObjSectionList.Count) then
  1524. begin
  1525. InputError('Segment name index for start address out of range');
  1526. ModEndRec.Free;
  1527. exit;
  1528. end;
  1529. case ModEndRec.FrameMethod of
  1530. ffmSegmentIndex:
  1531. begin
  1532. if (ModEndRec.FrameDatum<1) or (ModEndRec.FrameDatum>objdata.ObjSectionList.Count) then
  1533. begin
  1534. InputError('Frame segment name index for start address out of range');
  1535. ModEndRec.Free;
  1536. exit;
  1537. end;
  1538. if ModEndRec.FrameDatum<>ModEndRec.TargetDatum then
  1539. begin
  1540. InputError('Frame segment different than target segment is not supported supported for start address');
  1541. ModEndRec.Free;
  1542. exit;
  1543. end;
  1544. basegroup:=nil;
  1545. end;
  1546. ffmGroupIndex:
  1547. begin
  1548. if (ModEndRec.FrameDatum<1) or (ModEndRec.FrameDatum>objdata.GroupsList.Count) then
  1549. begin
  1550. InputError('Frame group name index for start address out of range');
  1551. ModEndRec.Free;
  1552. exit;
  1553. end;
  1554. basegroup:=TObjSectionGroup(objdata.GroupsList[ModEndRec.FrameDatum-1]);
  1555. end;
  1556. else
  1557. begin
  1558. InputError('Frame method for start address other than "Segment Index" or "Group Index" is not supported');
  1559. ModEndRec.Free;
  1560. exit;
  1561. end;
  1562. end;
  1563. objsec:=TOmfObjSection(objdata.ObjSectionList[ModEndRec.TargetDatum-1]);
  1564. objsym:=objdata.CreateSymbol('..start');
  1565. objsym.bind:=AB_GLOBAL;
  1566. objsym.typ:=AT_FUNCTION;
  1567. objsym.group:=basegroup;
  1568. objsym.objsection:=objsec;
  1569. objsym.offset:=ModEndRec.TargetDisplacement;
  1570. objsym.size:=0;
  1571. end;
  1572. ModEndRec.Free;
  1573. Result:=True;
  1574. end;
  1575. function TOmfObjInput.ReadLeOrLiDataAndFixups(RawRec: TOmfRawRecord; objdata: TObjData): Boolean;
  1576. var
  1577. Is32Bit: Boolean;
  1578. NextOfs: Integer;
  1579. SegmentIndex: Integer;
  1580. EnumeratedDataOffset: DWord;
  1581. BlockLength: Integer;
  1582. objsec: TOmfObjSection;
  1583. FixupRawRec: TOmfRawRecord=nil;
  1584. Fixup: TOmfSubRecord_FIXUP;
  1585. Thread: TOmfSubRecord_THREAD;
  1586. FixuppWithoutLeOrLiData: Boolean=False;
  1587. begin
  1588. objsec:=nil;
  1589. EnumeratedDataOffset:=0;
  1590. Result:=False;
  1591. case RawRec.RecordType of
  1592. RT_LEDATA,RT_LEDATA32:
  1593. begin
  1594. Is32Bit:=RawRec.RecordType=RT_LEDATA32;
  1595. NextOfs:=RawRec.ReadIndexedRef(0,SegmentIndex);
  1596. if Is32Bit then
  1597. begin
  1598. if (NextOfs+3)>=RawRec.RecordLength then
  1599. internalerror(2015040504);
  1600. EnumeratedDataOffset := RawRec.RawData[NextOfs]+
  1601. (RawRec.RawData[NextOfs+1] shl 8)+
  1602. (RawRec.RawData[NextOfs+2] shl 16)+
  1603. (RawRec.RawData[NextOfs+3] shl 24);
  1604. Inc(NextOfs,4);
  1605. end
  1606. else
  1607. begin
  1608. if (NextOfs+1)>=RawRec.RecordLength then
  1609. internalerror(2015040504);
  1610. EnumeratedDataOffset := RawRec.RawData[NextOfs]+
  1611. (RawRec.RawData[NextOfs+1] shl 8);
  1612. Inc(NextOfs,2);
  1613. end;
  1614. BlockLength:=RawRec.RecordLength-NextOfs-1;
  1615. if BlockLength<0 then
  1616. internalerror(2015060501);
  1617. if BlockLength>1024 then
  1618. begin
  1619. InputError('LEDATA contains more than 1024 bytes of data');
  1620. exit;
  1621. end;
  1622. if (SegmentIndex<1) or (SegmentIndex>objdata.ObjSectionList.Count) then
  1623. begin
  1624. InputError('Segment index in LEDATA field is out of range');
  1625. exit;
  1626. end;
  1627. objsec:=TOmfObjSection(objdata.ObjSectionList[SegmentIndex-1]);
  1628. objsec.SecOptions:=objsec.SecOptions+[oso_Data];
  1629. if (objsec.Data.Size>EnumeratedDataOffset) then
  1630. begin
  1631. InputError('LEDATA enumerated data offset field out of sequence');
  1632. exit;
  1633. end;
  1634. if (EnumeratedDataOffset+BlockLength)>objsec.Size then
  1635. begin
  1636. InputError('LEDATA goes beyond the segment size declared in the SEGDEF record');
  1637. exit;
  1638. end;
  1639. objsec.Data.seek(EnumeratedDataOffset);
  1640. objsec.Data.write(RawRec.RawData[NextOfs],BlockLength);
  1641. end;
  1642. RT_LIDATA,RT_LIDATA32:
  1643. begin
  1644. InputError('LIDATA records are not supported');
  1645. exit;
  1646. end;
  1647. RT_FIXUPP,RT_FIXUPP32:
  1648. begin
  1649. FixuppWithoutLeOrLiData:=True;
  1650. { a hack, used to indicate, that we must process this record }
  1651. { (RawRec) first in the FIXUPP record processing loop that follows }
  1652. FixupRawRec:=RawRec;
  1653. end;
  1654. else
  1655. internalerror(2015040301);
  1656. end;
  1657. { also read all the FIXUPP records that may follow; }
  1658. { (FixupRawRec=RawRec) indicates that we must process RawRec first, but }
  1659. { without freeing it }
  1660. while (FixupRawRec=RawRec) or (PeekNextRecordType in [RT_FIXUPP,RT_FIXUPP32]) do
  1661. begin
  1662. if FixupRawRec<>RawRec then
  1663. begin
  1664. FixupRawRec:=TOmfRawRecord.Create;
  1665. FixupRawRec.ReadFrom(FReader);
  1666. if not FRawRecord.VerifyChecksumByte then
  1667. begin
  1668. InputError('Invalid checksum in OMF record');
  1669. FixupRawRec.Free;
  1670. exit;
  1671. end;
  1672. end;
  1673. NextOfs:=0;
  1674. Thread:=TOmfSubRecord_THREAD.Create;
  1675. Fixup:=TOmfSubRecord_FIXUP.Create;
  1676. Fixup.Is32Bit:=FixupRawRec.RecordType=RT_FIXUPP32;
  1677. Fixup.DataRecordStartOffset:=EnumeratedDataOffset;
  1678. while NextOfs<(FixupRawRec.RecordLength-1) do
  1679. begin
  1680. if (FixupRawRec.RawData[NextOfs] and $80)<>0 then
  1681. begin
  1682. { FIXUP subrecord }
  1683. if FixuppWithoutLeOrLiData then
  1684. begin
  1685. InputError('FIXUP subrecord without previous LEDATA or LIDATA record');
  1686. Fixup.Free;
  1687. Thread.Free;
  1688. if FixupRawRec<>RawRec then
  1689. FixupRawRec.Free;
  1690. exit;
  1691. end;
  1692. NextOfs:=Fixup.ReadAt(FixupRawRec,NextOfs);
  1693. Fixup.ResolveByThread(FFixupThreads);
  1694. ImportOmfFixup(objdata,objsec,Fixup);
  1695. end
  1696. else
  1697. begin
  1698. { THREAD subrecord }
  1699. NextOfs:=Thread.ReadAt(FixupRawRec,NextOfs);
  1700. Thread.ApplyTo(FFixupThreads);
  1701. end;
  1702. end;
  1703. Fixup.Free;
  1704. Thread.Free;
  1705. if FixupRawRec<>RawRec then
  1706. FixupRawRec.Free;
  1707. { always set it to null, so that we read the next record on the next }
  1708. { loop iteration (this ensures that FixupRawRec<>RawRec, without }
  1709. { freeing RawRec) }
  1710. FixupRawRec:=nil;
  1711. end;
  1712. Result:=True;
  1713. end;
  1714. function TOmfObjInput.ReadImpDef(Rec: TOmfRecord_COMENT): Boolean;
  1715. var
  1716. ImpDefRec: TOmfRecord_COMENT_IMPDEF;
  1717. begin
  1718. ImpDefRec:=TOmfRecord_COMENT_IMPDEF.Create;
  1719. ImpDefRec.DecodeFrom(Rec);
  1720. {todo: implement}
  1721. Result:=True;
  1722. ImpDefRec.Free;
  1723. end;
  1724. function TOmfObjInput.ReadExpDef(Rec: TOmfRecord_COMENT): Boolean;
  1725. begin
  1726. {todo: implement}
  1727. Result:=True;
  1728. end;
  1729. function TOmfObjInput.ImportOmfFixup(objdata: TObjData; objsec: TOmfObjSection; Fixup: TOmfSubRecord_FIXUP): Boolean;
  1730. var
  1731. reloc: TOmfRelocation;
  1732. sym: TObjSymbol;
  1733. RelocType: TObjRelocationType;
  1734. target_section: TOmfObjSection;
  1735. target_group: TObjSectionGroup;
  1736. begin
  1737. Result:=False;
  1738. { range check location }
  1739. if (Fixup.LocationOffset+Fixup.LocationSize)>objsec.Size then
  1740. begin
  1741. InputError('Fixup location exceeds the current segment boundary');
  1742. exit;
  1743. end;
  1744. { range check target datum }
  1745. case Fixup.TargetMethod of
  1746. ftmSegmentIndex:
  1747. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.ObjSectionList.Count) then
  1748. begin
  1749. InputError('Segment name index in SI(<segment name>),<displacement> fixup target is out of range');
  1750. exit;
  1751. end;
  1752. ftmSegmentIndexNoDisp:
  1753. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.ObjSectionList.Count) then
  1754. begin
  1755. InputError('Segment name index in SI(<segment name>) fixup target is out of range');
  1756. exit;
  1757. end;
  1758. ftmGroupIndex:
  1759. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.GroupsList.Count) then
  1760. begin
  1761. InputError('Group name index in GI(<group name>),<displacement> fixup target is out of range');
  1762. exit;
  1763. end;
  1764. ftmGroupIndexNoDisp:
  1765. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>objdata.GroupsList.Count) then
  1766. begin
  1767. InputError('Group name index in GI(<group name>) fixup target is out of range');
  1768. exit;
  1769. end;
  1770. ftmExternalIndex:
  1771. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>ExtDefs.Count) then
  1772. begin
  1773. InputError('External symbol name index in EI(<symbol name>),<displacement> fixup target is out of range');
  1774. exit;
  1775. end;
  1776. ftmExternalIndexNoDisp:
  1777. begin
  1778. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>ExtDefs.Count) then
  1779. begin
  1780. InputError('External symbol name index in EI(<symbol name>) fixup target is out of range');
  1781. exit;
  1782. end;
  1783. end;
  1784. else
  1785. ;
  1786. end;
  1787. { range check frame datum }
  1788. case Fixup.FrameMethod of
  1789. ffmSegmentIndex:
  1790. if (Fixup.FrameDatum<1) or (Fixup.FrameDatum>objdata.ObjSectionList.Count) then
  1791. begin
  1792. InputError('Segment name index in SI(<segment name>) fixup frame is out of range');
  1793. exit;
  1794. end;
  1795. ffmGroupIndex:
  1796. if (Fixup.FrameDatum<1) or (Fixup.FrameDatum>objdata.GroupsList.Count) then
  1797. begin
  1798. InputError('Group name index in GI(<group name>) fixup frame is out of range');
  1799. exit;
  1800. end;
  1801. ffmExternalIndex:
  1802. if (Fixup.TargetDatum<1) or (Fixup.TargetDatum>ExtDefs.Count) then
  1803. begin
  1804. InputError('External symbol name index in EI(<symbol name>) fixup frame is out of range');
  1805. exit;
  1806. end;
  1807. else
  1808. ;
  1809. end;
  1810. if Fixup.TargetMethod in [ftmExternalIndex,ftmExternalIndexNoDisp] then
  1811. begin
  1812. sym:=objdata.symbolref(TOmfExternalNameElement(ExtDefs[Fixup.TargetDatum-1]).Name);
  1813. RelocType:=RELOC_NONE;
  1814. case Fixup.LocationType of
  1815. fltOffset:
  1816. case Fixup.Mode of
  1817. fmSegmentRelative:
  1818. RelocType:=RELOC_ABSOLUTE16;
  1819. fmSelfRelative:
  1820. RelocType:=RELOC_RELATIVE16;
  1821. end;
  1822. fltOffset32:
  1823. case Fixup.Mode of
  1824. fmSegmentRelative:
  1825. RelocType:=RELOC_ABSOLUTE32;
  1826. fmSelfRelative:
  1827. RelocType:=RELOC_RELATIVE32;
  1828. end;
  1829. fltBase:
  1830. case Fixup.Mode of
  1831. fmSegmentRelative:
  1832. RelocType:=RELOC_SEG;
  1833. fmSelfRelative:
  1834. RelocType:=RELOC_SEGREL;
  1835. end;
  1836. fltFarPointer:
  1837. case Fixup.Mode of
  1838. fmSegmentRelative:
  1839. RelocType:=RELOC_FARPTR;
  1840. fmSelfRelative:
  1841. RelocType:=RELOC_FARPTR_RELATIVEOFFSET;
  1842. end;
  1843. fltFarPointer48:
  1844. case Fixup.Mode of
  1845. fmSegmentRelative:
  1846. RelocType:=RELOC_FARPTR48;
  1847. fmSelfRelative:
  1848. RelocType:=RELOC_FARPTR48_RELATIVEOFFSET;
  1849. end;
  1850. else
  1851. ;
  1852. end;
  1853. if RelocType=RELOC_NONE then
  1854. begin
  1855. InputError('Unsupported fixup location type '+tostr(Ord(Fixup.LocationType))+' with mode '+tostr(ord(Fixup.Mode))+' in external reference to '+sym.Name);
  1856. exit;
  1857. end;
  1858. reloc:=TOmfRelocation.CreateSymbol(Fixup.LocationOffset,sym,RelocType);
  1859. objsec.ObjRelocations.Add(reloc);
  1860. case Fixup.FrameMethod of
  1861. ffmTarget:
  1862. {nothing};
  1863. ffmGroupIndex:
  1864. reloc.FrameGroup:=TObjSectionGroup(objdata.GroupsList[Fixup.FrameDatum-1]).Name;
  1865. else
  1866. begin
  1867. InputError('Unsupported frame method '+IntToStr(Ord(Fixup.FrameMethod))+' in external reference to '+sym.Name);
  1868. exit;
  1869. end;
  1870. end;
  1871. if Fixup.TargetDisplacement<>0 then
  1872. begin
  1873. InputError('Unsupported nonzero target displacement '+IntToStr(Fixup.TargetDisplacement)+' in external reference to '+sym.Name);
  1874. exit;
  1875. end;
  1876. end
  1877. else if Fixup.TargetMethod in [ftmSegmentIndex,ftmSegmentIndexNoDisp] then
  1878. begin
  1879. target_section:=TOmfObjSection(objdata.ObjSectionList[Fixup.TargetDatum-1]);
  1880. RelocType:=RELOC_NONE;
  1881. case Fixup.LocationType of
  1882. fltOffset:
  1883. case Fixup.Mode of
  1884. fmSegmentRelative:
  1885. RelocType:=RELOC_ABSOLUTE16;
  1886. fmSelfRelative:
  1887. RelocType:=RELOC_RELATIVE16;
  1888. end;
  1889. fltOffset32:
  1890. case Fixup.Mode of
  1891. fmSegmentRelative:
  1892. RelocType:=RELOC_ABSOLUTE32;
  1893. fmSelfRelative:
  1894. RelocType:=RELOC_RELATIVE32;
  1895. end;
  1896. fltBase:
  1897. case Fixup.Mode of
  1898. fmSegmentRelative:
  1899. RelocType:=RELOC_SEG;
  1900. fmSelfRelative:
  1901. RelocType:=RELOC_SEGREL;
  1902. end;
  1903. fltFarPointer:
  1904. case Fixup.Mode of
  1905. fmSegmentRelative:
  1906. RelocType:=RELOC_FARPTR;
  1907. fmSelfRelative:
  1908. RelocType:=RELOC_FARPTR_RELATIVEOFFSET;
  1909. end;
  1910. fltFarPointer48:
  1911. case Fixup.Mode of
  1912. fmSegmentRelative:
  1913. RelocType:=RELOC_FARPTR48;
  1914. fmSelfRelative:
  1915. RelocType:=RELOC_FARPTR48_RELATIVEOFFSET;
  1916. end;
  1917. else
  1918. ;
  1919. end;
  1920. if RelocType=RELOC_NONE then
  1921. begin
  1922. InputError('Unsupported fixup location type '+tostr(Ord(Fixup.LocationType))+' with mode '+tostr(ord(Fixup.Mode)));
  1923. exit;
  1924. end;
  1925. reloc:=TOmfRelocation.CreateSection(Fixup.LocationOffset,target_section,RelocType);
  1926. objsec.ObjRelocations.Add(reloc);
  1927. case Fixup.FrameMethod of
  1928. ffmTarget:
  1929. {nothing};
  1930. ffmGroupIndex:
  1931. reloc.FrameGroup:=TObjSectionGroup(objdata.GroupsList[Fixup.FrameDatum-1]).Name;
  1932. else
  1933. begin
  1934. InputError('Unsupported frame method '+IntToStr(Ord(Fixup.FrameMethod))+' in reference to segment '+target_section.Name);
  1935. exit;
  1936. end;
  1937. end;
  1938. if Fixup.TargetDisplacement<>0 then
  1939. begin
  1940. InputError('Unsupported nonzero target displacement '+IntToStr(Fixup.TargetDisplacement)+' in reference to segment '+target_section.Name);
  1941. exit;
  1942. end;
  1943. end
  1944. else if Fixup.TargetMethod in [ftmGroupIndex,ftmGroupIndexNoDisp] then
  1945. begin
  1946. target_group:=TObjSectionGroup(objdata.GroupsList[Fixup.TargetDatum-1]);
  1947. RelocType:=RELOC_NONE;
  1948. case Fixup.LocationType of
  1949. fltOffset:
  1950. case Fixup.Mode of
  1951. fmSegmentRelative:
  1952. RelocType:=RELOC_ABSOLUTE16;
  1953. fmSelfRelative:
  1954. RelocType:=RELOC_RELATIVE16;
  1955. end;
  1956. fltOffset32:
  1957. case Fixup.Mode of
  1958. fmSegmentRelative:
  1959. RelocType:=RELOC_ABSOLUTE32;
  1960. fmSelfRelative:
  1961. RelocType:=RELOC_RELATIVE32;
  1962. end;
  1963. fltBase:
  1964. case Fixup.Mode of
  1965. fmSegmentRelative:
  1966. RelocType:=RELOC_SEG;
  1967. fmSelfRelative:
  1968. RelocType:=RELOC_SEGREL;
  1969. end;
  1970. fltFarPointer:
  1971. case Fixup.Mode of
  1972. fmSegmentRelative:
  1973. RelocType:=RELOC_FARPTR;
  1974. fmSelfRelative:
  1975. RelocType:=RELOC_FARPTR_RELATIVEOFFSET;
  1976. end;
  1977. fltFarPointer48:
  1978. case Fixup.Mode of
  1979. fmSegmentRelative:
  1980. RelocType:=RELOC_FARPTR48;
  1981. fmSelfRelative:
  1982. RelocType:=RELOC_FARPTR48_RELATIVEOFFSET;
  1983. end;
  1984. else
  1985. ;
  1986. end;
  1987. if RelocType=RELOC_NONE then
  1988. begin
  1989. InputError('Unsupported fixup location type '+tostr(Ord(Fixup.LocationType))+' with mode '+tostr(ord(Fixup.Mode)));
  1990. exit;
  1991. end;
  1992. reloc:=TOmfRelocation.CreateGroup(Fixup.LocationOffset,target_group,RelocType);
  1993. objsec.ObjRelocations.Add(reloc);
  1994. case Fixup.FrameMethod of
  1995. ffmTarget:
  1996. {nothing};
  1997. else
  1998. begin
  1999. InputError('Unsupported frame method '+IntToStr(Ord(Fixup.FrameMethod))+' in reference to group '+target_group.Name);
  2000. exit;
  2001. end;
  2002. end;
  2003. if Fixup.TargetDisplacement<>0 then
  2004. begin
  2005. InputError('Unsupported nonzero target displacement '+IntToStr(Fixup.TargetDisplacement)+' in reference to group '+target_group.Name);
  2006. exit;
  2007. end;
  2008. end
  2009. else
  2010. begin
  2011. {todo: convert other fixup types as well }
  2012. InputError('Unsupported fixup target method '+IntToStr(Ord(Fixup.TargetMethod)));
  2013. exit;
  2014. end;
  2015. Result:=True;
  2016. end;
  2017. constructor TOmfObjInput.create;
  2018. begin
  2019. inherited create;
  2020. cobjdata:=TOmfObjData;
  2021. FLNames:=TOmfOrderedNameCollection.Create(True);
  2022. FExtDefs:=TFPHashObjectList.Create;
  2023. FPubDefs:=TFPHashObjectList.Create;
  2024. FFixupThreads:=TOmfThreads.Create;
  2025. FRawRecord:=TOmfRawRecord.Create;
  2026. CaseSensitiveSegments:=False;
  2027. CaseSensitiveSymbols:=True;
  2028. end;
  2029. destructor TOmfObjInput.destroy;
  2030. begin
  2031. FCOMENTRecord.Free;
  2032. FRawRecord.Free;
  2033. FFixupThreads.Free;
  2034. FPubDefs.Free;
  2035. FExtDefs.Free;
  2036. FLNames.Free;
  2037. inherited destroy;
  2038. end;
  2039. class function TOmfObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  2040. var
  2041. b: Byte;
  2042. begin
  2043. result:=false;
  2044. if AReader.Read(b,sizeof(b)) then
  2045. begin
  2046. if b=RT_THEADR then
  2047. { TODO: check additional fields }
  2048. result:=true;
  2049. end;
  2050. AReader.Seek(0);
  2051. end;
  2052. function TOmfObjInput.ReadObjData(AReader: TObjectreader; out objdata: TObjData): boolean;
  2053. begin
  2054. FReader:=AReader;
  2055. InputFileName:=AReader.FileName;
  2056. objdata:=CObjData.Create(InputFileName);
  2057. result:=false;
  2058. { the TOmfObjData constructor creates a group 'DGROUP', which is to be
  2059. used by the code generator, when writing files. When reading object
  2060. files, however, we need to start with an empty list of groups, so
  2061. let's clear the group list now. }
  2062. objdata.GroupsList.Clear;
  2063. LNames.Clear;
  2064. ExtDefs.Clear;
  2065. FRawRecord.ReadFrom(FReader);
  2066. if not FRawRecord.VerifyChecksumByte then
  2067. begin
  2068. InputError('Invalid checksum in OMF record');
  2069. exit;
  2070. end;
  2071. if FRawRecord.RecordType<>RT_THEADR then
  2072. begin
  2073. InputError('Can''t read OMF header');
  2074. exit;
  2075. end;
  2076. repeat
  2077. FRawRecord.ReadFrom(FReader);
  2078. if not FRawRecord.VerifyChecksumByte then
  2079. begin
  2080. InputError('Invalid checksum in OMF record');
  2081. exit;
  2082. end;
  2083. FreeAndNil(FCOMENTRecord);
  2084. case FRawRecord.RecordType of
  2085. RT_LNAMES:
  2086. if not ReadLNames(FRawRecord) then
  2087. exit;
  2088. RT_SEGDEF,RT_SEGDEF32:
  2089. if not ReadSegDef(FRawRecord,objdata) then
  2090. exit;
  2091. RT_GRPDEF:
  2092. if not ReadGrpDef(FRawRecord,objdata) then
  2093. exit;
  2094. RT_COMENT:
  2095. begin
  2096. FCOMENTRecord:=TOmfRecord_COMENT.Create;
  2097. FCOMENTRecord.DecodeFrom(FRawRecord);
  2098. case FCOMENTRecord.CommentClass of
  2099. CC_OmfExtension:
  2100. begin
  2101. if Length(FCOMENTRecord.CommentString)>=1 then
  2102. begin
  2103. case Ord(FCOMENTRecord.CommentString[1]) of
  2104. CC_OmfExtension_IMPDEF:
  2105. if not ReadImpDef(FCOMENTRecord) then
  2106. exit;
  2107. CC_OmfExtension_EXPDEF:
  2108. if not ReadExpDef(FCOMENTRecord) then
  2109. exit;
  2110. end;
  2111. end;
  2112. end;
  2113. CC_LIBMOD:
  2114. begin
  2115. {todo: do we need to read the module name here?}
  2116. end;
  2117. CC_EXESTR:
  2118. begin
  2119. InputError('EXESTR record (Executable String Record) is not supported');
  2120. exit;
  2121. end;
  2122. CC_INCERR:
  2123. begin
  2124. InputError('Invalid object file (contains indication of error encountered during incremental compilation)');
  2125. exit;
  2126. end;
  2127. CC_NOPAD:
  2128. begin
  2129. InputError('NOPAD (No Segment Padding) record is not supported');
  2130. exit;
  2131. end;
  2132. CC_WKEXT:
  2133. begin
  2134. InputError('Weak externals are not supported');
  2135. exit;
  2136. end;
  2137. CC_LZEXT:
  2138. begin
  2139. InputError('Lazy externals are not supported');
  2140. exit;
  2141. end;
  2142. else
  2143. begin
  2144. {the rest are ignored for now...}
  2145. end;
  2146. end;
  2147. end;
  2148. RT_EXTDEF:
  2149. if not ReadExtDef(FRawRecord,objdata) then
  2150. exit;
  2151. RT_LPUBDEF,RT_LPUBDEF32,
  2152. RT_PUBDEF,RT_PUBDEF32:
  2153. if not ReadPubDef(FRawRecord,objdata) then
  2154. exit;
  2155. RT_LEDATA,RT_LEDATA32,
  2156. RT_LIDATA,RT_LIDATA32,
  2157. RT_FIXUPP,RT_FIXUPP32:
  2158. if not ReadLeOrLiDataAndFixups(FRawRecord,objdata) then
  2159. exit;
  2160. RT_MODEND,RT_MODEND32:
  2161. if not ReadModEnd(FRawRecord,objdata) then
  2162. exit;
  2163. RT_LINNUM,RT_LINNUM32:
  2164. ;
  2165. else
  2166. begin
  2167. InputError('Unsupported OMF record type $'+HexStr(FRawRecord.RecordType,2));
  2168. exit;
  2169. end;
  2170. end;
  2171. until FRawRecord.RecordType in [RT_MODEND,RT_MODEND32];
  2172. result:=true;
  2173. end;
  2174. {****************************************************************************
  2175. TMZExeHeader
  2176. ****************************************************************************}
  2177. procedure TMZExeHeader.SetHeaderSizeAlignment(AValue: Integer);
  2178. begin
  2179. if (AValue<16) or ((AValue mod 16) <> 0) then
  2180. Internalerror(2015060601);
  2181. FHeaderSizeAlignment:=AValue;
  2182. end;
  2183. constructor TMZExeHeader.Create;
  2184. begin
  2185. FHeaderSizeAlignment:=16;
  2186. end;
  2187. procedure TMZExeHeader.WriteTo(aWriter: TObjectWriter);
  2188. var
  2189. NumRelocs: Word;
  2190. HeaderSizeInBytes: DWord;
  2191. HeaderParagraphs: Word;
  2192. RelocTableOffset: Word;
  2193. BytesInLastBlock: Word;
  2194. BlocksInFile: Word;
  2195. HeaderBytes: array [0..$1B] of Byte;
  2196. RelocBytes: array [0..3] of Byte;
  2197. TotalExeSize: DWord;
  2198. i: Integer;
  2199. begin
  2200. NumRelocs:=Length(Relocations);
  2201. RelocTableOffset:=$1C+Length(ExtraHeaderData);
  2202. HeaderSizeInBytes:=Align(RelocTableOffset+4*NumRelocs,16);
  2203. HeaderParagraphs:=HeaderSizeInBytes div 16;
  2204. TotalExeSize:=HeaderSizeInBytes+LoadableImageSize;
  2205. BlocksInFile:=(TotalExeSize+511) div 512;
  2206. BytesInLastBlock:=TotalExeSize mod 512;
  2207. HeaderBytes[$00]:=$4D; { 'M' }
  2208. HeaderBytes[$01]:=$5A; { 'Z' }
  2209. HeaderBytes[$02]:=Byte(BytesInLastBlock);
  2210. HeaderBytes[$03]:=Byte(BytesInLastBlock shr 8);
  2211. HeaderBytes[$04]:=Byte(BlocksInFile);
  2212. HeaderBytes[$05]:=Byte(BlocksInFile shr 8);
  2213. HeaderBytes[$06]:=Byte(NumRelocs);
  2214. HeaderBytes[$07]:=Byte(NumRelocs shr 8);
  2215. HeaderBytes[$08]:=Byte(HeaderParagraphs);
  2216. HeaderBytes[$09]:=Byte(HeaderParagraphs shr 8);
  2217. HeaderBytes[$0A]:=Byte(MinExtraParagraphs);
  2218. HeaderBytes[$0B]:=Byte(MinExtraParagraphs shr 8);
  2219. HeaderBytes[$0C]:=Byte(MaxExtraParagraphs);
  2220. HeaderBytes[$0D]:=Byte(MaxExtraParagraphs shr 8);
  2221. HeaderBytes[$0E]:=Byte(InitialSS);
  2222. HeaderBytes[$0F]:=Byte(InitialSS shr 8);
  2223. HeaderBytes[$10]:=Byte(InitialSP);
  2224. HeaderBytes[$11]:=Byte(InitialSP shr 8);
  2225. HeaderBytes[$12]:=Byte(Checksum);
  2226. HeaderBytes[$13]:=Byte(Checksum shr 8);
  2227. HeaderBytes[$14]:=Byte(InitialIP);
  2228. HeaderBytes[$15]:=Byte(InitialIP shr 8);
  2229. HeaderBytes[$16]:=Byte(InitialCS);
  2230. HeaderBytes[$17]:=Byte(InitialCS shr 8);
  2231. HeaderBytes[$18]:=Byte(RelocTableOffset);
  2232. HeaderBytes[$19]:=Byte(RelocTableOffset shr 8);
  2233. HeaderBytes[$1A]:=Byte(OverlayNumber);
  2234. HeaderBytes[$1B]:=Byte(OverlayNumber shr 8);
  2235. aWriter.write(HeaderBytes[0],$1C);
  2236. aWriter.write(ExtraHeaderData[0],Length(ExtraHeaderData));
  2237. for i:=0 to NumRelocs-1 do
  2238. with Relocations[i] do
  2239. begin
  2240. RelocBytes[0]:=Byte(offset);
  2241. RelocBytes[1]:=Byte(offset shr 8);
  2242. RelocBytes[2]:=Byte(segment);
  2243. RelocBytes[3]:=Byte(segment shr 8);
  2244. aWriter.write(RelocBytes[0],4);
  2245. end;
  2246. { pad with zeros until the end of header (paragraph aligned) }
  2247. aWriter.WriteZeros(HeaderSizeInBytes-aWriter.Size);
  2248. end;
  2249. procedure TMZExeHeader.AddRelocation(aSegment, aOffset: Word);
  2250. begin
  2251. SetLength(FRelocations,Length(FRelocations)+1);
  2252. with FRelocations[High(FRelocations)] do
  2253. begin
  2254. segment:=aSegment;
  2255. offset:=aOffset;
  2256. end;
  2257. end;
  2258. {****************************************************************************
  2259. TMZExeSection
  2260. ****************************************************************************}
  2261. procedure TMZExeSection.AddObjSection(objsec: TObjSection; ignoreprops: boolean);
  2262. begin
  2263. { allow mixing initialized and uninitialized data in the same section
  2264. => set ignoreprops=true }
  2265. inherited AddObjSection(objsec,true);
  2266. end;
  2267. {****************************************************************************
  2268. TMZExeUnifiedLogicalSegment
  2269. ****************************************************************************}
  2270. constructor TMZExeUnifiedLogicalSegment.create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  2271. var
  2272. Separator: SizeInt;
  2273. begin
  2274. inherited create(HashObjectList,s);
  2275. FObjSectionList:=TFPObjectList.Create(false);
  2276. { name format is 'SegName||ClassName' }
  2277. Separator:=Pos('||',s);
  2278. if Separator>0 then
  2279. begin
  2280. FSegName:=Copy(s,1,Separator-1);
  2281. FSegClass:=Copy(s,Separator+2,Length(s)-Separator-1);
  2282. end
  2283. else
  2284. begin
  2285. FSegName:=Name;
  2286. FSegClass:='';
  2287. end;
  2288. { wlink recognizes the stack segment by the class name 'STACK' }
  2289. { let's be compatible with wlink }
  2290. IsStack:=FSegClass='STACK';
  2291. end;
  2292. destructor TMZExeUnifiedLogicalSegment.destroy;
  2293. begin
  2294. FObjSectionList.Free;
  2295. inherited destroy;
  2296. end;
  2297. procedure TMZExeUnifiedLogicalSegment.AddObjSection(ObjSec: TOmfObjSection);
  2298. begin
  2299. ObjSectionList.Add(ObjSec);
  2300. ObjSec.MZExeUnifiedLogicalSegment:=self;
  2301. { tlink (and ms link?) use the scStack segment combination to recognize
  2302. the stack segment.
  2303. let's be compatible with tlink as well }
  2304. if ObjSec.Combination=scStack then
  2305. IsStack:=True;
  2306. end;
  2307. procedure TMZExeUnifiedLogicalSegment.CalcMemPos;
  2308. var
  2309. MinMemPos: qword=high(qword);
  2310. MaxMemPos: qword=0;
  2311. objsec: TOmfObjSection;
  2312. i: Integer;
  2313. begin
  2314. if ObjSectionList.Count=0 then
  2315. internalerror(2015082201);
  2316. for i:=0 to ObjSectionList.Count-1 do
  2317. begin
  2318. objsec:=TOmfObjSection(ObjSectionList[i]);
  2319. if objsec.MemPos<MinMemPos then
  2320. MinMemPos:=objsec.MemPos;
  2321. if (objsec.MemPos+objsec.Size)>MaxMemPos then
  2322. MaxMemPos:=objsec.MemPos+objsec.Size;
  2323. end;
  2324. MemPos:=MinMemPos;
  2325. Size:=MaxMemPos-MemPos;
  2326. end;
  2327. function TMZExeUnifiedLogicalSegment.MemPosStr: string;
  2328. begin
  2329. Result:=HexStr(MemBasePos shr 4,4)+':'+HexStr((MemPos-MemBasePos),4);
  2330. end;
  2331. {****************************************************************************
  2332. TMZExeUnifiedLogicalGroup
  2333. ****************************************************************************}
  2334. constructor TMZExeUnifiedLogicalGroup.create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  2335. begin
  2336. inherited create(HashObjectList,s);
  2337. FSegmentList:=TFPHashObjectList.Create(false);
  2338. end;
  2339. destructor TMZExeUnifiedLogicalGroup.destroy;
  2340. begin
  2341. FSegmentList.Free;
  2342. inherited destroy;
  2343. end;
  2344. procedure TMZExeUnifiedLogicalGroup.CalcMemPos;
  2345. var
  2346. MinMemPos: qword=high(qword);
  2347. MaxMemPos: qword=0;
  2348. UniSeg: TMZExeUnifiedLogicalSegment;
  2349. i: Integer;
  2350. begin
  2351. if SegmentList.Count=0 then
  2352. internalerror(2015082201);
  2353. for i:=0 to SegmentList.Count-1 do
  2354. begin
  2355. UniSeg:=TMZExeUnifiedLogicalSegment(SegmentList[i]);
  2356. if UniSeg.MemPos<MinMemPos then
  2357. MinMemPos:=UniSeg.MemPos;
  2358. if (UniSeg.MemPos+UniSeg.Size)>MaxMemPos then
  2359. MaxMemPos:=UniSeg.MemPos+UniSeg.Size;
  2360. end;
  2361. { align *down* on a paragraph boundary }
  2362. MemPos:=(MinMemPos shr 4) shl 4;
  2363. Size:=MaxMemPos-MemPos;
  2364. end;
  2365. function TMZExeUnifiedLogicalGroup.MemPosStr: string;
  2366. begin
  2367. Result:=HexStr(MemPos shr 4,4)+':'+HexStr(MemPos and $f,4);
  2368. end;
  2369. procedure TMZExeUnifiedLogicalGroup.AddSegment(UniSeg: TMZExeUnifiedLogicalSegment);
  2370. begin
  2371. SegmentList.Add(UniSeg.Name,UniSeg);
  2372. if UniSeg.PrimaryGroup='' then
  2373. UniSeg.PrimaryGroup:=Name;
  2374. end;
  2375. {****************************************************************************
  2376. TMZExeOutput
  2377. ****************************************************************************}
  2378. function TMZExeOutput.GetMZFlatContentSection: TMZExeSection;
  2379. begin
  2380. if not assigned(FMZFlatContentSection) then
  2381. FMZFlatContentSection:=TMZExeSection(FindExeSection('.MZ_flat_content'));
  2382. result:=FMZFlatContentSection;
  2383. end;
  2384. procedure TMZExeOutput.CalcDwarfUnifiedLogicalSegmentsForSection(const SecName: TSymStr);
  2385. var
  2386. ExeSec: TMZExeSection;
  2387. ObjSec: TOmfObjSection;
  2388. UniSeg: TMZExeUnifiedLogicalSegment;
  2389. i: Integer;
  2390. begin
  2391. ExeSec:=TMZExeSection(FindExeSection(SecName));
  2392. for i:=0 to ExeSec.ObjSectionList.Count-1 do
  2393. begin
  2394. ObjSec:=TOmfObjSection(ExeSec.ObjSectionList[i]);
  2395. UniSeg:=TMZExeUnifiedLogicalSegment(DwarfUnifiedLogicalSegments.Find(ObjSec.Name));
  2396. if not assigned(UniSeg) then
  2397. begin
  2398. UniSeg:=TMZExeUnifiedLogicalSegment.Create(DwarfUnifiedLogicalSegments,ObjSec.Name);
  2399. UniSeg.MemPos:=0;
  2400. end;
  2401. UniSeg.AddObjSection(ObjSec);
  2402. end;
  2403. for i:=0 to DwarfUnifiedLogicalSegments.Count-1 do
  2404. begin
  2405. UniSeg:=TMZExeUnifiedLogicalSegment(DwarfUnifiedLogicalSegments[i]);
  2406. UniSeg.CalcMemPos;
  2407. end;
  2408. end;
  2409. procedure TMZExeOutput.CalcExeUnifiedLogicalSegments;
  2410. var
  2411. ExeSec: TMZExeSection;
  2412. ObjSec: TOmfObjSection;
  2413. UniSeg: TMZExeUnifiedLogicalSegment;
  2414. i: Integer;
  2415. begin
  2416. ExeSec:=MZFlatContentSection;
  2417. for i:=0 to ExeSec.ObjSectionList.Count-1 do
  2418. begin
  2419. ObjSec:=TOmfObjSection(ExeSec.ObjSectionList[i]);
  2420. UniSeg:=TMZExeUnifiedLogicalSegment(ExeUnifiedLogicalSegments.Find(ObjSec.Name));
  2421. if not assigned(UniSeg) then
  2422. UniSeg:=TMZExeUnifiedLogicalSegment.Create(ExeUnifiedLogicalSegments,ObjSec.Name);
  2423. UniSeg.AddObjSection(ObjSec);
  2424. end;
  2425. for i:=0 to ExeUnifiedLogicalSegments.Count-1 do
  2426. begin
  2427. UniSeg:=TMZExeUnifiedLogicalSegment(ExeUnifiedLogicalSegments[i]);
  2428. UniSeg.CalcMemPos;
  2429. if UniSeg.Size>$10000 then
  2430. begin
  2431. if current_settings.x86memorymodel=mm_tiny then
  2432. Message1(link_e_program_segment_too_large,IntToStr(UniSeg.Size-$10000))
  2433. else if UniSeg.SegClass='CODE' then
  2434. Message2(link_e_code_segment_too_large,UniSeg.SegName,IntToStr(UniSeg.Size-$10000))
  2435. else if UniSeg.SegClass='DATA' then
  2436. Message2(link_e_data_segment_too_large,UniSeg.SegName,IntToStr(UniSeg.Size-$10000))
  2437. else
  2438. Message2(link_e_segment_too_large,UniSeg.SegName,IntToStr(UniSeg.Size-$10000)+' '+UniSeg.SegName);
  2439. end;
  2440. end;
  2441. end;
  2442. procedure TMZExeOutput.CalcExeGroups;
  2443. procedure AddToGroup(UniSeg:TMZExeUnifiedLogicalSegment;GroupName:TSymStr);
  2444. var
  2445. Group: TMZExeUnifiedLogicalGroup;
  2446. begin
  2447. Group:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(GroupName));
  2448. if not assigned(Group) then
  2449. Group:=TMZExeUnifiedLogicalGroup.Create(ExeUnifiedLogicalGroups,GroupName);
  2450. Group.AddSegment(UniSeg);
  2451. end;
  2452. var
  2453. objdataidx,groupidx,secidx: Integer;
  2454. ObjData: TObjData;
  2455. ObjGroup: TObjSectionGroup;
  2456. ObjSec: TOmfObjSection;
  2457. UniGrp: TMZExeUnifiedLogicalGroup;
  2458. begin
  2459. for objdataidx:=0 to ObjDataList.Count-1 do
  2460. begin
  2461. ObjData:=TObjData(ObjDataList[objdataidx]);
  2462. if assigned(ObjData.GroupsList) then
  2463. for groupidx:=0 to ObjData.GroupsList.Count-1 do
  2464. begin
  2465. ObjGroup:=TObjSectionGroup(ObjData.GroupsList[groupidx]);
  2466. for secidx:=low(ObjGroup.members) to high(ObjGroup.members) do
  2467. begin
  2468. ObjSec:=TOmfObjSection(ObjGroup.members[secidx]);
  2469. if assigned(ObjSec.MZExeUnifiedLogicalSegment) then
  2470. AddToGroup(ObjSec.MZExeUnifiedLogicalSegment,ObjGroup.Name);
  2471. end;
  2472. end;
  2473. end;
  2474. for groupidx:=0 to ExeUnifiedLogicalGroups.Count-1 do
  2475. begin
  2476. UniGrp:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups[groupidx]);
  2477. UniGrp.CalcMemPos;
  2478. if UniGrp.Size>$10000 then
  2479. begin
  2480. if current_settings.x86memorymodel=mm_tiny then
  2481. Message1(link_e_program_segment_too_large,IntToStr(UniGrp.Size-$10000))
  2482. else if UniGrp.Name='DGROUP' then
  2483. Message2(link_e_data_segment_too_large,UniGrp.Name,IntToStr(UniGrp.Size-$10000))
  2484. else
  2485. Message2(link_e_group_too_large,UniGrp.Name,IntToStr(UniGrp.Size-$10000));
  2486. end;
  2487. end;
  2488. end;
  2489. procedure TMZExeOutput.CalcSegments_MemBasePos;
  2490. var
  2491. lastbase:qword=0;
  2492. i: Integer;
  2493. UniSeg: TMZExeUnifiedLogicalSegment;
  2494. begin
  2495. for i:=0 to ExeUnifiedLogicalSegments.Count-1 do
  2496. begin
  2497. UniSeg:=TMZExeUnifiedLogicalSegment(ExeUnifiedLogicalSegments[i]);
  2498. if (UniSeg.PrimaryGroup<>'') or (UniSeg.IsStack) or
  2499. (((UniSeg.MemPos+UniSeg.Size-1)-lastbase)>$ffff) then
  2500. lastbase:=(UniSeg.MemPos shr 4) shl 4;
  2501. UniSeg.MemBasePos:=lastbase;
  2502. end;
  2503. end;
  2504. procedure TMZExeOutput.WriteMap_SegmentsAndGroups;
  2505. var
  2506. i, LongestGroupName, LongestSegmentName, LongestClassName: Integer;
  2507. UniSeg: TMZExeUnifiedLogicalSegment;
  2508. UniGrp: TMZExeUnifiedLogicalGroup;
  2509. GroupColumnSize, SegmentColumnSize, ClassColumnSize: LongInt;
  2510. begin
  2511. LongestGroupName:=0;
  2512. for i:=0 to ExeUnifiedLogicalGroups.Count-1 do
  2513. begin
  2514. UniGrp:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups[i]);
  2515. LongestGroupName:=max(LongestGroupName,Length(UniGrp.Name));
  2516. end;
  2517. LongestSegmentName:=0;
  2518. LongestClassName:=0;
  2519. for i:=0 to ExeUnifiedLogicalSegments.Count-1 do
  2520. begin
  2521. UniSeg:=TMZExeUnifiedLogicalSegment(ExeUnifiedLogicalSegments[i]);
  2522. LongestSegmentName:=max(LongestSegmentName,Length(UniSeg.SegName));
  2523. LongestClassName:=max(LongestClassName,Length(UniSeg.SegClass));
  2524. end;
  2525. GroupColumnSize:=max(32,LongestGroupName+1);
  2526. SegmentColumnSize:=max(23,LongestSegmentName+1);
  2527. ClassColumnSize:=max(15,LongestClassName+1);
  2528. exemap.AddHeader('Groups list');
  2529. exemap.Add('');
  2530. exemap.Add(PadSpace('Group',GroupColumnSize)+PadSpace('Address',21)+'Size');
  2531. exemap.Add(PadSpace('=====',GroupColumnSize)+PadSpace('=======',21)+'====');
  2532. exemap.Add('');
  2533. for i:=0 to ExeUnifiedLogicalGroups.Count-1 do
  2534. begin
  2535. UniGrp:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups[i]);
  2536. exemap.Add(PadSpace(UniGrp.Name,GroupColumnSize)+PadSpace(UniGrp.MemPosStr,21)+HexStr(UniGrp.Size,8));
  2537. end;
  2538. exemap.Add('');
  2539. GroupColumnSize:=max(15,LongestGroupName+1);
  2540. exemap.AddHeader('Segments list');
  2541. exemap.Add('');
  2542. exemap.Add(PadSpace('Segment',SegmentColumnSize)+PadSpace('Class',ClassColumnSize)+PadSpace('Group',GroupColumnSize)+PadSpace('Address',16)+'Size');
  2543. exemap.Add(PadSpace('=======',SegmentColumnSize)+PadSpace('=====',ClassColumnSize)+PadSpace('=====',GroupColumnSize)+PadSpace('=======',16)+'====');
  2544. exemap.Add('');
  2545. for i:=0 to ExeUnifiedLogicalSegments.Count-1 do
  2546. begin
  2547. UniSeg:=TMZExeUnifiedLogicalSegment(ExeUnifiedLogicalSegments[i]);
  2548. exemap.Add(PadSpace(UniSeg.SegName,SegmentColumnSize)+PadSpace(UniSeg.SegClass,ClassColumnSize)+PadSpace(UniSeg.PrimaryGroup,GroupColumnSize)+PadSpace(UniSeg.MemPosStr,16)+HexStr(UniSeg.Size,8));
  2549. end;
  2550. exemap.Add('');
  2551. end;
  2552. procedure TMZExeOutput.WriteMap_HeaderData;
  2553. begin
  2554. exemap.AddHeader('Header data');
  2555. exemap.Add('Loadable image size: '+HexStr(Header.LoadableImageSize,8));
  2556. exemap.Add('Min extra paragraphs: '+HexStr(Header.MinExtraParagraphs,4));
  2557. exemap.Add('Max extra paragraphs: '+HexStr(Header.MaxExtraParagraphs,4));
  2558. exemap.Add('Initial stack pointer: '+HexStr(Header.InitialSS,4)+':'+HexStr(Header.InitialSP,4));
  2559. exemap.Add('Entry point address: '+HexStr(Header.InitialCS,4)+':'+HexStr(Header.InitialIP,4));
  2560. end;
  2561. function TMZExeOutput.FindStackSegment: TMZExeUnifiedLogicalSegment;
  2562. var
  2563. i: Integer;
  2564. stackseg_wannabe: TMZExeUnifiedLogicalSegment;
  2565. begin
  2566. Result:=nil;
  2567. for i:=0 to ExeUnifiedLogicalSegments.Count-1 do
  2568. begin
  2569. stackseg_wannabe:=TMZExeUnifiedLogicalSegment(ExeUnifiedLogicalSegments[i]);
  2570. { if there are multiple stack segments, choose the largest one.
  2571. In theory, we're probably supposed to combine them all and put
  2572. them in a contiguous location in memory, but we don't care }
  2573. if stackseg_wannabe.IsStack and
  2574. (not assigned(result) or (Result.Size<stackseg_wannabe.Size)) then
  2575. Result:=stackseg_wannabe;
  2576. end;
  2577. end;
  2578. procedure TMZExeOutput.FillLoadableImageSize;
  2579. var
  2580. i: Integer;
  2581. ExeSec: TMZExeSection;
  2582. ObjSec: TOmfObjSection;
  2583. StartDataPos: LongWord;
  2584. buf: array [0..1023] of byte;
  2585. bytesread: LongWord;
  2586. begin
  2587. Header.LoadableImageSize:=0;
  2588. ExeSec:=MZFlatContentSection;
  2589. for i:=0 to ExeSec.ObjSectionList.Count-1 do
  2590. begin
  2591. ObjSec:=TOmfObjSection(ExeSec.ObjSectionList[i]);
  2592. if (ObjSec.Size>0) and assigned(ObjSec.Data) then
  2593. if (ObjSec.MemPos+ObjSec.Size)>Header.LoadableImageSize then
  2594. Header.LoadableImageSize:=ObjSec.MemPos+ObjSec.Size;
  2595. end;
  2596. end;
  2597. procedure TMZExeOutput.FillMinExtraParagraphs;
  2598. var
  2599. ExeSec: TMZExeSection;
  2600. begin
  2601. ExeSec:=MZFlatContentSection;
  2602. Header.MinExtraParagraphs:=(align(ExeSec.Size,16)-align(Header.LoadableImageSize,16)) div 16;
  2603. end;
  2604. procedure TMZExeOutput.FillMaxExtraParagraphs;
  2605. var
  2606. heapmin_paragraphs: Integer;
  2607. heapmax_paragraphs: Integer;
  2608. begin
  2609. if current_settings.x86memorymodel in x86_far_data_models then
  2610. begin
  2611. { calculate the additional number of paragraphs needed }
  2612. heapmin_paragraphs:=(heapsize + 15) div 16;
  2613. heapmax_paragraphs:=(maxheapsize + 15) div 16;
  2614. Header.MaxExtraParagraphs:=min(Header.MinExtraParagraphs-heapmin_paragraphs+heapmax_paragraphs,$FFFF);
  2615. end
  2616. else
  2617. Header.MaxExtraParagraphs:=$FFFF;
  2618. end;
  2619. procedure TMZExeOutput.FillStartAddress;
  2620. var
  2621. EntryMemPos: qword;
  2622. EntryMemBasePos: qword;
  2623. begin
  2624. EntryMemPos:=EntrySym.address;
  2625. if assigned(EntrySym.group) then
  2626. EntryMemBasePos:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(EntrySym.group.Name)).MemPos
  2627. else
  2628. EntryMemBasePos:=TOmfObjSection(EntrySym.objsection).MZExeUnifiedLogicalSegment.MemBasePos;
  2629. Header.InitialIP:=EntryMemPos-EntryMemBasePos;
  2630. Header.InitialCS:=EntryMemBasePos shr 4;
  2631. end;
  2632. procedure TMZExeOutput.FillStackAddress;
  2633. var
  2634. stackseg: TMZExeUnifiedLogicalSegment;
  2635. begin
  2636. stackseg:=FindStackSegment;
  2637. if assigned(stackseg) then
  2638. begin
  2639. Header.InitialSS:=stackseg.MemBasePos shr 4;
  2640. Header.InitialSP:=stackseg.MemPos+stackseg.Size-stackseg.MemBasePos;
  2641. end
  2642. else
  2643. begin
  2644. Header.InitialSS:=0;
  2645. Header.InitialSP:=0;
  2646. end;
  2647. end;
  2648. procedure TMZExeOutput.FillHeaderData;
  2649. begin
  2650. Header.MaxExtraParagraphs:=$FFFF;
  2651. FillLoadableImageSize;
  2652. FillMinExtraParagraphs;
  2653. FillMaxExtraParagraphs;
  2654. FillStartAddress;
  2655. FillStackAddress;
  2656. if assigned(exemap) then
  2657. WriteMap_HeaderData;
  2658. end;
  2659. function TMZExeOutput.writeExe: boolean;
  2660. var
  2661. ExeSec: TMZExeSection;
  2662. i: Integer;
  2663. ObjSec: TOmfObjSection;
  2664. begin
  2665. Result:=False;
  2666. FillHeaderData;
  2667. Header.WriteTo(FWriter);
  2668. ExeSec:=MZFlatContentSection;
  2669. ExeSec.DataPos:=FWriter.Size;
  2670. for i:=0 to ExeSec.ObjSectionList.Count-1 do
  2671. begin
  2672. ObjSec:=TOmfObjSection(ExeSec.ObjSectionList[i]);
  2673. if ObjSec.MemPos<Header.LoadableImageSize then
  2674. begin
  2675. FWriter.WriteZeros(max(0,ObjSec.MemPos-FWriter.Size+ExeSec.DataPos));
  2676. if assigned(ObjSec.Data) then
  2677. FWriter.writearray(ObjSec.Data);
  2678. end;
  2679. end;
  2680. Result:=True;
  2681. end;
  2682. function TMZExeOutput.writeCom: boolean;
  2683. const
  2684. ComFileOffset=$100;
  2685. var
  2686. i: Integer;
  2687. ExeSec: TMZExeSection;
  2688. ObjSec: TOmfObjSection;
  2689. StartDataPos: LongWord;
  2690. buf: array [0..1023] of byte;
  2691. bytesread: LongWord;
  2692. begin
  2693. FillHeaderData;
  2694. if Length(Header.Relocations)>0 then
  2695. begin
  2696. Message(link_e_com_program_uses_segment_relocations);
  2697. exit(False);
  2698. end;
  2699. ExeSec:=MZFlatContentSection;
  2700. for i:=0 to ExeSec.ObjSectionList.Count-1 do
  2701. begin
  2702. ObjSec:=TOmfObjSection(ExeSec.ObjSectionList[i]);
  2703. if ObjSec.MemPos<Header.LoadableImageSize then
  2704. begin
  2705. FWriter.WriteZeros(max(0,int64(ObjSec.MemPos)-ComFileOffset-int64(FWriter.Size)));
  2706. if assigned(ObjSec.Data) then
  2707. begin
  2708. if ObjSec.MemPos<ComFileOffset then
  2709. begin
  2710. ObjSec.Data.seek(ComFileOffset-ObjSec.MemPos);
  2711. repeat
  2712. bytesread:=ObjSec.Data.read(buf,sizeof(buf));
  2713. if bytesread<>0 then
  2714. FWriter.write(buf,bytesread);
  2715. until bytesread=0;
  2716. end
  2717. else
  2718. FWriter.writearray(ObjSec.Data);
  2719. end;
  2720. end;
  2721. end;
  2722. Result:=True;
  2723. end;
  2724. function TMZExeOutput.writeDebugElf: boolean;
  2725. label
  2726. cleanup;
  2727. var
  2728. debugsections: array of TMZExeSection;
  2729. debugsections_count: Word;
  2730. elfsections_count: Word;
  2731. elfsechdrs: array of TElf32sechdr;
  2732. shstrndx: Word;
  2733. next_section_ofs, elf_start_pos, elf_end_pos: LongWord;
  2734. ElfHeader: TElf32header;
  2735. shstrtabsect_data: TDynamicArray=Nil;
  2736. I, elfsecidx, J: Integer;
  2737. ObjSec: TOmfObjSection;
  2738. tis_trailer: TTISTrailer;
  2739. begin
  2740. debugsections:=nil;
  2741. elfsechdrs:=nil;
  2742. { mark the offset of the start of the ELF image }
  2743. elf_start_pos:=Writer.Size;
  2744. { count the debug sections }
  2745. debugsections_count:=0;
  2746. for I:=0 to ExeSectionList.Count-1 do
  2747. if oso_debug in TMZExeSection(ExeSectionList[I]).SecOptions then
  2748. Inc(debugsections_count);
  2749. { extract them into the debugsections array }
  2750. SetLength(debugsections,debugsections_count);
  2751. debugsections_count:=0;
  2752. for I:=0 to ExeSectionList.Count-1 do
  2753. if oso_debug in TMZExeSection(ExeSectionList[I]).SecOptions then
  2754. begin
  2755. debugsections[debugsections_count]:=TMZExeSection(ExeSectionList[I]);
  2756. Inc(debugsections_count);
  2757. end;
  2758. { prepare/allocate elf section headers }
  2759. elfsections_count:=debugsections_count+2;
  2760. SetLength(elfsechdrs,elfsections_count);
  2761. for I:=0 to elfsections_count-1 do
  2762. FillChar(elfsechdrs[I],SizeOf(elfsechdrs[I]),0);
  2763. shstrndx:=elfsections_count-1;
  2764. shstrtabsect_data:=tdynamicarray.Create(SectionDataMaxGrow);
  2765. shstrtabsect_data.writestr(#0);
  2766. next_section_ofs:=SizeOf(ElfHeader)+elfsections_count*SizeOf(TElf32sechdr);
  2767. for I:=0 to debugsections_count-1 do
  2768. begin
  2769. elfsecidx:=I+1;
  2770. with elfsechdrs[elfsecidx] do
  2771. begin
  2772. sh_name:=shstrtabsect_data.Pos;
  2773. sh_type:=SHT_PROGBITS;
  2774. sh_flags:=0;
  2775. sh_addr:=0;
  2776. sh_offset:=next_section_ofs;
  2777. sh_size:=debugsections[I].Size;
  2778. sh_link:=0;
  2779. sh_info:=0;
  2780. sh_addralign:=0;
  2781. sh_entsize:=0;
  2782. end;
  2783. Inc(next_section_ofs,debugsections[I].Size);
  2784. shstrtabsect_data.writestr(debugsections[I].Name+#0);
  2785. end;
  2786. with elfsechdrs[shstrndx] do
  2787. begin
  2788. sh_name:=shstrtabsect_data.Pos;
  2789. shstrtabsect_data.writestr('.shstrtab'#0);
  2790. sh_type:=SHT_STRTAB;
  2791. sh_flags:=0;
  2792. sh_addr:=0;
  2793. sh_offset:=next_section_ofs;
  2794. sh_size:=shstrtabsect_data.Size;
  2795. sh_link:=0;
  2796. sh_info:=0;
  2797. sh_addralign:=0;
  2798. sh_entsize:=0;
  2799. end;
  2800. { write header }
  2801. FillChar(ElfHeader,SizeOf(ElfHeader),0);
  2802. ElfHeader.e_ident[EI_MAG0]:=ELFMAG0; { = #127'ELF' }
  2803. ElfHeader.e_ident[EI_MAG1]:=ELFMAG1;
  2804. ElfHeader.e_ident[EI_MAG2]:=ELFMAG2;
  2805. ElfHeader.e_ident[EI_MAG3]:=ELFMAG3;
  2806. ElfHeader.e_ident[EI_CLASS]:=ELFCLASS32;
  2807. ElfHeader.e_ident[EI_DATA]:=ELFDATA2LSB;
  2808. ElfHeader.e_ident[EI_VERSION]:=1;
  2809. ElfHeader.e_ident[EI_OSABI]:=ELFOSABI_NONE;
  2810. ElfHeader.e_ident[EI_ABIVERSION]:=0;
  2811. ElfHeader.e_type:=ET_EXEC;
  2812. ElfHeader.e_machine:=EM_386;
  2813. ElfHeader.e_version:=1;
  2814. ElfHeader.e_entry:=0;
  2815. ElfHeader.e_phoff:=0;
  2816. ElfHeader.e_shoff:=SizeOf(ElfHeader);
  2817. ElfHeader.e_flags:=0;
  2818. ElfHeader.e_ehsize:=SizeOf(ElfHeader);
  2819. ElfHeader.e_phentsize:=SizeOf(TElf32proghdr);
  2820. ElfHeader.e_phnum:=0;
  2821. ElfHeader.e_shentsize:=SizeOf(TElf32sechdr);
  2822. ElfHeader.e_shnum:=elfsections_count;
  2823. ElfHeader.e_shstrndx:=shstrndx;
  2824. MaybeSwapHeader(ElfHeader);
  2825. Writer.write(ElfHeader,sizeof(ElfHeader));
  2826. { write section headers }
  2827. for I:=0 to elfsections_count-1 do
  2828. begin
  2829. MaybeSwapSecHeader(elfsechdrs[I]);
  2830. Writer.write(elfsechdrs[I],SizeOf(elfsechdrs[I]));
  2831. end;
  2832. { write section data }
  2833. for J:=0 to debugsections_count-1 do
  2834. begin
  2835. debugsections[J].DataPos:=Writer.Size;
  2836. for i:=0 to debugsections[J].ObjSectionList.Count-1 do
  2837. begin
  2838. ObjSec:=TOmfObjSection(debugsections[J].ObjSectionList[i]);
  2839. if assigned(ObjSec.Data) then
  2840. FWriter.writearray(ObjSec.Data);
  2841. end;
  2842. end;
  2843. { write .shstrtab section data }
  2844. Writer.writearray(shstrtabsect_data);
  2845. { mark the offset past the end of the ELF image }
  2846. elf_end_pos:=Writer.Size;
  2847. { write TIS trailer (not part of the ELF image) }
  2848. FillChar(tis_trailer,sizeof(tis_trailer),0);
  2849. with tis_trailer do
  2850. begin
  2851. tis_signature:=TIS_TRAILER_SIGNATURE;
  2852. tis_vendor:=TIS_TRAILER_VENDOR_TIS;
  2853. tis_type:=TIS_TRAILER_TYPE_TIS_DWARF;
  2854. tis_size:=(elf_end_pos-elf_start_pos)+sizeof(tis_trailer);
  2855. end;
  2856. MayBeSwapTISTrailer(tis_trailer);
  2857. Writer.write(tis_trailer,sizeof(tis_trailer));
  2858. Result:=True;
  2859. cleanup:
  2860. shstrtabsect_data.Free;
  2861. end;
  2862. procedure TMZExeOutput.Load_Symbol(const aname: string);
  2863. var
  2864. dgroup: TObjSectionGroup;
  2865. sym: TObjSymbol;
  2866. begin
  2867. { special handling for the '_edata' and '_end' symbols, which are
  2868. internally added by the linker }
  2869. if (aname='_edata') or (aname='_end') then
  2870. begin
  2871. { create an internal segment with the 'BSS' class }
  2872. internalObjData.createsection('*'+aname+'||BSS',0,[]);
  2873. { add to group 'DGROUP' }
  2874. dgroup:=nil;
  2875. if assigned(internalObjData.GroupsList) then
  2876. dgroup:=TObjSectionGroup(internalObjData.GroupsList.Find('DGROUP'));
  2877. if dgroup=nil then
  2878. dgroup:=internalObjData.createsectiongroup('DGROUP');
  2879. SetLength(dgroup.members,Length(dgroup.members)+1);
  2880. dgroup.members[Length(dgroup.members)-1]:=internalObjData.CurrObjSec;
  2881. { define the symbol itself }
  2882. sym:=internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_DATA);
  2883. sym.group:=dgroup;
  2884. end
  2885. else
  2886. inherited;
  2887. end;
  2888. procedure TMZExeOutput.DoRelocationFixup(objsec: TObjSection);
  2889. var
  2890. i: Integer;
  2891. omfsec: TOmfObjSection absolute objsec;
  2892. objreloc: TOmfRelocation;
  2893. target: DWord;
  2894. framebase: DWord;
  2895. fixupamount: Integer;
  2896. target_group: TMZExeUnifiedLogicalGroup;
  2897. procedure FixupOffset;
  2898. var
  2899. w: Word;
  2900. begin
  2901. omfsec.Data.seek(objreloc.DataOffset);
  2902. omfsec.Data.read(w,2);
  2903. w:=LEtoN(w);
  2904. Inc(w,fixupamount);
  2905. w:=LEtoN(w);
  2906. omfsec.Data.seek(objreloc.DataOffset);
  2907. omfsec.Data.write(w,2);
  2908. end;
  2909. procedure FixupOffset32;
  2910. var
  2911. lw: LongWord;
  2912. begin
  2913. omfsec.Data.seek(objreloc.DataOffset);
  2914. omfsec.Data.read(lw,4);
  2915. lw:=LEtoN(lw);
  2916. Inc(lw,fixupamount);
  2917. lw:=LEtoN(lw);
  2918. omfsec.Data.seek(objreloc.DataOffset);
  2919. omfsec.Data.write(lw,4);
  2920. end;
  2921. procedure FixupBase(DataOffset: LongWord);
  2922. var
  2923. w: Word;
  2924. begin
  2925. omfsec.Data.seek(DataOffset);
  2926. omfsec.Data.read(w,2);
  2927. w:=LEtoN(w);
  2928. Inc(w,framebase shr 4);
  2929. w:=LEtoN(w);
  2930. omfsec.Data.seek(DataOffset);
  2931. omfsec.Data.write(w,2);
  2932. Header.AddRelocation(omfsec.MZExeUnifiedLogicalSegment.MemBasePos shr 4,
  2933. omfsec.MemPos+DataOffset-omfsec.MZExeUnifiedLogicalSegment.MemBasePos);
  2934. end;
  2935. begin
  2936. for i:=0 to objsec.ObjRelocations.Count-1 do
  2937. begin
  2938. objreloc:=TOmfRelocation(objsec.ObjRelocations[i]);
  2939. if assigned(objreloc.symbol) then
  2940. begin
  2941. target:=objreloc.symbol.address;
  2942. if objreloc.FrameGroup<>'' then
  2943. framebase:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(objreloc.FrameGroup)).MemPos
  2944. else if assigned(objreloc.symbol.group) then
  2945. framebase:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(objreloc.symbol.group.Name)).MemPos
  2946. else
  2947. framebase:=TOmfObjSection(objreloc.symbol.objsection).MZExeUnifiedLogicalSegment.MemBasePos;
  2948. case objreloc.typ of
  2949. RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_SEG,RELOC_FARPTR,RELOC_FARPTR48:
  2950. fixupamount:=target-framebase;
  2951. RELOC_RELATIVE16,RELOC_SEGREL,RELOC_FARPTR_RELATIVEOFFSET:
  2952. fixupamount:=target-(omfsec.MemPos+objreloc.DataOffset)-2;
  2953. RELOC_RELATIVE32,RELOC_FARPTR48_RELATIVEOFFSET:
  2954. fixupamount:=target-(omfsec.MemPos+objreloc.DataOffset)-4;
  2955. else
  2956. internalerror(2015082402);
  2957. end;
  2958. case objreloc.typ of
  2959. RELOC_ABSOLUTE16,
  2960. RELOC_RELATIVE16:
  2961. FixupOffset;
  2962. RELOC_ABSOLUTE32,
  2963. RELOC_RELATIVE32:
  2964. FixupOffset32;
  2965. RELOC_SEG,
  2966. RELOC_SEGREL:
  2967. FixupBase(objreloc.DataOffset);
  2968. RELOC_FARPTR,
  2969. RELOC_FARPTR_RELATIVEOFFSET:
  2970. begin
  2971. FixupOffset;
  2972. FixupBase(objreloc.DataOffset+2);
  2973. end;
  2974. RELOC_FARPTR48,
  2975. RELOC_FARPTR48_RELATIVEOFFSET:
  2976. begin
  2977. FixupOffset32;
  2978. FixupBase(objreloc.DataOffset+4);
  2979. end;
  2980. else
  2981. internalerror(2015082403);
  2982. end;
  2983. end
  2984. else if assigned(objreloc.objsection) then
  2985. begin
  2986. target:=objreloc.objsection.MemPos;
  2987. if objreloc.FrameGroup<>'' then
  2988. framebase:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(objreloc.FrameGroup)).MemPos
  2989. else
  2990. begin
  2991. if assigned(TOmfObjSection(objreloc.objsection).MZExeUnifiedLogicalSegment) then
  2992. framebase:=TOmfObjSection(objreloc.objsection).MZExeUnifiedLogicalSegment.MemBasePos
  2993. else
  2994. begin
  2995. framebase:=0;
  2996. Comment(V_Warning,'Encountered an OMF reference to a section, that has been removed by smartlinking: '+TOmfObjSection(objreloc.objsection).Name);
  2997. end;
  2998. end;
  2999. case objreloc.typ of
  3000. RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_SEG,RELOC_FARPTR,RELOC_FARPTR48:
  3001. fixupamount:=target-framebase;
  3002. RELOC_RELATIVE16,RELOC_SEGREL,RELOC_FARPTR_RELATIVEOFFSET:
  3003. fixupamount:=target-(omfsec.MemPos+objreloc.DataOffset)-2;
  3004. RELOC_RELATIVE32,RELOC_FARPTR48_RELATIVEOFFSET:
  3005. fixupamount:=target-(omfsec.MemPos+objreloc.DataOffset)-4;
  3006. else
  3007. internalerror(2015082405);
  3008. end;
  3009. case objreloc.typ of
  3010. RELOC_ABSOLUTE16,
  3011. RELOC_RELATIVE16:
  3012. FixupOffset;
  3013. RELOC_ABSOLUTE32,
  3014. RELOC_RELATIVE32:
  3015. FixupOffset32;
  3016. RELOC_SEG,
  3017. RELOC_SEGREL:
  3018. FixupBase(objreloc.DataOffset);
  3019. RELOC_FARPTR,
  3020. RELOC_FARPTR_RELATIVEOFFSET:
  3021. begin
  3022. FixupOffset;
  3023. FixupBase(objreloc.DataOffset+2);
  3024. end;
  3025. RELOC_FARPTR48,
  3026. RELOC_FARPTR48_RELATIVEOFFSET:
  3027. begin
  3028. FixupOffset32;
  3029. FixupBase(objreloc.DataOffset+4);
  3030. end;
  3031. else
  3032. internalerror(2015082406);
  3033. end;
  3034. end
  3035. else if assigned(objreloc.group) then
  3036. begin
  3037. target_group:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(objreloc.group.Name));
  3038. target:=target_group.MemPos;
  3039. if objreloc.FrameGroup<>'' then
  3040. framebase:=TMZExeUnifiedLogicalGroup(ExeUnifiedLogicalGroups.Find(objreloc.FrameGroup)).MemPos
  3041. else
  3042. framebase:=target_group.MemPos;
  3043. case objreloc.typ of
  3044. RELOC_ABSOLUTE16,RELOC_ABSOLUTE32,RELOC_SEG,RELOC_FARPTR,RELOC_FARPTR48:
  3045. fixupamount:=target-framebase;
  3046. RELOC_RELATIVE16,RELOC_SEGREL,RELOC_FARPTR_RELATIVEOFFSET:
  3047. fixupamount:=target-(omfsec.MemPos+objreloc.DataOffset)-2;
  3048. RELOC_RELATIVE32,RELOC_FARPTR48_RELATIVEOFFSET:
  3049. fixupamount:=target-(omfsec.MemPos+objreloc.DataOffset)-4;
  3050. else
  3051. internalerror(2015111202);
  3052. end;
  3053. case objreloc.typ of
  3054. RELOC_ABSOLUTE16,
  3055. RELOC_RELATIVE16:
  3056. FixupOffset;
  3057. RELOC_ABSOLUTE32,
  3058. RELOC_RELATIVE32:
  3059. FixupOffset32;
  3060. RELOC_SEG,
  3061. RELOC_SEGREL:
  3062. FixupBase(objreloc.DataOffset);
  3063. RELOC_FARPTR,
  3064. RELOC_FARPTR_RELATIVEOFFSET:
  3065. begin
  3066. FixupOffset;
  3067. FixupBase(objreloc.DataOffset+2);
  3068. end;
  3069. RELOC_FARPTR48,
  3070. RELOC_FARPTR48_RELATIVEOFFSET:
  3071. begin
  3072. FixupOffset32;
  3073. FixupBase(objreloc.DataOffset+4);
  3074. end;
  3075. else
  3076. internalerror(2015111203);
  3077. end;
  3078. end
  3079. else
  3080. internalerror(2015082407);
  3081. end;
  3082. end;
  3083. function IOmfObjSectionClassNameCompare(Item1, Item2: Pointer): Integer;
  3084. var
  3085. I1 : TOmfObjSection absolute Item1;
  3086. I2 : TOmfObjSection absolute Item2;
  3087. begin
  3088. Result:=CompareStr(I1.ClassName,I2.ClassName);
  3089. if Result=0 then
  3090. Result:=CompareStr(I1.Name,I2.Name);
  3091. if Result=0 then
  3092. Result:=I1.SortOrder-I2.SortOrder;
  3093. end;
  3094. procedure TMZExeOutput.Order_ObjSectionList(ObjSectionList: TFPObjectList; const aPattern: string);
  3095. var
  3096. i: Integer;
  3097. begin
  3098. for i:=0 to ObjSectionList.Count-1 do
  3099. TOmfObjSection(ObjSectionList[i]).SortOrder:=i;
  3100. ObjSectionList.Sort(@IOmfObjSectionClassNameCompare);
  3101. end;
  3102. procedure TMZExeOutput.MemPos_ExeSection(const aname: string);
  3103. begin
  3104. { overlay all .exe sections on top of each other. In practice, the MZ
  3105. formats doesn't have sections, so really, everything goes to a single
  3106. section, called .MZ_flat_content. All the remaining sections, that we
  3107. use are the debug sections, which go to a separate ELF file, appended
  3108. after the end of the .exe. They live in a separate address space, with
  3109. each section starting at virtual offset 0. So, that's why we always
  3110. set CurrMemPos to 0 before each section here. }
  3111. CurrMemPos:=0;
  3112. inherited MemPos_ExeSection(aname);
  3113. end;
  3114. procedure TMZExeOutput.MemPos_EndExeSection;
  3115. var
  3116. SecName: TSymStr='';
  3117. begin
  3118. if assigned(CurrExeSec) then
  3119. SecName:=CurrExeSec.Name;
  3120. inherited MemPos_EndExeSection;
  3121. case SecName of
  3122. '.MZ_flat_content':
  3123. begin
  3124. CalcExeUnifiedLogicalSegments;
  3125. CalcExeGroups;
  3126. CalcSegments_MemBasePos;
  3127. if assigned(exemap) then
  3128. WriteMap_SegmentsAndGroups;
  3129. end;
  3130. '.debug_info',
  3131. '.debug_abbrev',
  3132. '.debug_line',
  3133. '.debug_aranges':
  3134. begin
  3135. CalcDwarfUnifiedLogicalSegmentsForSection(SecName);
  3136. with TMZExeSection(FindExeSection(SecName)) do
  3137. SecOptions:=SecOptions+[oso_debug];
  3138. end;
  3139. '':
  3140. {nothing to do};
  3141. else
  3142. internalerror(2018061401);
  3143. end;
  3144. end;
  3145. function TMZExeOutput.writeData: boolean;
  3146. begin
  3147. Result:=False;
  3148. if ExeWriteMode in [ewm_exefull,ewm_exeonly] then
  3149. begin
  3150. if apptype=app_com then
  3151. Result:=WriteCom
  3152. else
  3153. Result:=WriteExe;
  3154. if not Result then
  3155. exit;
  3156. end;
  3157. if ((cs_debuginfo in current_settings.moduleswitches) and
  3158. (target_dbg.id in [dbg_dwarf2,dbg_dwarf3,dbg_dwarf4])) and
  3159. ((ExeWriteMode=ewm_dbgonly) or
  3160. ((ExeWriteMode=ewm_exefull) and
  3161. not(cs_link_strip in current_settings.globalswitches))) then
  3162. Result:=writeDebugElf;
  3163. end;
  3164. constructor TMZExeOutput.create;
  3165. begin
  3166. inherited create;
  3167. CExeSection:=TMZExeSection;
  3168. CObjData:=TOmfObjData;
  3169. CObjSymbol:=TOmfObjSymbol;
  3170. { "640K ought to be enough for anybody" :) }
  3171. MaxMemPos:=$9FFFF;
  3172. FExeUnifiedLogicalSegments:=TFPHashObjectList.Create;
  3173. FExeUnifiedLogicalGroups:=TFPHashObjectList.Create;
  3174. FDwarfUnifiedLogicalSegments:=TFPHashObjectList.Create;
  3175. FHeader:=TMZExeHeader.Create;
  3176. end;
  3177. destructor TMZExeOutput.destroy;
  3178. begin
  3179. FHeader.Free;
  3180. FDwarfUnifiedLogicalSegments.Free;
  3181. FExeUnifiedLogicalGroups.Free;
  3182. FExeUnifiedLogicalSegments.Free;
  3183. inherited destroy;
  3184. end;
  3185. {****************************************************************************
  3186. TNewExeHeader
  3187. ****************************************************************************}
  3188. constructor TNewExeHeader.Create;
  3189. begin
  3190. SetLength(FMsDosStub,High(win16stub)-Low(win16stub)+1);
  3191. Move(win16stub[Low(win16stub)],FMsDosStub[0],High(win16stub)-Low(win16stub)+1);
  3192. { BP7 identifies itself as linker version 6.1 in the Win16 .exe files it produces }
  3193. LinkerVersion:=6;
  3194. LinkerRevision:=1;
  3195. LogicalSectorAlignmentShiftCount:=8; { 256-byte logical sectors }
  3196. TargetOS:=netoWindows;
  3197. ExpectedWindowsVersion:=$0300;
  3198. Flags:=[nehfNotWindowAPICompatible,nehfWindowAPICompatible,nehfMultipleData,nehfProtectedModeOnly];
  3199. AdditionalFlags:=[];
  3200. GangLoadAreaStart:=0;
  3201. GangLoadAreaLength:=0;
  3202. Reserved:=0;
  3203. Reserved2:=0;
  3204. end;
  3205. procedure TNewExeHeader.WriteTo(aWriter: TObjectWriter);
  3206. var
  3207. HeaderBytes: array [0..$3F] of Byte;
  3208. begin
  3209. aWriter.write(MsDosStub[0],Length(MsDosStub));
  3210. HeaderBytes[$00]:=$4E; { 'N' }
  3211. HeaderBytes[$01]:=$45; { 'E' }
  3212. HeaderBytes[$02]:=Byte(LinkerVersion);
  3213. HeaderBytes[$03]:=Byte(LinkerRevision);
  3214. HeaderBytes[$04]:=Byte(EntryTableOffset);
  3215. HeaderBytes[$05]:=Byte(EntryTableOffset shr 8);
  3216. HeaderBytes[$06]:=Byte(EntryTableLength);
  3217. HeaderBytes[$07]:=Byte(EntryTableLength shr 8);
  3218. HeaderBytes[$08]:=Byte(Reserved);
  3219. HeaderBytes[$09]:=Byte(Reserved shr 8);
  3220. HeaderBytes[$0A]:=Byte(Reserved shr 16);
  3221. HeaderBytes[$0B]:=Byte(Reserved shr 24);
  3222. HeaderBytes[$0C]:=Byte(Word(Flags));
  3223. HeaderBytes[$0D]:=Byte(Word(Flags) shr 8);
  3224. HeaderBytes[$0E]:=Byte(AutoDataSegmentNumber);
  3225. HeaderBytes[$0F]:=Byte(AutoDataSegmentNumber shr 8);
  3226. HeaderBytes[$10]:=Byte(InitialLocalHeapSize);
  3227. HeaderBytes[$11]:=Byte(InitialLocalHeapSize shr 8);
  3228. HeaderBytes[$12]:=Byte(InitialStackSize);
  3229. HeaderBytes[$13]:=Byte(InitialStackSize shr 8);
  3230. HeaderBytes[$14]:=Byte(InitialIP);
  3231. HeaderBytes[$15]:=Byte(InitialIP shr 8);
  3232. HeaderBytes[$16]:=Byte(InitialCS);
  3233. HeaderBytes[$17]:=Byte(InitialCS shr 8);
  3234. HeaderBytes[$18]:=Byte(InitialSP);
  3235. HeaderBytes[$19]:=Byte(InitialSP shr 8);
  3236. HeaderBytes[$1A]:=Byte(InitialSS);
  3237. HeaderBytes[$1B]:=Byte(InitialSS shr 8);
  3238. HeaderBytes[$1C]:=Byte(SegmentTableEntriesCount);
  3239. HeaderBytes[$1D]:=Byte(SegmentTableEntriesCount shr 8);
  3240. HeaderBytes[$1E]:=Byte(ModuleReferenceTableEntriesCount);
  3241. HeaderBytes[$1F]:=Byte(ModuleReferenceTableEntriesCount shr 8);
  3242. HeaderBytes[$20]:=Byte(NonresidentNameTableLength);
  3243. HeaderBytes[$21]:=Byte(NonresidentNameTableLength shr 8);
  3244. HeaderBytes[$22]:=Byte(SegmentTableStart);
  3245. HeaderBytes[$23]:=Byte(SegmentTableStart shr 8);
  3246. HeaderBytes[$24]:=Byte(ResourceTableStart);
  3247. HeaderBytes[$25]:=Byte(ResourceTableStart shr 8);
  3248. HeaderBytes[$26]:=Byte(ResidentNameTableStart);
  3249. HeaderBytes[$27]:=Byte(ResidentNameTableStart shr 8);
  3250. HeaderBytes[$28]:=Byte(ModuleReferenceTableStart);
  3251. HeaderBytes[$29]:=Byte(ModuleReferenceTableStart shr 8);
  3252. HeaderBytes[$2A]:=Byte(ImportedNameTableStart);
  3253. HeaderBytes[$2B]:=Byte(ImportedNameTableStart shr 8);
  3254. HeaderBytes[$2C]:=Byte(NonresidentNameTableStart);
  3255. HeaderBytes[$2D]:=Byte(NonresidentNameTableStart shr 8);
  3256. HeaderBytes[$2E]:=Byte(NonresidentNameTableStart shr 16);
  3257. HeaderBytes[$2F]:=Byte(NonresidentNameTableStart shr 24);
  3258. HeaderBytes[$30]:=Byte(MovableEntryPointsCount);
  3259. HeaderBytes[$31]:=Byte(MovableEntryPointsCount shr 8);
  3260. HeaderBytes[$32]:=Byte(LogicalSectorAlignmentShiftCount);
  3261. HeaderBytes[$33]:=Byte(LogicalSectorAlignmentShiftCount shr 8);
  3262. HeaderBytes[$34]:=Byte(ResourceSegmentsCount);
  3263. HeaderBytes[$35]:=Byte(ResourceSegmentsCount shr 8);
  3264. HeaderBytes[$36]:=Byte(Ord(TargetOS));
  3265. HeaderBytes[$37]:=Byte(AdditionalFlags);
  3266. HeaderBytes[$38]:=Byte(GangLoadAreaStart);
  3267. HeaderBytes[$39]:=Byte(GangLoadAreaStart shr 8);
  3268. HeaderBytes[$3A]:=Byte(GangLoadAreaLength);
  3269. HeaderBytes[$3B]:=Byte(GangLoadAreaLength shr 8);
  3270. HeaderBytes[$3C]:=Byte(Reserved2);
  3271. HeaderBytes[$3D]:=Byte(Reserved2 shr 8);
  3272. HeaderBytes[$3E]:=Byte(ExpectedWindowsVersion);
  3273. HeaderBytes[$3F]:=Byte(ExpectedWindowsVersion shr 8);
  3274. aWriter.write(HeaderBytes[0],$40);
  3275. end;
  3276. {****************************************************************************
  3277. TNewExeOutput
  3278. ****************************************************************************}
  3279. procedure TNewExeOutput.DoRelocationFixup(objsec: TObjSection);
  3280. begin
  3281. {todo}
  3282. end;
  3283. constructor TNewExeOutput.create;
  3284. begin
  3285. inherited create;
  3286. CObjData:=TOmfObjData;
  3287. CObjSymbol:=TOmfObjSymbol;
  3288. FHeader:=TNewExeHeader.Create;
  3289. end;
  3290. destructor TNewExeOutput.destroy;
  3291. begin
  3292. FHeader.Free;
  3293. inherited destroy;
  3294. end;
  3295. function TNewExeOutput.writeData: boolean;
  3296. begin
  3297. {todo}
  3298. Result:=False;
  3299. end;
  3300. {****************************************************************************
  3301. TOmfAssembler
  3302. ****************************************************************************}
  3303. constructor TOmfAssembler.Create(info: pasminfo; smart:boolean);
  3304. begin
  3305. inherited;
  3306. CObjOutput:=TOmfObjOutput;
  3307. CInternalAr:=TOmfLibObjectWriter;
  3308. end;
  3309. {*****************************************************************************
  3310. Initialize
  3311. *****************************************************************************}
  3312. {$ifdef i8086}
  3313. const
  3314. as_i8086_omf_info : tasminfo =
  3315. (
  3316. id : as_i8086_omf;
  3317. idtxt : 'OMF';
  3318. asmbin : '';
  3319. asmcmd : '';
  3320. supported_targets : [system_i8086_msdos,system_i8086_embedded];
  3321. flags : [af_outputbinary,af_smartlink_sections];
  3322. labelprefix : '..@';
  3323. comment : '; ';
  3324. dollarsign: '$';
  3325. );
  3326. {$endif i8086}
  3327. initialization
  3328. {$ifdef i8086}
  3329. RegisterAssembler(as_i8086_omf_info,TOmfAssembler);
  3330. {$endif i8086}
  3331. end.