ogcoff.pas 106 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965
  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. cpuinfo,cpubase,aasmbase,assemble,link,
  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. tcoffpeoptheader = packed record
  47. Magic : word;
  48. MajorLinkerVersion : byte;
  49. MinorLinkerVersion : byte;
  50. tsize : longword;
  51. dsize : longword;
  52. bsize : longword;
  53. entry : longword;
  54. text_start : longword;
  55. {$ifndef cpu64bitaddr}
  56. data_start : longword;
  57. {$endif cpu64bitaddr}
  58. ImageBase : aword;
  59. SectionAlignment : longword;
  60. FileAlignment : longword;
  61. MajorOperatingSystemVersion : word;
  62. MinorOperatingSystemVersion : word;
  63. MajorImageVersion : word;
  64. MinorImageVersion : word;
  65. MajorSubsystemVersion : word;
  66. MinorSubsystemVersion : word;
  67. Win32Version : longword;
  68. SizeOfImage : longword;
  69. SizeOfHeaders : longword;
  70. CheckSum : longword;
  71. Subsystem : word;
  72. DllCharacteristics : word;
  73. SizeOfStackReserve : aword;
  74. SizeOfStackCommit : aword;
  75. SizeOfHeapReserve : aword;
  76. SizeOfHeapCommit : aword;
  77. LoaderFlags : longword; { This field is obsolete }
  78. NumberOfRvaAndSizes : longword;
  79. DataDirectory : array[0..PE_DATADIR_ENTRIES-1] of tcoffpedatadir;
  80. end;
  81. tcoffsechdr = packed record
  82. name : array[0..7] of char;
  83. vsize : longword;
  84. rvaofs : longword;
  85. datasize : longword;
  86. datapos : longword;
  87. relocpos : longword;
  88. lineno1 : longword;
  89. nrelocs : word;
  90. lineno2 : word;
  91. flags : longword;
  92. end;
  93. TCoffObjSection = class(TObjSection)
  94. private
  95. orgmempos,
  96. coffrelocs,
  97. coffrelocpos : aword;
  98. public
  99. secidx : longword;
  100. flags : longword;
  101. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  102. procedure addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
  103. procedure fixuprelocs;override;
  104. end;
  105. TDJCoffObjSection = class(TCoffObjSection)
  106. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  107. end;
  108. TPECoffObjSection = class(TCoffObjSection)
  109. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  110. end;
  111. TCoffObjData = class(TObjData)
  112. private
  113. win32 : boolean;
  114. {$ifdef arm}
  115. eVCobj : boolean;
  116. {$endif arm}
  117. public
  118. constructor createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  119. destructor destroy;override;
  120. procedure CreateDebugSections;override;
  121. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  122. procedure writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);override;
  123. procedure afteralloc;override;
  124. end;
  125. TDJCoffObjData = class(TCoffObjData)
  126. constructor create(const n:string);override;
  127. end;
  128. TPECoffObjData = class(TCoffObjData)
  129. constructor create(const n:string);override;
  130. end;
  131. TCoffObjOutput = class(tObjOutput)
  132. private
  133. win32 : boolean;
  134. symidx : longint;
  135. FCoffSyms,
  136. FCoffStrs : tdynamicarray;
  137. procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  138. procedure section_write_symbol(p:TObject;arg:pointer);
  139. procedure section_write_relocs(p:TObject;arg:pointer);
  140. procedure create_symbols(data:TObjData);
  141. procedure section_set_datapos(p:TObject;arg:pointer);
  142. procedure section_set_reloc_datapos(p:TObject;arg:pointer);
  143. procedure section_write_header(p:TObject;arg:pointer);
  144. procedure section_write_data(p:TObject;arg:pointer);
  145. protected
  146. function writedata(data:TObjData):boolean;override;
  147. public
  148. constructor createcoff(AWriter:TObjectWriter;awin32:boolean);
  149. destructor destroy;override;
  150. end;
  151. TDJCoffObjOutput = class(TCoffObjOutput)
  152. constructor create(AWriter:TObjectWriter);override;
  153. end;
  154. TPECoffObjOutput = class(TCoffObjOutput)
  155. constructor create(AWriter:TObjectWriter);override;
  156. end;
  157. TCoffObjInput = class(tObjInput)
  158. private
  159. FCoffsyms,
  160. FCoffStrs : tdynamicarray;
  161. { Convert symidx -> TObjSymbol }
  162. FSymTbl : ^TObjSymbolArray;
  163. { Convert secidx -> TObjSection }
  164. FSecCount : smallint;
  165. FSecTbl : ^TObjSectionArray;
  166. win32 : boolean;
  167. function GetSection(secidx:longint):TObjSection;
  168. function Read_str(strpos:longword):string;
  169. procedure read_relocs(s:TCoffObjSection);
  170. procedure read_symbols(objdata:TObjData);
  171. procedure ObjSections_read_data(p:TObject;arg:pointer);
  172. procedure ObjSections_read_relocs(p:TObject;arg:pointer);
  173. public
  174. constructor createcoff(awin32:boolean);
  175. destructor destroy;override;
  176. function ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;override;
  177. end;
  178. TDJCoffObjInput = class(TCoffObjInput)
  179. constructor create;override;
  180. end;
  181. TPECoffObjInput = class(TCoffObjInput)
  182. constructor create;override;
  183. end;
  184. TCoffExeSection = class(TExeSection)
  185. private
  186. win32 : boolean;
  187. public
  188. constructor createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
  189. end;
  190. TDJCoffExeSection = class(TCoffExeSection)
  191. constructor create(AList:TFPHashObjectList;const n:string);override;
  192. end;
  193. TPECoffExeSection = class(TCoffExeSection)
  194. constructor create(AList:TFPHashObjectList;const n:string);override;
  195. end;
  196. TCoffexeoutput = class(texeoutput)
  197. private
  198. FCoffsyms,
  199. FCoffStrs : tdynamicarray;
  200. win32 : boolean;
  201. nsects : word;
  202. nsyms,
  203. sympos : aword;
  204. function totalheadersize:longword;
  205. procedure ExeSectionList_pass2_header(p:TObject;arg:pointer);
  206. procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  207. procedure globalsyms_write_symbol(p:TObject;arg:pointer);
  208. procedure ExeSectionList_write_header(p:TObject;arg:pointer);
  209. procedure ExeSectionList_write_data(p:TObject;arg:pointer);
  210. protected
  211. function writedata:boolean;override;
  212. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList);override;
  213. public
  214. constructor createcoff(awin32:boolean);
  215. procedure MemPos_Header;override;
  216. procedure DataPos_Header;override;
  217. procedure DataPos_Symbols;override;
  218. end;
  219. TDJCoffexeoutput = class(TCoffexeoutput)
  220. constructor create;override;
  221. end;
  222. TPECoffexeoutput = class(TCoffexeoutput)
  223. private
  224. idatalabnr : longword;
  225. FRelocsGenerated : boolean;
  226. procedure GenerateRelocs;
  227. public
  228. constructor create;override;
  229. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  230. procedure Order_End;override;
  231. procedure MemPos_ExeSection(const aname:string);override;
  232. end;
  233. TObjSymbolrec = record
  234. sym : TObjSymbol;
  235. orgsize : aword;
  236. end;
  237. TObjSymbolArray = array[0..high(word)] of TObjSymbolrec;
  238. TObjSectionArray = array[0..high(smallint)] of TObjSection;
  239. TDJCoffAssembler = class(tinternalassembler)
  240. constructor create(smart:boolean);override;
  241. end;
  242. TPECoffassembler = class(tinternalassembler)
  243. constructor create(smart:boolean);override;
  244. end;
  245. type
  246. Treaddllproc = procedure(const dllname,funcname:string) of object;
  247. const
  248. {$ifdef i386}
  249. COFF_MAGIC = $14c;
  250. COFF_OPT_MAGIC = $10b;
  251. {$endif i386}
  252. {$ifdef arm}
  253. COFF_MAGIC = $1c0;
  254. COFF_OPT_MAGIC = $10b;
  255. {$endif arm}
  256. {$ifdef x86_64}
  257. COFF_MAGIC = $8664;
  258. COFF_OPT_MAGIC = $20b;
  259. {$endif x86_64}
  260. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  261. implementation
  262. uses
  263. {$ifdef win32}
  264. Windows,
  265. {$endif win32}
  266. SysUtils,
  267. cutils,verbose,globals,
  268. fmodule,aasmtai,aasmdata,
  269. ogmap,
  270. version
  271. ;
  272. const
  273. COFF_FLAG_NORELOCS = $0001;
  274. COFF_FLAG_EXE = $0002;
  275. COFF_FLAG_NOLINES = $0004;
  276. COFF_FLAG_NOLSYMS = $0008;
  277. COFF_FLAG_AR16WR = $0080; { 16bit little endian }
  278. COFF_FLAG_AR32WR = $0100; { 32bit little endian }
  279. COFF_FLAG_AR32W = $0200; { 32bit big endian }
  280. COFF_FLAG_DLL = $2000;
  281. COFF_SYM_GLOBAL = 2;
  282. COFF_SYM_LOCAL = 3;
  283. COFF_SYM_LABEL = 6;
  284. COFF_SYM_FUNCTION = 101;
  285. COFF_SYM_FILE = 103;
  286. COFF_SYM_SECTION = 104;
  287. COFF_STYP_REG = $0000; { "regular": allocated, relocated, loaded }
  288. COFF_STYP_DSECT = $0001; { "dummy": relocated only }
  289. COFF_STYP_NOLOAD = $0002; { "noload": allocated, relocated, not loaded }
  290. COFF_STYP_GROUP = $0004; { "grouped": formed of input sections }
  291. COFF_STYP_PAD = $0008;
  292. COFF_STYP_COPY = $0010;
  293. COFF_STYP_TEXT = $0020;
  294. COFF_STYP_DATA = $0040;
  295. COFF_STYP_BSS = $0080;
  296. PE_SUBSYSTEM_WINDOWS_GUI = 2;
  297. PE_SUBSYSTEM_WINDOWS_CUI = 3;
  298. PE_SUBSYSTEM_WINDOWS_CE_GUI = 9;
  299. PE_FILE_RELOCS_STRIPPED = $0001;
  300. PE_FILE_EXECUTABLE_IMAGE = $0002;
  301. PE_FILE_LINE_NUMS_STRIPPED = $0004;
  302. PE_FILE_LOCAL_SYMS_STRIPPED = $0008;
  303. PE_FILE_AGGRESSIVE_WS_TRIM = $0010;
  304. PE_FILE_LARGE_ADDRESS_AWARE = $0020;
  305. PE_FILE_16BIT_MACHINE = $0040;
  306. PE_FILE_BYTES_REVERSED_LO = $0080;
  307. PE_FILE_32BIT_MACHINE = $0100;
  308. PE_FILE_DEBUG_STRIPPED = $0200;
  309. PE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
  310. PE_FILE_NET_RUN_FROM_SWAP = $0800;
  311. PE_FILE_SYSTEM = $1000;
  312. PE_FILE_DLL = $2000;
  313. PE_FILE_UP_SYSTEM_ONLY = $4000;
  314. PE_FILE_BYTES_REVERSED_HI = $8000;
  315. PE_SCN_CNT_CODE = $00000020; { Section contains code. }
  316. PE_SCN_CNT_INITIALIZED_DATA = $00000040; { Section contains initialized data. }
  317. PE_SCN_CNT_UNINITIALIZED_DATA = $00000080; { Section contains uninitialized data. }
  318. PE_SCN_LNK_OTHER = $00000100; { Reserved. }
  319. PE_SCN_LNK_INFO = $00000200; { Section contains comments or some other type of information. }
  320. PE_SCN_LNK_REMOVE = $00000800; { Section contents will not become part of image. }
  321. PE_SCN_LNK_COMDAT = $00001000; { Section contents comdat. }
  322. PE_SCN_MEM_FARDATA = $00008000;
  323. PE_SCN_MEM_PURGEABLE = $00020000;
  324. PE_SCN_MEM_16BIT = $00020000;
  325. PE_SCN_MEM_LOCKED = $00040000;
  326. PE_SCN_MEM_PRELOAD = $00080000;
  327. PE_SCN_ALIGN_MASK = $00f00000;
  328. PE_SCN_ALIGN_1BYTES = $00100000;
  329. PE_SCN_ALIGN_2BYTES = $00200000;
  330. PE_SCN_ALIGN_4BYTES = $00300000;
  331. PE_SCN_ALIGN_8BYTES = $00400000;
  332. PE_SCN_ALIGN_16BYTES = $00500000; { Default alignment if no others are specified. }
  333. PE_SCN_ALIGN_32BYTES = $00600000;
  334. PE_SCN_ALIGN_64BYTES = $00700000;
  335. PE_SCN_LNK_NRELOC_OVFL = $01000000; { Section contains extended relocations. }
  336. PE_SCN_MEM_NOT_CACHED = $04000000; { Section is not cachable. }
  337. PE_SCN_MEM_NOT_PAGED = $08000000; { Section is not pageable. }
  338. PE_SCN_MEM_SHARED = $10000000; { Section is shareable. }
  339. PE_SCN_MEM_DISCARDABLE = $02000000;
  340. PE_SCN_MEM_EXECUTE = $20000000;
  341. PE_SCN_MEM_READ = $40000000;
  342. PE_SCN_MEM_WRITE = $80000000;
  343. PE_DATADIR_EDATA = 0;
  344. PE_DATADIR_IDATA = 1;
  345. PE_DATADIR_RSRC = 2;
  346. PE_DATADIR_PDATA = 3;
  347. PE_DATADIR_SECURITY = 4;
  348. PE_DATADIR_RELOC = 5;
  349. PE_DATADIR_DEBUG = 6;
  350. PE_DATADIR_DESCRIPTION = 7;
  351. PE_DATADIR_SPECIAL = 8;
  352. PE_DATADIR_TLS = 9;
  353. PE_DATADIR_LOADCFG = 10;
  354. PE_DATADIR_BOUNDIMPORT = 11;
  355. PE_DATADIR_IMPORTADDRESSTABLE = 12;
  356. PE_DATADIR_DELAYIMPORT = 13;
  357. {$ifdef x86_64}
  358. IMAGE_REL_AMD64_ABSOLUTE = $0000; { Reference is absolute, no relocation is necessary }
  359. IMAGE_REL_AMD64_ADDR64 = $0001; { 64-bit address (VA). }
  360. IMAGE_REL_AMD64_ADDR32 = $0002; { 32-bit address (VA). }
  361. IMAGE_REL_AMD64_ADDR32NB = $0003; { 32-bit address w/o image base (RVA). }
  362. IMAGE_REL_AMD64_REL32 = $0004; { 32-bit relative address from byte following reloc }
  363. IMAGE_REL_AMD64_REL32_1 = $0005; { 32-bit relative address from byte distance 1 from reloc }
  364. IMAGE_REL_AMD64_REL32_2 = $0006; { 32-bit relative address from byte distance 2 from reloc }
  365. IMAGE_REL_AMD64_REL32_3 = $0007; { 32-bit relative address from byte distance 3 from reloc }
  366. IMAGE_REL_AMD64_REL32_4 = $0008; { 32-bit relative address from byte distance 4 from reloc }
  367. IMAGE_REL_AMD64_REL32_5 = $0009; { 32-bit relative address from byte distance 5 from reloc }
  368. IMAGE_REL_AMD64_SECTION = $000A; { Section index }
  369. IMAGE_REL_AMD64_SECREL = $000B; { 32 bit offset from base of section containing target }
  370. IMAGE_REL_AMD64_SECREL7 = $000C; { 7 bit unsigned offset from base of section containing target }
  371. IMAGE_REL_AMD64_TOKEN = $000D; { 32 bit metadata token }
  372. IMAGE_REL_AMD64_SREL32 = $000E; { 32 bit signed span-dependent value emitted into object }
  373. IMAGE_REL_AMD64_PAIR = $000F;
  374. IMAGE_REL_AMD64_SSPAN32 = $0010; { 32 bit signed span-dependent value applied at link time }
  375. {$endif x86_64}
  376. {$ifdef arm}
  377. IMAGE_REL_ARM_ABSOLUTE = $0000; { No relocation required }
  378. IMAGE_REL_ARM_ADDR32 = $0001; { 32 bit address }
  379. IMAGE_REL_ARM_ADDR32NB = $0002; { 32 bit address w/o image base }
  380. IMAGE_REL_ARM_BRANCH24 = $0003; { 24 bit offset << 2 & sign ext. }
  381. IMAGE_REL_ARM_BRANCH11 = $0004; { Thumb: 2 11 bit offsets }
  382. IMAGE_REL_ARM_TOKEN = $0005; { clr token }
  383. IMAGE_REL_ARM_GPREL12 = $0006; { GP-relative addressing (ARM) }
  384. IMAGE_REL_ARM_GPREL7 = $0007; { GP-relative addressing (Thumb) }
  385. IMAGE_REL_ARM_BLX24 = $0008;
  386. IMAGE_REL_ARM_BLX11 = $0009;
  387. IMAGE_REL_ARM_SECTION = $000E; { Section table index }
  388. IMAGE_REL_ARM_SECREL = $000F; { Offset within section }
  389. {$endif arm}
  390. {$ifdef i386}
  391. IMAGE_REL_I386_DIR32 = 6;
  392. IMAGE_REL_I386_IMAGEBASE = 7;
  393. IMAGE_REL_I386_SECREL32 = 11;
  394. IMAGE_REL_I386_PCRLONG = 20;
  395. {$endif i386}
  396. { .reloc section fixup types }
  397. IMAGE_REL_BASED_HIGHLOW = 3; { Applies the delta to the 32-bit field at Offset. }
  398. IMAGE_REL_BASED_DIR64 = 10; { Applies the delta to the 64-bit field at Offset. }
  399. type
  400. coffdjoptheader=packed record
  401. magic : word;
  402. vstamp : word;
  403. tsize : longint;
  404. dsize : longint;
  405. bsize : longint;
  406. entry : longint;
  407. text_start : longint;
  408. data_start : longint;
  409. end;
  410. coffsectionrec=packed record
  411. len : longword;
  412. nrelocs : word;
  413. empty : array[0..11] of char;
  414. end;
  415. coffreloc=packed record
  416. address : longword;
  417. sym : longword;
  418. reloctype : word;
  419. end;
  420. coffsymbol=packed record
  421. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  422. strpos : longword;
  423. value : longword;
  424. section : smallint;
  425. empty : word;
  426. typ : byte;
  427. aux : byte;
  428. end;
  429. const
  430. SymbolMaxGrow = 200*sizeof(coffsymbol);
  431. StrsMaxGrow = 8192;
  432. coffsecnames : array[TAsmSectiontype] of string[20] = ('',
  433. '.text','.data','.data','.data','.bss','.tls',
  434. '.text',
  435. '.pdata',
  436. '.stab','.stabstr',
  437. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  438. '.eh_frame',
  439. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  440. '.fpc',
  441. '',
  442. '.init',
  443. '.fini'
  444. );
  445. const go32v2stub : array[0..2047] of byte=(
  446. $4D,$5A,$00,$00,$04,$00,$00,$00,$20,$00,$27,$00,$FF,$FF,$00,
  447. $00,$60,$07,$00,$00,$54,$00,$00,$00,$00,$00,$00,$00,$0D,$0A,
  448. $73,$74,$75,$62,$2E,$68,$20,$67,$65,$6E,$65,$72,$61,$74,$65,
  449. $64,$20,$66,$72,$6F,$6D,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,
  450. $20,$62,$79,$20,$64,$6A,$61,$73,$6D,$2C,$20,$6F,$6E,$20,$54,
  451. $68,$75,$20,$44,$65,$63,$20,$20,$39,$20,$31,$30,$3A,$35,$39,
  452. $3A,$33,$31,$20,$31,$39,$39,$39,$0D,$0A,$54,$68,$65,$20,$53,
  453. $54,$55,$42,$2E,$45,$58,$45,$20,$73,$74,$75,$62,$20,$6C,$6F,
  454. $61,$64,$65,$72,$20,$69,$73,$20,$43,$6F,$70,$79,$72,$69,$67,
  455. $68,$74,$20,$28,$43,$29,$20,$31,$39,$39,$33,$2D,$31,$39,$39,
  456. $35,$20,$44,$4A,$20,$44,$65,$6C,$6F,$72,$69,$65,$2E,$20,$0D,
  457. $0A,$50,$65,$72,$6D,$69,$73,$73,$69,$6F,$6E,$20,$67,$72,$61,
  458. $6E,$74,$65,$64,$20,$74,$6F,$20,$75,$73,$65,$20,$66,$6F,$72,
  459. $20,$61,$6E,$79,$20,$70,$75,$72,$70,$6F,$73,$65,$20,$70,$72,
  460. $6F,$76,$69,$64,$65,$64,$20,$74,$68,$69,$73,$20,$63,$6F,$70,
  461. $79,$72,$69,$67,$68,$74,$20,$0D,$0A,$72,$65,$6D,$61,$69,$6E,
  462. $73,$20,$70,$72,$65,$73,$65,$6E,$74,$20,$61,$6E,$64,$20,$75,
  463. $6E,$6D,$6F,$64,$69,$66,$69,$65,$64,$2E,$20,$0D,$0A,$54,$68,
  464. $69,$73,$20,$6F,$6E,$6C,$79,$20,$61,$70,$70,$6C,$69,$65,$73,
  465. $20,$74,$6F,$20,$74,$68,$65,$20,$73,$74,$75,$62,$2C,$20,$61,
  466. $6E,$64,$20,$6E,$6F,$74,$20,$6E,$65,$63,$65,$73,$73,$61,$72,
  467. $69,$6C,$79,$20,$74,$68,$65,$20,$77,$68,$6F,$6C,$65,$20,$70,
  468. $72,$6F,$67,$72,$61,$6D,$2E,$0A,$0D,$0A,$24,$49,$64,$3A,$20,
  469. $73,$74,$75,$62,$2E,$61,$73,$6D,$20,$62,$75,$69,$6C,$74,$20,
  470. $31,$32,$2F,$30,$39,$2F,$39,$39,$20,$31,$30,$3A,$35,$39,$3A,
  471. $33,$31,$20,$62,$79,$20,$64,$6A,$61,$73,$6D,$20,$24,$0A,$0D,
  472. $0A,$40,$28,$23,$29,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,$20,
  473. $62,$75,$69,$6C,$74,$20,$31,$32,$2F,$30,$39,$2F,$39,$39,$20,
  474. $31,$30,$3A,$35,$39,$3A,$33,$31,$20,$62,$79,$20,$64,$6A,$61,
  475. $73,$6D,$0A,$0D,$0A,$1A,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  476. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  477. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  478. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  479. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  480. $00,$00,$67,$6F,$33,$32,$73,$74,$75,$62,$2C,$20,$76,$20,$32,
  481. $2E,$30,$32,$54,$00,$00,$00,$00,$00,$08,$00,$00,$00,$00,$00,
  482. $00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  483. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  484. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$43,$57,$53,$44,$50,
  485. $4D,$49,$2E,$45,$58,$45,$00,$00,$00,$00,$00,$0E,$1F,$8C,$1E,
  486. $24,$00,$8C,$06,$60,$07,$FC,$B4,$30,$CD,$21,$3C,$03,$73,$08,
  487. $B0,$6D,$BA,$A7,$05,$E9,$D4,$03,$A2,$69,$08,$BE,$20,$00,$8B,
  488. $04,$09,$C0,$75,$02,$B4,$FE,$BB,$70,$08,$39,$C3,$73,$02,$89,
  489. $C3,$89,$1C,$FE,$C7,$B9,$04,$FF,$D3,$EB,$B4,$4A,$CD,$21,$73,
  490. $08,$D3,$E3,$FE,$CF,$89,$1C,$EB,$D8,$26,$8E,$06,$2C,$00,$31,
  491. $FF,$30,$C0,$A9,$F2,$AE,$26,$81,$3D,$50,$41,$75,$15,$AF,$26,
  492. $81,$3D,$54,$48,$75,$0D,$AF,$26,$80,$3D,$3D,$75,$06,$47,$89,
  493. $3E,$8C,$04,$4F,$AE,$75,$DF,$AF,$B4,$3E,$BB,$13,$00,$CD,$21,
  494. $B4,$3E,$BB,$12,$00,$CD,$21,$06,$57,$31,$C9,$74,$12,$B0,$6E,
  495. $BA,$7E,$05,$E9,$5E,$03,$09,$C9,$75,$F4,$41,$E8,$A1,$03,$72,
  496. $EE,$B8,$87,$16,$CD,$2F,$09,$C0,$75,$ED,$80,$E3,$01,$74,$E8,
  497. $89,$3E,$00,$06,$8C,$06,$02,$06,$89,$36,$04,$06,$5F,$07,$E8,
  498. $D3,$02,$89,$3E,$2A,$00,$89,$36,$62,$07,$80,$3E,$2C,$00,$00,
  499. $74,$23,$B9,$08,$00,$BF,$2C,$00,$8A,$05,$47,$08,$C0,$74,$05,
  500. $88,$07,$43,$E2,$F4,$66,$C7,$07,$2E,$45,$58,$45,$83,$C3,$04,
  501. $C6,$07,$00,$89,$1E,$62,$07,$B8,$00,$3D,$BA,$64,$07,$CD,$21,
  502. $0F,$82,$B3,$02,$A3,$06,$06,$89,$C3,$B9,$06,$00,$BA,$B5,$07,
  503. $B4,$3F,$CD,$21,$31,$D2,$31,$C9,$A1,$B5,$07,$3D,$4C,$01,$74,
  504. $1B,$3D,$4D,$5A,$0F,$85,$98,$02,$8B,$16,$B9,$07,$C1,$E2,$09,
  505. $8B,$1E,$B7,$07,$09,$DB,$74,$05,$80,$EE,$02,$01,$DA,$89,$16,
  506. $BB,$07,$89,$0E,$BD,$07,$B8,$00,$42,$8B,$1E,$06,$06,$CD,$21,
  507. $B9,$A8,$00,$BA,$BF,$07,$B4,$3F,$CD,$21,$3D,$A8,$00,$75,$06,
  508. $81,$3E,$BF,$07,$4C,$01,$0F,$85,$61,$02,$66,$A1,$E3,$07,$66,
  509. $A3,$10,$06,$66,$8B,$0E,$BB,$07,$66,$A1,$03,$08,$66,$01,$C8,
  510. $66,$A3,$08,$06,$66,$A1,$2B,$08,$66,$01,$C8,$66,$A3,$0C,$06,
  511. $66,$8B,$1E,$4B,$08,$66,$A1,$4F,$08,$66,$01,$C3,$66,$B8,$01,
  512. $00,$01,$00,$66,$39,$C3,$73,$03,$66,$89,$C3,$66,$81,$C3,$FF,
  513. $FF,$00,$00,$31,$DB,$66,$89,$1E,$1C,$00,$E8,$F5,$02,$8B,$1E,
  514. $04,$06,$09,$DB,$74,$0A,$B4,$48,$CD,$21,$0F,$82,$15,$02,$8E,
  515. $C0,$E8,$08,$03,$B8,$01,$00,$FF,$1E,$00,$06,$0F,$82,$0F,$02,
  516. $8C,$06,$26,$00,$8C,$0E,$28,$00,$8C,$D8,$A3,$22,$00,$8E,$C0,
  517. $31,$C0,$B9,$01,$00,$CD,$31,$72,$07,$A3,$14,$06,$31,$C0,$CD,
  518. $31,$0F,$82,$F3,$01,$A3,$16,$06,$66,$8B,$0E,$1C,$00,$B8,$01,
  519. $05,$8B,$1E,$1E,$00,$CD,$31,$0F,$82,$E5,$01,$89,$1E,$1A,$06,
  520. $89,$0E,$18,$06,$89,$36,$1A,$00,$89,$3E,$18,$00,$B8,$07,$00,
  521. $8B,$1E,$14,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,$CD,$31,$B8,
  522. $09,$00,$8C,$C9,$83,$E1,$03,$C1,$E1,$05,$51,$81,$C9,$9B,$C0,
  523. $CD,$31,$B8,$08,$00,$8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,
  524. $B8,$07,$00,$8B,$1E,$16,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,
  525. $CD,$31,$B8,$09,$00,$59,$81,$C9,$93,$C0,$CD,$31,$B8,$08,$00,
  526. $8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,$B8,$00,$01,$BB,$00,
  527. $0F,$CD,$31,$73,$10,$3D,$08,$00,$0F,$85,$73,$01,$B8,$00,$01,
  528. $CD,$31,$0F,$82,$6A,$01,$A3,$1C,$06,$89,$16,$1E,$06,$C1,$E3,
  529. $04,$89,$1E,$20,$06,$66,$8B,$36,$08,$06,$66,$8B,$3E,$FB,$07,
  530. $66,$8B,$0E,$FF,$07,$E8,$49,$00,$66,$8B,$36,$0C,$06,$66,$8B,
  531. $3E,$23,$08,$66,$8B,$0E,$27,$08,$E8,$37,$00,$8E,$06,$16,$06,
  532. $66,$8B,$3E,$4B,$08,$66,$8B,$0E,$4F,$08,$66,$31,$C0,$66,$C1,
  533. $E9,$02,$67,$F3,$66,$AB,$B4,$3E,$8B,$1E,$06,$06,$CD,$21,$B8,
  534. $01,$01,$8B,$16,$1E,$06,$CD,$31,$1E,$0F,$A1,$8E,$1E,$16,$06,
  535. $66,$64,$FF,$2E,$10,$06,$66,$89,$F0,$66,$25,$FF,$01,$00,$00,
  536. $66,$01,$C1,$29,$C6,$66,$29,$C7,$66,$89,$0E,$26,$06,$66,$89,
  537. $3E,$22,$06,$E8,$0F,$01,$89,$36,$3E,$06,$66,$C1,$EE,$10,$89,
  538. $36,$42,$06,$8B,$1E,$06,$06,$89,$1E,$3A,$06,$C7,$06,$46,$06,
  539. $00,$42,$E8,$03,$01,$A1,$1C,$06,$A3,$4E,$06,$C7,$06,$3E,$06,
  540. $00,$00,$C6,$06,$47,$06,$3F,$A1,$28,$06,$09,$C0,$75,$09,$A1,
  541. $26,$06,$3B,$06,$20,$06,$76,$03,$A1,$20,$06,$A3,$42,$06,$E8,
  542. $D9,$00,$66,$31,$C9,$8B,$0E,$46,$06,$66,$8B,$3E,$22,$06,$66,
  543. $01,$0E,$22,$06,$66,$29,$0E,$26,$06,$66,$31,$F6,$C1,$E9,$02,
  544. $1E,$06,$8E,$06,$16,$06,$8E,$1E,$1E,$06,$67,$F3,$66,$A5,$07,
  545. $1F,$66,$03,$0E,$26,$06,$75,$AF,$C3,$3C,$3A,$74,$06,$3C,$2F,
  546. $74,$02,$3C,$5C,$C3,$BE,$64,$07,$89,$F3,$26,$8A,$05,$47,$88,
  547. $04,$38,$E0,$74,$0E,$08,$C0,$74,$0A,$46,$E8,$DE,$FF,$75,$EC,
  548. $89,$F3,$74,$E8,$C3,$B0,$66,$BA,$48,$05,$EB,$0C,$B0,$67,$BA,
  549. $55,$05,$EB,$05,$B0,$68,$BA,$5F,$05,$52,$8B,$1E,$62,$07,$C6,
  550. $07,$24,$BB,$64,$07,$EB,$28,$E8,$F5,$00,$B0,$69,$BA,$99,$05,
  551. $EB,$1A,$B0,$6A,$BA,$B2,$05,$EB,$13,$B0,$6B,$BA,$C4,$05,$EB,
  552. $0C,$B0,$6C,$BA,$D6,$05,$EB,$05,$B0,$69,$BA,$99,$05,$52,$BB,
  553. $3B,$05,$E8,$15,$00,$5B,$E8,$11,$00,$BB,$67,$04,$E8,$0B,$00,
  554. $B4,$4C,$CD,$21,$43,$50,$B4,$02,$CD,$21,$58,$8A,$17,$80,$FA,
  555. $24,$75,$F2,$C3,$0D,$0A,$24,$50,$51,$57,$31,$C0,$BF,$2A,$06,
  556. $B9,$19,$00,$F3,$AB,$5F,$59,$58,$C3,$B8,$00,$03,$BB,$21,$00,
  557. $31,$C9,$66,$BF,$2A,$06,$00,$00,$CD,$31,$C3,$00,$00,$30,$E4,
  558. $E8,$4E,$FF,$89,$DE,$8B,$3E,$8C,$04,$EB,$17,$B4,$3B,$E8,$41,
  559. $FF,$81,$FE,$64,$07,$74,$12,$8A,$44,$FF,$E8,$2A,$FF,$74,$04,
  560. $C6,$04,$5C,$46,$E8,$03,$00,$72,$E4,$C3,$E8,$34,$00,$BB,$44,
  561. $00,$8A,$07,$88,$04,$43,$46,$08,$C0,$75,$F6,$06,$57,$1E,$07,
  562. $E8,$9B,$FF,$BB,$2A,$06,$8C,$5F,$04,$89,$5F,$02,$BA,$64,$07,
  563. $B8,$00,$4B,$CD,$21,$5F,$07,$72,$09,$B4,$4D,$CD,$21,$2D,$00,
  564. $03,$F7,$D8,$EB,$28,$80,$3E,$69,$08,$05,$72,$20,$B8,$00,$58,
  565. $CD,$21,$A2,$67,$08,$B8,$02,$58,$CD,$21,$A2,$68,$08,$B8,$01,
  566. $58,$BB,$80,$00,$CD,$21,$B8,$03,$58,$BB,$01,$00,$CD,$21,$C3,
  567. $9C,$80,$3E,$69,$08,$05,$72,$1A,$50,$53,$B8,$03,$58,$8A,$1E,
  568. $68,$08,$30,$FF,$CD,$21,$B8,$01,$58,$8A,$1E,$67,$08,$30,$FF,
  569. $CD,$21,$5B,$58,$9D,$C3,$4C,$6F,$61,$64,$20,$65,$72,$72,$6F,
  570. $72,$3A,$20,$24,$3A,$20,$63,$61,$6E,$27,$74,$20,$6F,$70,$65,
  571. $6E,$24,$3A,$20,$6E,$6F,$74,$20,$45,$58,$45,$24,$3A,$20,$6E,
  572. $6F,$74,$20,$43,$4F,$46,$46,$20,$28,$43,$68,$65,$63,$6B,$20,
  573. $66,$6F,$72,$20,$76,$69,$72,$75,$73,$65,$73,$29,$24,$6E,$6F,
  574. $20,$44,$50,$4D,$49,$20,$2D,$20,$47,$65,$74,$20,$63,$73,$64,
  575. $70,$6D,$69,$2A,$62,$2E,$7A,$69,$70,$24,$6E,$6F,$20,$44,$4F,
  576. $53,$20,$6D,$65,$6D,$6F,$72,$79,$24,$6E,$65,$65,$64,$20,$44,
  577. $4F,$53,$20,$33,$24,$63,$61,$6E,$27,$74,$20,$73,$77,$69,$74,
  578. $63,$68,$20,$6D,$6F,$64,$65,$24,$6E,$6F,$20,$44,$50,$4D,$49,
  579. $20,$73,$65,$6C,$65,$63,$74,$6F,$72,$73,$24,$6E,$6F,$20,$44,
  580. $50,$4D,$49,$20,$6D,$65,$6D,$6F,$72,$79,$24,$90,$90,$90,$90,
  581. $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,
  582. $90,$90,$90,$90,$90,$90,$90,$90);
  583. const win32stub : array[0..127] of byte=(
  584. $4D,$5A,$90,$00,$03,$00,$00,$00,$04,$00,$00,$00,$FF,$FF,$00,$00,
  585. $B8,$00,$00,$00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,
  586. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  587. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$80,$00,$00,$00,
  588. $0E,$1F,$BA,$0E,$00,$B4,$09,$CD,$21,$B8,$01,$4C,$CD,$21,$54,$68,
  589. $69,$73,$20,$70,$72,$6F,$67,$72,$61,$6D,$20,$63,$61,$6E,$6E,$6F,
  590. $74,$20,$62,$65,$20,$72,$75,$6E,$20,$69,$6E,$20,$44,$4F,$53,$20,
  591. $6D,$6F,$64,$65,$2E,$0D,$0D,$0A,$24,$00,$00,$00,$00,$00,$00,$00);
  592. const pemagic : array[0..3] of byte = (
  593. $50,$45,$00,$00);
  594. {****************************************************************************
  595. Helpers
  596. ****************************************************************************}
  597. function djencodesechdrflags(aoptions:TObjSectionOptions):longword;
  598. begin
  599. if (oso_load in aoptions) then
  600. begin
  601. if oso_executable in aoptions then
  602. result:=COFF_STYP_TEXT
  603. else if not(oso_data in aoptions) then
  604. result:=COFF_STYP_BSS
  605. else
  606. result:=COFF_STYP_DATA;
  607. end
  608. else
  609. result:=COFF_STYP_REG;
  610. end;
  611. function djdecodesechdrflags(const aname:string;flags:longword):TObjSectionOptions;
  612. begin
  613. result:=[];
  614. if flags and COFF_STYP_TEXT<>0 then
  615. result:=[oso_data,oso_load,oso_executable]
  616. else if flags and COFF_STYP_BSS<>0 then
  617. result:=[oso_load]
  618. else if flags and COFF_STYP_DATA<>0 then
  619. result:=[oso_data,oso_load]
  620. else
  621. result:=[oso_data]
  622. end;
  623. function peencodesechdrflags(aoptions:TObjSectionOptions;aalign:shortint):longword;
  624. begin
  625. result:=0;
  626. if (oso_load in aoptions) then
  627. begin
  628. if oso_executable in aoptions then
  629. result:=result or PE_SCN_CNT_CODE or PE_SCN_MEM_EXECUTE
  630. else
  631. begin
  632. if (oso_data in aoptions) then
  633. result:=result or PE_SCN_CNT_INITIALIZED_DATA
  634. else
  635. result:=result or PE_SCN_CNT_UNINITIALIZED_DATA;
  636. end;
  637. if oso_write in aoptions then
  638. result:=result or PE_SCN_MEM_WRITE or PE_SCN_MEM_READ
  639. else
  640. result:=result or PE_SCN_MEM_READ;
  641. end
  642. else
  643. result:=result or PE_SCN_MEM_DISCARDABLE;
  644. case aalign of
  645. 1 : result:=result or PE_SCN_ALIGN_1BYTES;
  646. 2 : result:=result or PE_SCN_ALIGN_2BYTES;
  647. 4 : result:=result or PE_SCN_ALIGN_4BYTES;
  648. 8 : result:=result or PE_SCN_ALIGN_8BYTES;
  649. 16 : result:=result or PE_SCN_ALIGN_16BYTES;
  650. 32 : result:=result or PE_SCN_ALIGN_32BYTES;
  651. 64 : result:=result or PE_SCN_ALIGN_64BYTES;
  652. else result:=result or PE_SCN_ALIGN_16BYTES;
  653. end;
  654. end;
  655. procedure pedecodesechdrflags(const aname:string;flags:longword;out aoptions:TObjSectionOptions;out aalign:shortint);
  656. var
  657. alignflag : longword;
  658. begin
  659. aoptions:=[];
  660. if flags and PE_SCN_CNT_CODE<>0 then
  661. include(aoptions,oso_executable);
  662. if flags and PE_SCN_MEM_DISCARDABLE<>0 then
  663. include(aoptions,oso_debug);
  664. if flags and PE_SCN_CNT_UNINITIALIZED_DATA=0 then
  665. include(aoptions,oso_data);
  666. if (flags and PE_SCN_LNK_REMOVE<>0) or
  667. (flags and PE_SCN_MEM_DISCARDABLE<>0) then
  668. include(aoptions,oso_noload)
  669. else
  670. include(aoptions,oso_load);
  671. { read/write }
  672. if flags and PE_SCN_MEM_WRITE<>0 then
  673. include(aoptions,oso_write)
  674. else
  675. include(aoptions,oso_readonly);
  676. { alignment }
  677. alignflag:=flags and PE_SCN_ALIGN_MASK;
  678. if alignflag=PE_SCN_ALIGN_64BYTES then
  679. aalign:=64
  680. else if alignflag=PE_SCN_ALIGN_32BYTES then
  681. aalign:=32
  682. else if alignflag=PE_SCN_ALIGN_16BYTES then
  683. aalign:=16
  684. else if alignflag=PE_SCN_ALIGN_8BYTES then
  685. aalign:=8
  686. else if alignflag=PE_SCN_ALIGN_4BYTES then
  687. aalign:=4
  688. else if alignflag=PE_SCN_ALIGN_2BYTES then
  689. aalign:=2
  690. else if alignflag=PE_SCN_ALIGN_1BYTES then
  691. aalign:=1
  692. else if alignflag=0 then
  693. aalign:=0
  694. else
  695. Internalerror(2009050401);
  696. end;
  697. {****************************************************************************
  698. TCoffObjSection
  699. ****************************************************************************}
  700. constructor TCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  701. begin
  702. inherited create(AList,aname,aalign,aoptions);
  703. end;
  704. procedure TCoffObjSection.addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
  705. begin
  706. ObjRelocations.Add(TObjRelocation.createsymbolsize(ofs,p,symsize,reloctype));
  707. end;
  708. procedure TCoffObjSection.fixuprelocs;
  709. var
  710. i,zero,address_size : longint;
  711. objreloc : TObjRelocation;
  712. address,
  713. relocval : aint;
  714. relocsec : TObjSection;
  715. {$ifdef cpu64bitaddr}
  716. s : string;
  717. {$endif cpu64bitaddr}
  718. begin
  719. if (ObjRelocations.Count>0) and
  720. not assigned(data) then
  721. internalerror(200205183);
  722. for i:=0 to ObjRelocations.Count-1 do
  723. begin
  724. objreloc:=TObjRelocation(ObjRelocations[i]);
  725. address_size:=4;
  726. case objreloc.typ of
  727. RELOC_NONE:
  728. continue;
  729. RELOC_ZERO:
  730. begin
  731. data.Seek(objreloc.dataoffset);
  732. zero:=0;
  733. data.Write(zero,4);
  734. continue;
  735. end;
  736. {$ifdef cpu64bitaddr}
  737. RELOC_ABSOLUTE:
  738. address_size:=8;
  739. {$endif cpu64bitaddr}
  740. end;
  741. address:=0;
  742. data.Seek(objreloc.dataoffset);
  743. data.Read(address,address_size);
  744. if assigned(objreloc.symbol) then
  745. begin
  746. relocsec:=objreloc.symbol.objsection;
  747. relocval:=objreloc.symbol.address;
  748. end
  749. else
  750. if assigned(objreloc.objsection) then
  751. begin
  752. relocsec:=objreloc.objsection;
  753. relocval:=objreloc.objsection.mempos
  754. end
  755. else
  756. internalerror(200205183);
  757. { Only debug sections are allowed to have relocs pointing to unused sections }
  758. if not relocsec.used and not (oso_debug in secoptions) then
  759. internalerror(200603061);
  760. if relocsec.used then
  761. case objreloc.typ of
  762. RELOC_RELATIVE :
  763. begin
  764. address:=address-mempos+relocval;
  765. if TCoffObjData(objdata).win32 then
  766. dec(address,objreloc.dataoffset+4);
  767. end;
  768. RELOC_RVA:
  769. begin
  770. { fixup address when the symbol was known in defined object }
  771. if (relocsec.objdata=objdata) then
  772. dec(address,TCoffObjSection(relocsec).orgmempos);
  773. {$ifdef arm}
  774. if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
  775. inc(address, relocsec.MemPos)
  776. else
  777. {$endif arm}
  778. inc(address,relocval);
  779. end;
  780. RELOC_SECREL32 :
  781. begin
  782. { fixup address when the symbol was known in defined object }
  783. if (relocsec.objdata=objdata) then
  784. dec(address,relocsec.ExeSection.MemPos);
  785. inc(address,relocval);
  786. end;
  787. {$ifdef arm}
  788. RELOC_RELATIVE_24:
  789. begin
  790. relocval:=longint(relocval - mempos - objreloc.dataoffset) shr 2 - 2;
  791. address:=address or (relocval and $ffffff);
  792. relocval:=relocval shr 24;
  793. if (relocval<>$3f) and (relocval<>0) then
  794. internalerror(200606085); { offset overflow }
  795. end;
  796. {$endif arm}
  797. {$ifdef x86_64}
  798. { 64 bit coff only }
  799. RELOC_RELATIVE_1:
  800. begin
  801. address:=address-mempos+relocval;
  802. dec(address,objreloc.dataoffset+1);
  803. end;
  804. RELOC_RELATIVE_2:
  805. begin
  806. address:=address-mempos+relocval;
  807. dec(address,objreloc.dataoffset+2);
  808. end;
  809. RELOC_RELATIVE_3:
  810. begin
  811. address:=address-mempos+relocval;
  812. dec(address,objreloc.dataoffset+3);
  813. end;
  814. RELOC_RELATIVE_4:
  815. begin
  816. address:=address-mempos+relocval;
  817. dec(address,objreloc.dataoffset+4);
  818. end;
  819. RELOC_RELATIVE_5:
  820. begin
  821. address:=address-mempos+relocval;
  822. dec(address,objreloc.dataoffset+5);
  823. end;
  824. RELOC_ABSOLUTE32,
  825. {$endif x86_64}
  826. RELOC_ABSOLUTE :
  827. begin
  828. if oso_common in relocsec.secoptions then
  829. dec(address,objreloc.orgsize)
  830. else
  831. begin
  832. { fixup address when the symbol was known in defined object }
  833. if (relocsec.objdata=objdata) then
  834. dec(address,TCoffObjSection(relocsec).orgmempos);
  835. end;
  836. {$ifdef arm}
  837. if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
  838. inc(address, relocsec.MemPos)
  839. else
  840. {$endif arm}
  841. inc(address,relocval);
  842. inc(address,relocsec.objdata.imagebase);
  843. end;
  844. else
  845. internalerror(200604014);
  846. end
  847. else
  848. address:=0; { Relocation in debug section points to unused section, which is eliminated by linker }
  849. data.Seek(objreloc.dataoffset);
  850. data.Write(address,address_size);
  851. {$ifdef cpu64bitaddr}
  852. if objreloc.typ = RELOC_ABSOLUTE32 then begin
  853. if assigned(objreloc.symbol) then
  854. s:=objreloc.symbol.Name
  855. else
  856. s:=objreloc.objsection.Name;
  857. Message2(link_w_32bit_absolute_reloc, ObjData.Name, s);
  858. end;
  859. {$endif cpu64bitaddr}
  860. end;
  861. end;
  862. {****************************************************************************
  863. TDJCoffObjSection
  864. ****************************************************************************}
  865. constructor TDJCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  866. begin
  867. inherited create(alist,aname,aalign,aoptions);
  868. end;
  869. {****************************************************************************
  870. TPECoffObjSection
  871. ****************************************************************************}
  872. constructor TPECoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  873. begin
  874. inherited create(alist,aname,aalign,aoptions);
  875. end;
  876. {****************************************************************************
  877. TCoffObjData
  878. ****************************************************************************}
  879. constructor TCoffObjData.createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  880. begin
  881. inherited create(n);
  882. CObjSection:=ACObjSection;
  883. win32:=awin32;
  884. { we need at least the following 3 ObjSections }
  885. createsection(sec_code);
  886. createsection(sec_data);
  887. createsection(sec_bss);
  888. end;
  889. destructor TCoffObjData.destroy;
  890. begin
  891. inherited destroy;
  892. end;
  893. function TCoffObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  894. var
  895. sep : string[3];
  896. secname : string;
  897. begin
  898. secname:=coffsecnames[atype];
  899. if create_smartlink_sections and
  900. (aname<>'') then
  901. begin
  902. case aorder of
  903. secorder_begin :
  904. sep:='.b_';
  905. secorder_end :
  906. sep:='.z_';
  907. else
  908. sep:='.n_';
  909. end;
  910. result:=secname+sep+aname
  911. end
  912. else
  913. result:=secname;
  914. end;
  915. procedure TCoffObjData.CreateDebugSections;
  916. begin
  917. if target_dbg.id=dbg_stabs then
  918. begin
  919. stabssec:=createsection(sec_stab);
  920. stabstrsec:=createsection(sec_stabstr);
  921. end;
  922. end;
  923. procedure TCoffObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);
  924. var
  925. curraddr,
  926. symaddr : aword;
  927. begin
  928. if CurrObjSec=nil then
  929. internalerror(200403072);
  930. if assigned(p) then
  931. begin
  932. { current address }
  933. curraddr:=CurrObjSec.mempos+CurrObjSec.Size;
  934. { external/common symbols don't have a fixed memory position yet }
  935. if (p.bind=AB_COMMON) then
  936. begin
  937. { For go32v2 we need to use the size as address }
  938. if not win32 then
  939. symaddr:=p.size
  940. else
  941. symaddr:=0;
  942. end
  943. else
  944. symaddr:=p.address;
  945. { no symbol relocation need inside a section }
  946. if (p.objsection=CurrObjSec) and
  947. (p.bind<>AB_COMMON) then
  948. begin
  949. case reloctype of
  950. RELOC_ABSOLUTE :
  951. begin
  952. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE);
  953. inc(data,symaddr);
  954. end;
  955. {$ifdef cpu64bitaddr}
  956. RELOC_ABSOLUTE32 :
  957. begin
  958. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE32);
  959. inc(data,symaddr);
  960. end;
  961. {$endif cpu64bitaddr}
  962. RELOC_RELATIVE :
  963. begin
  964. inc(data,symaddr-len-CurrObjSec.Size);
  965. end;
  966. RELOC_RVA :
  967. begin
  968. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_RVA);
  969. inc(data,symaddr);
  970. end;
  971. else
  972. internalerror(200604013);
  973. end;
  974. end
  975. else
  976. begin
  977. if (p.objsection<>nil) and
  978. (p.bind<>AB_COMMON) and
  979. (reloctype<>RELOC_RELATIVE) then
  980. CurrObjSec.addsectionreloc(curraddr,p.objsection,reloctype)
  981. else
  982. CurrObjSec.addsymreloc(curraddr,p,reloctype);
  983. if (not win32) or
  984. ((reloctype<>RELOC_RELATIVE) and (p.objsection<>nil)) then
  985. inc(data,symaddr);
  986. if reloctype=RELOC_RELATIVE then
  987. begin
  988. if win32 then
  989. dec(data,len-4)
  990. else
  991. dec(data,len+CurrObjSec.Size);
  992. end;
  993. end;
  994. end
  995. else
  996. begin
  997. if reloctype=RELOC_RVA then
  998. internalerror(200603033);
  999. end;
  1000. CurrObjSec.write(data,len);
  1001. end;
  1002. procedure TCoffObjData.afteralloc;
  1003. var
  1004. mempos : qword;
  1005. i : longint;
  1006. begin
  1007. inherited afteralloc;
  1008. { DJ Coff requires mempositions }
  1009. if not win32 then
  1010. begin
  1011. mempos:=0;
  1012. for i:=0 to ObjSectionList.Count-1 do
  1013. mempos:=TObjSection(ObjSectionList[i]).setmempos(mempos);
  1014. end;
  1015. end;
  1016. {****************************************************************************
  1017. TDJCoffObjData
  1018. ****************************************************************************}
  1019. constructor TDJCoffObjData.create(const n:string);
  1020. begin
  1021. inherited createcoff(n,false,TDJCoffObjSection);
  1022. end;
  1023. {****************************************************************************
  1024. TPECoffObjData
  1025. ****************************************************************************}
  1026. constructor TPECoffObjData.create(const n:string);
  1027. begin
  1028. inherited createcoff(n,true,TPECoffObjSection);
  1029. end;
  1030. {****************************************************************************
  1031. TCoffObjOutput
  1032. ****************************************************************************}
  1033. constructor TCoffObjOutput.createcoff(AWriter:TObjectWriter;awin32:boolean);
  1034. begin
  1035. inherited create(AWriter);
  1036. win32:=awin32;
  1037. end;
  1038. destructor TCoffObjOutput.destroy;
  1039. begin
  1040. if assigned(FCoffSyms) then
  1041. FCoffSyms.free;
  1042. if assigned(FCoffStrs) then
  1043. FCoffStrs.free;
  1044. inherited destroy;
  1045. end;
  1046. procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  1047. var
  1048. sym : coffsymbol;
  1049. begin
  1050. FillChar(sym,sizeof(sym),0);
  1051. { symbolname }
  1052. if length(name)>8 then
  1053. begin
  1054. sym.strpos:=FCoffStrs.size+4;
  1055. FCoffStrs.writestr(name);
  1056. FCoffStrs.writestr(#0);
  1057. end
  1058. else
  1059. move(name[1],sym.name,length(name));
  1060. sym.value:=value;
  1061. sym.section:=section;
  1062. sym.typ:=typ;
  1063. sym.aux:=aux;
  1064. inc(symidx);
  1065. FCoffSyms.write(sym,sizeof(sym));
  1066. end;
  1067. procedure TCoffObjOutput.section_write_symbol(p:TObject;arg:pointer);
  1068. var
  1069. secrec : coffsectionrec;
  1070. begin
  1071. with TCoffObjSection(p) do
  1072. begin
  1073. secidx:=symidx div 2;
  1074. secsymidx:=symidx;
  1075. write_symbol(name,mempos,secidx,COFF_SYM_SECTION,1);
  1076. { AUX }
  1077. fillchar(secrec,sizeof(secrec),0);
  1078. secrec.len:=Size;
  1079. secrec.nrelocs:=ObjRelocations.count;
  1080. inc(symidx);
  1081. FCoffSyms.write(secrec,sizeof(secrec));
  1082. end;
  1083. end;
  1084. procedure TCoffObjOutput.section_write_relocs(p:TObject;arg:pointer);
  1085. var
  1086. i : longint;
  1087. rel : coffreloc;
  1088. objreloc : TObjRelocation;
  1089. begin
  1090. for i:=0 to TObjSection(p).ObjRelocations.Count-1 do
  1091. begin
  1092. objreloc:=TObjRelocation(TObjSection(p).ObjRelocations[i]);
  1093. rel.address:=objreloc.dataoffset;
  1094. if assigned(objreloc.symbol) then
  1095. begin
  1096. if (objreloc.symbol.bind=AB_LOCAL) then
  1097. rel.sym:=objreloc.symbol.objsection.secsymidx
  1098. else
  1099. begin
  1100. if objreloc.symbol.symidx=-1 then
  1101. internalerror(200602233);
  1102. rel.sym:=objreloc.symbol.symidx;
  1103. end;
  1104. end
  1105. else
  1106. begin
  1107. if objreloc.objsection<>nil then
  1108. rel.sym:=objreloc.objsection.secsymidx
  1109. else
  1110. rel.sym:=0;
  1111. end;
  1112. case objreloc.typ of
  1113. {$ifdef arm}
  1114. RELOC_ABSOLUTE :
  1115. rel.reloctype:=IMAGE_REL_ARM_ADDR32;
  1116. { I've no idea if this is correct (FK):
  1117. RELOC_RELATIVE :
  1118. rel.reloctype:=IMAGE_REL_ARM_GPREL12;
  1119. }
  1120. RELOC_RVA :
  1121. rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
  1122. RELOC_SECREL32 :
  1123. rel.reloctype:=IMAGE_REL_ARM_SECREL;
  1124. {$endif arm}
  1125. {$ifdef i386}
  1126. RELOC_RELATIVE :
  1127. rel.reloctype:=IMAGE_REL_I386_PCRLONG;
  1128. RELOC_ABSOLUTE :
  1129. rel.reloctype:=IMAGE_REL_I386_DIR32;
  1130. RELOC_RVA :
  1131. rel.reloctype:=IMAGE_REL_I386_IMAGEBASE;
  1132. RELOC_SECREL32 :
  1133. rel.reloctype:=IMAGE_REL_I386_SECREL32;
  1134. {$endif i386}
  1135. {$ifdef x86_64}
  1136. RELOC_RELATIVE :
  1137. rel.reloctype:=IMAGE_REL_AMD64_REL32;
  1138. RELOC_ABSOLUTE32 :
  1139. rel.reloctype:=IMAGE_REL_AMD64_ADDR32;
  1140. RELOC_ABSOLUTE :
  1141. rel.reloctype:=IMAGE_REL_AMD64_ADDR64;
  1142. RELOC_RVA :
  1143. rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB;
  1144. RELOC_RELATIVE_1 :
  1145. rel.reloctype:=IMAGE_REL_AMD64_REL32_1;
  1146. RELOC_RELATIVE_2 :
  1147. rel.reloctype:=IMAGE_REL_AMD64_REL32_2;
  1148. RELOC_RELATIVE_3 :
  1149. rel.reloctype:=IMAGE_REL_AMD64_REL32_3;
  1150. RELOC_RELATIVE_4 :
  1151. rel.reloctype:=IMAGE_REL_AMD64_REL32_4;
  1152. RELOC_RELATIVE_5 :
  1153. rel.reloctype:=IMAGE_REL_AMD64_REL32_5;
  1154. RELOC_SECREL32 :
  1155. rel.reloctype:=IMAGE_REL_AMD64_SECREL;
  1156. {$endif x86_64}
  1157. else
  1158. internalerror(200905071);
  1159. end;
  1160. FWriter.write(rel,sizeof(rel));
  1161. end;
  1162. end;
  1163. procedure TCoffObjOutput.create_symbols(data:TObjData);
  1164. var
  1165. filename : string[18];
  1166. sectionval : word;
  1167. globalval : byte;
  1168. i : longint;
  1169. value : aword;
  1170. objsym : TObjSymbol;
  1171. begin
  1172. with TCoffObjData(data) do
  1173. begin
  1174. symidx:=0;
  1175. { The `.file' record, and the file name auxiliary record }
  1176. write_symbol('.file', 0, -2, COFF_SYM_FILE, 1);
  1177. fillchar(filename,sizeof(filename),0);
  1178. filename:=ExtractFileName(current_module.mainsource^);
  1179. inc(symidx);
  1180. FCoffSyms.write(filename[1],sizeof(filename)-1);
  1181. { Sections }
  1182. ObjSectionList.ForEachCall(@section_write_symbol,nil);
  1183. { ObjSymbols }
  1184. for i:=0 to ObjSymbolList.Count-1 do
  1185. begin
  1186. objsym:=TObjSymbol(ObjSymbolList[i]);
  1187. if (objsym.typ=AT_LABEL) and (objsym.bind=AB_LOCAL) then
  1188. continue;
  1189. case objsym.bind of
  1190. AB_GLOBAL :
  1191. begin
  1192. globalval:=2;
  1193. sectionval:=TCoffObjSection(objsym.objsection).secidx;
  1194. value:=objsym.address;
  1195. end;
  1196. AB_LOCAL :
  1197. begin
  1198. globalval:=3;
  1199. sectionval:=TCoffObjSection(objsym.objsection).secidx;
  1200. value:=objsym.address;
  1201. end;
  1202. else
  1203. begin
  1204. globalval:=2;
  1205. sectionval:=0;
  1206. value:=objsym.size;
  1207. end;
  1208. end;
  1209. { symbolname }
  1210. objsym.symidx:=symidx;
  1211. write_symbol(objsym.name,value,sectionval,globalval,0);
  1212. end;
  1213. end;
  1214. end;
  1215. procedure TCoffObjOutput.section_set_datapos(p:TObject;arg:pointer);
  1216. begin
  1217. TObjSection(p).setdatapos(paword(arg)^);
  1218. end;
  1219. procedure TCoffObjOutput.section_set_reloc_datapos(p:TObject;arg:pointer);
  1220. begin
  1221. TCoffObjSection(p).coffrelocpos:=paint(arg)^;
  1222. inc(paint(arg)^,sizeof(coffreloc)*TObjSection(p).ObjRelocations.count);
  1223. end;
  1224. procedure TCoffObjOutput.section_write_header(p:TObject;arg:pointer);
  1225. var
  1226. sechdr : tcoffsechdr;
  1227. s : string;
  1228. strpos : aword;
  1229. begin
  1230. with TCoffObjSection(p) do
  1231. begin
  1232. fillchar(sechdr,sizeof(sechdr),0);
  1233. s:=name;
  1234. if length(s)>8 then
  1235. begin
  1236. strpos:=FCoffStrs.size+4;
  1237. FCoffStrs.writestr(s);
  1238. FCoffStrs.writestr(#0);
  1239. s:='/'+ToStr(strpos);
  1240. end;
  1241. move(s[1],sechdr.name,length(s));
  1242. if not win32 then
  1243. begin
  1244. sechdr.rvaofs:=mempos;
  1245. sechdr.vsize:=mempos;
  1246. end
  1247. else
  1248. begin
  1249. if not(oso_data in secoptions) then
  1250. sechdr.vsize:=Size;
  1251. end;
  1252. sechdr.DataSize:=size;
  1253. if (Size>0) and
  1254. (oso_data in secoptions) then
  1255. sechdr.datapos:=datapos;
  1256. sechdr.nrelocs:=ObjRelocations.count;
  1257. sechdr.relocpos:=coffrelocpos;
  1258. if win32 then
  1259. sechdr.flags:=peencodesechdrflags(secoptions,secalign)
  1260. else
  1261. sechdr.flags:=djencodesechdrflags(secoptions);
  1262. FWriter.write(sechdr,sizeof(sechdr));
  1263. end;
  1264. end;
  1265. procedure TCoffObjOutput.section_write_data(p:TObject;arg:pointer);
  1266. begin
  1267. with TObjSection(p) do
  1268. begin
  1269. if assigned(data) then
  1270. begin
  1271. FWriter.writezeros(dataalignbytes);
  1272. if Datapos<>FWriter.ObjSize then
  1273. internalerror(200603052);
  1274. FWriter.writearray(data);
  1275. end;
  1276. end;
  1277. end;
  1278. function TCoffObjOutput.writedata(data:TObjData):boolean;
  1279. var
  1280. orgdatapos,
  1281. datapos,
  1282. sympos : aword;
  1283. i : longint;
  1284. gotreloc : boolean;
  1285. header : tcoffheader;
  1286. begin
  1287. result:=false;
  1288. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1289. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1290. with TCoffObjData(data) do
  1291. begin
  1292. { Create Symbol Table }
  1293. create_symbols(data);
  1294. { Calculate the filepositions }
  1295. datapos:=sizeof(tcoffheader)+sizeof(tcoffsechdr)*ObjSectionList.Count;
  1296. { Sections first }
  1297. ObjSectionList.ForEachCall(@section_set_datapos,@datapos);
  1298. { relocs }
  1299. orgdatapos:=datapos;
  1300. ObjSectionList.ForEachCall(@section_set_reloc_datapos,@datapos);
  1301. gotreloc:=(orgdatapos<>datapos);
  1302. { Symbols }
  1303. sympos:=datapos;
  1304. { Generate COFF header }
  1305. fillchar(header,sizeof(tcoffheader),0);
  1306. header.mach:=COFF_MAGIC;
  1307. header.nsects:=ObjSectionList.Count;
  1308. header.sympos:=sympos;
  1309. header.syms:=symidx;
  1310. if win32 then
  1311. begin
  1312. {$ifdef arm}
  1313. header.flag:=PE_FILE_32BIT_MACHINE or
  1314. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1315. {$else arm}
  1316. header.flag:=PE_FILE_BYTES_REVERSED_LO or PE_FILE_32BIT_MACHINE or
  1317. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1318. {$endif arm}
  1319. if not gotreloc then
  1320. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  1321. end
  1322. else
  1323. begin
  1324. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
  1325. if not gotreloc then
  1326. header.flag:=header.flag or COFF_FLAG_NORELOCS;
  1327. end;
  1328. FWriter.write(header,sizeof(header));
  1329. { Section headers }
  1330. ObjSectionList.ForEachCall(@section_write_header,nil);
  1331. { ObjSections }
  1332. ObjSectionList.ForEachCall(@section_write_data,nil);
  1333. { Relocs }
  1334. ObjSectionList.ForEachCall(@section_write_relocs,nil);
  1335. { ObjSymbols }
  1336. if Sympos<>FWriter.ObjSize then
  1337. internalerror(200603051);
  1338. FWriter.writearray(FCoffSyms);
  1339. { Strings }
  1340. i:=FCoffStrs.size+4;
  1341. FWriter.write(i,4);
  1342. FWriter.writearray(FCoffStrs);
  1343. end;
  1344. FCoffStrs.Free;
  1345. FCoffStrs:=nil;
  1346. FCoffSyms.Free;
  1347. FCoffSyms:=nil;
  1348. end;
  1349. constructor TDJCoffObjOutput.create(AWriter:TObjectWriter);
  1350. begin
  1351. inherited createcoff(AWriter,false);
  1352. cobjdata:=TDJCoffObjData;
  1353. end;
  1354. constructor TPECoffObjOutput.create(AWriter:TObjectWriter);
  1355. begin
  1356. inherited createcoff(AWriter,true);
  1357. cobjdata:=TPECoffObjData;
  1358. end;
  1359. {****************************************************************************
  1360. TCoffObjInput
  1361. ****************************************************************************}
  1362. constructor TCoffObjInput.createcoff(awin32:boolean);
  1363. begin
  1364. inherited create;
  1365. win32:=awin32;
  1366. FSymTbl:=nil;
  1367. end;
  1368. destructor TCoffObjInput.destroy;
  1369. begin
  1370. if assigned(FCoffSyms) then
  1371. FCoffSyms.free;
  1372. if assigned(FCoffStrs) then
  1373. FCoffStrs.free;
  1374. if assigned(FSymTbl) then
  1375. freemem(FSymTbl);
  1376. if assigned(FSecTbl) then
  1377. freemem(FSecTbl);
  1378. inherited destroy;
  1379. end;
  1380. function TCoffObjInput.GetSection(secidx:longint):TObjSection;
  1381. begin
  1382. result:=nil;
  1383. if (secidx<1) or (secidx>FSecCount) then
  1384. begin
  1385. InputError('Failed reading coff file, invalid section index');
  1386. exit;
  1387. end;
  1388. result:=FSecTbl^[secidx];
  1389. end;
  1390. function TCoffObjInput.Read_str(strpos:longword):string;
  1391. begin
  1392. FCoffStrs.Seek(strpos-4);
  1393. FCoffStrs.Read(result[1],255);
  1394. result[255]:=#0;
  1395. result[0]:=chr(strlen(@result[1]));
  1396. if result='' then
  1397. Internalerror(200205172);
  1398. end;
  1399. procedure TCoffObjInput.read_relocs(s:TCoffObjSection);
  1400. var
  1401. rel : coffreloc;
  1402. rel_type : TObjRelocationType;
  1403. i : longint;
  1404. p : TObjSymbol;
  1405. begin
  1406. for i:=1 to s.coffrelocs do
  1407. begin
  1408. FReader.read(rel,sizeof(rel));
  1409. case rel.reloctype of
  1410. {$ifdef arm}
  1411. IMAGE_REL_ARM_ABSOLUTE:
  1412. rel_type:=RELOC_NONE;
  1413. IMAGE_REL_ARM_ADDR32:
  1414. rel_type:=RELOC_ABSOLUTE;
  1415. IMAGE_REL_ARM_ADDR32NB:
  1416. rel_type:=RELOC_RVA;
  1417. IMAGE_REL_ARM_BRANCH24:
  1418. rel_type:=RELOC_RELATIVE_24;
  1419. {$endif arm}
  1420. {$ifdef i386}
  1421. IMAGE_REL_I386_PCRLONG :
  1422. rel_type:=RELOC_RELATIVE;
  1423. IMAGE_REL_I386_DIR32 :
  1424. rel_type:=RELOC_ABSOLUTE;
  1425. IMAGE_REL_I386_IMAGEBASE :
  1426. rel_type:=RELOC_RVA;
  1427. IMAGE_REL_I386_SECREL32 :
  1428. rel_type:=RELOC_SECREL32;
  1429. {$endif i386}
  1430. {$ifdef x86_64}
  1431. IMAGE_REL_AMD64_REL32:
  1432. rel_type:=RELOC_RELATIVE;
  1433. IMAGE_REL_AMD64_ADDR32:
  1434. rel_type:=RELOC_ABSOLUTE32;
  1435. IMAGE_REL_AMD64_ADDR64:
  1436. rel_type:=RELOC_ABSOLUTE;
  1437. IMAGE_REL_AMD64_ADDR32NB:
  1438. rel_type:=RELOC_RVA;
  1439. IMAGE_REL_AMD64_REL32_1:
  1440. rel_type:=RELOC_RELATIVE_1;
  1441. IMAGE_REL_AMD64_REL32_2:
  1442. rel_type:=RELOC_RELATIVE_2;
  1443. IMAGE_REL_AMD64_REL32_3:
  1444. rel_type:=RELOC_RELATIVE_3;
  1445. IMAGE_REL_AMD64_REL32_4:
  1446. rel_type:=RELOC_RELATIVE_4;
  1447. IMAGE_REL_AMD64_REL32_5:
  1448. rel_type:=RELOC_RELATIVE_5;
  1449. IMAGE_REL_AMD64_SECREL:
  1450. rel_type:=RELOC_SECREL32;
  1451. {$endif x86_64}
  1452. else
  1453. begin
  1454. InputError('Failed reading coff file, illegal reloctype $'+system.hexstr(rel.reloctype,4));
  1455. exit;
  1456. end;
  1457. end;
  1458. p:=FSymTbl^[rel.sym].sym;
  1459. if assigned(p) then
  1460. s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type)
  1461. else
  1462. begin
  1463. InputError('Failed reading coff file, can''t resolve symbol of relocation');
  1464. exit;
  1465. end;
  1466. end;
  1467. end;
  1468. procedure TCoffObjInput.read_symbols(objdata:TObjData);
  1469. var
  1470. size,
  1471. address,
  1472. nsyms,
  1473. symidx : aint;
  1474. i : longint;
  1475. sym : coffsymbol;
  1476. objsym : TObjSymbol;
  1477. bind : Tasmsymbind;
  1478. strname : string;
  1479. auxrec : array[0..17] of byte;
  1480. objsec : TObjSection;
  1481. begin
  1482. with TCoffObjData(objdata) do
  1483. begin
  1484. nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
  1485. { Allocate memory for symidx -> TObjSymbol table }
  1486. GetMem(FSymTbl,nsyms*sizeof(TObjSymbolrec));
  1487. FillChar(FSymTbl^,nsyms*sizeof(TObjSymbolrec),0);
  1488. { Load the Symbols }
  1489. FCoffSyms.Seek(0);
  1490. symidx:=0;
  1491. while (symidx<nsyms) do
  1492. begin
  1493. FCoffSyms.Read(sym,sizeof(sym));
  1494. if plongint(@sym.name)^<>0 then
  1495. begin
  1496. move(sym.name,strname[1],8);
  1497. strname[9]:=#0;
  1498. strname[0]:=chr(strlen(@strname[1]));
  1499. if strname='' then
  1500. Internalerror(200205171);
  1501. end
  1502. else
  1503. strname:=Read_str(sym.strpos);
  1504. bind:=AB_EXTERNAL;
  1505. size:=0;
  1506. address:=0;
  1507. objsym:=nil;
  1508. objsec:=nil;
  1509. case sym.typ of
  1510. COFF_SYM_GLOBAL :
  1511. begin
  1512. if sym.section=0 then
  1513. begin
  1514. if sym.value=0 then
  1515. bind:=AB_EXTERNAL
  1516. else
  1517. begin
  1518. bind:=AB_COMMON;
  1519. size:=sym.value;
  1520. end;
  1521. end
  1522. else
  1523. begin
  1524. bind:=AB_GLOBAL;
  1525. objsec:=GetSection(sym.section);
  1526. if sym.value>=objsec.mempos then
  1527. address:=sym.value-objsec.mempos;
  1528. end;
  1529. objsym:=CreateSymbol(strname);
  1530. objsym.bind:=bind;
  1531. objsym.typ:=AT_FUNCTION;
  1532. objsym.objsection:=objsec;
  1533. objsym.offset:=address;
  1534. objsym.size:=size;
  1535. { Register in ObjSection }
  1536. if assigned(objsec) then
  1537. objsec.AddSymbolDefine(objsym);
  1538. end;
  1539. COFF_SYM_LABEL,
  1540. COFF_SYM_LOCAL :
  1541. begin
  1542. { do not add constants (section=-1) }
  1543. if sym.section<>-1 then
  1544. begin
  1545. bind:=AB_LOCAL;
  1546. objsec:=GetSection(sym.section);
  1547. if sym.value>=objsec.mempos then
  1548. address:=sym.value-objsec.mempos;
  1549. objsym:=CreateSymbol(strname);
  1550. objsym.bind:=bind;
  1551. objsym.typ:=AT_FUNCTION;
  1552. objsym.objsection:=objsec;
  1553. objsym.offset:=address;
  1554. objsym.size:=size;
  1555. end;
  1556. end;
  1557. COFF_SYM_SECTION :
  1558. begin
  1559. if sym.section=0 then
  1560. InputError('Failed reading coff file, illegal section');
  1561. objsec:=GetSection(sym.section);
  1562. if assigned(objsec) then
  1563. begin
  1564. if sym.value>=objsec.mempos then
  1565. address:=sym.value-objsec.mempos;
  1566. objsym:=CreateSymbol(strname);
  1567. objsym.bind:=AB_LOCAL;
  1568. objsym.typ:=AT_FUNCTION;
  1569. objsym.objsection:=objsec;
  1570. objsym.offset:=address;
  1571. objsym.size:=size;
  1572. end;
  1573. end;
  1574. COFF_SYM_FUNCTION,
  1575. COFF_SYM_FILE :
  1576. ;
  1577. else
  1578. internalerror(200602232);
  1579. end;
  1580. FSymTbl^[symidx].sym:=objsym;
  1581. FSymTbl^[symidx].orgsize:=size;
  1582. { read aux records }
  1583. for i:=1 to sym.aux do
  1584. begin
  1585. FCoffSyms.Read(auxrec,sizeof(auxrec));
  1586. inc(symidx);
  1587. end;
  1588. inc(symidx);
  1589. end;
  1590. end;
  1591. end;
  1592. procedure TCoffObjInput.ObjSections_read_data(p:TObject;arg:pointer);
  1593. begin
  1594. with TCoffObjSection(p) do
  1595. begin
  1596. { Skip debug sections }
  1597. if (oso_debug in secoptions) and
  1598. (cs_link_strip in current_settings.globalswitches) and
  1599. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1600. exit;
  1601. if assigned(data) then
  1602. begin
  1603. FReader.Seek(datapos);
  1604. if not FReader.ReadArray(data,Size) then
  1605. begin
  1606. Comment(V_Error,'Error reading coff file, can''t read object data');
  1607. exit;
  1608. end;
  1609. end;
  1610. end;
  1611. end;
  1612. procedure TCoffObjInput.ObjSections_read_relocs(p:TObject;arg:pointer);
  1613. begin
  1614. with TCoffObjSection(p) do
  1615. begin
  1616. { Skip debug sections }
  1617. if (oso_debug in secoptions) and
  1618. (cs_link_strip in current_settings.globalswitches) and
  1619. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1620. exit;
  1621. if coffrelocs>0 then
  1622. begin
  1623. FReader.Seek(coffrelocpos);
  1624. read_relocs(TCoffObjSection(p));
  1625. end;
  1626. end;
  1627. end;
  1628. function TCoffObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
  1629. var
  1630. secalign : shortint;
  1631. strsize,
  1632. strpos,
  1633. i : longint;
  1634. code : longint;
  1635. objsec : TCoffObjSection;
  1636. secoptions : TObjSectionOptions;
  1637. header : tcoffheader;
  1638. sechdr : tcoffsechdr;
  1639. secname : string;
  1640. secnamebuf : array[0..15] of char;
  1641. begin
  1642. FReader:=AReader;
  1643. InputFileName:=AReader.FileName;
  1644. result:=false;
  1645. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1646. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1647. with TCoffObjData(objdata) do
  1648. begin
  1649. { Read COFF header }
  1650. if not AReader.read(header,sizeof(tcoffheader)) then
  1651. begin
  1652. InputError('Can''t read COFF Header');
  1653. exit;
  1654. end;
  1655. if header.mach<>COFF_MAGIC then
  1656. begin
  1657. InputError('Illegal COFF Magic');
  1658. exit;
  1659. end;
  1660. {$ifdef arm}
  1661. eVCobj:=header.flag=$100;
  1662. {$endif arm}
  1663. { Strings }
  1664. AReader.Seek(header.sympos+header.syms*sizeof(CoffSymbol));
  1665. if not AReader.Read(strsize,4) then
  1666. begin
  1667. InputError('Error reading COFF Symtable');
  1668. exit;
  1669. end;
  1670. if (strsize>4) and not AReader.ReadArray(FCoffStrs,Strsize-4) then
  1671. begin
  1672. InputError('Error reading COFF Symtable');
  1673. exit;
  1674. end;
  1675. { Section headers }
  1676. { Allocate SecIdx -> TObjSection table, secidx is 1-based }
  1677. FSecCount:=header.nsects;
  1678. GetMem(FSecTbl,(header.nsects+1)*sizeof(TObjSection));
  1679. FillChar(FSecTbl^,(header.nsects+1)*sizeof(TObjSection),0);
  1680. AReader.Seek(sizeof(tcoffheader)+header.opthdr);
  1681. for i:=1 to header.nsects do
  1682. begin
  1683. if not AReader.read(sechdr,sizeof(sechdr)) then
  1684. begin
  1685. InputError('Error reading COFF Section Headers');
  1686. exit;
  1687. end;
  1688. move(sechdr.name,secnamebuf,8);
  1689. secnamebuf[8]:=#0;
  1690. secname:=strpas(secnamebuf);
  1691. if secname[1]='/' then
  1692. begin
  1693. Val(Copy(secname,2,8),strpos,code);
  1694. if code=0 then
  1695. secname:=Read_str(strpos)
  1696. else
  1697. begin
  1698. InputError('Error reading COFF Section Headers');
  1699. secname:='error';
  1700. end;
  1701. end;
  1702. if win32 then
  1703. pedecodesechdrflags(secname,sechdr.flags,secoptions,secalign)
  1704. else
  1705. begin
  1706. djdecodesechdrflags(secname,sechdr.flags);
  1707. secalign:=sizeof(pint);
  1708. end;
  1709. if (Length(secname)>3) and (secname[2] in ['e','f','i','p','r']) then
  1710. begin
  1711. if (Copy(secname,1,6)='.edata') or
  1712. (Copy(secname,1,5)='.rsrc') or
  1713. (Copy(secname,1,6)='.pdata') or
  1714. (Copy(secname,1,4)='.fpc') then
  1715. include(secoptions,oso_keep);
  1716. if (Copy(secname,1,6)='.idata') then
  1717. begin
  1718. { TODO: idata keep can maybe replaced with grouping of text and idata}
  1719. include(secoptions,oso_keep);
  1720. secname:=secname + '.' + ExtractFileName(InputFileName);
  1721. end;
  1722. end;
  1723. objsec:=TCoffObjSection(createsection(secname,secalign,secoptions,false));
  1724. FSecTbl^[i]:=objsec;
  1725. if not win32 then
  1726. objsec.mempos:=sechdr.rvaofs;
  1727. objsec.orgmempos:=sechdr.rvaofs;
  1728. objsec.coffrelocs:=sechdr.nrelocs;
  1729. objsec.coffrelocpos:=sechdr.relocpos;
  1730. objsec.datapos:=sechdr.datapos;
  1731. objsec.Size:=sechdr.dataSize;
  1732. end;
  1733. { ObjSymbols }
  1734. AReader.Seek(header.sympos);
  1735. if not AReader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
  1736. begin
  1737. Comment(V_Error,'Error reading coff file');
  1738. exit;
  1739. end;
  1740. { Insert all ObjSymbols }
  1741. read_symbols(objdata);
  1742. { Section Data }
  1743. ObjSectionList.ForEachCall(@objsections_read_data,nil);
  1744. { Relocs }
  1745. ObjSectionList.ForEachCall(@objsections_read_relocs,nil);
  1746. end;
  1747. FCoffStrs.Free;
  1748. FCoffStrs:=nil;
  1749. FCoffSyms.Free;
  1750. FCoffSyms:=nil;
  1751. result:=true;
  1752. end;
  1753. constructor TDJCoffObjInput.create;
  1754. begin
  1755. inherited createcoff(false);
  1756. cobjdata:=TDJCoffObjData;
  1757. end;
  1758. constructor TPECoffObjInput.create;
  1759. begin
  1760. inherited createcoff(true);
  1761. cobjdata:=TPECoffObjData;
  1762. end;
  1763. {****************************************************************************
  1764. TCoffexesection
  1765. ****************************************************************************}
  1766. constructor TCoffExeSection.createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
  1767. begin
  1768. inherited create(AList,n);
  1769. win32:=awin32;
  1770. end;
  1771. constructor TDJCoffExeSection.create(AList:TFPHashObjectList;const n:string);
  1772. begin
  1773. inherited createcoff(AList,n,false);
  1774. end;
  1775. constructor TPECoffExeSection.create(AList:TFPHashObjectList;const n:string);
  1776. begin
  1777. inherited createcoff(AList,n,false);
  1778. end;
  1779. {****************************************************************************
  1780. TCoffexeoutput
  1781. ****************************************************************************}
  1782. constructor TCoffexeoutput.createcoff(awin32:boolean);
  1783. begin
  1784. inherited create;
  1785. win32:=awin32;
  1786. if target_info.system in [system_x86_64_win64] then
  1787. MaxMemPos:=$FFFFFFFF
  1788. else
  1789. if target_info.system in system_wince then
  1790. MaxMemPos:=$1FFFFFF
  1791. else
  1792. MaxMemPos:=$7FFFFFFF;
  1793. end;
  1794. procedure TCoffexeoutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  1795. var
  1796. sym : coffsymbol;
  1797. begin
  1798. FillChar(sym,sizeof(sym),0);
  1799. if length(name)>8 then
  1800. begin
  1801. sym.strpos:=FCoffStrs.size+4;
  1802. FCoffStrs.writestr(name);
  1803. FCoffStrs.writestr(#0);
  1804. end
  1805. else
  1806. move(name[1],sym.name,length(name));
  1807. sym.value:=value;
  1808. sym.section:=section;
  1809. sym.typ:=typ;
  1810. sym.aux:=aux;
  1811. FWriter.write(sym,sizeof(sym));
  1812. end;
  1813. procedure TCoffexeoutput.globalsyms_write_symbol(p:TObject;arg:pointer);
  1814. var
  1815. secval,
  1816. value : aint;
  1817. globalval : byte;
  1818. exesec : TExeSection;
  1819. begin
  1820. if not assigned(texesymbol(p).objsymbol) then
  1821. internalerror(200603053);
  1822. with texesymbol(p).objsymbol do
  1823. begin
  1824. exesec:=TExeSection(objsection.exesection);
  1825. { There is no exesection defined for special internal symbols
  1826. like __image_base__ }
  1827. if assigned(exesec) then
  1828. begin
  1829. secval:=exesec.secsymidx;
  1830. value:=address-exesec.mempos;
  1831. end
  1832. else
  1833. begin
  1834. secval:=-1;
  1835. value:=address;
  1836. end;
  1837. if bind=AB_LOCAL then
  1838. globalval:=3
  1839. else
  1840. globalval:=2;
  1841. { reloctype address to the section in the executable }
  1842. write_symbol(name,value,secval,globalval,0);
  1843. end;
  1844. end;
  1845. procedure TCoffexeoutput.ExeSectionList_write_header(p:TObject;arg:pointer);
  1846. var
  1847. sechdr : tcoffsechdr;
  1848. s : string;
  1849. strpos : aword;
  1850. begin
  1851. with tExeSection(p) do
  1852. begin
  1853. fillchar(sechdr,sizeof(sechdr),0);
  1854. s:=name;
  1855. if length(s)>8 then
  1856. begin
  1857. strpos:=FCoffStrs.size+4;
  1858. FCoffStrs.writestr(s);
  1859. FCoffStrs.writestr(#0);
  1860. s:='/'+ToStr(strpos);
  1861. end;
  1862. move(s[1],sechdr.name,length(s));
  1863. sechdr.rvaofs:=mempos;
  1864. if win32 then
  1865. sechdr.vsize:=Size
  1866. else
  1867. sechdr.vsize:=mempos;
  1868. { sechdr.dataSize is size of initilized data. For .bss section it must be zero }
  1869. if (Name <> '.bss') then
  1870. sechdr.dataSize:=Size;
  1871. if (sechdr.dataSize>0) and
  1872. (oso_data in SecOptions) then
  1873. sechdr.datapos:=datapos;
  1874. sechdr.nrelocs:=0;
  1875. sechdr.relocpos:=0;
  1876. if win32 then
  1877. sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign)
  1878. else
  1879. sechdr.flags:=djencodesechdrflags(SecOptions);
  1880. FWriter.write(sechdr,sizeof(sechdr));
  1881. end;
  1882. end;
  1883. procedure TCoffexeoutput.ExeSectionList_pass2_header(p:TObject;arg:pointer);
  1884. begin
  1885. with TExeSection(p) do
  1886. begin
  1887. { The debuginfo sections should already be stripped }
  1888. { if (ExeWriteMode=ewm_exeonly) and
  1889. (oso_debug in SecOptions) then
  1890. internalerror(200801161); }
  1891. inc(plongint(arg)^);
  1892. secsymidx:=plongint(arg)^;
  1893. end;
  1894. end;
  1895. procedure Tcoffexeoutput.ExeSectionList_write_Data(p:TObject;arg:pointer);
  1896. var
  1897. objsec : TObjSection;
  1898. i : longint;
  1899. begin
  1900. with texesection(p) do
  1901. begin
  1902. { don't write normal section if writing only debug info }
  1903. if (ExeWriteMode=ewm_dbgonly) and
  1904. not(oso_debug in SecOptions) then
  1905. exit;
  1906. if oso_data in secoptions then
  1907. begin
  1908. FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
  1909. for i:=0 to ObjSectionList.Count-1 do
  1910. begin
  1911. objsec:=TObjSection(ObjSectionList[i]);
  1912. if oso_data in objsec.secoptions then
  1913. begin
  1914. if not assigned(objsec.data) then
  1915. internalerror(200603042);
  1916. FWriter.writezeros(objsec.dataalignbytes);
  1917. if objsec.DataPos<>FWriter.Size then
  1918. internalerror(200602251);
  1919. FWriter.writearray(objsec.data);
  1920. end;
  1921. end;
  1922. end;
  1923. end;
  1924. end;
  1925. function tcoffexeoutput.totalheadersize:longword;
  1926. var
  1927. stubsize,
  1928. optheadersize : longword;
  1929. begin
  1930. if win32 then
  1931. begin
  1932. stubsize:=sizeof(win32stub)+sizeof(pemagic);
  1933. optheadersize:=sizeof(tcoffpeoptheader);
  1934. end
  1935. else
  1936. begin
  1937. stubsize:=sizeof(go32v2stub);
  1938. optheadersize:=sizeof(coffdjoptheader);
  1939. end;
  1940. result:=stubsize+sizeof(tcoffheader)+optheadersize;
  1941. end;
  1942. procedure tcoffexeoutput.MemPos_Header;
  1943. begin
  1944. { calculate start positions after the headers }
  1945. currmempos:=totalheadersize+sizeof(tcoffsechdr)*longword(ExeSectionList.Count-2);
  1946. end;
  1947. procedure tcoffexeoutput.DataPos_Header;
  1948. begin
  1949. { retrieve amount of sections }
  1950. nsects:=0;
  1951. ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
  1952. { calculate start positions after the headers }
  1953. currdatapos:=totalheadersize+longword(nsects)*sizeof(tcoffsechdr);
  1954. end;
  1955. procedure tcoffexeoutput.DataPos_Symbols;
  1956. begin
  1957. inherited DataPos_Symbols;
  1958. { Calculating symbols position and size }
  1959. nsyms:=ExeSymbolList.Count;
  1960. sympos:=CurrDataPos;
  1961. inc(CurrDataPos,sizeof(coffsymbol)*nsyms);
  1962. end;
  1963. function TCoffexeoutput.writedata:boolean;
  1964. var
  1965. i : longword;
  1966. header : tcoffheader;
  1967. djoptheader : coffdjoptheader;
  1968. peoptheader : tcoffpeoptheader;
  1969. textExeSec,
  1970. dataExeSec,
  1971. bssExeSec,
  1972. idataExeSec : TExeSection;
  1973. hassymbols,
  1974. writeDbgStrings : boolean;
  1975. procedure UpdateDataDir(const secname:string;idx:longint);
  1976. var
  1977. exesec : TExeSection;
  1978. begin
  1979. exesec:=FindExeSection(secname);
  1980. if assigned(exesec) then
  1981. begin
  1982. peoptheader.DataDirectory[idx].vaddr:=exesec.mempos;
  1983. peoptheader.DataDirectory[idx].size:=exesec.Size;
  1984. end;
  1985. end;
  1986. begin
  1987. result:=false;
  1988. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1989. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1990. textExeSec:=FindExeSection('.text');
  1991. dataExeSec:=FindExeSection('.data');
  1992. bssExeSec:=FindExeSection('.bss');
  1993. if not assigned(TextExeSec) or
  1994. not assigned(DataExeSec) then
  1995. internalerror(200602231);
  1996. { do we need to write symbols? }
  1997. hassymbols:=(ExeWriteMode=ewm_dbgonly) or
  1998. (
  1999. (ExeWriteMode=ewm_exefull) and
  2000. not(cs_link_strip in current_settings.globalswitches)
  2001. );
  2002. writeDbgStrings:=hassymbols or ((ExeWriteMode=ewm_exeonly) and (cs_link_separate_dbg_file in current_settings.globalswitches));
  2003. { Stub }
  2004. if win32 then
  2005. begin
  2006. FWriter.write(win32stub,sizeof(win32stub));
  2007. FWriter.write(pemagic,sizeof(pemagic));
  2008. end
  2009. else
  2010. FWriter.write(go32v2stub,sizeof(go32v2stub));
  2011. { Initial header, will be updated later }
  2012. fillchar(header,sizeof(header),0);
  2013. header.mach:=COFF_MAGIC;
  2014. header.nsects:=nsects;
  2015. if writeDbgStrings then
  2016. header.sympos:=sympos;
  2017. if hassymbols then
  2018. header.syms:=nsyms;
  2019. if win32 then
  2020. header.opthdr:=sizeof(tcoffpeoptheader)
  2021. else
  2022. header.opthdr:=sizeof(coffdjoptheader);
  2023. if win32 then
  2024. begin
  2025. header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED;
  2026. if target_info.system in [system_x86_64_win64] then
  2027. header.flag:=header.flag or PE_FILE_LARGE_ADDRESS_AWARE
  2028. else
  2029. header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
  2030. if IsSharedLibrary then
  2031. header.flag:=header.flag or PE_FILE_DLL;
  2032. if FindExeSection('.reloc')=nil then
  2033. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  2034. if (FindExeSection('.stab')=nil) and
  2035. (FindExeSection('.debug_info')=nil) and
  2036. (FindExeSection('.gnu_debuglink')=nil) then
  2037. header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED;
  2038. if not hassymbols then
  2039. header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED;
  2040. if SetPEFlagsSetExplicity then
  2041. header.flag:=header.flag or peflags;
  2042. end
  2043. else
  2044. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
  2045. FWriter.write(header,sizeof(header));
  2046. { Optional COFF Header }
  2047. if win32 then
  2048. begin
  2049. fillchar(peoptheader,sizeof(peoptheader),0);
  2050. peoptheader.magic:=COFF_OPT_MAGIC;
  2051. peoptheader.MajorLinkerVersion:=ord(version_nr)-ord('0');
  2052. peoptheader.MinorLinkerVersion:=(ord(release_nr)-ord('0'))*10 + (ord(patch_nr)-ord('0'));
  2053. peoptheader.tsize:=TextExeSec.Size;
  2054. peoptheader.dsize:=DataExeSec.Size;
  2055. if assigned(BSSExeSec) then
  2056. peoptheader.bsize:=BSSExeSec.Size;
  2057. peoptheader.text_start:=TextExeSec.mempos;
  2058. {$ifndef cpu64bitaddr}
  2059. peoptheader.data_start:=DataExeSec.mempos;
  2060. {$endif cpu64bitaddr}
  2061. peoptheader.entry:=EntrySym.Address;
  2062. peoptheader.ImageBase:=ImageBase;
  2063. peoptheader.SectionAlignment:=SectionMemAlign;
  2064. peoptheader.FileAlignment:=SectionDataAlign;
  2065. peoptheader.MajorOperatingSystemVersion:=4;
  2066. peoptheader.MinorOperatingSystemVersion:=0;
  2067. peoptheader.MajorImageVersion:=dllmajor;
  2068. peoptheader.MinorImageVersion:=dllminor;
  2069. if target_info.system in system_wince then
  2070. peoptheader.MajorSubsystemVersion:=3
  2071. else
  2072. peoptheader.MajorSubsystemVersion:=4;
  2073. peoptheader.MinorSubsystemVersion:=0;
  2074. peoptheader.Win32Version:=0;
  2075. peoptheader.SizeOfImage:=Align(CurrMemPos,SectionMemAlign);
  2076. peoptheader.SizeOfHeaders:=textExeSec.DataPos;
  2077. peoptheader.CheckSum:=0;
  2078. if target_info.system in system_wince then
  2079. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CE_GUI
  2080. else
  2081. if apptype=app_gui then
  2082. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_GUI
  2083. else
  2084. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CUI;
  2085. peoptheader.DllCharacteristics:=0;
  2086. peoptheader.SizeOfStackReserve:=stacksize;
  2087. peoptheader.SizeOfStackCommit:=$1000;
  2088. if MinStackSizeSetExplicity then
  2089. peoptheader.SizeOfStackCommit:=minstacksize;
  2090. if MaxStackSizeSetExplicity then
  2091. peoptheader.SizeOfStackReserve:=maxstacksize;
  2092. peoptheader.SizeOfHeapReserve:=$100000;
  2093. peoptheader.SizeOfHeapCommit:=$1000;
  2094. peoptheader.NumberOfRvaAndSizes:=PE_DATADIR_ENTRIES;
  2095. UpdateDataDir('.idata',PE_DATADIR_IDATA);
  2096. UpdateDataDir('.edata',PE_DATADIR_EDATA);
  2097. UpdateDataDir('.rsrc',PE_DATADIR_RSRC);
  2098. UpdateDataDir('.pdata',PE_DATADIR_PDATA);
  2099. UpdateDataDir('.reloc',PE_DATADIR_RELOC);
  2100. FWriter.write(peoptheader,sizeof(peoptheader));
  2101. end
  2102. else
  2103. begin
  2104. fillchar(djoptheader,sizeof(djoptheader),0);
  2105. djoptheader.magic:=COFF_OPT_MAGIC;
  2106. djoptheader.tsize:=TextExeSec.Size;
  2107. djoptheader.dsize:=DataExeSec.Size;
  2108. if assigned(BSSExeSec) then
  2109. djoptheader.bsize:=BSSExeSec.Size;
  2110. djoptheader.text_start:=TextExeSec.mempos;
  2111. djoptheader.data_start:=DataExeSec.mempos;
  2112. djoptheader.entry:=EntrySym.offset;
  2113. FWriter.write(djoptheader,sizeof(djoptheader));
  2114. end;
  2115. { For some unknown reason WM 6.1 requires .idata section to be read only.
  2116. Otherwise it refuses to load DLLs greater than 64KB.
  2117. Earlier versions of WinCE load DLLs regardless of .idata flags. }
  2118. if target_info.system in system_wince then
  2119. begin
  2120. idataExeSec:=FindExeSection('.idata');
  2121. if idataExeSec<>nil then
  2122. idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write] + [oso_readonly];
  2123. end;
  2124. { Section headers }
  2125. ExeSectionList.ForEachCall(@ExeSectionList_write_header,nil);
  2126. { Section data }
  2127. ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil);
  2128. { Optional Symbols }
  2129. if SymPos<>FWriter.Size then
  2130. internalerror(200602252);
  2131. if hassymbols then
  2132. ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil);
  2133. if writeDbgStrings then
  2134. begin
  2135. { Strings }
  2136. i:=FCoffStrs.size+4;
  2137. FWriter.write(i,4);
  2138. FWriter.writearray(FCoffStrs);
  2139. end;
  2140. { Release }
  2141. FCoffStrs.Free;
  2142. FCoffSyms.Free;
  2143. result:=true;
  2144. end;
  2145. function IdataObjSectionCompare(Item1, Item2: Pointer): Integer;
  2146. var
  2147. I1 : TObjSection absolute Item1;
  2148. I2 : TObjSection absolute Item2;
  2149. begin
  2150. Result:=CompareStr(I1.Name,I2.Name);
  2151. end;
  2152. procedure TCoffexeoutput.Order_ObjSectionList(ObjSectionList: TFPObjectList);
  2153. begin
  2154. if CurrExeSec.Name = '.idata' then
  2155. ObjSectionList.Sort(@IdataObjSectionCompare);
  2156. end;
  2157. constructor TDJCoffexeoutput.create;
  2158. begin
  2159. inherited createcoff(false);
  2160. CExeSection:=TDJCoffExeSection;
  2161. CObjData:=TPECoffObjData;
  2162. end;
  2163. constructor TPECoffexeoutput.create;
  2164. begin
  2165. inherited createcoff(true);
  2166. CExeSection:=TPECoffExeSection;
  2167. CObjData:=TPECoffObjData;
  2168. end;
  2169. procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2170. var
  2171. textobjsection,
  2172. idata2objsection,
  2173. idata4objsection,
  2174. idata5objsection,
  2175. idata6objsection,
  2176. idata7objsection : TObjSection;
  2177. idata2label : TObjSymbol;
  2178. basedllname : string;
  2179. procedure StartImport(const dllname:string);
  2180. var
  2181. idata4label,
  2182. idata5label,
  2183. idata7label : TObjSymbol;
  2184. emptyint : longint;
  2185. begin
  2186. if assigned(exemap) then
  2187. begin
  2188. exemap.Add('');
  2189. exemap.Add('Importing from DLL '+dllname);
  2190. end;
  2191. emptyint:=0;
  2192. basedllname:=ExtractFileName(dllname);
  2193. idata2objsection:=internalobjdata.createsection(sec_idata2,basedllname);
  2194. idata2label:=internalobjdata.SymbolDefine('__imp_dir_'+basedllname,AB_LOCAL,AT_DATA);
  2195. idata4objsection:=internalobjdata.createsection(sec_idata4,basedllname);
  2196. idata4label:=internalobjdata.SymbolDefine('__imp_names_'+basedllname,AB_LOCAL,AT_DATA);
  2197. idata5objsection:=internalobjdata.createsection(sec_idata5,basedllname);
  2198. idata5label:=internalobjdata.SymbolDefine('__imp_fixup_'+basedllname,AB_LOCAL,AT_DATA);
  2199. idata7objsection:=internalobjdata.createsection(sec_idata7,basedllname);
  2200. idata7label:=internalobjdata.SymbolDefine('__imp_dll_'+basedllname,AB_LOCAL,AT_DATA);
  2201. { idata2 }
  2202. internalobjdata.SetSection(idata2objsection);
  2203. { dummy links to imports finalization }
  2204. internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_names_end_'+basedllname),RELOC_NONE);
  2205. internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_fixup_end_'+basedllname),RELOC_NONE);
  2206. { section data }
  2207. internalobjdata.writereloc(0,sizeof(longint),idata4label,RELOC_RVA);
  2208. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2209. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2210. internalobjdata.writereloc(0,sizeof(longint),idata7label,RELOC_RVA);
  2211. internalobjdata.writereloc(0,sizeof(longint),idata5label,RELOC_RVA);
  2212. { idata7 }
  2213. internalobjdata.SetSection(idata7objsection);
  2214. internalobjdata.writebytes(basedllname[1],length(basedllname));
  2215. internalobjdata.writebytes(emptyint,1);
  2216. end;
  2217. procedure EndImport;
  2218. var
  2219. emptyint : longint;
  2220. begin
  2221. emptyint:=0;
  2222. idata4objsection:=internalobjdata.createsection(sec_idata4, basedllname+'_z_');
  2223. internalobjdata.SymbolDefine('__imp_names_end_'+basedllname,AB_LOCAL,AT_DATA);
  2224. idata5objsection:=internalobjdata.createsection(sec_idata5, basedllname+'_z_');
  2225. internalobjdata.SymbolDefine('__imp_fixup_end_'+basedllname,AB_LOCAL,AT_DATA);
  2226. { idata4 }
  2227. internalobjdata.SetSection(idata4objsection);
  2228. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2229. if target_info.system=system_x86_64_win64 then
  2230. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2231. { idata5 }
  2232. internalobjdata.SetSection(idata5objsection);
  2233. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2234. if target_info.system=system_x86_64_win64 then
  2235. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2236. { be sure that this will not be removed }
  2237. idata4objsection.SecOptions:=idata4objsection.SecOptions + [oso_keep];
  2238. idata5objsection.SecOptions:=idata5objsection.SecOptions + [oso_keep];
  2239. end;
  2240. function AddImport(const afuncname,amangledname:string; AOrdNr:longint;isvar:boolean):TObjSymbol;
  2241. const
  2242. {$ifdef x86_64}
  2243. jmpopcode : array[0..1] of byte = (
  2244. $ff,$25 // jmp qword [rip + offset32]
  2245. );
  2246. {$else x86_64}
  2247. {$ifdef arm}
  2248. jmpopcode : array[0..7] of byte = (
  2249. $00,$c0,$9f,$e5, // ldr ip, [pc, #0]
  2250. $00,$f0,$9c,$e5 // ldr pc, [ip]
  2251. );
  2252. {$else arm}
  2253. jmpopcode : array[0..1] of byte = (
  2254. $ff,$25
  2255. );
  2256. {$endif arm}
  2257. {$endif x86_64}
  2258. nopopcodes : array[0..1] of byte = (
  2259. $90,$90
  2260. );
  2261. var
  2262. idata4label,
  2263. idata5label,
  2264. idata6label : TObjSymbol;
  2265. emptyint : longint;
  2266. secname,
  2267. num : string;
  2268. absordnr: word;
  2269. procedure WriteTableEntry;
  2270. var
  2271. ordint: dword;
  2272. begin
  2273. if AOrdNr <= 0 then
  2274. begin
  2275. { import by name }
  2276. internalobjdata.writereloc(0,sizeof(longint),idata6label,RELOC_RVA);
  2277. if target_info.system=system_x86_64_win64 then
  2278. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2279. end
  2280. else
  2281. begin
  2282. { import by ordinal }
  2283. ordint:=AOrdNr;
  2284. if target_info.system=system_x86_64_win64 then
  2285. begin
  2286. internalobjdata.writebytes(ordint,sizeof(ordint));
  2287. ordint:=$80000000;
  2288. internalobjdata.writebytes(ordint,sizeof(ordint));
  2289. end
  2290. else
  2291. begin
  2292. ordint:=ordint or $80000000;
  2293. internalobjdata.writebytes(ordint,sizeof(ordint));
  2294. end;
  2295. end;
  2296. end;
  2297. begin
  2298. result:=nil;
  2299. emptyint:=0;
  2300. if assigned(exemap) then
  2301. begin
  2302. if AOrdNr <= 0 then
  2303. exemap.Add(' Importing Function '+afuncname)
  2304. else
  2305. exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
  2306. end;
  2307. with internalobjdata do
  2308. begin
  2309. secname:=basedllname+'_i_'+amangledname;
  2310. textobjsection:=createsection(sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,sectiontype2options(sec_code) - [oso_keep]);
  2311. idata4objsection:=createsection(sec_idata4, secname);
  2312. idata5objsection:=createsection(sec_idata5, secname);
  2313. idata6objsection:=createsection(sec_idata6, secname);
  2314. end;
  2315. { idata6, import data (ordnr+name) }
  2316. internalobjdata.SetSection(idata6objsection);
  2317. inc(idatalabnr);
  2318. num:=tostr(idatalabnr);
  2319. idata6label:=internalobjdata.SymbolDefine('__imp_'+num,AB_LOCAL,AT_DATA);
  2320. absordnr:=Abs(AOrdNr);
  2321. { write index hint }
  2322. internalobjdata.writebytes(absordnr,2);
  2323. if AOrdNr <= 0 then
  2324. internalobjdata.writebytes(afuncname[1],length(afuncname));
  2325. internalobjdata.writebytes(emptyint,1);
  2326. internalobjdata.writebytes(emptyint,align(internalobjdata.CurrObjSec.size,2)-internalobjdata.CurrObjSec.size);
  2327. { idata4, import lookup table }
  2328. internalobjdata.SetSection(idata4objsection);
  2329. idata4label:=internalobjdata.SymbolDefine('__imp_lookup_'+num,AB_LOCAL,AT_DATA);
  2330. WriteTableEntry;
  2331. { idata5, import address table }
  2332. internalobjdata.SetSection(idata5objsection);
  2333. { dummy back links }
  2334. internalobjdata.writereloc(0,0,idata4label,RELOC_NONE);
  2335. internalobjdata.writereloc(0,0,idata2label,RELOC_NONE);
  2336. { section data }
  2337. if isvar then
  2338. result:=internalobjdata.SymbolDefine(amangledname,AB_GLOBAL,AT_DATA)
  2339. else
  2340. idata5label:=internalobjdata.SymbolDefine('__imp_'+amangledname,AB_LOCAL,AT_DATA);
  2341. WriteTableEntry;
  2342. { text, jmp }
  2343. if not isvar then
  2344. begin
  2345. internalobjdata.SetSection(textobjsection);
  2346. result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
  2347. internalobjdata.writebytes(jmpopcode,sizeof(jmpopcode));
  2348. {$ifdef x86_64}
  2349. internalobjdata.writereloc(0,4,idata5label,RELOC_RELATIVE);
  2350. {$else}
  2351. internalobjdata.writereloc(0,4,idata5label,RELOC_ABSOLUTE32);
  2352. {$endif x86_64}
  2353. internalobjdata.writebytes(nopopcodes,align(internalobjdata.CurrObjSec.size,sizeof(nopopcodes))-internalobjdata.CurrObjSec.size);
  2354. end;
  2355. end;
  2356. var
  2357. i,j : longint;
  2358. ImportLibrary : TImportLibrary;
  2359. ImportSymbol : TImportSymbol;
  2360. exesym : TExeSymbol;
  2361. begin
  2362. for i:=0 to ImportLibraryList.Count-1 do
  2363. begin
  2364. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  2365. idata2objsection:=nil;
  2366. idata4objsection:=nil;
  2367. idata5objsection:=nil;
  2368. idata6objsection:=nil;
  2369. idata7objsection:=nil;
  2370. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  2371. begin
  2372. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  2373. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  2374. if assigned(exesym) and
  2375. (exesym.State<>symstate_defined) then
  2376. begin
  2377. if not assigned(idata2objsection) then
  2378. StartImport(ImportLibrary.Name);
  2379. exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
  2380. exesym.State:=symstate_defined;
  2381. end;
  2382. end;
  2383. if assigned(idata2objsection) then
  2384. EndImport;
  2385. end;
  2386. PackUnresolvedExeSymbols('after DLL imports');
  2387. end;
  2388. procedure TPECoffexeoutput.GenerateRelocs;
  2389. var
  2390. pgaddr, hdrpos : longword;
  2391. procedure FinishBlock;
  2392. var
  2393. p,len : longint;
  2394. begin
  2395. if hdrpos = longword(-1) then
  2396. exit;
  2397. p:=0;
  2398. internalobjdata.writebytes(p,align(internalobjdata.CurrObjSec.size,4)-internalobjdata.CurrObjSec.size);
  2399. p:=internalObjData.CurrObjSec.Data.Pos;
  2400. internalObjData.CurrObjSec.Data.seek(hdrpos+4);
  2401. len:=p-hdrpos;
  2402. internalObjData.CurrObjSec.Data.write(len,4);
  2403. internalObjData.CurrObjSec.Data.seek(p);
  2404. hdrpos:=longword(-1);
  2405. end;
  2406. var
  2407. exesec : TExeSection;
  2408. objsec : TObjSection;
  2409. objreloc : TObjRelocation;
  2410. i,j,k : longint;
  2411. offset : longword;
  2412. w: word;
  2413. begin
  2414. if not RelocSection or FRelocsGenerated then
  2415. exit;
  2416. exesec:=FindExeSection('.reloc');
  2417. if exesec=nil then
  2418. exit;
  2419. objsec:=internalObjData.createsection('.reloc',0,exesec.SecOptions+[oso_data]);
  2420. exesec.AddObjSection(objsec);
  2421. pgaddr:=longword(-1);
  2422. hdrpos:=longword(-1);
  2423. for i:=0 to ExeSectionList.Count-1 do
  2424. begin
  2425. exesec:=TExeSection(ExeSectionList[i]);
  2426. for j:=0 to exesec.ObjSectionList.count-1 do
  2427. begin
  2428. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2429. { create relocs only for sections which are loaded in memory }
  2430. if not (oso_load in objsec.SecOptions) then
  2431. continue;
  2432. for k:=0 to objsec.ObjRelocations.Count-1 do
  2433. begin
  2434. objreloc:=TObjRelocation(objsec.ObjRelocations[k]);
  2435. if not (objreloc.typ in [{$ifdef cpu64bitaddr}RELOC_ABSOLUTE32,{$endif cpu64bitaddr}RELOC_ABSOLUTE]) then
  2436. continue;
  2437. offset:=objsec.MemPos+objreloc.dataoffset;
  2438. if (offset<pgaddr) and (pgaddr<>longword(-1)) then
  2439. Internalerror(2007062701);
  2440. if (offset-pgaddr>=4096) or (pgaddr=longword(-1)) then
  2441. begin
  2442. FinishBlock;
  2443. pgaddr:=(offset div 4096)*4096;
  2444. hdrpos:=internalObjData.CurrObjSec.Data.Pos;
  2445. internalObjData.writebytes(pgaddr,4);
  2446. { Reserving space for block size. The size will be written later in FinishBlock }
  2447. internalObjData.writebytes(k,4);
  2448. end;
  2449. {$ifdef cpu64bitaddr}
  2450. if objreloc.typ = RELOC_ABSOLUTE then
  2451. w:=IMAGE_REL_BASED_DIR64
  2452. else
  2453. {$endif cpu64bitaddr}
  2454. w:=IMAGE_REL_BASED_HIGHLOW;
  2455. w:=(w shl 12) or (offset-pgaddr);
  2456. internalObjData.writebytes(w,2);
  2457. end;
  2458. end;
  2459. end;
  2460. FinishBlock;
  2461. FRelocsGenerated:=true;
  2462. end;
  2463. procedure TPECoffexeoutput.Order_End;
  2464. var
  2465. exesec : TExeSection;
  2466. begin
  2467. inherited;
  2468. if not IsSharedLibrary then
  2469. exit;
  2470. exesec:=FindExeSection('.reloc');
  2471. if exesec=nil then
  2472. exit;
  2473. exesec.SecOptions:=exesec.SecOptions + [oso_Data,oso_keep,oso_load];
  2474. end;
  2475. procedure TPECoffexeoutput.MemPos_ExeSection(const aname:string);
  2476. begin
  2477. if aname='.reloc' then
  2478. GenerateRelocs;
  2479. inherited;
  2480. end;
  2481. {****************************************************************************
  2482. TDJCoffAssembler
  2483. ****************************************************************************}
  2484. constructor TDJCoffAssembler.Create(smart:boolean);
  2485. begin
  2486. inherited Create(smart);
  2487. CObjOutput:=TDJCoffObjOutput;
  2488. end;
  2489. {****************************************************************************
  2490. TPECoffAssembler
  2491. ****************************************************************************}
  2492. constructor TPECoffAssembler.Create(smart:boolean);
  2493. begin
  2494. inherited Create(smart);
  2495. CObjOutput:=TPECoffObjOutput;
  2496. end;
  2497. {*****************************************************************************
  2498. DLLReader
  2499. *****************************************************************************}
  2500. {$ifdef win32}
  2501. var
  2502. Wow64DisableWow64FsRedirection : function (var OldValue : pointer) : boolean;stdcall;
  2503. Wow64RevertWow64FsRedirection : function (OldValue : pointer) : boolean;stdcall;
  2504. {$endif win32}
  2505. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  2506. type
  2507. TPECoffExpDir=packed record
  2508. flag,
  2509. stamp : cardinal;
  2510. Major,
  2511. Minor : word;
  2512. Name,
  2513. Base,
  2514. NumFuncs,
  2515. NumNames,
  2516. AddrFuncs,
  2517. AddrNames,
  2518. AddrOrds : cardinal;
  2519. end;
  2520. var
  2521. DLLReader : TObjectReader;
  2522. DosHeader : array[0..$7f] of byte;
  2523. PEMagic : array[0..3] of byte;
  2524. Header : TCoffHeader;
  2525. peheader : tcoffpeoptheader;
  2526. NameOfs,
  2527. newheaderofs : longword;
  2528. FuncName : string;
  2529. expdir : TPECoffExpDir;
  2530. i : longint;
  2531. found : boolean;
  2532. sechdr : tCoffSecHdr;
  2533. {$ifdef win32}
  2534. p : pointer;
  2535. {$endif win32}
  2536. begin
  2537. result:=false;
  2538. {$ifdef win32}
  2539. if (target_info.system=system_x86_64_win64) and
  2540. assigned(Wow64DisableWow64FsRedirection) then
  2541. Wow64DisableWow64FsRedirection(p);
  2542. {$endif win32}
  2543. DLLReader:=TObjectReader.Create;
  2544. DLLReader.OpenFile(dllname);
  2545. {$ifdef win32}
  2546. if (target_info.system=system_x86_64_win64) and
  2547. assigned(Wow64RevertWow64FsRedirection) then
  2548. Wow64RevertWow64FsRedirection(p);
  2549. {$endif win32}
  2550. if not DLLReader.Read(DosHeader,sizeof(DosHeader)) or
  2551. (DosHeader[0]<>$4d) or (DosHeader[1]<>$5a) then
  2552. begin
  2553. Comment(V_Error,'Invalid DLL '+dllname+', Dos Header invalid');
  2554. exit;
  2555. end;
  2556. newheaderofs:=cardinal(DosHeader[$3c]) or (DosHeader[$3d] shl 8) or (DosHeader[$3e] shl 16) or (DosHeader[$3f] shl 24);
  2557. DLLReader.Seek(newheaderofs);
  2558. if not DLLReader.Read(PEMagic,sizeof(PEMagic)) or
  2559. (PEMagic[0]<>$50) or (PEMagic[1]<>$45) or (PEMagic[2]<>$00) or (PEMagic[3]<>$00) then
  2560. begin
  2561. Comment(V_Error,'Invalid DLL '+dllname+': invalid magic code');
  2562. exit;
  2563. end;
  2564. if not DLLReader.Read(Header,sizeof(TCoffHeader)) or
  2565. (Header.mach<>COFF_MAGIC) or
  2566. (Header.opthdr<>sizeof(tcoffpeoptheader)) then
  2567. begin
  2568. Comment(V_Error,'Invalid DLL '+dllname+', invalid header size');
  2569. exit;
  2570. end;
  2571. { Read optheader }
  2572. DLLreader.Read(peheader,sizeof(tcoffpeoptheader));
  2573. { Section headers }
  2574. found:=false;
  2575. for i:=1 to header.nsects do
  2576. begin
  2577. if not DLLreader.read(sechdr,sizeof(sechdr)) then
  2578. begin
  2579. Comment(V_Error,'Error reading coff file '+DLLName);
  2580. exit;
  2581. end;
  2582. if (sechdr.rvaofs<=peheader.DataDirectory[PE_DATADIR_EDATA].vaddr) and
  2583. (peheader.DataDirectory[PE_DATADIR_EDATA].vaddr<sechdr.rvaofs+sechdr.vsize) then
  2584. begin
  2585. found:=true;
  2586. break;
  2587. end;
  2588. end;
  2589. if not found then
  2590. begin
  2591. Comment(V_Warning,'DLL '+DLLName+' does not contain any exports');
  2592. exit;
  2593. end;
  2594. { Process edata }
  2595. DLLReader.Seek(sechdr.datapos+peheader.DataDirectory[PE_DATADIR_EDATA].vaddr-sechdr.rvaofs);
  2596. DLLReader.Read(expdir,sizeof(expdir));
  2597. for i:=0 to expdir.NumNames-1 do
  2598. begin
  2599. DLLReader.Seek(sechdr.datapos+expdir.AddrNames-sechdr.rvaofs+i*4);
  2600. DLLReader.Read(NameOfs,4);
  2601. Dec(NameOfs,sechdr.rvaofs);
  2602. if (NameOfs<0) or
  2603. (NameOfs>sechdr.vsize) then
  2604. begin
  2605. Comment(V_Error,'DLL does contains invalid exports');
  2606. break;
  2607. end;
  2608. { Read Function name from DLL, prepend _ and terminate with #0 }
  2609. DLLReader.Seek(sechdr.datapos+NameOfs);
  2610. DLLReader.Read((@FuncName[1])^,sizeof(FuncName)-3);
  2611. FuncName[sizeof(FuncName)-1]:=#0;
  2612. FuncName[0]:=chr(Strlen(@FuncName[1]));
  2613. readdllproc(DLLName,FuncName);
  2614. end;
  2615. DLLReader.Free;
  2616. end;
  2617. {*****************************************************************************
  2618. Initialize
  2619. *****************************************************************************}
  2620. {$ifdef i386}
  2621. const
  2622. as_i386_coff_info : tasminfo =
  2623. (
  2624. id : as_i386_coff;
  2625. idtxt : 'COFF';
  2626. asmbin : '';
  2627. asmcmd : '';
  2628. supported_targets : [system_i386_go32v2];
  2629. flags : [af_outputbinary];
  2630. labelprefix : '.L';
  2631. comment : '';
  2632. );
  2633. as_i386_pecoff_info : tasminfo =
  2634. (
  2635. id : as_i386_pecoff;
  2636. idtxt : 'PECOFF';
  2637. asmbin : '';
  2638. asmcmd : '';
  2639. supported_targets : [system_i386_win32];
  2640. flags : [af_outputbinary,af_smartlink_sections];
  2641. labelprefix : '.L';
  2642. comment : '';
  2643. );
  2644. as_i386_pecoffwdosx_info : tasminfo =
  2645. (
  2646. id : as_i386_pecoffwdosx;
  2647. idtxt : 'PEWDOSX';
  2648. asmbin : '';
  2649. asmcmd : '';
  2650. supported_targets : [system_i386_wdosx];
  2651. flags : [af_outputbinary];
  2652. labelprefix : '.L';
  2653. comment : '';
  2654. );
  2655. as_i386_pecoffwince_info : tasminfo =
  2656. (
  2657. id : as_i386_pecoffwince;
  2658. idtxt : 'PECOFFWINCE';
  2659. asmbin : '';
  2660. asmcmd : '';
  2661. supported_targets : [system_i386_wince];
  2662. flags : [af_outputbinary,af_smartlink_sections];
  2663. labelprefix : '.L';
  2664. comment : '';
  2665. );
  2666. {$endif i386}
  2667. {$ifdef x86_64}
  2668. const
  2669. as_x86_64_pecoff_info : tasminfo =
  2670. (
  2671. id : as_x86_64_pecoff;
  2672. idtxt : 'PECOFF';
  2673. asmbin : '';
  2674. asmcmd : '';
  2675. supported_targets : [system_x86_64_win64];
  2676. flags : [af_outputbinary,af_smartlink_sections];
  2677. labelprefix : '.L';
  2678. comment : '';
  2679. );
  2680. {$endif x86_64}
  2681. {$ifdef arm}
  2682. const
  2683. as_arm_pecoffwince_info : tasminfo =
  2684. (
  2685. id : as_arm_pecoffwince;
  2686. idtxt : 'PECOFFWINCE';
  2687. asmbin : '';
  2688. asmcmd : '';
  2689. supported_targets : [system_arm_wince];
  2690. flags : [af_outputbinary];
  2691. labelprefix : '.L';
  2692. comment : '';
  2693. );
  2694. {$endif arm}
  2695. {$ifdef win32}
  2696. procedure SetupProcVars;
  2697. var
  2698. hinstLib : THandle;
  2699. begin
  2700. Wow64DisableWow64FsRedirection:=nil;
  2701. Wow64RevertWow64FsRedirection:=nil;
  2702. hinstLib:=LoadLibrary('kernel32.dll');
  2703. if hinstLib<>0 then
  2704. begin
  2705. pointer(Wow64DisableWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64DisableWow64FsRedirection');
  2706. pointer(Wow64RevertWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64RevertWow64FsRedirection');
  2707. FreeLibrary(hinstLib);
  2708. end;
  2709. end;
  2710. {$endif win32}
  2711. initialization
  2712. {$ifdef i386}
  2713. RegisterAssembler(as_i386_coff_info,TDJCoffAssembler);
  2714. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  2715. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  2716. RegisterAssembler(as_i386_pecoffwince_info,TPECoffAssembler);
  2717. {$endif i386}
  2718. {$ifdef x86_64}
  2719. RegisterAssembler(as_x86_64_pecoff_info,TPECoffAssembler);
  2720. {$endif x86_64}
  2721. {$ifdef arm}
  2722. RegisterAssembler(as_arm_pecoffwince_info,TPECoffAssembler);
  2723. {$endif arm}
  2724. {$ifdef win32}
  2725. SetupProcVars;
  2726. {$endif win32}
  2727. end.