ogomf.pas 188 KB

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