ogcoff.pas 106 KB

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