ogcoff.pas 127 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511
  1. {
  2. Copyright (c) 1998-2006 by Peter Vreman
  3. Contains the binary coff/PE reader and writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogcoff;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,
  25. { assembler }
  26. aasmbase,assemble,
  27. { output }
  28. ogbase,
  29. owbase;
  30. const
  31. PE_DATADIR_ENTRIES = 16;
  32. type
  33. tcoffpedatadir = packed record
  34. vaddr : longword;
  35. size : longword;
  36. end;
  37. tcoffheader = packed record
  38. mach : word;
  39. nsects : word;
  40. time : longword;
  41. sympos : longword;
  42. syms : longword;
  43. opthdr : word;
  44. flag : word;
  45. end;
  46. tcoffbigobjheader = packed record
  47. Sig1 : word;
  48. Sig2 : word;
  49. Version : word;
  50. Machine : word;
  51. TimeDateStame : longword;
  52. UUID : array[0..15] of byte;
  53. unused : array[0..3] of longword;
  54. NumberOfSections : longword;
  55. PointerToSymbolTable : longword;
  56. NumberOfSymbols : longword;
  57. end;
  58. tcoffpeoptheader = packed record
  59. Magic : word;
  60. MajorLinkerVersion : byte;
  61. MinorLinkerVersion : byte;
  62. tsize : longword;
  63. dsize : longword;
  64. bsize : longword;
  65. entry : longword;
  66. text_start : longword;
  67. {$ifndef cpu64bitaddr}
  68. data_start : longword;
  69. {$endif cpu64bitaddr}
  70. ImageBase : aword;
  71. SectionAlignment : longword;
  72. FileAlignment : longword;
  73. MajorOperatingSystemVersion : word;
  74. MinorOperatingSystemVersion : word;
  75. MajorImageVersion : word;
  76. MinorImageVersion : word;
  77. MajorSubsystemVersion : word;
  78. MinorSubsystemVersion : word;
  79. Win32Version : longword;
  80. SizeOfImage : longword;
  81. SizeOfHeaders : longword;
  82. CheckSum : longword;
  83. Subsystem : word;
  84. DllCharacteristics : word;
  85. SizeOfStackReserve : aword;
  86. SizeOfStackCommit : aword;
  87. SizeOfHeapReserve : aword;
  88. SizeOfHeapCommit : aword;
  89. LoaderFlags : longword; { This field is obsolete }
  90. NumberOfRvaAndSizes : longword;
  91. DataDirectory : array[0..PE_DATADIR_ENTRIES-1] of tcoffpedatadir;
  92. end;
  93. tcoffsechdr = packed record
  94. name : array[0..7] of char;
  95. vsize : longword;
  96. rvaofs : longword;
  97. datasize : longword;
  98. datapos : longword;
  99. relocpos : longword;
  100. lineno1 : longword;
  101. nrelocs : word;
  102. lineno2 : word;
  103. flags : longword;
  104. end;
  105. TCoffObjSection = class(TObjSection)
  106. private
  107. orgmempos,
  108. coffrelocs,
  109. coffrelocpos : aword;
  110. public
  111. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
  112. procedure writereloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);override;
  113. end;
  114. TCoffObjData = class(TObjData)
  115. private
  116. win32 : boolean;
  117. {$ifdef arm}
  118. eVCobj : boolean;
  119. {$endif arm}
  120. public
  121. constructor createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  122. procedure CreateDebugSections;override;
  123. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  124. function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;override;
  125. procedure writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);override;
  126. end;
  127. TDJCoffObjData = class(TCoffObjData)
  128. constructor create(const n:string);override;
  129. end;
  130. TPECoffObjData = class(TCoffObjData)
  131. constructor create(const n:string);override;
  132. end;
  133. TCoffObjOutput = class(tObjOutput)
  134. private
  135. win32 : boolean;
  136. bigobj : boolean;
  137. symidx : longint;
  138. FCoffSyms,
  139. FCoffStrs : tdynamicarray;
  140. procedure write_symbol(const name:string;value:aword;section:longint;typ,aux:byte);
  141. procedure section_write_symbol(p:TObject;arg:pointer);
  142. procedure section_write_relocs(p:TObject;arg:pointer);
  143. procedure create_symbols(data:TObjData);
  144. procedure section_set_reloc_datapos(p:TCoffObjSection;var datapos:aword);
  145. procedure section_write_header(p:TObject;arg:pointer);
  146. protected
  147. function writedata(data:TObjData):boolean;override;
  148. public
  149. constructor createcoff(AWriter:TObjectWriter;awin32:boolean);
  150. destructor destroy;override;
  151. end;
  152. TDJCoffObjOutput = class(TCoffObjOutput)
  153. constructor create(AWriter:TObjectWriter);override;
  154. end;
  155. TPECoffObjOutput = class(TCoffObjOutput)
  156. constructor create(AWriter:TObjectWriter);override;
  157. end;
  158. TCoffObjInput = class(tObjInput)
  159. private
  160. FCoffsyms : tdynamicarray;
  161. FCoffStrs : PChar;
  162. FCoffStrSize: longword;
  163. { Convert symidx -> TObjSymbol }
  164. FSymTbl : ^TObjSymbolArray;
  165. { Convert secidx -> TObjSection }
  166. FSecCount : Longint;
  167. FSecTbl : ^TObjSectionArray;
  168. win32 : boolean;
  169. bigobj : boolean;
  170. function GetSection(secidx:longint):TObjSection;
  171. function Read_str(strpos:longword):string;
  172. procedure read_relocs(s:TCoffObjSection);
  173. procedure read_symbols(objdata:TObjData);
  174. procedure ObjSections_read_relocs(p:TObject;arg:pointer);
  175. public
  176. constructor createcoff(awin32:boolean);
  177. destructor destroy;override;
  178. function ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;override;
  179. end;
  180. TDJCoffObjInput = class(TCoffObjInput)
  181. constructor create;override;
  182. end;
  183. TPECoffObjInput = class(TCoffObjInput)
  184. constructor create;override;
  185. end;
  186. TCoffexeoutput = class(texeoutput)
  187. private
  188. FCoffStrs : tdynamicarray;
  189. win32 : boolean;
  190. nsects : word;
  191. nsyms,
  192. sympos : aword;
  193. datapos_offset: longword;
  194. function totalheadersize:longword;
  195. procedure ExeSectionList_pass2_header(p:TObject;arg:pointer);
  196. procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  197. procedure globalsyms_write_symbol(p:TObject;arg:pointer);
  198. procedure ExeSectionList_write_header(p:TObject;arg:pointer);
  199. protected
  200. function writedata:boolean;override;
  201. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList;const aPattern:string);override;
  202. procedure DoRelocationFixup(objsec:TObjSection);override;
  203. public
  204. constructor createcoff(awin32:boolean);
  205. procedure MemPos_Header;override;
  206. procedure DataPos_Header;override;
  207. procedure DataPos_Symbols;override;
  208. end;
  209. TDJCoffexeoutput = class(TCoffexeoutput)
  210. constructor create;override;
  211. procedure MemPos_Header;override;
  212. end;
  213. TPECoffexeoutput = class(TCoffexeoutput)
  214. private
  215. FImports: TFPHashObjectList;
  216. textobjsection,
  217. idata2objsection,
  218. idata4objsection,
  219. idata5objsection,
  220. idata6objsection,
  221. idata7objsection : TObjSection;
  222. FRelocsGenerated : boolean;
  223. procedure GenerateRelocs;
  224. public
  225. constructor create;override;
  226. procedure MarkTargetSpecificSections(WorkList:TFPObjectList);override;
  227. procedure AfterUnusedSectionRemoval;override;
  228. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  229. procedure MemPos_Start;override;
  230. procedure MemPos_ExeSection(const aname:string);override;
  231. end;
  232. TObjSymbolArray = array[0..high(word)] of TObjSymbol;
  233. TObjSectionArray = array[0..high(smallint)] of TObjSection;
  234. TDJCoffAssembler = class(tinternalassembler)
  235. constructor create(info: pasminfo; smart:boolean);override;
  236. end;
  237. TPECoffassembler = class(tinternalassembler)
  238. constructor create(info: pasminfo; smart:boolean);override;
  239. end;
  240. type
  241. Treaddllproc = procedure(const dllname,funcname:string) of object;
  242. const
  243. {$ifdef i386}
  244. COFF_MAGIC = $14c;
  245. COFF_OPT_MAGIC = $10b;
  246. TLSDIR_SIZE = $18;
  247. {$endif i386}
  248. {$ifdef arm}
  249. COFF_OPT_MAGIC = $10b;
  250. TLSDIR_SIZE = $18;
  251. function COFF_MAGIC: word;
  252. const
  253. {$endif arm}
  254. {$ifdef x86_64}
  255. COFF_MAGIC = $8664;
  256. COFF_OPT_MAGIC = $20b;
  257. TLSDIR_SIZE = $28;
  258. {$endif x86_64}
  259. COFF_BIG_OBJ_MAGIC: array[0..15] of byte = ($C7, $A1, $BA, $D1, $EE, $BA, $A9, $4B, $AF, $20, $FA, $F6, $6A, $A4, $DC, $B8);
  260. COFF_BIG_OBJ_VERSION = 2;
  261. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  262. implementation
  263. uses
  264. {$ifdef win32}
  265. Windows,
  266. {$endif win32}
  267. SysUtils,
  268. cutils,verbose,globals,
  269. cpubase,cpuinfo,
  270. fmodule,
  271. ogmap,
  272. owar,
  273. version
  274. ;
  275. const
  276. COFF_FLAG_NORELOCS = $0001;
  277. COFF_FLAG_EXE = $0002;
  278. COFF_FLAG_NOLINES = $0004;
  279. COFF_FLAG_NOLSYMS = $0008;
  280. COFF_FLAG_AR16WR = $0080; { 16bit little endian }
  281. COFF_FLAG_AR32WR = $0100; { 32bit little endian }
  282. COFF_FLAG_AR32W = $0200; { 32bit big endian }
  283. COFF_FLAG_DLL = $2000;
  284. COFF_SYM_GLOBAL = 2;
  285. COFF_SYM_LOCAL = 3;
  286. COFF_SYM_LABEL = 6;
  287. COFF_SYM_FUNCTION = 101;
  288. COFF_SYM_FILE = 103;
  289. COFF_SYM_SECTION = 104;
  290. COFF_STYP_REG = $0000; { "regular": allocated, relocated, loaded }
  291. COFF_STYP_DSECT = $0001; { "dummy": relocated only }
  292. COFF_STYP_NOLOAD = $0002; { "noload": allocated, relocated, not loaded }
  293. COFF_STYP_GROUP = $0004; { "grouped": formed of input sections }
  294. COFF_STYP_PAD = $0008;
  295. COFF_STYP_COPY = $0010;
  296. COFF_STYP_TEXT = $0020;
  297. COFF_STYP_DATA = $0040;
  298. COFF_STYP_BSS = $0080;
  299. COFF_STYP_INFO = $0200;
  300. COFF_STYP_OVER = $0400;
  301. COFF_STYP_LIB = $0800;
  302. PE_SUBSYSTEM_NATIVE = 1;
  303. PE_SUBSYSTEM_WINDOWS_GUI = 2;
  304. PE_SUBSYSTEM_WINDOWS_CUI = 3;
  305. PE_SUBSYSTEM_WINDOWS_CE_GUI = 9;
  306. PE_FILE_RELOCS_STRIPPED = $0001;
  307. PE_FILE_EXECUTABLE_IMAGE = $0002;
  308. PE_FILE_LINE_NUMS_STRIPPED = $0004;
  309. PE_FILE_LOCAL_SYMS_STRIPPED = $0008;
  310. PE_FILE_AGGRESSIVE_WS_TRIM = $0010;
  311. PE_FILE_LARGE_ADDRESS_AWARE = $0020;
  312. PE_FILE_16BIT_MACHINE = $0040;
  313. PE_FILE_BYTES_REVERSED_LO = $0080;
  314. PE_FILE_32BIT_MACHINE = $0100;
  315. PE_FILE_DEBUG_STRIPPED = $0200;
  316. PE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
  317. PE_FILE_NET_RUN_FROM_SWAP = $0800;
  318. PE_FILE_SYSTEM = $1000;
  319. PE_FILE_DLL = $2000;
  320. PE_FILE_UP_SYSTEM_ONLY = $4000;
  321. PE_FILE_BYTES_REVERSED_HI = $8000;
  322. PE_SCN_CNT_CODE = $00000020; { Section contains code. }
  323. PE_SCN_CNT_INITIALIZED_DATA = $00000040; { Section contains initialized data. }
  324. PE_SCN_CNT_UNINITIALIZED_DATA = $00000080; { Section contains uninitialized data. }
  325. PE_SCN_LNK_OTHER = $00000100; { Reserved. }
  326. PE_SCN_LNK_INFO = $00000200; { Section contains comments or some other type of information. }
  327. PE_SCN_LNK_REMOVE = $00000800; { Section contents will not become part of image. }
  328. PE_SCN_LNK_COMDAT = $00001000; { Section contents comdat. }
  329. PE_SCN_MEM_FARDATA = $00008000;
  330. PE_SCN_MEM_PURGEABLE = $00020000;
  331. PE_SCN_MEM_16BIT = $00020000;
  332. PE_SCN_MEM_LOCKED = $00040000;
  333. PE_SCN_MEM_PRELOAD = $00080000;
  334. PE_SCN_ALIGN_MASK = $00f00000;
  335. PE_SCN_ALIGN_1BYTES = $00100000;
  336. PE_SCN_ALIGN_2BYTES = $00200000;
  337. PE_SCN_ALIGN_4BYTES = $00300000;
  338. PE_SCN_ALIGN_8BYTES = $00400000;
  339. PE_SCN_ALIGN_16BYTES = $00500000; { Default alignment if no others are specified. }
  340. PE_SCN_ALIGN_32BYTES = $00600000;
  341. PE_SCN_ALIGN_64BYTES = $00700000;
  342. PE_SCN_ALIGN_128BYTES = $00800000;
  343. PE_SCN_ALIGN_256BYTES = $00900000;
  344. PE_SCN_ALIGN_512BYTES = $00A00000;
  345. PE_SCN_ALIGN_1024BYTES = $00B00000;
  346. PE_SCN_ALIGN_2048BYTES = $00C00000;
  347. PE_SCN_ALIGN_4096BYTES = $00D00000;
  348. PE_SCN_ALIGN_8192BYTES = $00E00000;
  349. PE_SCN_LNK_NRELOC_OVFL = $01000000; { Section contains extended relocations. }
  350. PE_SCN_MEM_NOT_CACHED = $04000000; { Section is not cachable. }
  351. PE_SCN_MEM_NOT_PAGED = $08000000; { Section is not pageable. }
  352. PE_SCN_MEM_SHARED = $10000000; { Section is shareable. }
  353. PE_SCN_MEM_DISCARDABLE = $02000000;
  354. PE_SCN_MEM_EXECUTE = $20000000;
  355. PE_SCN_MEM_READ = $40000000;
  356. PE_SCN_MEM_WRITE = $80000000;
  357. PE_DATADIR_EDATA = 0;
  358. PE_DATADIR_IDATA = 1;
  359. PE_DATADIR_RSRC = 2;
  360. PE_DATADIR_PDATA = 3;
  361. PE_DATADIR_SECURITY = 4;
  362. PE_DATADIR_RELOC = 5;
  363. PE_DATADIR_DEBUG = 6;
  364. PE_DATADIR_DESCRIPTION = 7;
  365. PE_DATADIR_SPECIAL = 8;
  366. PE_DATADIR_TLS = 9;
  367. PE_DATADIR_LOADCFG = 10;
  368. PE_DATADIR_BOUNDIMPORT = 11;
  369. PE_DATADIR_IMPORTADDRESSTABLE = 12;
  370. PE_DATADIR_DELAYIMPORT = 13;
  371. {$ifdef x86_64}
  372. IMAGE_REL_AMD64_ABSOLUTE = $0000; { Reference is absolute, no relocation is necessary }
  373. IMAGE_REL_AMD64_ADDR64 = $0001; { 64-bit address (VA). }
  374. IMAGE_REL_AMD64_ADDR32 = $0002; { 32-bit address (VA). }
  375. IMAGE_REL_AMD64_ADDR32NB = $0003; { 32-bit address w/o image base (RVA). }
  376. IMAGE_REL_AMD64_REL32 = $0004; { 32-bit relative address from byte following reloc }
  377. IMAGE_REL_AMD64_REL32_1 = $0005; { 32-bit relative address from byte distance 1 from reloc }
  378. IMAGE_REL_AMD64_REL32_2 = $0006; { 32-bit relative address from byte distance 2 from reloc }
  379. IMAGE_REL_AMD64_REL32_3 = $0007; { 32-bit relative address from byte distance 3 from reloc }
  380. IMAGE_REL_AMD64_REL32_4 = $0008; { 32-bit relative address from byte distance 4 from reloc }
  381. IMAGE_REL_AMD64_REL32_5 = $0009; { 32-bit relative address from byte distance 5 from reloc }
  382. IMAGE_REL_AMD64_SECTION = $000A; { Section index }
  383. IMAGE_REL_AMD64_SECREL = $000B; { 32 bit offset from base of section containing target }
  384. IMAGE_REL_AMD64_SECREL7 = $000C; { 7 bit unsigned offset from base of section containing target }
  385. IMAGE_REL_AMD64_TOKEN = $000D; { 32 bit metadata token }
  386. IMAGE_REL_AMD64_SREL32 = $000E; { 32 bit signed span-dependent value emitted into object }
  387. IMAGE_REL_AMD64_PAIR = $000F;
  388. IMAGE_REL_AMD64_SSPAN32 = $0010; { 32 bit signed span-dependent value applied at link time }
  389. { Direct 32 bit sign extended,
  390. win64 mingw GNU compiler
  391. also generates this type
  392. inside coff objects
  393. We assume they are equivalent to
  394. IMAGE_REL_AMD64_ADDR32 PM 2010-11-27 }
  395. R_X86_64_32S = $11;
  396. {$endif x86_64}
  397. {$ifdef arm}
  398. IMAGE_REL_ARM_ABSOLUTE = $0000; { No relocation required }
  399. IMAGE_REL_ARM_ADDR32 = $0001; { 32 bit address }
  400. IMAGE_REL_ARM_ADDR32NB = $0002; { 32 bit address w/o image base }
  401. IMAGE_REL_ARM_BRANCH24 = $0003; { 24 bit offset << 2 & sign ext. }
  402. IMAGE_REL_ARM_BRANCH11 = $0004; { Thumb: 2 11 bit offsets }
  403. IMAGE_REL_ARM_TOKEN = $0005; { clr token }
  404. IMAGE_REL_ARM_GPREL12 = $0006; { GP-relative addressing (ARM) }
  405. IMAGE_REL_ARM_GPREL7 = $0007; { GP-relative addressing (Thumb) }
  406. IMAGE_REL_ARM_BLX24 = $0008;
  407. IMAGE_REL_ARM_BLX11 = $0009;
  408. IMAGE_REL_ARM_SECTION = $000E; { Section table index }
  409. IMAGE_REL_ARM_SECREL = $000F; { Offset within section }
  410. IMAGE_REL_ARM_MOV32A = $0010; { 32-bit VA applied to MOVW+MOVT pair, added to existing imm (ARM) }
  411. IMAGE_REL_ARM_MOV32T = $0011; { 32-bit VA applied to MOVW+MOVT pair, added to existing imm (THUMB) }
  412. IMAGE_REL_ARM_BRANCH20T = $0012; { Thumb: 20 most significant bits of 32 bit B cond instruction }
  413. IMAGE_REL_ARM_BRANCH24T = $0014; { Thumb: 24 most significant bits of 32 bit B uncond instruction }
  414. IMAGE_REL_ARM_BLX23T = $0015; { 23 most significant bits of 32 bit BL/BLX instruction. Transformed to BLX if target is Thumb }
  415. {$endif arm}
  416. {$ifdef i386}
  417. IMAGE_REL_I386_DIR32 = 6;
  418. IMAGE_REL_I386_IMAGEBASE = 7;
  419. IMAGE_REL_I386_SECREL32 = 11;
  420. IMAGE_REL_I386_PCRLONG = 20;
  421. {$endif i386}
  422. { .reloc section fixup types }
  423. IMAGE_REL_BASED_HIGHLOW = 3; { Applies the delta to the 32-bit field at Offset. }
  424. IMAGE_REL_BASED_DIR64 = 10; { Applies the delta to the 64-bit field at Offset. }
  425. { values for coffsectionrec.select }
  426. IMAGE_COMDAT_SELECT_NODUPLICATES = 1;
  427. IMAGE_COMDAT_SELECT_ANY = 2;
  428. IMAGE_COMDAT_SELECT_SAME_SIZE = 3;
  429. IMAGE_COMDAT_SELECT_EXACT_MATCH = 4;
  430. IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5;
  431. IMAGE_COMDAT_SELECT_LARGEST = 6;
  432. type
  433. coffdjoptheader=packed record
  434. magic : word;
  435. vstamp : word;
  436. tsize : longint;
  437. dsize : longint;
  438. bsize : longint;
  439. entry : longint;
  440. text_start : longint;
  441. data_start : longint;
  442. end;
  443. coffsectionrec=packed record
  444. len : longword;
  445. nrelocs : word;
  446. nlines : word;
  447. checksum: longword;
  448. assoc : word;
  449. select : byte;
  450. empty : array[0..2] of char;
  451. end;
  452. pcoffsectionrec=^coffsectionrec;
  453. coffreloc=packed record
  454. address : longword;
  455. sym : longword;
  456. reloctype : word;
  457. end;
  458. strtableoffset=packed record
  459. Zeroes : longword;
  460. Offset : longword;
  461. end;
  462. coffsymbol=packed record
  463. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  464. strpos : longword;
  465. value : longword;
  466. section : smallint;
  467. empty : word; { actually type, $20: function, 0: not a function }
  468. typ : byte;
  469. aux : byte;
  470. end;
  471. coffbigobjsymbol=packed record
  472. Name : record
  473. case boolean of
  474. True: (ShortName : array[0..7] of char);
  475. False: (Offset : strtableoffset)
  476. end;
  477. Value : longword;
  478. SectionNumber : longword;
  479. _Type : word;
  480. StorageClass : byte;
  481. NumberOfAuxSymbols : byte;
  482. end;
  483. { This is defined in rtl/win/sysos.inc source }
  484. tlsdirectory=packed record
  485. data_start, data_end : PUInt;
  486. index_pointer, callbacks_pointer : PUInt;
  487. zero_fill_size : dword;
  488. flags : dword;
  489. end;
  490. const
  491. SymbolMaxGrow = 200*sizeof(coffsymbol);
  492. StrsMaxGrow = 8192;
  493. coffsecnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  494. '.text','.data','.rdata','.rdata','.bss','.tls',
  495. '.pdata',{pdata}
  496. '.text', {stub}
  497. '.data',
  498. '.data',
  499. '.data',
  500. '.data',
  501. '.stab','.stabstr',
  502. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  503. '.eh_frame',
  504. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  505. '.fpc',
  506. '',
  507. '.init',
  508. '.fini',
  509. '.objc_class',
  510. '.objc_meta_class',
  511. '.objc_cat_cls_meth',
  512. '.objc_cat_inst_meth',
  513. '.objc_protocol',
  514. '.objc_string_object',
  515. '.objc_cls_meth',
  516. '.objc_inst_meth',
  517. '.objc_cls_refs',
  518. '.objc_message_refs',
  519. '.objc_symbols',
  520. '.objc_category',
  521. '.objc_class_vars',
  522. '.objc_instance_vars',
  523. '.objc_module_info',
  524. '.objc_class_names',
  525. '.objc_meth_var_types',
  526. '.objc_meth_var_names',
  527. '.objc_selector_strs',
  528. '.objc_protocol_ext',
  529. '.objc_class_ext',
  530. '.objc_property',
  531. '.objc_image_info',
  532. '.objc_cstring_object',
  533. '.objc_sel_fixup',
  534. '__DATA,__objc_data',
  535. '__DATA,__objc_const',
  536. '.objc_superrefs',
  537. '__DATA, __datacoal_nt,coalesced',
  538. '.objc_classlist',
  539. '.objc_nlclasslist',
  540. '.objc_catlist',
  541. '.obcj_nlcatlist',
  542. '.objc_protolist',
  543. '.stack',
  544. '.heap',
  545. '.gcc_except_table'
  546. );
  547. const go32v2stub : array[0..2047] of byte=(
  548. $4D,$5A,$00,$00,$04,$00,$00,$00,$20,$00,$27,$00,$FF,$FF,$00,
  549. $00,$60,$07,$00,$00,$54,$00,$00,$00,$00,$00,$00,$00,$0D,$0A,
  550. $73,$74,$75,$62,$2E,$68,$20,$67,$65,$6E,$65,$72,$61,$74,$65,
  551. $64,$20,$66,$72,$6F,$6D,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,
  552. $20,$62,$79,$20,$64,$6A,$61,$73,$6D,$2C,$20,$6F,$6E,$20,$54,
  553. $68,$75,$20,$44,$65,$63,$20,$20,$39,$20,$31,$30,$3A,$35,$39,
  554. $3A,$33,$31,$20,$31,$39,$39,$39,$0D,$0A,$54,$68,$65,$20,$53,
  555. $54,$55,$42,$2E,$45,$58,$45,$20,$73,$74,$75,$62,$20,$6C,$6F,
  556. $61,$64,$65,$72,$20,$69,$73,$20,$43,$6F,$70,$79,$72,$69,$67,
  557. $68,$74,$20,$28,$43,$29,$20,$31,$39,$39,$33,$2D,$31,$39,$39,
  558. $35,$20,$44,$4A,$20,$44,$65,$6C,$6F,$72,$69,$65,$2E,$20,$0D,
  559. $0A,$50,$65,$72,$6D,$69,$73,$73,$69,$6F,$6E,$20,$67,$72,$61,
  560. $6E,$74,$65,$64,$20,$74,$6F,$20,$75,$73,$65,$20,$66,$6F,$72,
  561. $20,$61,$6E,$79,$20,$70,$75,$72,$70,$6F,$73,$65,$20,$70,$72,
  562. $6F,$76,$69,$64,$65,$64,$20,$74,$68,$69,$73,$20,$63,$6F,$70,
  563. $79,$72,$69,$67,$68,$74,$20,$0D,$0A,$72,$65,$6D,$61,$69,$6E,
  564. $73,$20,$70,$72,$65,$73,$65,$6E,$74,$20,$61,$6E,$64,$20,$75,
  565. $6E,$6D,$6F,$64,$69,$66,$69,$65,$64,$2E,$20,$0D,$0A,$54,$68,
  566. $69,$73,$20,$6F,$6E,$6C,$79,$20,$61,$70,$70,$6C,$69,$65,$73,
  567. $20,$74,$6F,$20,$74,$68,$65,$20,$73,$74,$75,$62,$2C,$20,$61,
  568. $6E,$64,$20,$6E,$6F,$74,$20,$6E,$65,$63,$65,$73,$73,$61,$72,
  569. $69,$6C,$79,$20,$74,$68,$65,$20,$77,$68,$6F,$6C,$65,$20,$70,
  570. $72,$6F,$67,$72,$61,$6D,$2E,$0A,$0D,$0A,$24,$49,$64,$3A,$20,
  571. $73,$74,$75,$62,$2E,$61,$73,$6D,$20,$62,$75,$69,$6C,$74,$20,
  572. $31,$32,$2F,$30,$39,$2F,$39,$39,$20,$31,$30,$3A,$35,$39,$3A,
  573. $33,$31,$20,$62,$79,$20,$64,$6A,$61,$73,$6D,$20,$24,$0A,$0D,
  574. $0A,$40,$28,$23,$29,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,$20,
  575. $62,$75,$69,$6C,$74,$20,$31,$32,$2F,$30,$39,$2F,$39,$39,$20,
  576. $31,$30,$3A,$35,$39,$3A,$33,$31,$20,$62,$79,$20,$64,$6A,$61,
  577. $73,$6D,$0A,$0D,$0A,$1A,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  578. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  579. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  580. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  581. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  582. $00,$00,$67,$6F,$33,$32,$73,$74,$75,$62,$2C,$20,$76,$20,$32,
  583. $2E,$30,$32,$54,$00,$00,$00,$00,$00,$08,$00,$00,$00,$00,$00,
  584. $00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  585. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  586. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$43,$57,$53,$44,$50,
  587. $4D,$49,$2E,$45,$58,$45,$00,$00,$00,$00,$00,$0E,$1F,$8C,$1E,
  588. $24,$00,$8C,$06,$60,$07,$FC,$B4,$30,$CD,$21,$3C,$03,$73,$08,
  589. $B0,$6D,$BA,$A7,$05,$E9,$D4,$03,$A2,$69,$08,$BE,$20,$00,$8B,
  590. $04,$09,$C0,$75,$02,$B4,$FE,$BB,$70,$08,$39,$C3,$73,$02,$89,
  591. $C3,$89,$1C,$FE,$C7,$B9,$04,$FF,$D3,$EB,$B4,$4A,$CD,$21,$73,
  592. $08,$D3,$E3,$FE,$CF,$89,$1C,$EB,$D8,$26,$8E,$06,$2C,$00,$31,
  593. $FF,$30,$C0,$A9,$F2,$AE,$26,$81,$3D,$50,$41,$75,$15,$AF,$26,
  594. $81,$3D,$54,$48,$75,$0D,$AF,$26,$80,$3D,$3D,$75,$06,$47,$89,
  595. $3E,$8C,$04,$4F,$AE,$75,$DF,$AF,$B4,$3E,$BB,$13,$00,$CD,$21,
  596. $B4,$3E,$BB,$12,$00,$CD,$21,$06,$57,$31,$C9,$74,$12,$B0,$6E,
  597. $BA,$7E,$05,$E9,$5E,$03,$09,$C9,$75,$F4,$41,$E8,$A1,$03,$72,
  598. $EE,$B8,$87,$16,$CD,$2F,$09,$C0,$75,$ED,$80,$E3,$01,$74,$E8,
  599. $89,$3E,$00,$06,$8C,$06,$02,$06,$89,$36,$04,$06,$5F,$07,$E8,
  600. $D3,$02,$89,$3E,$2A,$00,$89,$36,$62,$07,$80,$3E,$2C,$00,$00,
  601. $74,$23,$B9,$08,$00,$BF,$2C,$00,$8A,$05,$47,$08,$C0,$74,$05,
  602. $88,$07,$43,$E2,$F4,$66,$C7,$07,$2E,$45,$58,$45,$83,$C3,$04,
  603. $C6,$07,$00,$89,$1E,$62,$07,$B8,$00,$3D,$BA,$64,$07,$CD,$21,
  604. $0F,$82,$B3,$02,$A3,$06,$06,$89,$C3,$B9,$06,$00,$BA,$B5,$07,
  605. $B4,$3F,$CD,$21,$31,$D2,$31,$C9,$A1,$B5,$07,$3D,$4C,$01,$74,
  606. $1B,$3D,$4D,$5A,$0F,$85,$98,$02,$8B,$16,$B9,$07,$C1,$E2,$09,
  607. $8B,$1E,$B7,$07,$09,$DB,$74,$05,$80,$EE,$02,$01,$DA,$89,$16,
  608. $BB,$07,$89,$0E,$BD,$07,$B8,$00,$42,$8B,$1E,$06,$06,$CD,$21,
  609. $B9,$A8,$00,$BA,$BF,$07,$B4,$3F,$CD,$21,$3D,$A8,$00,$75,$06,
  610. $81,$3E,$BF,$07,$4C,$01,$0F,$85,$61,$02,$66,$A1,$E3,$07,$66,
  611. $A3,$10,$06,$66,$8B,$0E,$BB,$07,$66,$A1,$03,$08,$66,$01,$C8,
  612. $66,$A3,$08,$06,$66,$A1,$2B,$08,$66,$01,$C8,$66,$A3,$0C,$06,
  613. $66,$8B,$1E,$4B,$08,$66,$A1,$4F,$08,$66,$01,$C3,$66,$B8,$01,
  614. $00,$01,$00,$66,$39,$C3,$73,$03,$66,$89,$C3,$66,$81,$C3,$FF,
  615. $FF,$00,$00,$31,$DB,$66,$89,$1E,$1C,$00,$E8,$F5,$02,$8B,$1E,
  616. $04,$06,$09,$DB,$74,$0A,$B4,$48,$CD,$21,$0F,$82,$15,$02,$8E,
  617. $C0,$E8,$08,$03,$B8,$01,$00,$FF,$1E,$00,$06,$0F,$82,$0F,$02,
  618. $8C,$06,$26,$00,$8C,$0E,$28,$00,$8C,$D8,$A3,$22,$00,$8E,$C0,
  619. $31,$C0,$B9,$01,$00,$CD,$31,$72,$07,$A3,$14,$06,$31,$C0,$CD,
  620. $31,$0F,$82,$F3,$01,$A3,$16,$06,$66,$8B,$0E,$1C,$00,$B8,$01,
  621. $05,$8B,$1E,$1E,$00,$CD,$31,$0F,$82,$E5,$01,$89,$1E,$1A,$06,
  622. $89,$0E,$18,$06,$89,$36,$1A,$00,$89,$3E,$18,$00,$B8,$07,$00,
  623. $8B,$1E,$14,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,$CD,$31,$B8,
  624. $09,$00,$8C,$C9,$83,$E1,$03,$C1,$E1,$05,$51,$81,$C9,$9B,$C0,
  625. $CD,$31,$B8,$08,$00,$8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,
  626. $B8,$07,$00,$8B,$1E,$16,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,
  627. $CD,$31,$B8,$09,$00,$59,$81,$C9,$93,$C0,$CD,$31,$B8,$08,$00,
  628. $8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,$B8,$00,$01,$BB,$00,
  629. $0F,$CD,$31,$73,$10,$3D,$08,$00,$0F,$85,$73,$01,$B8,$00,$01,
  630. $CD,$31,$0F,$82,$6A,$01,$A3,$1C,$06,$89,$16,$1E,$06,$C1,$E3,
  631. $04,$89,$1E,$20,$06,$66,$8B,$36,$08,$06,$66,$8B,$3E,$FB,$07,
  632. $66,$8B,$0E,$FF,$07,$E8,$49,$00,$66,$8B,$36,$0C,$06,$66,$8B,
  633. $3E,$23,$08,$66,$8B,$0E,$27,$08,$E8,$37,$00,$8E,$06,$16,$06,
  634. $66,$8B,$3E,$4B,$08,$66,$8B,$0E,$4F,$08,$66,$31,$C0,$66,$C1,
  635. $E9,$02,$67,$F3,$66,$AB,$B4,$3E,$8B,$1E,$06,$06,$CD,$21,$B8,
  636. $01,$01,$8B,$16,$1E,$06,$CD,$31,$1E,$0F,$A1,$8E,$1E,$16,$06,
  637. $66,$64,$FF,$2E,$10,$06,$66,$89,$F0,$66,$25,$FF,$01,$00,$00,
  638. $66,$01,$C1,$29,$C6,$66,$29,$C7,$66,$89,$0E,$26,$06,$66,$89,
  639. $3E,$22,$06,$E8,$0F,$01,$89,$36,$3E,$06,$66,$C1,$EE,$10,$89,
  640. $36,$42,$06,$8B,$1E,$06,$06,$89,$1E,$3A,$06,$C7,$06,$46,$06,
  641. $00,$42,$E8,$03,$01,$A1,$1C,$06,$A3,$4E,$06,$C7,$06,$3E,$06,
  642. $00,$00,$C6,$06,$47,$06,$3F,$A1,$28,$06,$09,$C0,$75,$09,$A1,
  643. $26,$06,$3B,$06,$20,$06,$76,$03,$A1,$20,$06,$A3,$42,$06,$E8,
  644. $D9,$00,$66,$31,$C9,$8B,$0E,$46,$06,$66,$8B,$3E,$22,$06,$66,
  645. $01,$0E,$22,$06,$66,$29,$0E,$26,$06,$66,$31,$F6,$C1,$E9,$02,
  646. $1E,$06,$8E,$06,$16,$06,$8E,$1E,$1E,$06,$67,$F3,$66,$A5,$07,
  647. $1F,$66,$03,$0E,$26,$06,$75,$AF,$C3,$3C,$3A,$74,$06,$3C,$2F,
  648. $74,$02,$3C,$5C,$C3,$BE,$64,$07,$89,$F3,$26,$8A,$05,$47,$88,
  649. $04,$38,$E0,$74,$0E,$08,$C0,$74,$0A,$46,$E8,$DE,$FF,$75,$EC,
  650. $89,$F3,$74,$E8,$C3,$B0,$66,$BA,$48,$05,$EB,$0C,$B0,$67,$BA,
  651. $55,$05,$EB,$05,$B0,$68,$BA,$5F,$05,$52,$8B,$1E,$62,$07,$C6,
  652. $07,$24,$BB,$64,$07,$EB,$28,$E8,$F5,$00,$B0,$69,$BA,$99,$05,
  653. $EB,$1A,$B0,$6A,$BA,$B2,$05,$EB,$13,$B0,$6B,$BA,$C4,$05,$EB,
  654. $0C,$B0,$6C,$BA,$D6,$05,$EB,$05,$B0,$69,$BA,$99,$05,$52,$BB,
  655. $3B,$05,$E8,$15,$00,$5B,$E8,$11,$00,$BB,$67,$04,$E8,$0B,$00,
  656. $B4,$4C,$CD,$21,$43,$50,$B4,$02,$CD,$21,$58,$8A,$17,$80,$FA,
  657. $24,$75,$F2,$C3,$0D,$0A,$24,$50,$51,$57,$31,$C0,$BF,$2A,$06,
  658. $B9,$19,$00,$F3,$AB,$5F,$59,$58,$C3,$B8,$00,$03,$BB,$21,$00,
  659. $31,$C9,$66,$BF,$2A,$06,$00,$00,$CD,$31,$C3,$00,$00,$30,$E4,
  660. $E8,$4E,$FF,$89,$DE,$8B,$3E,$8C,$04,$EB,$17,$B4,$3B,$E8,$41,
  661. $FF,$81,$FE,$64,$07,$74,$12,$8A,$44,$FF,$E8,$2A,$FF,$74,$04,
  662. $C6,$04,$5C,$46,$E8,$03,$00,$72,$E4,$C3,$E8,$34,$00,$BB,$44,
  663. $00,$8A,$07,$88,$04,$43,$46,$08,$C0,$75,$F6,$06,$57,$1E,$07,
  664. $E8,$9B,$FF,$BB,$2A,$06,$8C,$5F,$04,$89,$5F,$02,$BA,$64,$07,
  665. $B8,$00,$4B,$CD,$21,$5F,$07,$72,$09,$B4,$4D,$CD,$21,$2D,$00,
  666. $03,$F7,$D8,$EB,$28,$80,$3E,$69,$08,$05,$72,$20,$B8,$00,$58,
  667. $CD,$21,$A2,$67,$08,$B8,$02,$58,$CD,$21,$A2,$68,$08,$B8,$01,
  668. $58,$BB,$80,$00,$CD,$21,$B8,$03,$58,$BB,$01,$00,$CD,$21,$C3,
  669. $9C,$80,$3E,$69,$08,$05,$72,$1A,$50,$53,$B8,$03,$58,$8A,$1E,
  670. $68,$08,$30,$FF,$CD,$21,$B8,$01,$58,$8A,$1E,$67,$08,$30,$FF,
  671. $CD,$21,$5B,$58,$9D,$C3,$4C,$6F,$61,$64,$20,$65,$72,$72,$6F,
  672. $72,$3A,$20,$24,$3A,$20,$63,$61,$6E,$27,$74,$20,$6F,$70,$65,
  673. $6E,$24,$3A,$20,$6E,$6F,$74,$20,$45,$58,$45,$24,$3A,$20,$6E,
  674. $6F,$74,$20,$43,$4F,$46,$46,$20,$28,$43,$68,$65,$63,$6B,$20,
  675. $66,$6F,$72,$20,$76,$69,$72,$75,$73,$65,$73,$29,$24,$6E,$6F,
  676. $20,$44,$50,$4D,$49,$20,$2D,$20,$47,$65,$74,$20,$63,$73,$64,
  677. $70,$6D,$69,$2A,$62,$2E,$7A,$69,$70,$24,$6E,$6F,$20,$44,$4F,
  678. $53,$20,$6D,$65,$6D,$6F,$72,$79,$24,$6E,$65,$65,$64,$20,$44,
  679. $4F,$53,$20,$33,$24,$63,$61,$6E,$27,$74,$20,$73,$77,$69,$74,
  680. $63,$68,$20,$6D,$6F,$64,$65,$24,$6E,$6F,$20,$44,$50,$4D,$49,
  681. $20,$73,$65,$6C,$65,$63,$74,$6F,$72,$73,$24,$6E,$6F,$20,$44,
  682. $50,$4D,$49,$20,$6D,$65,$6D,$6F,$72,$79,$24,$90,$90,$90,$90,
  683. $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,
  684. $90,$90,$90,$90,$90,$90,$90,$90);
  685. const win32stub : array[0..127] of byte=(
  686. $4D,$5A,$90,$00,$03,$00,$00,$00,$04,$00,$00,$00,$FF,$FF,$00,$00,
  687. $B8,$00,$00,$00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,
  688. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  689. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$80,$00,$00,$00,
  690. $0E,$1F,$BA,$0E,$00,$B4,$09,$CD,$21,$B8,$01,$4C,$CD,$21,$54,$68,
  691. $69,$73,$20,$70,$72,$6F,$67,$72,$61,$6D,$20,$63,$61,$6E,$6E,$6F,
  692. $74,$20,$62,$65,$20,$72,$75,$6E,$20,$69,$6E,$20,$44,$4F,$53,$20,
  693. $6D,$6F,$64,$65,$2E,$0D,$0D,$0A,$24,$00,$00,$00,$00,$00,$00,$00);
  694. const pemagic : array[0..3] of byte = (
  695. $50,$45,$00,$00);
  696. {****************************************************************************
  697. Helpers
  698. ****************************************************************************}
  699. function djencodesechdrflags(aoptions:TObjSectionOptions):longword;
  700. begin
  701. if (oso_load in aoptions) then
  702. begin
  703. if oso_executable in aoptions then
  704. result:=COFF_STYP_TEXT
  705. else if not(oso_data in aoptions) then
  706. result:=COFF_STYP_BSS
  707. else
  708. result:=COFF_STYP_DATA;
  709. end
  710. else if oso_debug in aoptions then
  711. result:=COFF_STYP_INFO
  712. else
  713. result:=COFF_STYP_REG;
  714. end;
  715. function djdecodesechdrflags(const aname:string;flags:longword):TObjSectionOptions;
  716. begin
  717. result:=[];
  718. if flags and COFF_STYP_TEXT<>0 then
  719. result:=[oso_data,oso_load,oso_executable]
  720. else if flags and COFF_STYP_BSS<>0 then
  721. result:=[oso_load]
  722. else if flags and COFF_STYP_DATA<>0 then
  723. result:=[oso_data,oso_load]
  724. else if flags and COFF_STYP_INFO<>0 then
  725. result:=[oso_data,oso_debug]
  726. else
  727. result:=[oso_data]
  728. end;
  729. function peencodesechdrflags(aoptions:TObjSectionOptions;aalign:longint):longword;
  730. begin
  731. if oso_executable in aoptions then
  732. result:=PE_SCN_CNT_CODE or PE_SCN_MEM_EXECUTE
  733. else
  734. begin
  735. if (oso_data in aoptions) then
  736. result:=PE_SCN_CNT_INITIALIZED_DATA
  737. else
  738. result:=PE_SCN_CNT_UNINITIALIZED_DATA;
  739. end;
  740. if oso_write in aoptions then
  741. result:=result or PE_SCN_MEM_WRITE or PE_SCN_MEM_READ
  742. else
  743. result:=result or PE_SCN_MEM_READ;
  744. if not (oso_load in aoptions) then
  745. result:=result or PE_SCN_MEM_DISCARDABLE;
  746. case aalign of
  747. 1 : result:=result or PE_SCN_ALIGN_1BYTES;
  748. 2 : result:=result or PE_SCN_ALIGN_2BYTES;
  749. 4 : result:=result or PE_SCN_ALIGN_4BYTES;
  750. 8 : result:=result or PE_SCN_ALIGN_8BYTES;
  751. 16 : result:=result or PE_SCN_ALIGN_16BYTES;
  752. 32 : result:=result or PE_SCN_ALIGN_32BYTES;
  753. 64 : result:=result or PE_SCN_ALIGN_64BYTES;
  754. 128 : result:=result or PE_SCN_ALIGN_128BYTES;
  755. 256 : result:=result or PE_SCN_ALIGN_256BYTES;
  756. 512 : result:=result or PE_SCN_ALIGN_512BYTES;
  757. 1024 : result:=result or PE_SCN_ALIGN_1024BYTES;
  758. 2048 : result:=result or PE_SCN_ALIGN_2048BYTES;
  759. 4096 : result:=result or PE_SCN_ALIGN_4096BYTES;
  760. 8192 : result:=result or PE_SCN_ALIGN_8192BYTES;
  761. else result:=result or PE_SCN_ALIGN_16BYTES;
  762. end;
  763. end;
  764. procedure pedecodesechdrflags(const aname:string;flags:longword;out aoptions:TObjSectionOptions;out aalign:longint);
  765. var
  766. alignflag : longword;
  767. begin
  768. aoptions:=[];
  769. if flags and PE_SCN_CNT_CODE<>0 then
  770. include(aoptions,oso_executable);
  771. if flags and PE_SCN_MEM_DISCARDABLE<>0 then
  772. include(aoptions,oso_debug);
  773. if flags and PE_SCN_CNT_UNINITIALIZED_DATA=0 then
  774. include(aoptions,oso_data);
  775. if (flags and (PE_SCN_LNK_REMOVE or PE_SCN_MEM_DISCARDABLE)=0) then
  776. include(aoptions,oso_load);
  777. if flags and PE_SCN_LNK_COMDAT<>0 then
  778. include(aoptions,oso_comdat);
  779. { read/write }
  780. if flags and PE_SCN_MEM_WRITE<>0 then
  781. include(aoptions,oso_write);
  782. { alignment }
  783. alignflag:=flags and PE_SCN_ALIGN_MASK;
  784. if alignflag=PE_SCN_ALIGN_8192BYTES then
  785. aalign:=8192
  786. else if alignflag=PE_SCN_ALIGN_4096BYTES then
  787. aalign:=4096
  788. else if alignflag=PE_SCN_ALIGN_2048BYTES then
  789. aalign:=2048
  790. else if alignflag=PE_SCN_ALIGN_1024BYTES then
  791. aalign:=1024
  792. else if alignflag=PE_SCN_ALIGN_512BYTES then
  793. aalign:=512
  794. else if alignflag=PE_SCN_ALIGN_256BYTES then
  795. aalign:=256
  796. else if alignflag=PE_SCN_ALIGN_128BYTES then
  797. aalign:=128
  798. else if alignflag=PE_SCN_ALIGN_64BYTES then
  799. aalign:=64
  800. else if alignflag=PE_SCN_ALIGN_32BYTES then
  801. aalign:=32
  802. else if alignflag=PE_SCN_ALIGN_16BYTES then
  803. aalign:=16
  804. else if alignflag=PE_SCN_ALIGN_8BYTES then
  805. aalign:=8
  806. else if alignflag=PE_SCN_ALIGN_4BYTES then
  807. aalign:=4
  808. else if alignflag=PE_SCN_ALIGN_2BYTES then
  809. aalign:=2
  810. else if alignflag=PE_SCN_ALIGN_1BYTES then
  811. aalign:=1
  812. else if alignflag=0 then
  813. aalign:=0
  814. else
  815. Internalerror(2009050401);
  816. end;
  817. function encodeBase64(p:aword):string;
  818. const
  819. alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
  820. 'abcdefghijklmnopqrstuvwxyz' +
  821. '0123456789+/';
  822. var
  823. i,
  824. idx,
  825. rem : longint;
  826. begin
  827. setlength(result,6);
  828. idx := 6;
  829. for i:=0 to 5 do
  830. begin
  831. rem:=p mod 64;
  832. p:=p div 64;
  833. result[idx]:=alphabet[rem+1];
  834. dec(idx);
  835. end;
  836. if p<>0 then
  837. internalerror(2020091601);
  838. end;
  839. function decodeBase64(const s:string;out p:longint):boolean;
  840. var
  841. i : longint;
  842. v : aword;
  843. begin
  844. if length(s)>6 then
  845. exit(false);
  846. p:=0;
  847. for i:=1 to length(s) do
  848. begin
  849. v:=0;
  850. if (s[i]>='A') and (s[i]<='Z') then // 0..25
  851. v:=Ord(s[i])-Ord('A')
  852. else if (s[i]>='a') and (s[i]<='z') then // 26..51
  853. v:=Ord(s[i])-Ord('a')+26
  854. else if (s[i]>='0') and (s[i]<='9') then // 52..61
  855. v:=Ord(s[i])-Ord('0')+52
  856. else if s[i]='+' then // 62
  857. v:=62
  858. else if s[i]='/' then // 63
  859. v:=63
  860. else
  861. exit(false);
  862. p:=(p*64)+v;
  863. end;
  864. result:=true;
  865. end;
  866. {****************************************************************************
  867. TCoffObjSection
  868. ****************************************************************************}
  869. constructor TCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:longint;aoptions:TObjSectionOptions);
  870. begin
  871. inherited create(AList,aname,aalign,aoptions);
  872. end;
  873. procedure TCoffObjSection.writereloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);
  874. begin
  875. AddSectionReloc(size,aTarget,reltype);
  876. write(offset,len);
  877. end;
  878. { We don't want overflow nor range checks here,
  879. wrapping is accepted in the address computation below }
  880. {$r-}
  881. {$q-}
  882. procedure TCoffExeOutput.DoRelocationFixup(objsec:TObjSection);
  883. var
  884. i,zero,address_size : longint;
  885. objreloc : TObjRelocation;
  886. address,
  887. relocval : aint;
  888. {$ifdef arm}
  889. addend : aint;
  890. {$endif arm}
  891. relocsec : TObjSection;
  892. {$ifdef cpu64bitaddr}
  893. s : string;
  894. {$endif cpu64bitaddr}
  895. data : TDynamicArray;
  896. begin
  897. data:=objsec.data;
  898. for i:=0 to objsec.ObjRelocations.Count-1 do
  899. begin
  900. objreloc:=TObjRelocation(objsec.ObjRelocations[i]);
  901. address_size:=4;
  902. case objreloc.typ of
  903. RELOC_NONE:
  904. continue;
  905. RELOC_ZERO:
  906. begin
  907. data.Seek(objreloc.dataoffset);
  908. zero:=0;
  909. data.Write(zero,4);
  910. continue;
  911. end;
  912. {$ifdef cpu64bitaddr}
  913. RELOC_ABSOLUTE:
  914. address_size:=8;
  915. {$endif cpu64bitaddr}
  916. end;
  917. address:=0;
  918. data.Seek(objreloc.dataoffset);
  919. data.Read(address,address_size);
  920. if assigned(objreloc.symbol) then
  921. begin
  922. relocsec:=objreloc.symbol.objsection;
  923. relocval:=objreloc.symbol.address;
  924. end
  925. else
  926. if assigned(objreloc.objsection) then
  927. begin
  928. relocsec:=objreloc.objsection;
  929. relocval:=objreloc.objsection.mempos
  930. end
  931. else
  932. internalerror(200205183);
  933. { Only debug sections are allowed to have relocs pointing to unused sections }
  934. if not relocsec.used and not (oso_debug in objsec.secoptions) then
  935. internalerror(200603061);
  936. if relocsec.used then
  937. case objreloc.typ of
  938. RELOC_RELATIVE :
  939. begin
  940. address:=address-objsec.mempos+relocval;
  941. if win32 then
  942. dec(address,objreloc.dataoffset+4);
  943. end;
  944. RELOC_RVA:
  945. begin
  946. { fixup address when the symbol was known in defined object }
  947. if (relocsec.objdata=objsec.objdata) then
  948. dec(address,TCoffObjSection(relocsec).orgmempos);
  949. {$ifdef arm}
  950. if (relocsec.objdata=objsec.objdata) and not TCoffObjData(objsec.objdata).eVCobj then
  951. inc(address, relocsec.MemPos)
  952. else
  953. {$endif arm}
  954. inc(address,relocval);
  955. end;
  956. RELOC_SECREL32 :
  957. begin
  958. { fixup address when the symbol was known in defined object }
  959. if (relocsec.objdata=objsec.objdata) then
  960. dec(address,relocsec.ExeSection.MemPos);
  961. inc(address,relocval);
  962. end;
  963. {$ifdef arm}
  964. RELOC_RELATIVE_24,
  965. RELOC_RELATIVE_CALL:
  966. begin
  967. addend:=sarlongint(((address and $ffffff) shl 8),6); // Sign-extend while shifting left twice
  968. relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset + addend) shr 2;
  969. address:=(address and $ff000000) or (relocval and $ffffff);
  970. relocval:=relocval shr 24;
  971. if (relocval<>$3f) and (relocval<>0) then
  972. internalerror(200606085); { offset overflow }
  973. end;
  974. RELOC_RELATIVE_24_THUMB,
  975. RELOC_RELATIVE_CALL_THUMB:
  976. begin
  977. addend:=sarlongint(((address and $ffffff) shl 8),6); // Sign-extend while shifting left twice, the assembler never sets the H bit
  978. relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset + addend) shr 1;
  979. address:=(address and $ff000000) or ((relocval shr 1) and $ffffff) or ((relocval and 1) shl 24);
  980. relocval:=relocval shr 25;
  981. if (relocval<>$3f) and (relocval<>0) then
  982. internalerror(200606085); { offset overflow }
  983. end;
  984. {$endif arm}
  985. {$ifdef x86_64}
  986. { 64 bit coff only }
  987. RELOC_RELATIVE_1:
  988. begin
  989. address:=address-objsec.mempos+relocval;
  990. dec(address,objreloc.dataoffset+5);
  991. end;
  992. RELOC_RELATIVE_2:
  993. begin
  994. address:=address-objsec.mempos+relocval;
  995. dec(address,objreloc.dataoffset+6);
  996. end;
  997. RELOC_RELATIVE_3:
  998. begin
  999. address:=address-objsec.mempos+relocval;
  1000. dec(address,objreloc.dataoffset+7);
  1001. end;
  1002. RELOC_RELATIVE_4:
  1003. begin
  1004. address:=address-objsec.mempos+relocval;
  1005. dec(address,objreloc.dataoffset+8);
  1006. end;
  1007. RELOC_RELATIVE_5:
  1008. begin
  1009. address:=address-objsec.mempos+relocval;
  1010. dec(address,objreloc.dataoffset+9);
  1011. end;
  1012. RELOC_ABSOLUTE32,
  1013. {$endif x86_64}
  1014. RELOC_ABSOLUTE :
  1015. begin
  1016. if (not win32) and assigned(objreloc.symbol) and
  1017. (objreloc.symbol.bind=AB_COMMON) then
  1018. begin
  1019. dec(address,objreloc.symbol.size);
  1020. end
  1021. else
  1022. begin
  1023. { fixup address when the symbol was known in defined object }
  1024. if (relocsec.objdata=objsec.objdata) then
  1025. dec(address,TCoffObjSection(relocsec).orgmempos);
  1026. end;
  1027. {$ifdef arm}
  1028. if (relocsec.objdata=objsec.objdata) and not TCoffObjData(objsec.objdata).eVCobj then
  1029. inc(address, relocsec.MemPos)
  1030. else
  1031. {$endif arm}
  1032. inc(address,relocval);
  1033. inc(address,imagebase);
  1034. end;
  1035. else
  1036. internalerror(200604014);
  1037. end
  1038. else
  1039. address:=0; { Relocation in debug section points to unused section, which is eliminated by linker }
  1040. data.Seek(objreloc.dataoffset);
  1041. data.Write(address,address_size);
  1042. {$ifdef cpu64bitaddr}
  1043. if (objreloc.typ = RELOC_ABSOLUTE32) and (objsec.name <> '.stab') then
  1044. begin
  1045. if assigned(objreloc.symbol) then
  1046. s:=objreloc.symbol.Name
  1047. else
  1048. s:=objreloc.objsection.Name;
  1049. Message2(link_w_32bit_absolute_reloc, objsec.ObjData.Name, s);
  1050. end;
  1051. {$endif cpu64bitaddr}
  1052. end;
  1053. end;
  1054. {****************************************************************************
  1055. TCoffObjData
  1056. ****************************************************************************}
  1057. constructor TCoffObjData.createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  1058. begin
  1059. inherited create(n);
  1060. CObjSection:=ACObjSection;
  1061. win32:=awin32;
  1062. end;
  1063. function TCoffObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1064. var
  1065. sep : string[3];
  1066. secname : string;
  1067. begin
  1068. { section type user gives the user full controll on the section name }
  1069. if atype=sec_user then
  1070. result:=aname
  1071. else
  1072. begin
  1073. { non-PECOFF targets lack rodata support }
  1074. if (atype in [sec_rodata,sec_rodata_norel]) and
  1075. not (target_info.system in systems_all_windows) then
  1076. atype:=sec_data;
  1077. secname:=coffsecnames[atype];
  1078. if create_smartlink_sections and
  1079. (aname<>'') then
  1080. begin
  1081. case aorder of
  1082. secorder_begin :
  1083. sep:='.b_';
  1084. secorder_end :
  1085. sep:='.z_';
  1086. else
  1087. sep:='.n_';
  1088. end;
  1089. result:=secname+sep+aname
  1090. end
  1091. else
  1092. result:=secname;
  1093. end;
  1094. end;
  1095. function TCoffObjData.sectiontype2options(aType:TAsmSectionType): TObjSectionOptions;
  1096. begin
  1097. if (aType in [sec_rodata,sec_rodata_norel]) then
  1098. begin
  1099. if (target_info.system in systems_all_windows) then
  1100. aType:=sec_rodata_norel
  1101. else
  1102. aType:=sec_data;
  1103. end;
  1104. result:=inherited sectiontype2options(aType);
  1105. end;
  1106. procedure TCoffObjData.CreateDebugSections;
  1107. begin
  1108. if target_dbg.id=dbg_stabs then
  1109. begin
  1110. stabssec:=createsection(sec_stab);
  1111. stabstrsec:=createsection(sec_stabstr);
  1112. end;
  1113. end;
  1114. procedure TCoffObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);
  1115. var
  1116. curraddr,
  1117. symaddr : aword;
  1118. begin
  1119. if CurrObjSec=nil then
  1120. internalerror(200403072);
  1121. if assigned(p) then
  1122. begin
  1123. { current address }
  1124. curraddr:=CurrObjSec.mempos+CurrObjSec.Size;
  1125. { external/common symbols don't have a fixed memory position yet }
  1126. if (p.bind=AB_COMMON) then
  1127. begin
  1128. { For go32v2 we need to use the size as address }
  1129. if not win32 then
  1130. symaddr:=p.size
  1131. else
  1132. symaddr:=0;
  1133. end
  1134. else
  1135. symaddr:=p.address;
  1136. { no symbol relocation need inside a section }
  1137. if (p.objsection=CurrObjSec) and
  1138. (p.bind<>AB_COMMON) then
  1139. begin
  1140. case reloctype of
  1141. RELOC_ABSOLUTE :
  1142. begin
  1143. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE);
  1144. inc(data,symaddr);
  1145. end;
  1146. {$ifdef cpu64bitaddr}
  1147. RELOC_ABSOLUTE32 :
  1148. begin
  1149. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE32);
  1150. inc(data,symaddr);
  1151. end;
  1152. {$endif cpu64bitaddr}
  1153. RELOC_RELATIVE :
  1154. begin
  1155. //inc(data,symaddr-len-CurrObjSec.Size);
  1156. data:=data+symaddr-len-CurrObjSec.Size;
  1157. end;
  1158. {$ifdef ARM}
  1159. RELOC_RELATIVE_24,
  1160. RELOC_RELATIVE_CALL:
  1161. begin
  1162. data:=(data and $ff000000) or (((((data and $ffffff) shl 2)+(symaddr-CurrObjSec.Size)) shr 2) and $FFFFFF); // TODO: Check overflow
  1163. end;
  1164. {$endif ARM}
  1165. RELOC_RVA,
  1166. RELOC_SECREL32 :
  1167. begin
  1168. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,reloctype);
  1169. inc(data,symaddr);
  1170. end;
  1171. else
  1172. internalerror(200604013);
  1173. end;
  1174. end
  1175. else
  1176. begin
  1177. if (p.objsection<>nil) and
  1178. (p.bind<>AB_COMMON) then
  1179. CurrObjSec.addsectionreloc(curraddr,p.objsection,reloctype)
  1180. else
  1181. CurrObjSec.addsymreloc(curraddr,p,reloctype);
  1182. if (not win32) or
  1183. (p.objsection<>nil) then
  1184. inc(data,symaddr);
  1185. if reloctype=RELOC_RELATIVE then
  1186. begin
  1187. if win32 then
  1188. dec(data,len-4)
  1189. else
  1190. dec(data,len+CurrObjSec.Size);
  1191. end;
  1192. end;
  1193. end
  1194. else
  1195. begin
  1196. if reloctype=RELOC_RVA then
  1197. internalerror(200603033);
  1198. end;
  1199. CurrObjSec.write(data,len);
  1200. end;
  1201. {****************************************************************************
  1202. TDJCoffObjData
  1203. ****************************************************************************}
  1204. constructor TDJCoffObjData.create(const n:string);
  1205. begin
  1206. inherited createcoff(n,false,TCoffObjSection);
  1207. end;
  1208. {****************************************************************************
  1209. TPECoffObjData
  1210. ****************************************************************************}
  1211. constructor TPECoffObjData.create(const n:string);
  1212. begin
  1213. inherited createcoff(n,true,TCoffObjSection);
  1214. end;
  1215. {****************************************************************************
  1216. TCoffObjOutput
  1217. ****************************************************************************}
  1218. constructor TCoffObjOutput.createcoff(AWriter:TObjectWriter;awin32:boolean);
  1219. begin
  1220. inherited create(AWriter);
  1221. win32:=awin32;
  1222. end;
  1223. destructor TCoffObjOutput.destroy;
  1224. begin
  1225. FCoffSyms.free;
  1226. FCoffStrs.free;
  1227. inherited destroy;
  1228. end;
  1229. procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:longint;typ,aux:byte);
  1230. var
  1231. sym : coffsymbol;
  1232. bosym : coffbigobjsymbol;
  1233. strpos : longword;
  1234. begin
  1235. { symbolname }
  1236. if length(name)>8 then
  1237. begin
  1238. strpos:=FCoffStrs.size+4;
  1239. FCoffStrs.writestr(name);
  1240. FCoffStrs.writestr(#0);
  1241. end
  1242. else
  1243. strpos:=0;
  1244. if bigobj then
  1245. begin
  1246. fillchar(bosym,sizeof(bosym),0);
  1247. if length(name)>8 then
  1248. bosym.name.offset.offset:=strpos
  1249. else
  1250. move(name[1],bosym.name.shortname,length(name));
  1251. bosym.value:=value;
  1252. bosym.SectionNumber:=longword(section);
  1253. bosym.StorageClass:=typ;
  1254. bosym.NumberOfAuxSymbols:=aux;
  1255. inc(symidx);
  1256. FCoffSyms.write(bosym,sizeof(bosym));
  1257. end
  1258. else
  1259. begin
  1260. if section>$7fff then
  1261. internalerror(2017020302);
  1262. FillChar(sym,sizeof(sym),0);
  1263. if length(name)>8 then
  1264. sym.strpos:=strpos
  1265. else
  1266. move(name[1],sym.name,length(name));
  1267. sym.value:=value;
  1268. sym.section:=section;
  1269. sym.typ:=typ;
  1270. sym.aux:=aux;
  1271. inc(symidx);
  1272. FCoffSyms.write(sym,sizeof(sym));
  1273. end;
  1274. end;
  1275. procedure TCoffObjOutput.section_write_symbol(p:TObject;arg:pointer);
  1276. var
  1277. secrec : coffsectionrec;
  1278. padding : word;
  1279. begin
  1280. with TCoffObjSection(p) do
  1281. begin
  1282. Inc(plongword(arg)^);
  1283. index:=plongword(arg)^;
  1284. secsymidx:=symidx;
  1285. { Both GNU and Microsoft toolchains write section symbols using
  1286. storage class 3 (STATIC).
  1287. No reason to use COFF_SYM_SECTION, it is silently converted to 3 by
  1288. PE binutils and causes warnings with DJGPP binutils. }
  1289. write_symbol(name,mempos,index,COFF_SYM_LOCAL,1);
  1290. { AUX }
  1291. fillchar(secrec,sizeof(secrec),0);
  1292. secrec.len:=Size;
  1293. if ObjRelocations.count<65535 then
  1294. secrec.nrelocs:=ObjRelocations.count
  1295. else
  1296. secrec.nrelocs:=65535;
  1297. inc(symidx);
  1298. FCoffSyms.write(secrec,sizeof(secrec));
  1299. { aux recs have the same size as symbols, so we need to add two
  1300. Byte of padding in case of a Big Obj Coff }
  1301. padding:=0;
  1302. if bigobj then
  1303. FCoffSyms.write(padding,sizeof(padding));
  1304. end;
  1305. end;
  1306. procedure TCoffObjOutput.section_write_relocs(p:TObject;arg:pointer);
  1307. var
  1308. i : longint;
  1309. rel : coffreloc;
  1310. objreloc : TObjRelocation;
  1311. begin
  1312. if (TObjSection(p).ObjRelocations.Count>65535) then
  1313. begin
  1314. rel.address:=TObjSection(p).ObjRelocations.Count+1;
  1315. rel.sym:=0;
  1316. rel.reloctype:=0;
  1317. FWriter.Write(rel,sizeof(rel));
  1318. end;
  1319. for i:=0 to TObjSection(p).ObjRelocations.Count-1 do
  1320. begin
  1321. objreloc:=TObjRelocation(TObjSection(p).ObjRelocations[i]);
  1322. rel.address:=objreloc.dataoffset;
  1323. if assigned(objreloc.symbol) then
  1324. begin
  1325. if (objreloc.symbol.bind=AB_LOCAL) then
  1326. rel.sym:=objreloc.symbol.objsection.secsymidx
  1327. else
  1328. begin
  1329. if objreloc.symbol.symidx=-1 then
  1330. internalerror(200602233);
  1331. rel.sym:=objreloc.symbol.symidx;
  1332. end;
  1333. end
  1334. else
  1335. begin
  1336. if objreloc.objsection<>nil then
  1337. rel.sym:=objreloc.objsection.secsymidx
  1338. else
  1339. rel.sym:=0;
  1340. end;
  1341. case objreloc.typ of
  1342. {$ifdef arm}
  1343. RELOC_ABSOLUTE :
  1344. rel.reloctype:=IMAGE_REL_ARM_ADDR32;
  1345. { I've no idea if this is correct (FK):
  1346. RELOC_RELATIVE :
  1347. rel.reloctype:=IMAGE_REL_ARM_GPREL12;
  1348. }
  1349. RELOC_RVA :
  1350. rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
  1351. RELOC_SECREL32 :
  1352. rel.reloctype:=IMAGE_REL_ARM_SECREL;
  1353. RELOC_RELATIVE_24 :
  1354. rel.reloctype:=IMAGE_REL_ARM_BRANCH24;
  1355. RELOC_RELATIVE_CALL :
  1356. rel.reloctype:=IMAGE_REL_ARM_BLX24;
  1357. RELOC_RELATIVE_24_THUMB:
  1358. rel.reloctype:=IMAGE_REL_ARM_BLX23T;
  1359. {$endif arm}
  1360. {$ifdef i386}
  1361. RELOC_RELATIVE :
  1362. rel.reloctype:=IMAGE_REL_I386_PCRLONG;
  1363. RELOC_ABSOLUTE :
  1364. rel.reloctype:=IMAGE_REL_I386_DIR32;
  1365. RELOC_RVA :
  1366. rel.reloctype:=IMAGE_REL_I386_IMAGEBASE;
  1367. RELOC_SECREL32 :
  1368. rel.reloctype:=IMAGE_REL_I386_SECREL32;
  1369. {$endif i386}
  1370. {$ifdef x86_64}
  1371. RELOC_NONE :
  1372. rel.reloctype:=IMAGE_REL_AMD64_ABSOLUTE;
  1373. RELOC_RELATIVE :
  1374. rel.reloctype:=IMAGE_REL_AMD64_REL32;
  1375. RELOC_ABSOLUTE32 :
  1376. rel.reloctype:=IMAGE_REL_AMD64_ADDR32;
  1377. RELOC_ABSOLUTE :
  1378. rel.reloctype:=IMAGE_REL_AMD64_ADDR64;
  1379. RELOC_RVA :
  1380. rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB;
  1381. RELOC_RELATIVE_1 :
  1382. rel.reloctype:=IMAGE_REL_AMD64_REL32_1;
  1383. RELOC_RELATIVE_2 :
  1384. rel.reloctype:=IMAGE_REL_AMD64_REL32_2;
  1385. RELOC_RELATIVE_3 :
  1386. rel.reloctype:=IMAGE_REL_AMD64_REL32_3;
  1387. RELOC_RELATIVE_4 :
  1388. rel.reloctype:=IMAGE_REL_AMD64_REL32_4;
  1389. RELOC_RELATIVE_5 :
  1390. rel.reloctype:=IMAGE_REL_AMD64_REL32_5;
  1391. RELOC_SECREL32 :
  1392. rel.reloctype:=IMAGE_REL_AMD64_SECREL;
  1393. {$endif x86_64}
  1394. else
  1395. internalerror(200905071);
  1396. end;
  1397. FWriter.write(rel,sizeof(rel));
  1398. end;
  1399. end;
  1400. procedure TCoffObjOutput.create_symbols(data:TObjData);
  1401. var
  1402. filename : string[20];
  1403. filenamelen : longint;
  1404. sectionval : word;
  1405. globalval : byte;
  1406. i : longint;
  1407. value : aword;
  1408. objsym : TObjSymbol;
  1409. secidx : longword;
  1410. begin
  1411. with TCoffObjData(data) do
  1412. begin
  1413. symidx:=0;
  1414. { The `.file' record, and the file name auxiliary record }
  1415. write_symbol('.file', 0, -2, COFF_SYM_FILE, 1);
  1416. fillchar(filename,sizeof(filename),0);
  1417. filename:=ExtractFileName(current_module.mainsource);
  1418. inc(symidx);
  1419. if bigobj then
  1420. filenamelen:=sizeof(coffbigobjsymbol)
  1421. else
  1422. filenamelen:=sizeof(coffsymbol);
  1423. FCoffSyms.write(filename[1],filenamelen);
  1424. { Sections }
  1425. secidx:=0;
  1426. ObjSectionList.ForEachCall(@section_write_symbol,@secidx);
  1427. { ObjSymbols }
  1428. for i:=0 to ObjSymbolList.Count-1 do
  1429. begin
  1430. objsym:=TObjSymbol(ObjSymbolList[i]);
  1431. if (objsym.bind=AB_LOCAL) then
  1432. continue;
  1433. case objsym.bind of
  1434. AB_GLOBAL :
  1435. begin
  1436. globalval:=COFF_SYM_GLOBAL;
  1437. sectionval:=objsym.objsection.index;
  1438. value:=objsym.address;
  1439. end;
  1440. AB_LOCAL :
  1441. begin
  1442. globalval:=COFF_SYM_LOCAL;
  1443. sectionval:=objsym.objsection.index;
  1444. value:=objsym.address;
  1445. end;
  1446. else
  1447. begin
  1448. globalval:=COFF_SYM_GLOBAL;
  1449. sectionval:=0;
  1450. value:=objsym.size;
  1451. end;
  1452. end;
  1453. { symbolname }
  1454. objsym.symidx:=symidx;
  1455. write_symbol(objsym.name,value,sectionval,globalval,0);
  1456. end;
  1457. end;
  1458. end;
  1459. procedure TCoffObjOutput.section_set_reloc_datapos(p:TCoffObjSection;var datapos:aword);
  1460. begin
  1461. p.coffrelocpos:=datapos;
  1462. inc(datapos,sizeof(coffreloc)*p.ObjRelocations.count);
  1463. if p.ObjRelocations.count>65535 then
  1464. begin
  1465. if win32 then
  1466. inc(datapos,sizeof(coffreloc))
  1467. else
  1468. Message1(asmw_f_too_many_relocations,p.fullname);
  1469. end;
  1470. end;
  1471. procedure TCoffObjOutput.section_write_header(p:TObject;arg:pointer);
  1472. var
  1473. sechdr : tcoffsechdr;
  1474. s : string;
  1475. strpos : aword;
  1476. begin
  1477. with TCoffObjSection(p) do
  1478. begin
  1479. fillchar(sechdr,sizeof(sechdr),0);
  1480. s:=name;
  1481. if length(s)>8 then
  1482. begin
  1483. strpos:=FCoffStrs.size+4;
  1484. FCoffStrs.writestr(s);
  1485. FCoffStrs.writestr(#0);
  1486. if strpos>=10000000 then
  1487. s:='//'+encodeBase64(strpos)
  1488. else
  1489. s:='/'+ToStr(strpos);
  1490. if length(s)>8 then
  1491. internalerror(2020091501);
  1492. end;
  1493. move(s[1],sechdr.name,length(s));
  1494. if not win32 then
  1495. begin
  1496. sechdr.rvaofs:=mempos;
  1497. sechdr.vsize:=mempos;
  1498. end
  1499. else
  1500. begin
  1501. if not(oso_data in secoptions) then
  1502. sechdr.vsize:=Size;
  1503. end;
  1504. sechdr.DataSize:=size;
  1505. if (Size>0) and
  1506. (oso_data in secoptions) then
  1507. sechdr.datapos:=datapos;
  1508. if ObjRelocations.count<65535 then
  1509. sechdr.nrelocs:=ObjRelocations.count
  1510. else
  1511. sechdr.nrelocs:=65535;
  1512. sechdr.relocpos:=coffrelocpos;
  1513. if win32 then
  1514. begin
  1515. sechdr.flags:=peencodesechdrflags(secoptions,secalign);
  1516. if ObjRelocations.count>65535 then
  1517. sechdr.flags:=sechdr.flags or PE_SCN_LNK_NRELOC_OVFL;
  1518. end
  1519. else
  1520. sechdr.flags:=djencodesechdrflags(secoptions);
  1521. FWriter.write(sechdr,sizeof(sechdr));
  1522. end;
  1523. end;
  1524. function TCoffObjOutput.writedata(data:TObjData):boolean;
  1525. var
  1526. datapos,
  1527. sympos : aword;
  1528. i : longint;
  1529. header : tcoffheader;
  1530. boheader : tcoffbigobjheader;
  1531. begin
  1532. result:=false;
  1533. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1534. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1535. with TCoffObjData(data) do
  1536. begin
  1537. bigobj:=(ObjSectionList.Count>$7fff) and win32;
  1538. { Create Symbol Table }
  1539. create_symbols(data);
  1540. { Calculate the filepositions }
  1541. if bigobj then
  1542. datapos:=sizeof(tcoffbigobjheader)
  1543. else
  1544. datapos:=sizeof(tcoffheader);
  1545. datapos:=datapos+sizeof(tcoffsechdr)*ObjSectionList.Count;
  1546. { Sections first }
  1547. layoutsections(datapos);
  1548. { relocs }
  1549. for i:=0 to ObjSectionList.Count-1 do
  1550. section_set_reloc_datapos(TCoffObjSection(ObjSectionList[i]),datapos);
  1551. { Symbols }
  1552. sympos:=datapos;
  1553. { Generate COFF header }
  1554. if bigobj then
  1555. begin
  1556. fillchar(boheader,sizeof(boheader),0);
  1557. boheader.Sig1:=0;
  1558. boheader.Sig2:=$ffff;
  1559. boheader.Machine:=COFF_MAGIC;
  1560. boheader.Version:=COFF_BIG_OBJ_VERSION;
  1561. boheader.NumberOfSections:=longword(ObjSectionList.Count);
  1562. boheader.NumberOfSymbols:=longword(symidx);
  1563. boheader.PointerToSymbolTable:=sympos;
  1564. Move(COFF_BIG_OBJ_MAGIC,boheader.UUID,length(boheader.UUID));
  1565. FWriter.write(boheader,sizeof(boheader));
  1566. end
  1567. else
  1568. begin
  1569. fillchar(header,sizeof(tcoffheader),0);
  1570. header.mach:=COFF_MAGIC;
  1571. header.nsects:=ObjSectionList.Count;
  1572. header.sympos:=sympos;
  1573. header.syms:=symidx;
  1574. if win32 then
  1575. begin
  1576. {$ifndef x86_64}
  1577. header.flag:=PE_FILE_32BIT_MACHINE or
  1578. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1579. {$else x86_64}
  1580. header.flag:=PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1581. {$endif x86_64}
  1582. end
  1583. else
  1584. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
  1585. FWriter.write(header,sizeof(header));
  1586. end;
  1587. { Section headers }
  1588. ObjSectionList.ForEachCall(@section_write_header,nil);
  1589. { ObjSections }
  1590. WriteSectionContent(data);
  1591. { Relocs }
  1592. ObjSectionList.ForEachCall(@section_write_relocs,nil);
  1593. { ObjSymbols }
  1594. if Sympos<>FWriter.ObjSize then
  1595. internalerror(200603051);
  1596. FWriter.writearray(FCoffSyms);
  1597. { Strings }
  1598. i:=FCoffStrs.size+4;
  1599. FWriter.write(i,4);
  1600. FWriter.writearray(FCoffStrs);
  1601. end;
  1602. FCoffStrs.Free;
  1603. FCoffStrs:=nil;
  1604. FCoffSyms.Free;
  1605. FCoffSyms:=nil;
  1606. end;
  1607. constructor TDJCoffObjOutput.create(AWriter:TObjectWriter);
  1608. begin
  1609. inherited createcoff(AWriter,false);
  1610. cobjdata:=TDJCoffObjData;
  1611. end;
  1612. constructor TPECoffObjOutput.create(AWriter:TObjectWriter);
  1613. begin
  1614. inherited createcoff(AWriter,true);
  1615. cobjdata:=TPECoffObjData;
  1616. end;
  1617. {****************************************************************************
  1618. TCoffObjInput
  1619. ****************************************************************************}
  1620. constructor TCoffObjInput.createcoff(awin32:boolean);
  1621. begin
  1622. inherited create;
  1623. win32:=awin32;
  1624. bigobj:=false;
  1625. FSymTbl:=nil;
  1626. end;
  1627. destructor TCoffObjInput.destroy;
  1628. begin
  1629. FCoffSyms.free;
  1630. if assigned(FCoffStrs) then
  1631. freemem(FCoffStrs);
  1632. if assigned(FSymTbl) then
  1633. freemem(FSymTbl);
  1634. if assigned(FSecTbl) then
  1635. freemem(FSecTbl);
  1636. inherited destroy;
  1637. end;
  1638. function TCoffObjInput.GetSection(secidx:longint):TObjSection;
  1639. begin
  1640. result:=nil;
  1641. if (secidx<1) or (secidx>FSecCount) then
  1642. begin
  1643. InputError('Failed reading coff file, invalid section index');
  1644. exit;
  1645. end;
  1646. result:=FSecTbl^[secidx];
  1647. end;
  1648. function TCoffObjInput.Read_str(strpos:longword):string;
  1649. begin
  1650. if (FCoffStrs=nil) or (strpos>=FCoffStrSize) or (FCoffStrs[strpos]=#0) then
  1651. Internalerror(200205172);
  1652. result:=string(PChar(@FCoffStrs[strpos]));
  1653. end;
  1654. procedure TCoffObjInput.read_relocs(s:TCoffObjSection);
  1655. var
  1656. rel : coffreloc;
  1657. rel_type : TObjRelocationType;
  1658. i : longint;
  1659. p : TObjSymbol;
  1660. begin
  1661. if s.coffrelocs=high(aword) then
  1662. begin
  1663. { If number of relocations exceeds 65535, it is stored in address field
  1664. of the first record, and includes this first fake relocation. }
  1665. FReader.read(rel,sizeof(rel));
  1666. s.coffrelocs:=rel.address-1;
  1667. if s.coffrelocs<=65535 then
  1668. InternalError(2013012503);
  1669. end;
  1670. for i:=1 to s.coffrelocs do
  1671. begin
  1672. FReader.read(rel,sizeof(rel));
  1673. case rel.reloctype of
  1674. {$ifdef arm}
  1675. IMAGE_REL_ARM_ABSOLUTE:
  1676. rel_type:=RELOC_NONE;
  1677. IMAGE_REL_ARM_ADDR32:
  1678. rel_type:=RELOC_ABSOLUTE;
  1679. IMAGE_REL_ARM_ADDR32NB:
  1680. rel_type:=RELOC_RVA;
  1681. IMAGE_REL_ARM_BRANCH24:
  1682. rel_type:=RELOC_RELATIVE_24;
  1683. IMAGE_REL_ARM_BLX24:
  1684. rel_type:=RELOC_RELATIVE_CALL;
  1685. IMAGE_REL_ARM_SECREL:
  1686. rel_type:=RELOC_SECREL32;
  1687. IMAGE_REL_ARM_BLX23T:
  1688. rel_type:=RELOC_RELATIVE_24_THUMB;
  1689. {$endif arm}
  1690. {$ifdef i386}
  1691. IMAGE_REL_I386_PCRLONG :
  1692. rel_type:=RELOC_RELATIVE;
  1693. IMAGE_REL_I386_DIR32 :
  1694. rel_type:=RELOC_ABSOLUTE;
  1695. IMAGE_REL_I386_IMAGEBASE :
  1696. rel_type:=RELOC_RVA;
  1697. IMAGE_REL_I386_SECREL32 :
  1698. rel_type:=RELOC_SECREL32;
  1699. {$endif i386}
  1700. {$ifdef x86_64}
  1701. IMAGE_REL_AMD64_ABSOLUTE:
  1702. rel_type:=RELOC_NONE;
  1703. IMAGE_REL_AMD64_REL32:
  1704. rel_type:=RELOC_RELATIVE;
  1705. IMAGE_REL_AMD64_ADDR32,
  1706. R_X86_64_32S:
  1707. rel_type:=RELOC_ABSOLUTE32;
  1708. IMAGE_REL_AMD64_ADDR64:
  1709. rel_type:=RELOC_ABSOLUTE;
  1710. IMAGE_REL_AMD64_ADDR32NB:
  1711. rel_type:=RELOC_RVA;
  1712. IMAGE_REL_AMD64_REL32_1:
  1713. rel_type:=RELOC_RELATIVE_1;
  1714. IMAGE_REL_AMD64_REL32_2:
  1715. rel_type:=RELOC_RELATIVE_2;
  1716. IMAGE_REL_AMD64_REL32_3:
  1717. rel_type:=RELOC_RELATIVE_3;
  1718. IMAGE_REL_AMD64_REL32_4:
  1719. rel_type:=RELOC_RELATIVE_4;
  1720. IMAGE_REL_AMD64_REL32_5:
  1721. rel_type:=RELOC_RELATIVE_5;
  1722. IMAGE_REL_AMD64_SECREL:
  1723. rel_type:=RELOC_SECREL32;
  1724. {$endif x86_64}
  1725. else
  1726. begin
  1727. InputError('Failed reading coff file, illegal reloctype $'+system.hexstr(rel.reloctype,4));
  1728. exit;
  1729. end;
  1730. end;
  1731. p:=FSymTbl^[rel.sym];
  1732. if assigned(p) then
  1733. s.addsymreloc(rel.address-s.mempos,p,rel_type)
  1734. else
  1735. begin
  1736. InputError('Failed reading coff file, can''t resolve symbol of relocation');
  1737. exit;
  1738. end;
  1739. end;
  1740. end;
  1741. procedure TCoffObjInput.read_symbols(objdata:TObjData);
  1742. var
  1743. size,
  1744. address,
  1745. nsyms,
  1746. symidx : aint;
  1747. i : longint;
  1748. sym : coffsymbol;
  1749. bosym : coffbigobjsymbol;
  1750. objsym : TObjSymbol;
  1751. bind : Tasmsymbind;
  1752. strname : string;
  1753. auxrec : array[0..sizeof(coffsymbol)-1] of byte;
  1754. boauxrec : array[0..sizeof(coffbigobjsymbol)-1] of byte;
  1755. secrec : pcoffsectionrec;
  1756. objsec : TObjSection;
  1757. secidx : longint;
  1758. symvalue : longword;
  1759. auxcount : byte;
  1760. symcls : byte;
  1761. comdatsel : TObjSectionComdatSelection;
  1762. { keeps string manipulations out of main routine }
  1763. procedure UnsupportedSymbolType;
  1764. begin
  1765. Comment(V_Fatal,'Unsupported COFF symbol type '+tostr(symcls)+' at index '+tostr(symidx)+' while reading '+InputFileName);
  1766. end;
  1767. begin
  1768. with TCoffObjData(objdata) do
  1769. begin
  1770. if bigobj then
  1771. nsyms:=FCoffSyms.Size div sizeof(coffbigobjsymbol)
  1772. else
  1773. nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
  1774. { Allocate memory for symidx -> TObjSymbol table }
  1775. FSymTbl:=AllocMem(nsyms*sizeof(TObjSymbol));
  1776. { Load the Symbols }
  1777. FCoffSyms.Seek(0);
  1778. symidx:=0;
  1779. while (symidx<nsyms) do
  1780. begin
  1781. if bigobj then
  1782. begin
  1783. FCoffSyms.Read(bosym,sizeof(bosym));
  1784. if bosym.Name.Offset.Zeroes<>0 then
  1785. begin
  1786. move(bosym.Name.ShortName,strname[1],8);
  1787. strname[9]:=#0;
  1788. strname[0]:=chr(strlen(@strname[1]));
  1789. if strname='' then
  1790. internalerror(2017020301);
  1791. end
  1792. else
  1793. strname:=Read_str(bosym.Name.Offset.Offset);
  1794. secidx:=longint(bosym.SectionNumber);
  1795. symvalue:=bosym.Value;
  1796. auxcount:=bosym.NumberOfAuxSymbols;
  1797. symcls:=bosym.StorageClass;
  1798. end
  1799. else
  1800. begin
  1801. FCoffSyms.Read(sym,sizeof(sym));
  1802. if plongint(@sym.name)^<>0 then
  1803. begin
  1804. move(sym.name,strname[1],8);
  1805. strname[9]:=#0;
  1806. strname[0]:=chr(strlen(@strname[1]));
  1807. if strname='' then
  1808. Internalerror(200205171);
  1809. end
  1810. else
  1811. strname:=Read_str(sym.strpos);
  1812. secidx:=sym.section;
  1813. symvalue:=sym.value;
  1814. auxcount:=sym.aux;
  1815. symcls:=sym.typ;
  1816. end;
  1817. bind:=AB_EXTERNAL;
  1818. size:=0;
  1819. address:=0;
  1820. objsym:=nil;
  1821. objsec:=nil;
  1822. case symcls of
  1823. COFF_SYM_GLOBAL :
  1824. begin
  1825. if secidx=0 then
  1826. begin
  1827. if symvalue=0 then
  1828. bind:=AB_EXTERNAL
  1829. else
  1830. begin
  1831. bind:=AB_COMMON;
  1832. size:=symvalue;
  1833. end;
  1834. end
  1835. else
  1836. begin
  1837. bind:=AB_GLOBAL;
  1838. objsec:=GetSection(secidx);
  1839. if symvalue>=objsec.mempos then
  1840. address:=symvalue-objsec.mempos;
  1841. end;
  1842. objsym:=CreateSymbol(strname);
  1843. objsym.bind:=bind;
  1844. objsym.typ:=AT_FUNCTION;
  1845. objsym.objsection:=objsec;
  1846. objsym.offset:=address;
  1847. objsym.size:=size;
  1848. end;
  1849. COFF_SYM_LABEL,
  1850. COFF_SYM_LOCAL :
  1851. begin
  1852. { do not add constants (section=-1) }
  1853. if secidx<>-1 then
  1854. begin
  1855. objsec:=GetSection(secidx);
  1856. if symvalue>=objsec.mempos then
  1857. address:=symvalue-objsec.mempos;
  1858. objsym:=CreateSymbol(strname);
  1859. objsym.bind:=AB_LOCAL;
  1860. objsym.typ:=AT_FUNCTION;
  1861. objsym.objsection:=objsec;
  1862. objsym.offset:=address;
  1863. objsym.size:=size;
  1864. end;
  1865. end;
  1866. COFF_SYM_SECTION :
  1867. begin
  1868. { GetSection checks that index is in range }
  1869. objsec:=GetSection(secidx);
  1870. if assigned(objsec) then
  1871. begin
  1872. if symvalue>=objsec.mempos then
  1873. address:=symvalue-objsec.mempos;
  1874. objsym:=CreateSymbol(strname);
  1875. objsym.bind:=AB_LOCAL;
  1876. objsym.typ:=AT_FUNCTION;
  1877. objsym.objsection:=objsec;
  1878. objsym.offset:=address;
  1879. objsym.size:=size;
  1880. end;
  1881. end;
  1882. COFF_SYM_FUNCTION,
  1883. COFF_SYM_FILE :
  1884. ;
  1885. else
  1886. UnsupportedSymbolType;
  1887. end;
  1888. FSymTbl^[symidx]:=objsym;
  1889. { read aux records }
  1890. { handle COMDAT symbols }
  1891. if (symcls=COFF_SYM_LOCAL) and (auxcount=1) and (symvalue=0) and (oso_comdat in objsym.objsection.SecOptions) then
  1892. begin
  1893. if bigobj then
  1894. begin
  1895. FCoffSyms.Read(boauxrec,sizeof(boauxrec));
  1896. secrec:=pcoffsectionrec(@boauxrec[0]);
  1897. end
  1898. else
  1899. begin
  1900. FCoffSyms.Read(auxrec,sizeof(auxrec));
  1901. secrec:=pcoffsectionrec(@auxrec);
  1902. end;
  1903. case secrec^.select of
  1904. IMAGE_COMDAT_SELECT_NODUPLICATES:
  1905. comdatsel:=oscs_none;
  1906. IMAGE_COMDAT_SELECT_ANY:
  1907. comdatsel:=oscs_any;
  1908. IMAGE_COMDAT_SELECT_SAME_SIZE:
  1909. comdatsel:=oscs_same_size;
  1910. IMAGE_COMDAT_SELECT_EXACT_MATCH:
  1911. comdatsel:=oscs_exact_match;
  1912. IMAGE_COMDAT_SELECT_ASSOCIATIVE:
  1913. comdatsel:=oscs_associative;
  1914. IMAGE_COMDAT_SELECT_LARGEST:
  1915. comdatsel:=oscs_largest;
  1916. else begin
  1917. comdatsel:=oscs_none;
  1918. Message2(link_e_comdat_select_unsupported,inttostr(secrec^.select),objsym.objsection.name);
  1919. end;
  1920. end;
  1921. if comdatsel in [oscs_associative,oscs_exact_match] then
  1922. { only temporary }
  1923. Comment(V_Error,'Associative or exact match COMDAT sections are not yet supported (symbol: '+objsym.objsection.Name+')')
  1924. else if (comdatsel=oscs_associative) and (secrec^.assoc=0) then
  1925. Message1(link_e_comdat_associative_section_expected,objsym.objsection.name)
  1926. else if (objsym.objsection.ComdatSelection<>oscs_none) and (comdatsel<>oscs_none) and (objsym.objsection.ComdatSelection<>comdatsel) then
  1927. Message2(link_e_comdat_not_matching,objsym.objsection.Name,objsym.Name)
  1928. else
  1929. begin
  1930. objsym.objsection.ComdatSelection:=comdatsel;
  1931. if (secrec^.assoc<>0) and not assigned(objsym.objsection.AssociativeSection) then
  1932. begin
  1933. objsym.objsection.AssociativeSection:=GetSection(secrec^.assoc);
  1934. if not assigned(objsym.objsection.AssociativeSection) then
  1935. Message1(link_e_comdat_associative_section_not_found,objsym.objsection.Name);
  1936. end;
  1937. end;
  1938. dec(auxcount);
  1939. inc(symidx);
  1940. end;
  1941. for i:=1 to auxcount do
  1942. begin
  1943. if bigobj then
  1944. FCoffSyms.Read(boauxrec,sizeof(boauxrec))
  1945. else
  1946. FCoffSyms.Read(auxrec,sizeof(auxrec));
  1947. inc(symidx);
  1948. end;
  1949. inc(symidx);
  1950. end;
  1951. end;
  1952. end;
  1953. procedure TCoffObjInput.ObjSections_read_relocs(p:TObject;arg:pointer);
  1954. begin
  1955. with TCoffObjSection(p) do
  1956. begin
  1957. { Skip debug sections }
  1958. if (oso_debug in secoptions) and
  1959. (cs_link_strip in current_settings.globalswitches) and
  1960. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1961. exit;
  1962. if coffrelocs>0 then
  1963. begin
  1964. FReader.Seek(coffrelocpos);
  1965. read_relocs(TCoffObjSection(p));
  1966. end;
  1967. end;
  1968. end;
  1969. function TCoffObjInput.ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;
  1970. var
  1971. secalign : longint;
  1972. secofs,
  1973. strpos,
  1974. i : longint;
  1975. sympos,
  1976. symcount,
  1977. symsize,
  1978. code : longint;
  1979. objsec : TCoffObjSection;
  1980. secoptions : TObjSectionOptions;
  1981. header : tcoffheader;
  1982. boheader : tcoffbigobjheader;
  1983. sechdr : tcoffsechdr;
  1984. secname : string;
  1985. secnamebuf : array[0..15] of char;
  1986. begin
  1987. FReader:=AReader;
  1988. InputFileName:=AReader.FileName;
  1989. objdata:=CObjData.Create(InputFileName);
  1990. result:=false;
  1991. boheader:=default(tcoffbigobjheader);
  1992. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1993. with TCoffObjData(objdata) do
  1994. begin
  1995. { Read COFF header }
  1996. if not AReader.read(header,sizeof(tcoffheader)) then
  1997. begin
  1998. InputError('Can''t read COFF Header');
  1999. exit;
  2000. end;
  2001. if (header.mach=0) and (header.nsects=$ffff) then
  2002. begin
  2003. { either a library or big obj COFF }
  2004. AReader.seek(0);
  2005. if not AReader.read(boheader,sizeof(boheader)) then
  2006. begin
  2007. InputError('Can''t read Big Obj COFF Header');
  2008. exit;
  2009. end;
  2010. if CompareByte(boheader.UUID,COFF_BIG_OBJ_MAGIC,length(boheader.uuid))<>0 then
  2011. begin
  2012. { ToDo: this should be treated as a library }
  2013. InputError('Illegal Big Obj COFF Magic');
  2014. exit;
  2015. end;
  2016. if boheader.Version<>COFF_BIG_OBJ_VERSION then
  2017. begin
  2018. InputError('Illegal Big Obj COFF Version');
  2019. exit;
  2020. end;
  2021. if boheader.Machine<>COFF_MAGIC then
  2022. begin
  2023. InputError('Illegal COFF Machine type');
  2024. exit;
  2025. end;
  2026. bigobj:=true;
  2027. end
  2028. else if header.mach<>COFF_MAGIC then
  2029. begin
  2030. InputError('Illegal COFF Magic');
  2031. exit;
  2032. end;
  2033. {$ifdef arm}
  2034. eVCobj:=header.flag=$100;
  2035. {$endif arm}
  2036. { ObjSymbols }
  2037. if bigobj then
  2038. begin
  2039. sympos:=longint(boheader.PointerToSymbolTable);
  2040. symcount:=longint(boheader.NumberOfSymbols);
  2041. symsize:=sizeof(CoffBigObjSymbol);
  2042. end
  2043. else
  2044. begin
  2045. sympos:=longint(header.sympos);
  2046. symcount:=longint(header.syms);
  2047. symsize:=sizeof(CoffSymbol);
  2048. end;
  2049. AReader.Seek(sympos);
  2050. if not AReader.ReadArray(FCoffSyms,symcount*symsize) then
  2051. begin
  2052. InputError('Error reading coff symbol table');
  2053. exit;
  2054. end;
  2055. { Strings }
  2056. if not AReader.Read(FCoffStrSize,4) then
  2057. begin
  2058. InputError('Error reading COFF string table');
  2059. exit;
  2060. end;
  2061. if (FCoffStrSize>4) then
  2062. begin
  2063. { allocate an extra byte and null-terminate }
  2064. GetMem(FCoffStrs,FCoffStrSize+1);
  2065. FCoffStrs[FCoffStrSize]:=#0;
  2066. for i:=0 to 3 do
  2067. FCoffStrs[i]:=#0;
  2068. if not AReader.Read(FCoffStrs[4],FCoffStrSize-4) then
  2069. begin
  2070. InputError('Error reading COFF string table');
  2071. exit;
  2072. end;
  2073. end;
  2074. { Section headers }
  2075. { Allocate SecIdx -> TObjSection table, secidx is 1-based }
  2076. if bigobj then
  2077. FSecCount:=longint(boheader.NumberOfSections)
  2078. else
  2079. FSecCount:=header.nsects;
  2080. FSecTbl:=AllocMem((FSecCount+1)*sizeof(TObjSection));
  2081. if bigobj then
  2082. secofs:=sizeof(tcoffbigobjheader)
  2083. else
  2084. secofs:=sizeof(tcoffheader)+header.opthdr;
  2085. AReader.Seek(secofs);
  2086. for i:=1 to FSecCount do
  2087. begin
  2088. if not AReader.read(sechdr,sizeof(sechdr)) then
  2089. begin
  2090. InputError('Error reading COFF Section Headers');
  2091. exit;
  2092. end;
  2093. move(sechdr.name,secnamebuf,8);
  2094. secnamebuf[8]:=#0;
  2095. secname:=strpas(secnamebuf);
  2096. if secname[1]='/' then
  2097. begin
  2098. if secname[2]='/' then
  2099. begin
  2100. if not decodeBase64(copy(secname,3,8),strpos) then
  2101. begin
  2102. InputError('Error reading COFF Section Headers');
  2103. secname:='error';
  2104. end
  2105. else
  2106. secname:=Read_str(strpos);
  2107. end
  2108. else
  2109. begin
  2110. Val(Copy(secname,2,8),strpos,code);
  2111. if code=0 then
  2112. secname:=Read_str(strpos)
  2113. else
  2114. begin
  2115. InputError('Error reading COFF Section Headers');
  2116. secname:='error';
  2117. end;
  2118. end;
  2119. end;
  2120. if win32 then
  2121. pedecodesechdrflags(secname,sechdr.flags,secoptions,secalign)
  2122. else
  2123. begin
  2124. secoptions:=djdecodesechdrflags(secname,sechdr.flags);
  2125. secalign:=sizeof(pint);
  2126. end;
  2127. if (Length(secname)>3) and (secname[2] in ['e','f','i','p','r']) then
  2128. begin
  2129. if (Pos('.edata',secname)=1) or
  2130. (Pos('.rsrc',secname)=1) or
  2131. {$ifndef x86_64}
  2132. (Pos('.pdata',secname)=1) or
  2133. {$endif}
  2134. (Pos('.fpc',secname)=1) then
  2135. include(secoptions,oso_keep);
  2136. if (Pos('.idata',secname)=1) then
  2137. begin
  2138. { TODO: idata keep can maybe replaced with grouping of text and idata}
  2139. include(secoptions,oso_keep);
  2140. secname:=secname + '.' + ExtractFileName(InputFileName);
  2141. end;
  2142. end;
  2143. objsec:=TCoffObjSection(createsection(secname,secalign,secoptions,false));
  2144. FSecTbl^[i]:=objsec;
  2145. if not win32 then
  2146. objsec.mempos:=sechdr.rvaofs;
  2147. objsec.orgmempos:=sechdr.rvaofs;
  2148. objsec.coffrelocs:=sechdr.nrelocs;
  2149. if win32 then
  2150. begin
  2151. if (sechdr.flags and PE_SCN_LNK_NRELOC_OVFL)<>0 then
  2152. objsec.coffrelocs:=high(aword);
  2153. end;
  2154. objsec.coffrelocpos:=sechdr.relocpos;
  2155. objsec.datapos:=sechdr.datapos;
  2156. objsec.Size:=sechdr.dataSize;
  2157. end;
  2158. { Insert all ObjSymbols }
  2159. read_symbols(objdata);
  2160. { Section Data }
  2161. ReadSectionContent(objdata);
  2162. { Relocs }
  2163. ObjSectionList.ForEachCall(@objsections_read_relocs,nil);
  2164. end;
  2165. if assigned(FCoffStrs) then
  2166. freemem(FCoffStrs);
  2167. FCoffStrs:=nil;
  2168. FCoffSyms.Free;
  2169. FCoffSyms:=nil;
  2170. result:=true;
  2171. end;
  2172. constructor TDJCoffObjInput.create;
  2173. begin
  2174. inherited createcoff(false);
  2175. cobjdata:=TDJCoffObjData;
  2176. end;
  2177. constructor TPECoffObjInput.create;
  2178. begin
  2179. inherited createcoff(true);
  2180. cobjdata:=TPECoffObjData;
  2181. end;
  2182. {****************************************************************************
  2183. TCoffexeoutput
  2184. ****************************************************************************}
  2185. constructor TCoffexeoutput.createcoff(awin32:boolean);
  2186. begin
  2187. inherited create;
  2188. win32:=awin32;
  2189. if target_info.system in [system_x86_64_win64] then
  2190. MaxMemPos:=$FFFFFFFF
  2191. else
  2192. if target_info.system in systems_wince then
  2193. MaxMemPos:=$1FFFFFF
  2194. else
  2195. MaxMemPos:=$7FFFFFFF;
  2196. end;
  2197. procedure TCoffexeoutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  2198. var
  2199. sym : coffsymbol;
  2200. begin
  2201. FillChar(sym,sizeof(sym),0);
  2202. if length(name)>8 then
  2203. begin
  2204. sym.strpos:=FCoffStrs.size+4;
  2205. FCoffStrs.writestr(name);
  2206. FCoffStrs.writestr(#0);
  2207. end
  2208. else
  2209. move(name[1],sym.name,length(name));
  2210. sym.value:=value;
  2211. sym.section:=section;
  2212. sym.typ:=typ;
  2213. sym.aux:=aux;
  2214. FWriter.write(sym,sizeof(sym));
  2215. end;
  2216. procedure TCoffexeoutput.globalsyms_write_symbol(p:TObject;arg:pointer);
  2217. var
  2218. secval,
  2219. value : aint;
  2220. globalval : byte;
  2221. exesec : TExeSection;
  2222. begin
  2223. if not assigned(texesymbol(p).objsymbol) then
  2224. internalerror(200603053);
  2225. with texesymbol(p).objsymbol do
  2226. begin
  2227. if assigned(objsection) then
  2228. exesec:=TExeSection(objsection.exesection)
  2229. else
  2230. exesec:=nil;
  2231. { There is no exesection defined for special internal symbols
  2232. like __image_base__ }
  2233. if assigned(exesec) then
  2234. begin
  2235. secval:=exesec.secsymidx;
  2236. if win32 then
  2237. value:=address-exesec.mempos
  2238. else
  2239. value:=address;
  2240. end
  2241. else
  2242. begin
  2243. secval:=-1;
  2244. value:=address;
  2245. end;
  2246. if bind=AB_LOCAL then
  2247. globalval:=COFF_SYM_LOCAL
  2248. else
  2249. globalval:=COFF_SYM_GLOBAL;
  2250. { reloctype address to the section in the executable }
  2251. write_symbol(name,value,secval,globalval,0);
  2252. end;
  2253. end;
  2254. procedure TCoffexeoutput.ExeSectionList_write_header(p:TObject;arg:pointer);
  2255. var
  2256. sechdr : tcoffsechdr;
  2257. s : string;
  2258. strpos : aword;
  2259. begin
  2260. with tExeSection(p) do
  2261. begin
  2262. fillchar(sechdr,sizeof(sechdr),0);
  2263. s:=name;
  2264. if length(s)>8 then
  2265. begin
  2266. strpos:=FCoffStrs.size+4;
  2267. FCoffStrs.writestr(s);
  2268. FCoffStrs.writestr(#0);
  2269. s:='/'+ToStr(strpos);
  2270. end;
  2271. move(s[1],sechdr.name,length(s));
  2272. if win32 then
  2273. begin
  2274. sechdr.rvaofs:=mempos;
  2275. sechdr.vsize:=Size;
  2276. { sechdr.dataSize is size of initialized data, rounded up to FileAlignment
  2277. (so it can be greater than VirtualSize). Must be zero for sections that
  2278. do not contain initialized data. }
  2279. if (oso_data in SecOptions) then
  2280. sechdr.datasize:=Align(Size,SectionDataAlign);
  2281. end
  2282. else
  2283. begin
  2284. if not (oso_debug in SecOptions) then
  2285. begin
  2286. sechdr.rvaofs:=mempos;
  2287. sechdr.vsize:=mempos;
  2288. end;
  2289. sechdr.datasize:=Size;
  2290. end;
  2291. if (Size>0) then
  2292. sechdr.datapos:=datapos-datapos_offset;
  2293. sechdr.nrelocs:=0;
  2294. sechdr.relocpos:=0;
  2295. if win32 then
  2296. begin
  2297. if (target_info.system in systems_nativent) and
  2298. (apptype = app_native) then
  2299. sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign) or PE_SCN_MEM_NOT_PAGED
  2300. else
  2301. sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign);
  2302. { some flags are invalid in executables, reset them }
  2303. sechdr.flags:=sechdr.flags and
  2304. not(PE_SCN_LNK_INFO or PE_SCN_LNK_REMOVE or
  2305. PE_SCN_LNK_COMDAT or PE_SCN_ALIGN_MASK);
  2306. end
  2307. else
  2308. sechdr.flags:=djencodesechdrflags(SecOptions);
  2309. FWriter.write(sechdr,sizeof(sechdr));
  2310. end;
  2311. end;
  2312. procedure TCoffexeoutput.ExeSectionList_pass2_header(p:TObject;arg:pointer);
  2313. begin
  2314. with TExeSection(p) do
  2315. begin
  2316. { The debuginfo sections should already be stripped }
  2317. { if (ExeWriteMode=ewm_exeonly) and
  2318. (oso_debug in SecOptions) then
  2319. internalerror(200801161); }
  2320. inc(plongint(arg)^);
  2321. secsymidx:=plongint(arg)^;
  2322. end;
  2323. end;
  2324. function tcoffexeoutput.totalheadersize:longword;
  2325. var
  2326. stubsize,
  2327. optheadersize : longword;
  2328. begin
  2329. if win32 then
  2330. begin
  2331. stubsize:=sizeof(win32stub)+sizeof(pemagic);
  2332. optheadersize:=sizeof(tcoffpeoptheader);
  2333. end
  2334. else
  2335. begin
  2336. stubsize:=sizeof(go32v2stub);
  2337. optheadersize:=sizeof(coffdjoptheader);
  2338. end;
  2339. result:=stubsize+sizeof(tcoffheader)+optheadersize;
  2340. end;
  2341. procedure tcoffexeoutput.MemPos_Header;
  2342. begin
  2343. { calculate start positions after the headers }
  2344. currmempos:=totalheadersize+sizeof(tcoffsechdr)*longword(ExeSectionList.Count-2);
  2345. end;
  2346. procedure tcoffexeoutput.DataPos_Header;
  2347. begin
  2348. { retrieve amount of sections }
  2349. nsects:=0;
  2350. ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
  2351. { calculate start positions after the headers }
  2352. currdatapos:=totalheadersize+longword(nsects)*sizeof(tcoffsechdr);
  2353. end;
  2354. procedure tcoffexeoutput.DataPos_Symbols;
  2355. begin
  2356. inherited DataPos_Symbols;
  2357. { Calculating symbols position and size }
  2358. nsyms:=ExeSymbolList.Count;
  2359. sympos:=Align(CurrDataPos,SectionDataAlign);
  2360. inc(CurrDataPos,sizeof(coffsymbol)*nsyms);
  2361. end;
  2362. function TCoffexeoutput.writedata:boolean;
  2363. var
  2364. i : longword;
  2365. header : tcoffheader;
  2366. djoptheader : coffdjoptheader;
  2367. peoptheader : tcoffpeoptheader;
  2368. textExeSec,
  2369. dataExeSec,
  2370. bssExeSec,
  2371. idataExeSec : TExeSection;
  2372. hassymbols,
  2373. writeDbgStrings : boolean;
  2374. procedure UpdateDataDir(const secname:string;idx:longint);
  2375. var
  2376. exesec : TExeSection;
  2377. begin
  2378. exesec:=FindExeSection(secname);
  2379. if assigned(exesec) then
  2380. begin
  2381. peoptheader.DataDirectory[idx].vaddr:=exesec.mempos;
  2382. peoptheader.DataDirectory[idx].size:=exesec.Size;
  2383. end;
  2384. end;
  2385. procedure UpdateImports;
  2386. var
  2387. exesec: TExeSection;
  2388. objsec, iat_start, iat_end, ilt_start: TObjSection;
  2389. i: longint;
  2390. begin
  2391. exesec:=FindExeSection('.idata');
  2392. if exesec=nil then
  2393. exit;
  2394. iat_start:=nil;
  2395. iat_end:=nil;
  2396. ilt_start:=nil;
  2397. for i:=0 to exesec.ObjSectionList.Count-1 do
  2398. begin
  2399. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2400. if (ilt_start=nil) and (Pos('.idata$4',objsec.Name)=1) then
  2401. ilt_start:=objsec;
  2402. if Pos('.idata$5',objsec.Name)=1 then
  2403. begin
  2404. if iat_start=nil then
  2405. iat_start:=objsec;
  2406. end
  2407. else
  2408. if Assigned(iat_start) then
  2409. begin
  2410. iat_end:=objsec;
  2411. Break;
  2412. end;
  2413. end;
  2414. peoptheader.DataDirectory[PE_DATADIR_IDATA].vaddr:=exesec.mempos;
  2415. if Assigned(ilt_start) then
  2416. peoptheader.DataDirectory[PE_DATADIR_IDATA].size:=ilt_start.mempos-exesec.mempos
  2417. else { should not happen }
  2418. peoptheader.DataDirectory[PE_DATADIR_IDATA].size:=exesec.Size;
  2419. if Assigned(iat_start) and Assigned(iat_end) then
  2420. begin
  2421. peoptheader.DataDirectory[PE_DATADIR_IMPORTADDRESSTABLE].vaddr:=iat_start.mempos;
  2422. peoptheader.DataDirectory[PE_DATADIR_IMPORTADDRESSTABLE].size:=iat_end.mempos-iat_start.mempos;
  2423. end;
  2424. end;
  2425. procedure UpdateTlsDataDir;
  2426. var
  2427. {callbacksection : TExeSection;}
  2428. tlsexesymbol: TExeSymbol;
  2429. tlssymbol: TObjSymbol;
  2430. callbackexesymbol: TExeSymbol;
  2431. //callbacksymbol: TObjSymbol;
  2432. begin
  2433. { according to GNU ld,
  2434. the callback routines should be placed into .CRT$XL*
  2435. sections, and the thread local variables in .tls
  2436. __tls_start__ and __tls_end__ symbols
  2437. should be used for the initialized part,
  2438. which we do not support yet. }
  2439. { For now, we only pass the address of the __tls_used
  2440. asm symbol into PE_DATADIR_TLS with the correct
  2441. size of this table (different for win32/win64 }
  2442. tlsexesymbol:=texesymbol(ExeSymbolList.Find(
  2443. target_info.Cprefix+'_tls_used'));
  2444. if assigned(tlsexesymbol) then
  2445. begin
  2446. tlssymbol:=tlsexesymbol.ObjSymbol;
  2447. peoptheader.DataDirectory[PE_DATADIR_TLS].vaddr:=tlssymbol.address;
  2448. { sizeof(TlsDirectory) is different on host and target when cross-compiling }
  2449. peoptheader.DataDirectory[PE_DATADIR_TLS].size:=TLSDIR_SIZE;
  2450. if IsSharedLibrary then
  2451. begin
  2452. { Here we should reset __FPC_tls_callbacks value to nil }
  2453. callbackexesymbol:=texesymbol(ExeSymbolList.Find(
  2454. '__FPC_tls_callbacks'));
  2455. if assigned (callbackexesymbol) then
  2456. begin
  2457. //callbacksymbol:=callbackexesymbol.ObjSymbol;
  2458. end;
  2459. end;
  2460. end;
  2461. end;
  2462. begin
  2463. result:=false;
  2464. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  2465. textExeSec:=FindExeSection('.text');
  2466. dataExeSec:=FindExeSection('.data');
  2467. bssExeSec:=FindExeSection('.bss');
  2468. if not assigned(TextExeSec) or
  2469. not assigned(DataExeSec) then
  2470. internalerror(200602231);
  2471. { do we need to write symbols? }
  2472. hassymbols:=(ExeWriteMode=ewm_dbgonly) or
  2473. (
  2474. (ExeWriteMode=ewm_exefull) and
  2475. not(cs_link_strip in current_settings.globalswitches)
  2476. );
  2477. writeDbgStrings:=hassymbols or ((ExeWriteMode=ewm_exeonly) and (cs_link_separate_dbg_file in current_settings.globalswitches));
  2478. { Stub }
  2479. if win32 then
  2480. begin
  2481. FWriter.write(win32stub,sizeof(win32stub));
  2482. FWriter.write(pemagic,sizeof(pemagic));
  2483. end
  2484. else
  2485. FWriter.write(go32v2stub,sizeof(go32v2stub));
  2486. { Initial header, will be updated later }
  2487. fillchar(header,sizeof(header),0);
  2488. header.mach:=COFF_MAGIC;
  2489. header.nsects:=nsects;
  2490. if writeDbgStrings then
  2491. header.sympos:=sympos-datapos_offset;
  2492. if hassymbols then
  2493. header.syms:=nsyms;
  2494. if win32 then
  2495. header.opthdr:=sizeof(tcoffpeoptheader)
  2496. else
  2497. header.opthdr:=sizeof(coffdjoptheader);
  2498. if win32 then
  2499. begin
  2500. header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED;
  2501. if target_info.system in [system_x86_64_win64] then
  2502. header.flag:=header.flag or PE_FILE_LARGE_ADDRESS_AWARE
  2503. else
  2504. header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
  2505. if IsSharedLibrary then
  2506. header.flag:=header.flag or PE_FILE_DLL;
  2507. if FindExeSection('.reloc')=nil then
  2508. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  2509. if (FindExeSection('.stab')=nil) and
  2510. (FindExeSection('.debug_info')=nil) and
  2511. (FindExeSection('.gnu_debuglink')=nil) then
  2512. header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED;
  2513. if not hassymbols then
  2514. header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED;
  2515. if SetPEFlagsSetExplicity then
  2516. header.flag:=header.flag or peflags;
  2517. end
  2518. else
  2519. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
  2520. FWriter.write(header,sizeof(header));
  2521. { Optional COFF Header }
  2522. if win32 then
  2523. begin
  2524. fillchar(peoptheader,sizeof(peoptheader),0);
  2525. peoptheader.magic:=COFF_OPT_MAGIC;
  2526. peoptheader.MajorLinkerVersion:=ord(version_nr)-ord('0');
  2527. peoptheader.MinorLinkerVersion:=(ord(release_nr)-ord('0'))*10 + (ord(patch_nr)-ord('0'));
  2528. peoptheader.tsize:=TextExeSec.Size;
  2529. peoptheader.dsize:=DataExeSec.Size;
  2530. if assigned(BSSExeSec) then
  2531. peoptheader.bsize:=BSSExeSec.Size;
  2532. peoptheader.text_start:=TextExeSec.mempos;
  2533. {$ifndef cpu64bitaddr}
  2534. peoptheader.data_start:=DataExeSec.mempos;
  2535. {$endif cpu64bitaddr}
  2536. peoptheader.entry:=EntrySym.Address;
  2537. peoptheader.ImageBase:=ImageBase;
  2538. peoptheader.SectionAlignment:=SectionMemAlign;
  2539. peoptheader.FileAlignment:=SectionDataAlign;
  2540. if SetPEOSVersionSetExplicitely then
  2541. begin
  2542. peoptheader.MajorOperatingSystemVersion:=peosversionmajor;
  2543. peoptheader.MinorOperatingSystemVersion:=peosversionminor;
  2544. end
  2545. else
  2546. begin
  2547. peoptheader.MajorOperatingSystemVersion:=4;
  2548. peoptheader.MinorOperatingSystemVersion:=0;
  2549. end;
  2550. if SetPEUserVersionSetExplicitely then
  2551. begin
  2552. peoptheader.MajorImageVersion:=peuserversionmajor;
  2553. peoptheader.MinorImageVersion:=peuserversionminor;
  2554. end
  2555. else
  2556. begin
  2557. peoptheader.MajorImageVersion:=dllmajor;
  2558. peoptheader.MinorImageVersion:=dllminor;
  2559. end;
  2560. if SetPESubSysVersionSetExplicitely then
  2561. begin
  2562. peoptheader.MajorSubsystemVersion:=pesubsysversionmajor;
  2563. peoptheader.MinorSubsystemVersion:=pesubsysversionminor;
  2564. end
  2565. else
  2566. begin
  2567. if target_info.system in systems_wince then
  2568. peoptheader.MajorSubsystemVersion:=3
  2569. else
  2570. peoptheader.MajorSubsystemVersion:=4;
  2571. peoptheader.MinorSubsystemVersion:=0;
  2572. end;
  2573. peoptheader.Win32Version:=0;
  2574. peoptheader.SizeOfImage:=Align(CurrMemPos,SectionMemAlign);
  2575. peoptheader.SizeOfHeaders:=textExeSec.DataPos;
  2576. peoptheader.CheckSum:=0;
  2577. if (target_info.system in systems_nativent) and (not IsSharedLibrary or (apptype = app_native)) then
  2578. { Although I did not really test this, it seems that Subsystem is
  2579. not checked in DLLs except for maybe drivers}
  2580. peoptheader.Subsystem:=PE_SUBSYSTEM_NATIVE
  2581. else
  2582. if target_info.system in systems_wince then
  2583. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CE_GUI
  2584. else
  2585. if apptype=app_gui then
  2586. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_GUI
  2587. else
  2588. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CUI;
  2589. if SetPEOptFlagsSetExplicity then
  2590. peoptheader.DllCharacteristics:=peoptflags
  2591. else
  2592. peoptheader.DllCharacteristics:=0;
  2593. peoptheader.SizeOfStackReserve:=stacksize;
  2594. peoptheader.SizeOfStackCommit:=$1000;
  2595. if MinStackSizeSetExplicity then
  2596. peoptheader.SizeOfStackCommit:=minstacksize;
  2597. if MaxStackSizeSetExplicity then
  2598. peoptheader.SizeOfStackReserve:=maxstacksize;
  2599. peoptheader.SizeOfHeapReserve:=$100000;
  2600. peoptheader.SizeOfHeapCommit:=$1000;
  2601. peoptheader.NumberOfRvaAndSizes:=PE_DATADIR_ENTRIES;
  2602. UpdateImports;
  2603. UpdateTlsDataDir;
  2604. UpdateDataDir('.edata',PE_DATADIR_EDATA);
  2605. UpdateDataDir('.rsrc',PE_DATADIR_RSRC);
  2606. UpdateDataDir('.pdata',PE_DATADIR_PDATA);
  2607. UpdateDataDir('.reloc',PE_DATADIR_RELOC);
  2608. FWriter.write(peoptheader,sizeof(peoptheader));
  2609. end
  2610. else
  2611. begin
  2612. fillchar(djoptheader,sizeof(djoptheader),0);
  2613. djoptheader.magic:=COFF_OPT_MAGIC;
  2614. djoptheader.tsize:=TextExeSec.Size;
  2615. djoptheader.dsize:=DataExeSec.Size;
  2616. if assigned(BSSExeSec) then
  2617. djoptheader.bsize:=BSSExeSec.Size;
  2618. djoptheader.text_start:=TextExeSec.mempos;
  2619. djoptheader.data_start:=DataExeSec.mempos;
  2620. djoptheader.entry:=EntrySym.Address;
  2621. FWriter.write(djoptheader,sizeof(djoptheader));
  2622. end;
  2623. { For some unknown reason WM 6.1 requires .idata section to be read only.
  2624. Otherwise it refuses to load DLLs greater than 64KB.
  2625. Earlier versions of WinCE load DLLs regardless of .idata flags. }
  2626. if target_info.system in systems_wince then
  2627. begin
  2628. idataExeSec:=FindExeSection('.idata');
  2629. if idataExeSec<>nil then
  2630. idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write];
  2631. end;
  2632. { Section headers }
  2633. ExeSectionList.ForEachCall(@ExeSectionList_write_header,nil);
  2634. { Section data }
  2635. WriteExeSectionContent;
  2636. { Align after the last section }
  2637. FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
  2638. { Optional Symbols }
  2639. if SymPos<>FWriter.Size then
  2640. internalerror(200602252);
  2641. if hassymbols then
  2642. ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil);
  2643. if writeDbgStrings then
  2644. begin
  2645. { Strings }
  2646. i:=FCoffStrs.size+4;
  2647. FWriter.write(i,4);
  2648. FWriter.writearray(FCoffStrs);
  2649. end;
  2650. { Release }
  2651. FCoffStrs.Free;
  2652. result:=true;
  2653. end;
  2654. function IdataObjSectionCompare(Item1, Item2: Pointer): Integer;
  2655. var
  2656. I1 : TObjSection absolute Item1;
  2657. I2 : TObjSection absolute Item2;
  2658. begin
  2659. Result:=CompareStr(I1.Name,I2.Name);
  2660. end;
  2661. procedure TCoffexeoutput.Order_ObjSectionList(ObjSectionList: TFPObjectList;const aPattern:string);
  2662. begin
  2663. { Sort sections having '$' in the name, that's how PECOFF documentation
  2664. tells to handle them. However, look for '$' in the pattern, not in section
  2665. names, because the latter often get superfluous '$' due to mangling. }
  2666. if Pos('$',aPattern)>0 then
  2667. ObjSectionList.Sort(@IdataObjSectionCompare);
  2668. end;
  2669. constructor TDJCoffexeoutput.create;
  2670. begin
  2671. inherited createcoff(false);
  2672. datapos_offset:=sizeof(go32v2stub);
  2673. CExeSection:=TExeSection;
  2674. CObjData:=TDJCoffObjData;
  2675. end;
  2676. procedure TDJCoffexeoutput.MemPos_Header;
  2677. begin
  2678. { Headers are not loaded, first 4K page is reserved }
  2679. CurrMemPos:=$1000;
  2680. end;
  2681. constructor TPECoffexeoutput.create;
  2682. begin
  2683. inherited createcoff(true);
  2684. CExeSection:=TExeSection;
  2685. CObjData:=TPECoffObjData;
  2686. end;
  2687. procedure TPECoffexeoutput.MarkTargetSpecificSections(WorkList:TFPObjectList);
  2688. var
  2689. exesec:TExeSection;
  2690. objsec,textsec:TObjSection;
  2691. objreloc:TObjRelocation;
  2692. i,j:longint;
  2693. begin
  2694. if target_info.system<>system_x86_64_win64 then
  2695. exit;
  2696. exesec:=FindExeSection('.pdata');
  2697. if exesec=nil then
  2698. exit;
  2699. for i:=0 to exesec.ObjSectionList.Count-1 do
  2700. begin
  2701. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2702. if objsec.Used then
  2703. continue;
  2704. j:=0;
  2705. while j<objsec.ObjRelocations.Count do
  2706. begin
  2707. objreloc:=TObjRelocation(objsec.ObjRelocations[j]);
  2708. if objreloc.symbol=nil then
  2709. InternalError(2013041201);
  2710. textsec:=objreloc.symbol.objsection;
  2711. if textsec.used then
  2712. begin
  2713. WorkList.Add(objsec);
  2714. objsec.used:=true;
  2715. { The exact algorithm for non-smartlinked .pdata sections
  2716. is subject for refinement. Extreme cases are:
  2717. - several disjoint .pdata entries for a function, if function
  2718. is complex or if compiler splits it into chunks,
  2719. - single .pdata section referencing several .text sections,
  2720. may need to remove irrelevant parts like BFD does for
  2721. .eh_frame sections. }
  2722. break;
  2723. end;
  2724. inc(j,3);
  2725. end;
  2726. end;
  2727. end;
  2728. procedure TPECoffexeoutput.AfterUnusedSectionRemoval;
  2729. var
  2730. basedllname : string;
  2731. procedure StartImport(const dllname:string);
  2732. begin
  2733. if assigned(exemap) then
  2734. begin
  2735. exemap.Add('');
  2736. exemap.Add('Importing from DLL '+dllname);
  2737. end;
  2738. basedllname:=ExtractFileName(dllname);
  2739. { idata2 }
  2740. idata2objsection.writereloc_internal(idata4objsection,idata4objsection.size,sizeof(longint),RELOC_RVA);
  2741. idata2objsection.writezeros(2*sizeof(longint));
  2742. idata2objsection.writereloc_internal(idata7objsection,idata7objsection.size,sizeof(longint),RELOC_RVA);
  2743. idata2objsection.writereloc_internal(idata5objsection,idata5objsection.size,sizeof(longint),RELOC_RVA);
  2744. { idata7 }
  2745. idata7objsection.writestr(basedllname);
  2746. end;
  2747. procedure EndImport;
  2748. begin
  2749. { idata4 }
  2750. idata4objsection.writezeros(sizeof(longint));
  2751. if target_info.system=system_x86_64_win64 then
  2752. idata4objsection.writezeros(sizeof(longint));
  2753. { idata5 }
  2754. idata5objsection.writezeros(sizeof(longint));
  2755. if target_info.system=system_x86_64_win64 then
  2756. idata5objsection.writezeros(sizeof(longint));
  2757. end;
  2758. function AddImport(const afuncname,amangledname:string; AOrdNr:longint;isvar:boolean):TObjSymbol;
  2759. const
  2760. {$ifdef arm}
  2761. jmpopcode : array[0..7] of byte = (
  2762. $00,$c0,$9f,$e5, // ldr ip, [pc, #0]
  2763. $00,$f0,$9c,$e5 // ldr pc, [ip]
  2764. );
  2765. {$else arm}
  2766. jmpopcode : array[0..1] of byte = (
  2767. $ff,$25
  2768. );
  2769. {$endif arm}
  2770. nopopcodes : array[0..1] of byte = (
  2771. $90,$90
  2772. );
  2773. var
  2774. ordint: dword;
  2775. procedure WriteTableEntry(objsec:TObjSection);
  2776. begin
  2777. if AOrdNr <= 0 then
  2778. begin
  2779. objsec.writereloc_internal(idata6objsection,idata6objsection.size,sizeof(longint),RELOC_RVA);
  2780. if target_info.system=system_x86_64_win64 then
  2781. objsec.writezeros(sizeof(longint));
  2782. end
  2783. else
  2784. begin
  2785. { import by ordinal }
  2786. ordint:=AOrdNr;
  2787. if target_info.system=system_x86_64_win64 then
  2788. begin
  2789. objsec.write(ordint,sizeof(ordint));
  2790. ordint:=$80000000;
  2791. objsec.write(ordint,sizeof(ordint));
  2792. end
  2793. else
  2794. begin
  2795. ordint:=ordint or $80000000;
  2796. objsec.write(ordint,sizeof(ordint));
  2797. end;
  2798. end;
  2799. end;
  2800. begin
  2801. result:=nil;
  2802. if assigned(exemap) then
  2803. begin
  2804. if AOrdNr <= 0 then
  2805. exemap.Add(' Importing Function '+afuncname)
  2806. else
  2807. exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
  2808. end;
  2809. { idata4, import lookup table }
  2810. WriteTableEntry(idata4objsection);
  2811. { idata5, import address table }
  2812. internalobjdata.SetSection(idata5objsection);
  2813. if isvar then
  2814. result:=internalobjdata.SymbolDefine(amangledname,AB_GLOBAL,AT_DATA)
  2815. else
  2816. begin
  2817. internalobjdata.SetSection(textobjsection);
  2818. textobjsection.writezeros(align_aword(textobjsection.size,16)-textobjsection.size);
  2819. result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
  2820. textobjsection.write(jmpopcode,sizeof(jmpopcode));
  2821. {$ifdef x86_64}
  2822. textobjsection.writereloc_internal(idata5objsection,idata5objsection.size,4,RELOC_RELATIVE);
  2823. {$else}
  2824. textobjsection.writereloc_internal(idata5objsection,idata5objsection.size,4,RELOC_ABSOLUTE32);
  2825. {$endif x86_64}
  2826. textobjsection.write(nopopcodes,align(textobjsection.size,qword(sizeof(nopopcodes)))-textobjsection.size);
  2827. end;
  2828. { idata5 section data }
  2829. WriteTableEntry(idata5objsection);
  2830. if (AOrdNr<=0) then
  2831. begin
  2832. { index hint, function name, null terminator and align }
  2833. ordint:=abs(AOrdNr);
  2834. idata6objsection.write(ordint,2);
  2835. idata6objsection.writestr(afuncname);
  2836. idata6objsection.writezeros(align(idata6objsection.size,2)-idata6objsection.size);
  2837. end;
  2838. end;
  2839. var
  2840. i,j : longint;
  2841. ImportLibrary : TImportLibrary;
  2842. ImportSymbol : TImportSymbol;
  2843. exesym : TExeSymbol;
  2844. newdll : boolean;
  2845. begin
  2846. for i:=0 to FImports.Count-1 do
  2847. begin
  2848. ImportLibrary:=TImportLibrary(FImports[i]);
  2849. newdll:=False;
  2850. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  2851. begin
  2852. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  2853. exesym:=ImportSymbol.CachedExeSymbol;
  2854. if assigned(exesym) and
  2855. exesym.Used then
  2856. begin
  2857. if (not newdll) then
  2858. StartImport(ImportLibrary.Name);
  2859. newdll:=True;
  2860. exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
  2861. end;
  2862. end;
  2863. if newdll then
  2864. EndImport;
  2865. end;
  2866. FixupSymbols;
  2867. end;
  2868. procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2869. var
  2870. i,j: longint;
  2871. ImportLibrary: TImportLibrary;
  2872. ImportSymbol: TImportSymbol;
  2873. exesym: TExeSymbol;
  2874. begin
  2875. { Here map import symbols to exe symbols and create necessary sections.
  2876. Actual import generation is done after unused sections (and symbols) are removed. }
  2877. FImports:=ImportLibraryList;
  2878. textobjsection:=internalObjData.CreateSection(sec_code);
  2879. textobjsection.SecOptions:=[oso_keep];
  2880. idata2objsection:=internalObjData.CreateSection(sec_idata2);
  2881. idata2objsection.SecOptions:=[oso_keep];
  2882. idata4objsection:=internalObjData.CreateSection(sec_idata4);
  2883. idata4objsection.SecOptions:=[oso_keep];
  2884. idata5objsection:=internalObjData.CreateSection(sec_idata5);
  2885. idata5objsection.SecOptions:=[oso_keep];
  2886. idata6objsection:=internalObjData.CreateSection(sec_idata6);
  2887. idata6objsection.SecOptions:=[oso_keep];
  2888. idata7objsection:=internalObjData.CreateSection(sec_idata7);
  2889. idata7objsection.SecOptions:=[oso_keep];
  2890. for i:=0 to ImportLibraryList.Count-1 do
  2891. begin
  2892. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  2893. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  2894. begin
  2895. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  2896. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  2897. if assigned(exesym) and
  2898. (exesym.State<>symstate_defined) then
  2899. begin
  2900. ImportSymbol.CachedExeSymbol:=exesym;
  2901. exesym.State:=symstate_defined;
  2902. end;
  2903. end;
  2904. end;
  2905. PackUnresolvedExeSymbols('after DLL imports');
  2906. end;
  2907. procedure TPECoffexeoutput.GenerateRelocs;
  2908. var
  2909. pgaddr, hdrpos : longword;
  2910. procedure FinishBlock;
  2911. var
  2912. p,len : longint;
  2913. begin
  2914. if hdrpos = longword(-1) then
  2915. exit;
  2916. p:=0;
  2917. internalobjdata.writebytes(p,align(internalobjdata.CurrObjSec.size,4)-internalobjdata.CurrObjSec.size);
  2918. p:=internalObjData.CurrObjSec.Data.Pos;
  2919. internalObjData.CurrObjSec.Data.seek(hdrpos+4);
  2920. len:=p-hdrpos;
  2921. internalObjData.CurrObjSec.Data.write(len,4);
  2922. internalObjData.CurrObjSec.Data.seek(p);
  2923. hdrpos:=longword(-1);
  2924. end;
  2925. var
  2926. exesec : TExeSection;
  2927. objsec : TObjSection;
  2928. objreloc : TObjRelocation;
  2929. i,j,k : longint;
  2930. offset : longword;
  2931. w: word;
  2932. begin
  2933. if not RelocSection or FRelocsGenerated then
  2934. exit;
  2935. exesec:=FindExeSection('.reloc');
  2936. if exesec=nil then
  2937. exit;
  2938. objsec:=internalObjData.createsection('.reloc',0,[oso_data,oso_keep]);
  2939. exesec.AddObjSection(objsec);
  2940. pgaddr:=longword(-1);
  2941. hdrpos:=longword(-1);
  2942. for i:=0 to ExeSectionList.Count-1 do
  2943. begin
  2944. exesec:=TExeSection(ExeSectionList[i]);
  2945. for j:=0 to exesec.ObjSectionList.count-1 do
  2946. begin
  2947. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2948. { create relocs only for sections which are loaded in memory }
  2949. if not (oso_load in objsec.SecOptions) then
  2950. continue;
  2951. for k:=0 to objsec.ObjRelocations.Count-1 do
  2952. begin
  2953. objreloc:=TObjRelocation(objsec.ObjRelocations[k]);
  2954. if not (objreloc.typ in [{$ifdef cpu64bitaddr}RELOC_ABSOLUTE32,{$endif cpu64bitaddr}RELOC_ABSOLUTE]) then
  2955. continue;
  2956. offset:=objsec.MemPos+objreloc.dataoffset;
  2957. if (offset<pgaddr) and (pgaddr<>longword(-1)) then
  2958. Internalerror(2007062701);
  2959. if (offset-pgaddr>=4096) or (pgaddr=longword(-1)) then
  2960. begin
  2961. FinishBlock;
  2962. pgaddr:=(offset div 4096)*4096;
  2963. hdrpos:=internalObjData.CurrObjSec.Data.Pos;
  2964. internalObjData.writebytes(pgaddr,4);
  2965. { Reserving space for block size. The size will be written later in FinishBlock }
  2966. internalObjData.writebytes(k,4);
  2967. end;
  2968. {$ifdef cpu64bitaddr}
  2969. if objreloc.typ = RELOC_ABSOLUTE then
  2970. w:=IMAGE_REL_BASED_DIR64
  2971. else
  2972. {$endif cpu64bitaddr}
  2973. w:=IMAGE_REL_BASED_HIGHLOW;
  2974. w:=(w shl 12) or (offset-pgaddr);
  2975. internalObjData.writebytes(w,2);
  2976. end;
  2977. end;
  2978. end;
  2979. FinishBlock;
  2980. FRelocsGenerated:=true;
  2981. end;
  2982. procedure TPECoffexeoutput.MemPos_Start;
  2983. var
  2984. exesec : TExeSection;
  2985. begin
  2986. if RelocSection then
  2987. begin
  2988. exesec:=FindExeSection('.reloc');
  2989. if exesec=nil then
  2990. InternalError(2012072401);
  2991. exesec.Disabled:=false;
  2992. end;
  2993. inherited;
  2994. end;
  2995. procedure TPECoffexeoutput.MemPos_ExeSection(const aname:string);
  2996. begin
  2997. if aname='.reloc' then
  2998. GenerateRelocs;
  2999. inherited;
  3000. end;
  3001. {****************************************************************************
  3002. TDJCoffAssembler
  3003. ****************************************************************************}
  3004. constructor TDJCoffAssembler.Create(info: pasminfo; smart:boolean);
  3005. begin
  3006. inherited;
  3007. CObjOutput:=TDJCoffObjOutput;
  3008. CInternalAr:=tarobjectwriter;
  3009. end;
  3010. {****************************************************************************
  3011. TPECoffAssembler
  3012. ****************************************************************************}
  3013. constructor TPECoffAssembler.Create(info: pasminfo; smart:boolean);
  3014. begin
  3015. inherited;
  3016. CObjOutput:=TPECoffObjOutput;
  3017. CInternalAr:=tarobjectwriter;
  3018. end;
  3019. {*****************************************************************************
  3020. DLLReader
  3021. *****************************************************************************}
  3022. {$ifdef win32}
  3023. var
  3024. Wow64DisableWow64FsRedirection : function (var OldValue : pointer) : boolean;stdcall;
  3025. Wow64RevertWow64FsRedirection : function (OldValue : pointer) : boolean;stdcall;
  3026. {$endif win32}
  3027. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  3028. type
  3029. TPECoffExpDir=packed record
  3030. flag,
  3031. stamp : cardinal;
  3032. Major,
  3033. Minor : word;
  3034. Name,
  3035. Base,
  3036. NumFuncs,
  3037. NumNames,
  3038. AddrFuncs,
  3039. AddrNames,
  3040. AddrOrds : cardinal;
  3041. end;
  3042. var
  3043. DLLReader : TObjectReader;
  3044. DosHeader : array[0..$7f] of byte;
  3045. PEMagic : array[0..3] of byte;
  3046. Header : TCoffHeader;
  3047. peheader : tcoffpeoptheader;
  3048. NameOfs,
  3049. newheaderofs : longword;
  3050. FuncName : string;
  3051. expdir : TPECoffExpDir;
  3052. i : longint;
  3053. found : boolean;
  3054. sechdr : tCoffSecHdr;
  3055. {$ifdef win32}
  3056. p : pointer;
  3057. {$endif win32}
  3058. begin
  3059. result:=false;
  3060. fillchar(sechdr,sizeof(sechdr),0);
  3061. {$ifdef win32}
  3062. if (target_info.system=system_x86_64_win64) and
  3063. assigned(Wow64DisableWow64FsRedirection) then
  3064. Wow64DisableWow64FsRedirection(p);
  3065. {$endif win32}
  3066. DLLReader:=TObjectReader.Create;
  3067. DLLReader.OpenFile(dllname);
  3068. {$ifdef win32}
  3069. if (target_info.system=system_x86_64_win64) and
  3070. assigned(Wow64RevertWow64FsRedirection) then
  3071. Wow64RevertWow64FsRedirection(p);
  3072. {$endif win32}
  3073. if not DLLReader.Read(DosHeader,sizeof(DosHeader)) or
  3074. (DosHeader[0]<>$4d) or (DosHeader[1]<>$5a) then
  3075. begin
  3076. Comment(V_Error,'Invalid DLL '+dllname+', Dos Header invalid');
  3077. exit;
  3078. end;
  3079. newheaderofs:=cardinal(DosHeader[$3c]) or (DosHeader[$3d] shl 8) or (DosHeader[$3e] shl 16) or (DosHeader[$3f] shl 24);
  3080. DLLReader.Seek(newheaderofs);
  3081. if not DLLReader.Read(PEMagic,sizeof(PEMagic)) or
  3082. (PEMagic[0]<>$50) or (PEMagic[1]<>$45) or (PEMagic[2]<>$00) or (PEMagic[3]<>$00) then
  3083. begin
  3084. Comment(V_Error,'Invalid DLL '+dllname+': invalid magic code');
  3085. exit;
  3086. end;
  3087. if not DLLReader.Read(Header,sizeof(TCoffHeader)) or
  3088. (Header.mach<>COFF_MAGIC) or
  3089. (Header.opthdr<>sizeof(tcoffpeoptheader)) then
  3090. begin
  3091. Comment(V_Error,'Invalid DLL '+dllname+', invalid header size');
  3092. exit;
  3093. end;
  3094. { Read optheader }
  3095. DLLreader.Read(peheader,sizeof(tcoffpeoptheader));
  3096. { Section headers }
  3097. found:=false;
  3098. for i:=1 to header.nsects do
  3099. begin
  3100. if not DLLreader.read(sechdr,sizeof(sechdr)) then
  3101. begin
  3102. Comment(V_Error,'Error reading coff file '+DLLName);
  3103. exit;
  3104. end;
  3105. if (sechdr.rvaofs<=peheader.DataDirectory[PE_DATADIR_EDATA].vaddr) and
  3106. (peheader.DataDirectory[PE_DATADIR_EDATA].vaddr<sechdr.rvaofs+sechdr.vsize) then
  3107. begin
  3108. found:=true;
  3109. break;
  3110. end;
  3111. end;
  3112. if not found then
  3113. begin
  3114. Comment(V_Warning,'DLL '+DLLName+' does not contain any exports');
  3115. exit;
  3116. end;
  3117. { Process edata }
  3118. DLLReader.Seek(sechdr.datapos+peheader.DataDirectory[PE_DATADIR_EDATA].vaddr-sechdr.rvaofs);
  3119. DLLReader.Read(expdir,sizeof(expdir));
  3120. for i:=0 to expdir.NumNames-1 do
  3121. begin
  3122. DLLReader.Seek(sechdr.datapos+expdir.AddrNames-sechdr.rvaofs+i*4);
  3123. DLLReader.Read(NameOfs,4);
  3124. Dec(NameOfs,sechdr.rvaofs);
  3125. if {(NameOfs<0) or}
  3126. (NameOfs>sechdr.vsize) then
  3127. begin
  3128. Comment(V_Error,'DLL does contains invalid exports');
  3129. break;
  3130. end;
  3131. { Read Function name from DLL, prepend _ and terminate with #0 }
  3132. DLLReader.Seek(sechdr.datapos+NameOfs);
  3133. DLLReader.Read((@FuncName[1])^,sizeof(FuncName)-3);
  3134. FuncName[sizeof(FuncName)-1]:=#0;
  3135. FuncName[0]:=chr(Strlen(@FuncName[1]));
  3136. readdllproc(DLLName,FuncName);
  3137. end;
  3138. DLLReader.Free;
  3139. end;
  3140. {$ifdef arm}
  3141. function COFF_MAGIC: word;
  3142. begin
  3143. if GenerateThumb2Code and (current_settings.cputype>=cpu_armv7) then
  3144. COFF_MAGIC:=$1c4 // IMAGE_FILE_MACHINE_ARMNT
  3145. else
  3146. COFF_MAGIC:=$1c0; // IMAGE_FILE_MACHINE_ARM
  3147. end;
  3148. {$endif arm}
  3149. {*****************************************************************************
  3150. Initialize
  3151. *****************************************************************************}
  3152. {$ifdef i386}
  3153. const
  3154. as_i386_coff_info : tasminfo =
  3155. (
  3156. id : as_i386_coff;
  3157. idtxt : 'COFF';
  3158. asmbin : '';
  3159. asmcmd : '';
  3160. supported_targets : [system_i386_go32v2];
  3161. flags : [af_outputbinary,af_smartlink_sections];
  3162. labelprefix : '.L';
  3163. comment : '';
  3164. dollarsign: '$';
  3165. );
  3166. as_i386_pecoff_info : tasminfo =
  3167. (
  3168. id : as_i386_pecoff;
  3169. idtxt : 'PECOFF';
  3170. asmbin : '';
  3171. asmcmd : '';
  3172. supported_targets : [system_i386_win32,system_i386_nativent];
  3173. flags : [af_outputbinary,af_smartlink_sections];
  3174. labelprefix : '.L';
  3175. comment : '';
  3176. dollarsign: '$';
  3177. );
  3178. as_i386_pecoffwdosx_info : tasminfo =
  3179. (
  3180. id : as_i386_pecoffwdosx;
  3181. idtxt : 'PEWDOSX';
  3182. asmbin : '';
  3183. asmcmd : '';
  3184. supported_targets : [system_i386_wdosx];
  3185. flags : [af_outputbinary];
  3186. labelprefix : '.L';
  3187. comment : '';
  3188. dollarsign: '$';
  3189. );
  3190. as_i386_pecoffwince_info : tasminfo =
  3191. (
  3192. id : as_i386_pecoffwince;
  3193. idtxt : 'PECOFFWINCE';
  3194. asmbin : '';
  3195. asmcmd : '';
  3196. supported_targets : [system_i386_wince];
  3197. flags : [af_outputbinary,af_smartlink_sections];
  3198. labelprefix : '.L';
  3199. comment : '';
  3200. dollarsign: '$';
  3201. );
  3202. {$endif i386}
  3203. {$ifdef x86_64}
  3204. const
  3205. as_x86_64_pecoff_info : tasminfo =
  3206. (
  3207. id : as_x86_64_pecoff;
  3208. idtxt : 'PECOFF';
  3209. asmbin : '';
  3210. asmcmd : '';
  3211. supported_targets : [system_x86_64_win64];
  3212. flags : [af_outputbinary,af_smartlink_sections];
  3213. labelprefix : '.L';
  3214. comment : '';
  3215. dollarsign: '$';
  3216. );
  3217. {$endif x86_64}
  3218. {$ifdef arm}
  3219. const
  3220. as_arm_pecoffwince_info : tasminfo =
  3221. (
  3222. id : as_arm_pecoffwince;
  3223. idtxt : 'PECOFFWINCE';
  3224. asmbin : '';
  3225. asmcmd : '';
  3226. supported_targets : [system_arm_wince];
  3227. flags : [af_outputbinary,af_smartlink_sections];
  3228. labelprefix : '.L';
  3229. comment : '';
  3230. dollarsign: '$';
  3231. );
  3232. {$endif arm}
  3233. {$ifdef win32}
  3234. procedure SetupProcVars;
  3235. var
  3236. hinstLib : THandle;
  3237. begin
  3238. Wow64DisableWow64FsRedirection:=nil;
  3239. Wow64RevertWow64FsRedirection:=nil;
  3240. hinstLib:=LoadLibrary('kernel32.dll');
  3241. if hinstLib<>0 then
  3242. begin
  3243. pointer(Wow64DisableWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64DisableWow64FsRedirection');
  3244. pointer(Wow64RevertWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64RevertWow64FsRedirection');
  3245. FreeLibrary(hinstLib);
  3246. end;
  3247. end;
  3248. {$endif win32}
  3249. initialization
  3250. {$ifdef i386}
  3251. RegisterAssembler(as_i386_coff_info,TDJCoffAssembler);
  3252. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  3253. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  3254. RegisterAssembler(as_i386_pecoffwince_info,TPECoffAssembler);
  3255. {$endif i386}
  3256. {$ifdef x86_64}
  3257. RegisterAssembler(as_x86_64_pecoff_info,TPECoffAssembler);
  3258. {$endif x86_64}
  3259. {$ifdef arm}
  3260. RegisterAssembler(as_arm_pecoffwince_info,TPECoffAssembler);
  3261. {$endif arm}
  3262. {$ifdef win32}
  3263. SetupProcVars;
  3264. {$endif win32}
  3265. end.