ogomf.pas 157 KB

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